install.pas 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. This is the install program for the DOS and OS/2 versions of Free Pascal
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. program install;
  13. { $DEFINE DLL} (* TH - if defined, UNZIP32.DLL library is used to unpack. *)
  14. { $DEFINE DOSSTUB} (* TH - should _not_ be defined unless creating a bound DOS and OS/2 installer!!! *)
  15. (* Defining DOSSTUB causes adding a small piece of code *)
  16. (* for starting the OS/2 part from the DOS part of a bound *)
  17. (* application if running in OS/2 VDM (DOS) window. Used *)
  18. (* only if compiling with TP/BP (see conditionals below). *)
  19. {$IFDEF OS2}
  20. {$DEFINE DLL}
  21. {$ENDIF DLL}
  22. {$IFDEF VER60}
  23. {$DEFINE TP}
  24. {$ENDIF}
  25. {$IFDEF VER70}
  26. {$DEFINE TP}
  27. {$ENDIF}
  28. {$IFNDEF TP}
  29. {$UNDEF DOSSTUB}
  30. {$ELSE}
  31. {$IFDEF OS2}
  32. {$UNDEF DOSSTUB}
  33. {$ENDIF}
  34. {$ENDIF}
  35. {$IFDEF DPMI}
  36. {$UNDEF DOSSTUB}
  37. {$ENDIF}
  38. {$ifdef go32v2}
  39. {$define MAYBE_LFN}
  40. {$endif}
  41. {$ifdef debug}
  42. {$ifdef win32}
  43. {$define MAYBE_LFN}
  44. {$endif win32}
  45. {$endif debug}
  46. {$ifdef TP}
  47. {$define MAYBE_LFN}
  48. {$endif}
  49. uses
  50. {$IFDEF OS2}
  51. {$IFDEF FPC}
  52. DosCalls,
  53. {$ELSE FPC}
  54. {$IFDEF VirtualPascal}
  55. OS2Base,
  56. {$ELSE VirtualPascal}
  57. BseDos,
  58. {$ENDIF VirtualPascal}
  59. {$ENDIF FPC}
  60. {$ENDIF OS2}
  61. {$IFDEF GO32V2}
  62. emu387,
  63. {$ENDIF}
  64. {$ifdef HEAPTRC}
  65. heaptrc,
  66. {$endif HEAPTRC}
  67. strings,dos,objects,drivers,
  68. {$IFNDEF FVISION}
  69. commands,
  70. HelpCtx,
  71. {$ENDIF}
  72. unzip,ziptypes,
  73. {$IFDEF DLL}
  74. unzipdll,
  75. {$ENDIF}
  76. app,dialogs,views,menus,msgbox,colortxt,tabs,scroll,
  77. WHTMLScn,insthelp;
  78. const
  79. installerversion='2.2.0';
  80. installercopyright='Copyright (c) 1993-2007 Florian Klaempfl';
  81. maxpacks=30;
  82. maxpackages=25;
  83. maxdefcfgs=1024;
  84. HTMLIndexExt = '.htx';
  85. CfgExt = '.dat';
  86. MaxStatusPos = 4;
  87. StatusChars: string [MaxStatusPos] = '/-\|';
  88. StatusPos: byte = 1;
  89. { this variable is set to true if an ide is installed }
  90. haside : boolean = false;
  91. hashtmlhelp : boolean = false;
  92. {$ifdef Unix}
  93. DirSep='/';
  94. {$else}
  95. DirSep='\';
  96. {$endif}
  97. type
  98. tpackage=record
  99. name : string[60];
  100. zip : string[40]; { default zipname }
  101. zipshort : string[12]; { 8.3 zipname }
  102. diskspace : int64; { diskspace required }
  103. end;
  104. tpack=record
  105. name : string[12];
  106. binsub : string[40];
  107. ppc386 : string[20];
  108. targetname : string[40];
  109. defidecfgfile,
  110. defideinifile,
  111. defcfgfile,
  112. setpathfile : string[12];
  113. include : boolean;
  114. { filechk : string[40]; Obsolete }
  115. packages : longint;
  116. package : array[1..maxpackages] of tpackage;
  117. end;
  118. tcfgarray = array[1..maxdefcfgs] of pstring;
  119. cfgrec=record
  120. title : string[80];
  121. version : string[20];
  122. helpidx,
  123. docsub,
  124. basepath : DirStr;
  125. packs : word;
  126. pack : array[1..maxpacks] of tpack;
  127. defideinis,
  128. defidecfgs,
  129. defcfgs,
  130. defsetpaths : longint;
  131. defideini,
  132. defidecfg,
  133. defcfg,
  134. defsetpath : tcfgarray;
  135. end;
  136. datarec=record
  137. basepath : DirStr;
  138. cfgval : word;
  139. packmask : array[1..maxpacks] of sw_word;
  140. end;
  141. punzipdialog=^tunzipdialog;
  142. tunzipdialog=object(tdialog)
  143. filetext : pstatictext;
  144. extractfiletext : pstatictext;
  145. currentfile : string;
  146. constructor Init(var Bounds: TRect; ATitle: TTitleStr);
  147. procedure do_unzip(s,topath:string);
  148. end;
  149. penddialog = ^tenddialog;
  150. tenddialog = object(tdialog)
  151. constructor init;
  152. end;
  153. pinstalldialog = ^tinstalldialog;
  154. tinstalldialog = object(tdialog)
  155. constructor init;
  156. procedure handleevent(var event : tevent);virtual;
  157. end;
  158. PFPHTMLFileLinkScanner = ^TFPHTMLFileLinkScanner;
  159. TFPHTMLFileLinkScanner = object(THTMLFileLinkScanner)
  160. function CheckURL(const URL: string): boolean; virtual;
  161. function CheckText(const Text: string): boolean; virtual;
  162. procedure ProcessDoc(Doc: PHTMLLinkScanFile); virtual;
  163. end;
  164. phtmlindexdialog = ^thtmlindexdialog;
  165. thtmlindexdialog = object(tdialog)
  166. text : pstatictext;
  167. constructor init(var Bounds: TRect; ATitle: TTitleStr);
  168. end;
  169. tapp = object(tapplication)
  170. procedure initmenubar;virtual;
  171. procedure handleevent(var event : tevent);virtual;
  172. procedure do_installdialog;
  173. procedure readcfg(const fn:string);
  174. procedure checkavailpack;
  175. end;
  176. PSpecialInputLine= ^TSpecialInputLine;
  177. TSpecialInputLine = object (TInputLine)
  178. procedure GetData(var Rec); virtual;
  179. end;
  180. {$IFDEF DOSSTUB}
  181. PByte = ^byte;
  182. PRunBlock = ^TRunBlock;
  183. TRunBlock = record
  184. Length: word;
  185. Dependent: word;
  186. Background: word;
  187. TraceLevel: word;
  188. PrgTitle: PChar;
  189. PrgName: PChar;
  190. Args: PChar;
  191. TermQ: longint;
  192. Environment: pointer;
  193. Inheritance: word;
  194. SesType: word;
  195. Icon: pointer;
  196. PgmHandle: longint;
  197. PgmControl: word;
  198. Column: word;
  199. Row: word;
  200. Width: word;
  201. Height: word;
  202. end;
  203. {$ENDIF}
  204. var
  205. installapp : tapp;
  206. startpath : string;
  207. successfull : boolean;
  208. cfg : cfgrec;
  209. data : datarec;
  210. CfgName: NameStr;
  211. DStr: DirStr;
  212. EStr: ExtStr;
  213. UnzDlg : punzipdialog;
  214. log : text;
  215. createlog : boolean;
  216. {$IFNDEF DLL}
  217. const
  218. UnzipErr: longint = 0;
  219. {$ENDIF}
  220. {$ifdef MAYBE_LFN}
  221. const
  222. locallfnsupport : boolean = false;
  223. {$endif MAYBE_LFN}
  224. {*****************************************************************************
  225. Helpers
  226. *****************************************************************************}
  227. procedure errorhalt;
  228. begin
  229. installapp.done;
  230. if CreateLog then
  231. begin
  232. WriteLn (Log, 'Installation hasn''t been completed.');
  233. Close (Log);
  234. end;
  235. halt(1);
  236. end;
  237. procedure WriteLog (const S: string);
  238. begin
  239. if CreateLog then
  240. begin
  241. WriteLn (Log, S);
  242. Flush (Log);
  243. end;
  244. end;
  245. function packagemask(i:longint):longint;
  246. begin
  247. packagemask:=1 shl (i-1);
  248. end;
  249. function upper(const s : string):string;
  250. var
  251. i : integer;
  252. begin
  253. for i:=1 to length(s) do
  254. if s[i] in ['a'..'z'] then
  255. upper[i]:=chr(ord(s[i])-32)
  256. else
  257. upper[i]:=s[i];
  258. upper[0]:=s[0];
  259. end;
  260. procedure Replace(var s:string;const s1,s2:string);
  261. var
  262. i : longint;
  263. begin
  264. repeat
  265. i:=pos(s1,s);
  266. if i>0 then
  267. begin
  268. Delete(s,i,length(s1));
  269. Insert(s2,s,i);
  270. end;
  271. until i=0;
  272. end;
  273. function DotStr(l:longint):string;
  274. var
  275. TmpStr : string[32];
  276. i : longint;
  277. begin
  278. Str(l,TmpStr);
  279. i:=Length(TmpStr);
  280. while (i>3) do
  281. begin
  282. i:=i-3;
  283. if TmpStr[i]<>'-' then
  284. Insert('.',TmpStr,i+1);
  285. end;
  286. DotStr:=TmpStr;
  287. end;
  288. function file_exists(const f : string;const path : string) : boolean;
  289. begin
  290. file_exists:=fsearch(f,path)<>'';
  291. end;
  292. function createdir(s:string):boolean;
  293. var
  294. s1,start : string;
  295. err : boolean;
  296. i : longint;
  297. begin
  298. err:=false;
  299. {$I-}
  300. getdir(0,start);
  301. {$ifndef Unix}
  302. if (s[2]=':') and (s[3]=DirSep) then
  303. begin
  304. chdir(Copy(s,1,3));
  305. Delete(S,1,3);
  306. end;
  307. {$endif}
  308. repeat
  309. i:=Pos(DirSep,s);
  310. if i=0 then
  311. i:=255;
  312. s1:=Copy(s,1,i-1);
  313. Delete(s,1,i);
  314. ChDir(s1);
  315. if ioresult<>0 then
  316. begin
  317. mkdir(s1);
  318. chdir(s1);
  319. if ioresult<>0 then
  320. begin
  321. err:=true;
  322. break;
  323. end;
  324. end;
  325. until s='';
  326. chdir(start);
  327. {$I+}
  328. createdir:=err;
  329. end;
  330. function DiskSpaceN(const zipfile : string) : longint;
  331. var
  332. compressed,uncompressed : longint;
  333. s : string;
  334. begin
  335. s:=zipfile+#0;
  336. if not (IsZip (@S [1])) then
  337. DiskSpaceN := -1
  338. else
  339. begin
  340. Uncompressed:=UnzipSize(@s[1],compressed);
  341. DiskSpaceN:=uncompressed shr 10;
  342. end;
  343. end;
  344. function diskspacestr(uncompressed : longint) : string;
  345. begin
  346. if Uncompressed = -1 then
  347. DiskSpacestr := ' [INVALID]'
  348. else
  349. diskspacestr:=' ('+DotStr(uncompressed)+' KB)';
  350. end;
  351. function createinstalldir(s : string) : boolean;
  352. var
  353. err : boolean;
  354. dir : searchrec;
  355. params : array[0..0] of pointer;
  356. begin
  357. if s[length(s)]=DirSep then
  358. dec(s[0]);
  359. FindFirst(s,AnyFile,dir);
  360. if doserror=0 then
  361. begin
  362. if Dir.Attr and Directory = 0 then
  363. begin
  364. messagebox('A file with the name chosen as the installation '+
  365. 'directory exists already. Cannot create this directory!',nil,
  366. mferror+mfokbutton);
  367. createinstalldir:=false;
  368. end else
  369. createinstalldir:=messagebox('The installation directory exists already. '+
  370. 'Do you want to continue ?',nil,
  371. mferror+mfyesbutton+mfnobutton)=cmYes;
  372. exit;
  373. end;
  374. err:=Createdir(s);
  375. if err then
  376. begin
  377. params[0]:=@s;
  378. messagebox('The installation directory %s couldn''t be created',
  379. @params,mferror+mfokbutton);
  380. createinstalldir:=false;
  381. exit;
  382. end;
  383. {$ifndef TP}
  384. {$IFNDEF OS2}
  385. FindClose (dir);
  386. {$ENDIF}
  387. {$endif}
  388. createinstalldir:=true;
  389. end;
  390. function GetProgDir: DirStr;
  391. var
  392. D: DirStr;
  393. N: NameStr;
  394. E: ExtStr;
  395. begin
  396. FSplit (FExpand (ParamStr (0)), D, N, E);
  397. if (D [0] <> #0) and (D [byte (D [0])] = '\') then Dec (D [0]);
  398. GetProgDir := D;
  399. end;
  400. function GetZipErrorInfo(error : longint) : string;
  401. var
  402. ErrorStr : string;
  403. begin
  404. case error of
  405. unzip_CRCErr : GetZipErrorInfo:='CRC error';
  406. unzip_WriteErr : GetZipErrorInfo:='Write error';
  407. unzip_ReadErr : GetZipErrorInfo:='Read error';
  408. unzip_ZipFileErr : GetZipErrorInfo:='ZipFile erroe';
  409. unzip_UserAbort : GetZipErrorInfo:='User abort';
  410. unzip_NotSupported : GetZipErrorInfo:='Not supported';
  411. unzip_Encrypted : GetZipErrorInfo:='File is encrypted';
  412. unzip_InUse : GetZipErrorInfo:='Fie is in use';
  413. unzip_InternalError : GetZipErrorInfo:='Internal error'; {Error in zip format}
  414. unzip_NoMoreItems : GetZipErrorInfo:='No more items';
  415. unzip_FileError : GetZipErrorInfo:='File error'; {Error Accessing file}
  416. unzip_NotZipfile : GetZipErrorInfo:='Not a zipfile'; {not a zip file}
  417. unzip_SeriousError : GetZipErrorInfo:='Serious error'; {serious error}
  418. unzip_MissingParameter : GetZipErrorInfo:='Missing parameter'; {missing parameter}
  419. else
  420. begin
  421. Str(Error,ErrorStr);
  422. GetZipErrorInfo:='Unknown error '+errorstr;
  423. end;
  424. end;
  425. end;
  426. {*****************************************************************************
  427. HTML-Index Generation
  428. *****************************************************************************}
  429. var
  430. indexdlg : phtmlindexdialog;
  431. constructor thtmlindexdialog.Init(var Bounds: TRect; ATitle: TTitleStr);
  432. var
  433. r : trect;
  434. begin
  435. inherited init(bounds,atitle);
  436. Options:=Options or ofCentered;
  437. R.Assign (4, 2,bounds.B.X-Bounds.A.X-2, 4);
  438. text:=new(pstatictext,init(r,'Please wait ...'));
  439. insert(text);
  440. end;
  441. procedure TFPHTMLFileLinkScanner.ProcessDoc(Doc: PHTMLLinkScanFile);
  442. var
  443. oldtext : pstring;
  444. begin
  445. oldtext:=indexdlg^.text^.text;
  446. indexdlg^.text^.text:=newstr('Processing '+Doc^.GetDocumentURL);
  447. indexdlg^.text^.drawview;
  448. inherited ProcessDoc(Doc);
  449. disposestr(indexdlg^.text^.text);
  450. indexdlg^.text^.text:=oldtext;
  451. indexdlg^.text^.drawview;
  452. end;
  453. function TFPHTMLFileLinkScanner.CheckURL(const URL: string): boolean;
  454. var OK: boolean;
  455. const HTTPPrefix = 'http:';
  456. FTPPrefix = 'ftp:';
  457. begin
  458. OK:=inherited CheckURL(URL);
  459. if OK then OK:=DirAndNameOf(URL)<>'';
  460. if OK then OK:=CompareText(copy(ExtOf(URL),1,4),'.HTM')=0;
  461. if OK then OK:=CompareText(copy(URL,1,length(HTTPPrefix)),HTTPPrefix)<>0;
  462. if OK then OK:=CompareText(copy(URL,1,length(FTPPrefix)),FTPPrefix)<>0;
  463. CheckURL:=OK;
  464. end;
  465. function TFPHTMLFileLinkScanner.CheckText(const Text: string): boolean;
  466. var OK: boolean;
  467. S: string;
  468. begin
  469. S:=Trim(Text);
  470. OK:=(S<>'') and (copy(S,1,1)<>'[');
  471. CheckText:=OK;
  472. end;
  473. procedure writehlpindex(filename : string);
  474. var
  475. LS : PFPHTMLFileLinkScanner;
  476. BS : PBufStream;
  477. Re : Word;
  478. params : array[0..0] of pointer;
  479. dir : searchrec;
  480. r : trect;
  481. begin
  482. r.assign(10,10,70,15);
  483. indexdlg:=new(phtmlindexdialog,init(r,'Creating HTML index file, please wait ...'));
  484. desktop^.insert(indexdlg);
  485. { warning FIXME !!!!, don't know what is to fix here ... PM }
  486. New(LS, Init(DirOf(FileName)));
  487. LS^.ProcessDocument(FileName,[soSubDocsOnly]);
  488. if LS^.GetDocumentCount=0 then
  489. begin
  490. params[0]:=@filename;
  491. MessageBox('Problem creating help index %1, aborting',@params,
  492. mferror+mfokbutton);
  493. end
  494. else
  495. begin
  496. FileName:=DirAndNameOf(FileName)+HTMLIndexExt;
  497. findfirst(filename,AnyFile,dir);
  498. if doserror=0 then
  499. begin
  500. params[0]:=@filename;
  501. Re:=MessageBox('Help index %s already exists, overwrite it?',@params,
  502. mfinformation+mfyesbutton+mfnobutton);
  503. end
  504. else
  505. Re:=cmYes;
  506. if Re<>cmNo then
  507. begin
  508. New(BS, Init(FileName, stCreate, 4096));
  509. if Assigned(BS)=false then
  510. begin
  511. MessageBox('Error while writing help index! '+
  512. 'No help index is created',@params,
  513. mferror+mfokbutton);
  514. Re:=cmCancel;
  515. end
  516. else
  517. begin
  518. LS^.StoreDocuments(BS^);
  519. if BS^.Status<>stOK then
  520. begin
  521. MessageBox('Error while writing help index!'#13+
  522. 'No help index is created',@params,
  523. mferror+mfokbutton);
  524. Re:=cmCancel;
  525. end;
  526. Dispose(BS, Done);
  527. end;
  528. end;
  529. end;
  530. Dispose(LS, Done);
  531. desktop^.delete(indexdlg);
  532. dispose(indexdlg,done);
  533. end;
  534. {*****************************************************************************
  535. Writing of fpc.cfg
  536. *****************************************************************************}
  537. procedure writedefcfg(const fn:string;const cfgdata : tcfgarray;count : longint;const targetname : string);
  538. var
  539. t : text;
  540. i : longint;
  541. s : string;
  542. dir : searchrec;
  543. params : array[0..0] of pointer;
  544. d : dirstr;
  545. n : namestr;
  546. e : extstr;
  547. begin
  548. { already exists }
  549. findfirst(fn,AnyFile,dir);
  550. if doserror=0 then
  551. begin
  552. params[0]:=@fn;
  553. if MessageBox('Config %s already exists, continue writing default config?',@params,
  554. mfinformation+mfyesbutton+mfnobutton)=cmNo then
  555. exit;
  556. end;
  557. { create directory }
  558. fsplit(fn,d,n,e);
  559. createdir(d);
  560. { create the fpc.cfg }
  561. assign(t,fn);
  562. {$I-}
  563. rewrite(t);
  564. {$I+}
  565. if ioresult<>0 then
  566. begin
  567. params[0]:=@fn;
  568. MessageBox(#3'A config not written.'#13#3'%s'#13#3'couldn''t be created',@params,mfinformation+mfokbutton);
  569. exit;
  570. end;
  571. for i:=1 to count do
  572. if assigned(cfgdata[i]) then
  573. begin
  574. s:=cfgdata[i]^;
  575. Replace(s,'%basepath%',data.basepath);
  576. Replace(s,'%targetname%',targetname);
  577. if pos('-',targetname)=0 then
  578. begin
  579. Replace(s,'%targetos%',targetname);
  580. Replace(s,'%fpctargetmacro%','$FPCOS')
  581. end
  582. else
  583. begin
  584. Replace(s,'%targetos%',Copy(targetname,pos('-',targetname)+1,255));
  585. Replace(s,'%fpctargetmacro%','$FPCTARGET');
  586. end;
  587. writeln(t,s);
  588. end
  589. else
  590. writeln(t,'');
  591. close(t);
  592. end;
  593. {*****************************************************************************
  594. TUnZipDialog
  595. *****************************************************************************}
  596. constructor tunzipdialog.Init(var Bounds: TRect; ATitle: TTitleStr);
  597. var
  598. r : trect;
  599. begin
  600. inherited init(bounds,atitle);
  601. Options:=Options or ofCentered;
  602. (* R.Assign (11, 4, 38, 6);*)
  603. R.Assign (1, 4,bounds.B.X-Bounds.A.X-2, 6);
  604. filetext:=new(pstatictext,init(r,#3'File: '));
  605. insert(filetext);
  606. R.Assign (1, 7,bounds.B.X-Bounds.A.X-2, 9);
  607. extractfiletext:=new(pstatictext,init(r,#3' '));
  608. insert(extractfiletext);
  609. end;
  610. {$IFNDEF DLL}
  611. procedure UnzipCheckFn (Retcode: longint; Rec: pReportRec );{$ifdef Delphi32}STDCALL;{$endif}
  612. {$ifndef fpc}{$IFNDEF BIT32} FAR;{$ENDIF BIT32}{$endif}
  613. var
  614. name : string;
  615. begin
  616. case Rec^.Status of
  617. unzip_starting:
  618. UnzipErr := 0;
  619. file_starting:
  620. begin
  621. with UnzDlg^.extractfiletext^ do
  622. begin
  623. Disposestr(text);
  624. name:=Strpas(Rec^.FileName);
  625. UnzDlg^.currentfile:=name;
  626. Text:=NewStr(#3+name);
  627. DrawView;
  628. end;
  629. end;
  630. file_failure:
  631. UnzipErr := RetCode;
  632. file_unzipping:
  633. begin
  634. with UnzDlg^.FileText^ do
  635. begin
  636. Inc (StatusPos);
  637. if StatusPos > MaxStatusPos then StatusPos := 1;
  638. Text^ [Length (Text^)] := StatusChars [StatusPos];
  639. DrawView;
  640. end;
  641. end;
  642. end;
  643. end;
  644. {$ENDIF}
  645. procedure tunzipdialog.do_unzip(s,topath : string);
  646. var
  647. {$ifdef MAYBE_LFN}
  648. p : pathstr;
  649. n : namestr;
  650. e : extstr;
  651. islfn : boolean;
  652. {$endif MAYBE_LFN}
  653. again : boolean;
  654. st2,fn,dir,wild : string;
  655. begin
  656. Disposestr(filetext^.text);
  657. filetext^.Text:=NewStr(#3'File: '+s + #13#3' ');
  658. filetext^.drawview;
  659. if not(file_exists(s,startpath)) then
  660. begin
  661. messagebox('File "'+s+'" missing for the selected installation. '+
  662. 'Installation hasn''t been completed.',nil,mferror+mfokbutton);
  663. WriteLog ('File "' + S +
  664. '" missing for the selected installation!');
  665. errorhalt;
  666. end;
  667. {$IFNDEF DLL}
  668. {$IFDEF FPC}
  669. SetUnzipReportProc (@UnzipCheckFn);
  670. {$ELSE FPC}
  671. SetUnzipReportProc (UnzipCheckFn);
  672. {$ENDIF FPC}
  673. {$ENDIF DLL}
  674. WriteLog ('Unpacking ' + AllFiles + ' from '
  675. + StartPath + DirSep + S + ' to ' + ToPath);
  676. repeat
  677. fn:=startpath+DirSep+s+#0;
  678. dir:=topath+#0;
  679. wild:=AllFiles + #0;
  680. again:=false;
  681. FileUnzipEx(@fn[1],@dir[1],@wild[1]);
  682. if (UnzipErr <> 0) and (UnzipErr <> 1) then
  683. begin
  684. if CreateLog then
  685. begin
  686. WriteLn (Log, 'Error ', UnzipErr, ' while unpacking!');
  687. Flush (Log);
  688. end;
  689. s:=GetZipErrorInfo(UnzipErr);
  690. { Str(UnzipErr,s);}
  691. st2:='';
  692. if UnzipErr=unzip_WriteErr then
  693. begin
  694. {$ifdef MAYBE_LFN}
  695. if not(locallfnsupport) then
  696. begin
  697. islfn:=false;
  698. fsplit(currentfile,p,n,e);
  699. if (length(n)>8) or (length(e)>4) or
  700. (pos('.',n)>0) or (upper(p+n+e)<>upper(currentfile)) then
  701. islfn:=true;
  702. if islfn then
  703. begin
  704. WriteLog ('Error while extracting ' +
  705. CurrentFile + ' because of missing LFN support,' +
  706. LineEnding + ' skipping rest of ZIP file.');
  707. messagebox('Error while extracting '+currentfile+
  708. #13#3'because of missing lfn support'+
  709. #13#3'skipping rest of zipfile '+s
  710. ,nil,mferror+mfOkButton);
  711. again:=false;
  712. exit;
  713. end;
  714. end
  715. else
  716. {$endif MAYBE_LFN}
  717. st2:=' Disk full?';
  718. end;
  719. if CreateLog then
  720. WriteLog ('Error (' + S + ') while extracting.' + ST2);
  721. if messagebox('Error (' + S + ') while extracting.'+st2+#13+
  722. #13#3'Try again?',nil,mferror+mfyesbutton+mfnobutton)=cmYes then
  723. again:=true
  724. else
  725. errorhalt;
  726. end;
  727. until not again;
  728. end;
  729. {*****************************************************************************
  730. TEndDialog
  731. *****************************************************************************}
  732. constructor tenddialog.init;
  733. var
  734. R : TRect;
  735. P : PStaticText;
  736. Control : PButton;
  737. YB: word;
  738. {$IFNDEF UNIX}
  739. i : longint;
  740. S: string;
  741. WPath: boolean;
  742. MixedCasePath: boolean;
  743. {$ENDIF}
  744. {$IFDEF OS2}
  745. ErrPath: array [0..259] of char;
  746. Handle: longint;
  747. WLibPath: boolean;
  748. const
  749. EMXName: array [1..4] of char = 'EMX'#0;
  750. BFD2EName: array [1..6] of char = 'BFD2E'#0;
  751. {$ENDIF}
  752. begin
  753. if haside then
  754. YB := 15
  755. else
  756. YB := 14;
  757. {$IFNDEF UNIX}
  758. s:='';
  759. for i:=1 to cfg.packs do
  760. if cfg.pack[i].binsub<>'' then
  761. begin
  762. if s<>'' then
  763. s:=s+';';
  764. S := s+Data.BasePath + Cfg.pack[i].BinSub;
  765. end;
  766. if Pos (Upper (S), Upper (GetEnv ('PATH'))) = 0 then
  767. begin
  768. WPath := true;
  769. Inc (YB, 3);
  770. end
  771. else
  772. WPath := false;
  773. { look if path is set as Path,
  774. this leads to problems for mingw32 make PM }
  775. MixedCasePath:=false;
  776. for i:=1 to EnvCount do
  777. begin
  778. if Pos('PATH=',Upper(EnvStr(i)))=1 then
  779. if Pos('PATH=',EnvStr(i))<>1 then
  780. Begin
  781. MixedCasePath:=true;
  782. Inc(YB, 2);
  783. End;
  784. end;
  785. {$IFDEF OS2}
  786. if DosLoadModule (@ErrPath, SizeOf (ErrPath), @EMXName, Handle) = 0 then
  787. begin
  788. WLibPath := false;
  789. DosFreeModule (Handle);
  790. end
  791. else
  792. if DosLoadModule (@ErrPath, SizeOf (ErrPath), @BFD2EName, Handle) = 0 then
  793. begin
  794. WLibPath := false;
  795. DosFreeModule (Handle);
  796. end
  797. else
  798. begin
  799. WLibPath := true;
  800. Inc (YB, 2);
  801. end;
  802. {$ENDIF}
  803. {$ENDIF}
  804. R.Assign(6, 6, 74, YB);
  805. inherited init(r,'Installation successful.');
  806. Options:=Options or ofCentered;
  807. {$IFNDEF UNIX}
  808. if WPath then
  809. begin
  810. R.Assign(2, 3, 64, 5);
  811. P:=new(pstatictext,init(r,'Extend your PATH variable with '''+S+''''));
  812. insert(P);
  813. end;
  814. {$IFDEF OS2}
  815. if WLibPath then
  816. begin
  817. if WPath then
  818. S := 'and your LIBPATH with ''' + S + '\dll'''
  819. else
  820. S := 'Extend your LIBPATH with ''' + S + '\dll''';
  821. R.Assign (2, YB - 14, 64, YB - 12);
  822. P := New (PStaticText, Init (R, S));
  823. Insert (P);
  824. end;
  825. {$ELSE OS2}
  826. if MixedCasePath then
  827. begin
  828. R.Assign(2, 5, 64, 6);
  829. P:=new(pstatictext,init(r,'You need to use setpath.bat file if you want to use Makefiles'));
  830. insert(P);
  831. end;
  832. {$ENDIF OS2}
  833. {$ENDIF}
  834. R.Assign(2, YB - 13, 64, YB - 12);
  835. P:=new(pstatictext,init(r,'To compile files enter fpc [file]'''));
  836. insert(P);
  837. if haside then
  838. begin
  839. R.Assign(2, YB - 12, 64, YB - 10);
  840. P:=new(pstatictext,init(r,'To start the IDE (Integrated Development Environment) type ''fp'' at a command line prompt'));
  841. insert(P);
  842. end;
  843. R.Assign (29, YB - 9, 39, YB - 7);
  844. Control := New (PButton, Init (R,'~O~k', cmOK, bfDefault));
  845. Insert (Control);
  846. end;
  847. {*****************************************************************************
  848. TInstallDialog
  849. *****************************************************************************}
  850. {$ifdef MAYBE_LFN}
  851. var
  852. islfn : boolean;
  853. procedure lfnreport( Retcode : longint;Rec : pReportRec );
  854. var
  855. p : pathstr;
  856. n : namestr;
  857. e : extstr;
  858. begin
  859. fsplit(strpas(rec^.Filename),p,n,e);
  860. if (length(n)>8) or (length(e)>4) or
  861. (pos('.',n)>0) or (upper(p+n+e)<>upper(strpas(rec^.Filename))) then
  862. islfn:=true;
  863. end;
  864. function haslfn(const zipfile : string) : boolean;
  865. var
  866. buf : array[0..255] of char;
  867. begin
  868. strpcopy(buf,zipfile);
  869. islfn:=false;
  870. {$ifdef FPC}
  871. ViewZip(buf,AllFiles,@lfnreport);
  872. {$else FPC}
  873. ViewZip(buf,AllFiles,lfnreport);
  874. {$endif FPC}
  875. haslfn:=islfn;
  876. end;
  877. {$endif MAYBE_LFN}
  878. var
  879. AllFilesPresent : boolean;
  880. procedure presentreport( Retcode : longint;Rec : pReportRec );
  881. var
  882. st : string;
  883. f : file;
  884. size,time : longint;
  885. p : pathstr;
  886. n : namestr;
  887. e : extstr;
  888. begin
  889. if not ALLFilesPresent then
  890. exit;
  891. st:=Data.BasePath+strpas(rec^.Filename);
  892. fsplit(st,p,n,e);
  893. if not file_exists(n+e,p) then
  894. AllFilesPresent:=false
  895. else
  896. begin
  897. Assign(f,st);
  898. Reset(f,1);
  899. if IOresult<>0 then
  900. begin
  901. ALLfilesPresent:=false;
  902. exit;
  903. end;
  904. GetFtime(f,time);
  905. size:=FileSize(f);
  906. if (rec^.Time<>time) or (rec^.size<>size) then
  907. ALLFilesPresent:=false;
  908. close(f);
  909. end;
  910. end;
  911. function AreAllFilesPresent(const zipfile : string) : boolean;
  912. var
  913. buf : array[0..255] of char;
  914. begin
  915. strpcopy(buf,zipfile);
  916. AllFilesPresent:=true;
  917. {$ifdef FPC}
  918. ViewZip(buf,AllFiles,@presentreport);
  919. {$else FPC}
  920. ViewZip(buf,AllFiles,presentreport);
  921. {$endif FPC}
  922. AreAllFilesPresent:=AllFilesPresent;
  923. end;
  924. constructor tinstalldialog.init;
  925. const
  926. width = 76;
  927. height = 20;
  928. x1 = (79-width) div 2;
  929. y1 = (23-height) div 2;
  930. x2 = x1+width;
  931. y2 = y1+height;
  932. var
  933. tabr,tabir,r : trect;
  934. packmask : array[1..maxpacks] of longint;
  935. enabmask : array[1..maxpacks] of longint;
  936. i,line,j : integer;
  937. items : array[1..maxpacks] of psitem;
  938. f : pview;
  939. found : boolean;
  940. okbut,cancelbut : pbutton;
  941. firstitem : array[1..maxpacks] of integer;
  942. packcbs : array[1..maxpacks] of pcheckboxes;
  943. packtd : ptabdef;
  944. labpath : plabel;
  945. ilpath : pspecialinputline;
  946. tab : ptab;
  947. titletext : pcoloredtext;
  948. labcfg : plabel;
  949. cfgcb : pcheckboxes;
  950. scrollbox: pscrollbox;
  951. sbr,sbsbr: trect;
  952. sbsb: pscrollbar;
  953. zipfile : string;
  954. begin
  955. f:=nil;
  956. { walk packages reverse and insert a newsitem for each, and set the mask }
  957. for j:=1 to cfg.packs do
  958. with cfg.pack[j] do
  959. begin
  960. firstitem[j]:=0;
  961. items[j]:=nil;
  962. packmask[j]:=0;
  963. enabmask[j]:=0;
  964. for i:=packages downto 1 do
  965. begin
  966. zipfile:='';
  967. if file_exists(package[i].zip,startpath) then
  968. zipfile:=startpath+DirSep+package[i].zip
  969. else if file_exists(package[i].zipshort,startpath) then
  970. begin
  971. zipfile:=startpath+DirSep+package[i].zipshort;
  972. { update package to replace the full zipname with the short name }
  973. package[i].zip:=package[i].zipshort;
  974. end;
  975. if zipfile<>'' then
  976. begin
  977. { get diskspace required }
  978. package[i].diskspace:=diskspaceN(zipfile);
  979. {$ifdef MAYBE_LFN}
  980. if not(locallfnsupport) then
  981. begin
  982. if not(haslfn(zipfile)) then
  983. begin
  984. items[j]:=newsitem(package[i].name+diskspacestr(package[i].diskspace),items[j]);
  985. packmask[j]:=packmask[j] or packagemask(i);
  986. enabmask[j]:=enabmask[j] or packagemask(i);
  987. firstitem[j]:=i-1;
  988. WriteLog ('Checking lfn usage for ' + zipfile + ' ... no lfn');
  989. end
  990. else
  991. begin
  992. items[j]:=newsitem(package[i].name+' (requires LFN support)',items[j]);
  993. enabmask[j]:=enabmask[j] or packagemask(i);
  994. firstitem[j]:=i-1;
  995. WriteLog ('Checking lfn usage for ' + zipfile + ' ... uses lfn');
  996. end;
  997. end
  998. else
  999. {$endif MAYBE_LFN}
  1000. begin
  1001. items[j]:=newsitem(package[i].name+diskspacestr(package[i].diskspace),items[j]);
  1002. packmask[j]:=packmask[j] or packagemask(i);
  1003. enabmask[j]:=enabmask[j] or packagemask(i);
  1004. firstitem[j]:=i-1;
  1005. end;
  1006. end
  1007. else
  1008. items[j]:=newsitem(package[i].name,items[j]);
  1009. end;
  1010. end;
  1011. { If no component found abort }
  1012. found:=false;
  1013. for j:=1 to cfg.packs do
  1014. if packmask[j]<>0 then
  1015. found:=true;
  1016. if not found then
  1017. begin
  1018. messagebox('No components found to install, aborting.',nil,mferror+mfokbutton);
  1019. if CreateLog then
  1020. WriteLog ('No components found to install, aborting.');
  1021. errorhalt;
  1022. end;
  1023. r.assign(x1,y1,x2,y2);
  1024. inherited init(r,'');
  1025. Options:=Options or ofCentered;
  1026. GetExtent(R);
  1027. R.Grow(-2,-1);
  1028. Dec(R.B.Y,2);
  1029. TabR.Copy(R);
  1030. TabIR.Copy(R);
  1031. TabIR.Grow(-2,-2);
  1032. TabIR.Move(-2,0);
  1033. {-------- General Sheets ----------}
  1034. R.Copy(TabIR);
  1035. r.move(0,1);
  1036. r.b.x:=r.a.x+40;
  1037. r.b.y:=r.a.y+1;
  1038. new(titletext,init(r,cfg.title,$71));
  1039. r.move(0,2);
  1040. r.b.x:=r.a.x+40;
  1041. new(labpath,init(r,'~B~ase path',f));
  1042. r.move(0,1);
  1043. r.b.x:=r.a.x+40;
  1044. r.b.y:=r.a.y+1;
  1045. new(ilpath,init(r,high(DirStr)));
  1046. r.move(0,2);
  1047. r.b.x:=r.a.x+40;
  1048. new(labcfg,init(r,'Con~f~ig',f));
  1049. r.move(0,1);
  1050. r.b.x:=r.a.x+40;
  1051. r.b.y:=r.a.y+1;
  1052. new(cfgcb,init(r,newsitem('create fpc.cfg',nil)));
  1053. data.cfgval:=1;
  1054. {-------- Pack Sheets ----------}
  1055. for j:=1 to cfg.packs do
  1056. begin
  1057. R.Copy(TabIR);
  1058. if R.A.Y+cfg.pack[j].packages>R.B.Y then
  1059. R.B.Y:=R.A.Y+cfg.pack[j].packages;
  1060. new(packcbs[j],init(r,items[j]));
  1061. if data.packmask[j]=high(sw_word) then
  1062. data.packmask[j]:=packmask[j];
  1063. packcbs[j]^.enablemask:={$ifdef DEV}$7fffffff{$else}enabmask[j]{$endif};
  1064. packcbs[j]^.sel:=firstitem[j];
  1065. end;
  1066. {--------- Main ---------}
  1067. packtd:=nil;
  1068. sbr.assign(1,3,tabr.b.x-tabr.a.x-3,tabr.b.y-tabr.a.y-1);
  1069. for j:=cfg.packs downto 1 do
  1070. begin
  1071. if (sbr.b.y-sbr.a.y)<cfg.pack[j].packages then
  1072. begin
  1073. sbsbr.assign(sbr.b.x,sbr.a.y,sbr.b.x+1,sbr.b.y);
  1074. New(sbsb, init(sbsbr));
  1075. end
  1076. else
  1077. sbsb:=nil;
  1078. New(ScrollBox, Init(sbr, nil, sbsb));
  1079. PackCbs[j]^.MoveTo(0,0);
  1080. ScrollBox^.Insert(PackCbs[j]);
  1081. packtd:=NewTabDef(
  1082. cfg.pack[j].name,ScrollBox,
  1083. NewTabItem(sbsb,
  1084. NewTabItem(ScrollBox,
  1085. nil)),
  1086. packtd);
  1087. end;
  1088. New(Tab, Init(TabR,
  1089. NewTabDef('~G~eneral',IlPath,
  1090. NewTabItem(TitleText,
  1091. NewTabItem(LabPath,
  1092. NewTabItem(ILPath,
  1093. NewTabItem(LabCfg,
  1094. NewTabItem(CfgCB,
  1095. nil))))),
  1096. packtd)
  1097. ));
  1098. Tab^.GrowMode:=0;
  1099. Insert(Tab);
  1100. line:=tabr.b.y;
  1101. r.assign((width div 2)-18,line,(width div 2)-4,line+2);
  1102. new(okbut,init(r,'~C~ontinue',cmok,bfdefault));
  1103. Insert(OkBut);
  1104. r.assign((width div 2)+4,line,(width div 2)+14,line+2);
  1105. new(cancelbut,init(r,'~Q~uit',cmcancel,bfnormal));
  1106. Insert(CancelBut);
  1107. Tab^.Select;
  1108. end;
  1109. procedure tinstalldialog.handleevent(var event : tevent);
  1110. begin
  1111. if event.what=evcommand then
  1112. if event.command=cmquit then
  1113. begin
  1114. putevent(event);
  1115. event.command:=cmCancel;
  1116. end;
  1117. inherited handleevent(event);
  1118. end;
  1119. {*****************************************************************************
  1120. TSpecialInputLine
  1121. *****************************************************************************}
  1122. { this should use AreAllFilesPresent if the base dir is changed...
  1123. but what if the installer has already choosen which files he wants ... }
  1124. procedure TSpecialInputLine.GetData(var Rec);
  1125. begin
  1126. inherited GetData(Rec);
  1127. end;
  1128. {*****************************************************************************
  1129. TApp
  1130. *****************************************************************************}
  1131. const
  1132. cmstart = 1000;
  1133. procedure tapp.do_installdialog;
  1134. var
  1135. p : pinstalldialog;
  1136. p3 : penddialog;
  1137. r : trect;
  1138. result,
  1139. c : word;
  1140. i,j : longint;
  1141. found : boolean;
  1142. {$ifndef Unix}
  1143. DSize,Space,ASpace : int64;
  1144. S: DirStr;
  1145. {$endif}
  1146. procedure doconfigwrite;
  1147. var
  1148. i : longint;
  1149. begin
  1150. for i:=1 to cfg.packs do
  1151. begin
  1152. if cfg.pack[i].defcfgfile<>'' then
  1153. writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defcfgfile,cfg.defcfg,cfg.defcfgs,cfg.pack[i].targetname);
  1154. if cfg.pack[i].setpathfile<>'' then
  1155. writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].setpathfile,cfg.defsetpath,cfg.defsetpaths,cfg.pack[i].targetname);
  1156. end;
  1157. if haside then
  1158. begin
  1159. for i:=1 to cfg.packs do
  1160. if cfg.pack[i].defidecfgfile<>'' then
  1161. writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defidecfgfile,cfg.defidecfg,cfg.defidecfgs,cfg.pack[i].targetname);
  1162. for i:=1 to cfg.packs do
  1163. if cfg.pack[i].defideinifile<>'' then
  1164. writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defideinifile,cfg.defideini,cfg.defideinis,cfg.pack[i].targetname);
  1165. if hashtmlhelp then
  1166. writehlpindex(data.basepath+DirSep+cfg.DocSub+DirSep+cfg.helpidx);
  1167. end;
  1168. end;
  1169. begin
  1170. data.basepath:=cfg.basepath;
  1171. data.cfgval:=0;
  1172. for j:=1 to cfg.packs do
  1173. data.packmask[j]:=high(sw_word);
  1174. repeat
  1175. { select components }
  1176. p:=new(pinstalldialog,init);
  1177. c:=executedialog(p,@data);
  1178. if (c=cmok) then
  1179. begin
  1180. if Data.BasePath = '' then
  1181. messagebox('Please, choose the directory for installation first.',nil,mferror+mfokbutton)
  1182. else
  1183. begin
  1184. found:=false;
  1185. for j:=1 to cfg.packs do
  1186. if data.packmask[j]>0 then
  1187. found:=true;
  1188. if found then
  1189. begin
  1190. {$IFNDEF UNIX}
  1191. { TH - check the available disk space here }
  1192. DSize := 0;
  1193. for j:=1 to cfg.packs do
  1194. with cfg.pack[j] do
  1195. begin
  1196. for i:=1 to packages do
  1197. begin
  1198. if data.packmask[j] and packagemask(i)<>0 then
  1199. begin
  1200. ASpace := package[i].diskspace;
  1201. if ASpace = -1 then
  1202. begin
  1203. MessageBox ('File ' + package[i].zip +
  1204. ' is probably corrupted!', nil,
  1205. mferror + mfokbutton);
  1206. WriteLog ('File ' + package[i].zip +
  1207. ' is probably corrupted!');
  1208. end
  1209. else Inc (DSize, ASpace);
  1210. end;
  1211. end;
  1212. end;
  1213. WriteLog ('Diskspace needed: ' + DotStr (DSize) + ' Kb');
  1214. S := FExpand (Data.BasePath);
  1215. if S [Length (S)] = DirSep then
  1216. Dec (S [0]);
  1217. Space := DiskFree (byte (Upcase(S [1])) - 64);
  1218. { -1 means that the drive is invalid }
  1219. if Space=-1 then
  1220. begin
  1221. WriteLog ('The drive ' + S [1] + ': is not valid');
  1222. if messagebox('The drive '+S[1]+': is not valid. Do you ' +
  1223. 'want to change the installation path?',nil,
  1224. mferror+mfyesbutton+mfnobutton) = cmYes then
  1225. Continue;
  1226. Space:=0;
  1227. end;
  1228. Space := Space shr 10;
  1229. WriteLog ('Free space on drive ' + S [1] + ': ' +
  1230. DotStr (Space) + ' Kb');
  1231. if Space < DSize then
  1232. S := 'is not '
  1233. else
  1234. S := '';
  1235. if (Space < DSize + 500) then
  1236. begin
  1237. if S = '' then
  1238. S := 'might not be ';
  1239. if messagebox('There ' + S + 'enough space on the target ' +
  1240. 'drive for all the selected components. Do you ' +
  1241. 'want to change the installation path?',nil,
  1242. mferror+mfyesbutton+mfnobutton) = cmYes then
  1243. Continue;
  1244. end;
  1245. {$ENDIF}
  1246. if createinstalldir(data.basepath) then
  1247. break;
  1248. end
  1249. else
  1250. begin
  1251. { maybe only config }
  1252. if (data.cfgval and 1)<>0 then
  1253. begin
  1254. result:=messagebox('No components selected.'#13#13'Create a configfile ?',nil,
  1255. mfinformation+mfyesbutton+mfnobutton);
  1256. if (result=cmYes) and createinstalldir(data.basepath) then
  1257. doconfigwrite;
  1258. exit;
  1259. end
  1260. else
  1261. begin
  1262. result:=messagebox('No components selected.'#13#13'Abort installation?',nil,
  1263. mferror+mfyesbutton+mfnobutton);
  1264. if result=cmYes then
  1265. exit;
  1266. end;
  1267. end;
  1268. end;
  1269. end
  1270. else
  1271. exit;
  1272. until false;
  1273. { extract packages }
  1274. for j:=1 to cfg.packs do
  1275. with cfg.pack[j] do
  1276. begin
  1277. r.assign(10,7,70,18);
  1278. UnzDlg:=new(punzipdialog,init(r,'Extracting Packages'));
  1279. desktop^.insert(UnzDlg);
  1280. for i:=1 to packages do
  1281. begin
  1282. if data.packmask[j] and packagemask(i)<>0 then
  1283. begin
  1284. UnzDlg^.do_unzip(package[i].zip,data.basepath);
  1285. { gather some information about the installed files }
  1286. if copy(package[i].zip,1,3)='ide' then
  1287. haside:=true;
  1288. if copy(package[i].zip,1,7)='doc-htm' then
  1289. begin
  1290. hashtmlhelp:=true;
  1291. { correct the fpctoc file name if .html files are used }
  1292. if package[i].zip='doc-html.zip' then
  1293. if copy(cfg.helpidx,length(cfg.helpidx)-3,4)='.htm' then
  1294. cfg.helpidx:=cfg.helpidx+'l';
  1295. end;
  1296. end;
  1297. end;
  1298. desktop^.delete(UnzDlg);
  1299. dispose(UnzDlg,done);
  1300. end;
  1301. { write config }
  1302. if (data.cfgval and 1)<>0 then
  1303. doconfigwrite;
  1304. { show end message }
  1305. p3:=new(penddialog,init);
  1306. executedialog(p3,nil);
  1307. end;
  1308. procedure tapp.readcfg(const fn:string);
  1309. var
  1310. t : text;
  1311. i,j,k,
  1312. line : longint;
  1313. item,
  1314. s,hs : string;
  1315. params : array[0..0] of pointer;
  1316. {$ifndef FPC}
  1317. procedure readln(var t:text;var s:string);
  1318. var
  1319. c : char;
  1320. i : longint;
  1321. begin
  1322. c:=#0;
  1323. i:=0;
  1324. while (not eof(t)) and (c<>#10) do
  1325. begin
  1326. read(t,c);
  1327. if c<>#10 then
  1328. begin
  1329. inc(i);
  1330. s[i]:=c;
  1331. end;
  1332. end;
  1333. if (i>0) and (s[i]=#13) then
  1334. dec(i);
  1335. s[0]:=chr(i);
  1336. end;
  1337. {$endif}
  1338. begin
  1339. assign(t,StartPath + DirSep + fn);
  1340. {$I-}
  1341. reset(t);
  1342. {$I+}
  1343. if ioresult<>0 then
  1344. begin
  1345. StartPath := GetProgDir;
  1346. assign(t,StartPath + DirSep + fn);
  1347. {$I-}
  1348. reset(t);
  1349. {$I+}
  1350. if ioresult<>0 then
  1351. begin
  1352. params[0]:=@fn;
  1353. messagebox('File %s not found!',@params,mferror+mfokbutton);
  1354. WriteLog ('File "' + fn + '" not found!');
  1355. errorhalt;
  1356. end;
  1357. end;
  1358. line:=0;
  1359. while not eof(t) do
  1360. begin
  1361. readln(t,s);
  1362. inc(line);
  1363. if (s<>'') and not(s[1] in ['#',';']) then
  1364. begin
  1365. i:=pos('=',s);
  1366. if i>0 then
  1367. begin
  1368. item:=upper(Copy(s,1,i-1));
  1369. system.delete(s,1,i);
  1370. if item='VERSION' then
  1371. cfg.version:=s
  1372. else
  1373. if item='TITLE' then
  1374. cfg.title:=s
  1375. else
  1376. if item='BASEPATH' then
  1377. cfg.basepath:=s
  1378. else
  1379. if item='HELPIDX' then
  1380. cfg.helpidx:=s
  1381. else
  1382. if item='DOCSUB' then
  1383. cfg.docsub:=s
  1384. else
  1385. if item='DEFAULTCFG' then
  1386. begin
  1387. repeat
  1388. readln(t,s);
  1389. if upper(s)='ENDCFG' then
  1390. break;
  1391. if cfg.defcfgs<maxdefcfgs then
  1392. begin
  1393. inc(cfg.defcfgs);
  1394. cfg.defcfg[cfg.defcfgs]:=newstr(s);
  1395. end;
  1396. until false;
  1397. end
  1398. else
  1399. if item='DEFAULTIDECFG' then
  1400. begin
  1401. repeat
  1402. readln(t,s);
  1403. if upper(s)='ENDCFG' then
  1404. break;
  1405. if cfg.defidecfgs<maxdefcfgs then
  1406. begin
  1407. inc(cfg.defidecfgs);
  1408. cfg.defidecfg[cfg.defidecfgs]:=newstr(s);
  1409. end;
  1410. until false;
  1411. end
  1412. else
  1413. if item='DEFAULTSETPATH' then
  1414. begin
  1415. repeat
  1416. readln(t,s);
  1417. if upper(s)='ENDCFG' then
  1418. break;
  1419. if cfg.defsetpaths<maxdefcfgs then
  1420. begin
  1421. inc(cfg.defsetpaths);
  1422. cfg.defsetpath[cfg.defsetpaths]:=newstr(s);
  1423. end;
  1424. until false;
  1425. end
  1426. else
  1427. if item='DEFAULTIDEINI' then
  1428. begin
  1429. repeat
  1430. readln(t,s);
  1431. if upper(s)='ENDCFG' then
  1432. break;
  1433. if cfg.defideinis<maxdefcfgs then
  1434. begin
  1435. inc(cfg.defideinis);
  1436. cfg.defideini[cfg.defideinis]:=newstr(s);
  1437. end;
  1438. until false;
  1439. end
  1440. else
  1441. if item='PACK' then
  1442. begin
  1443. inc(cfg.packs);
  1444. if cfg.packs>maxpacks then
  1445. begin
  1446. MessageBox ('Too many packs!', nil,
  1447. mfError + mfOkButton);
  1448. if CreateLog then
  1449. begin
  1450. WriteLn (Log, 'Too many packs');
  1451. close(log);
  1452. end;
  1453. halt(1);
  1454. end;
  1455. cfg.pack[cfg.packs].name:=s;
  1456. end
  1457. else
  1458. if item='CFGFILE' then
  1459. begin
  1460. if cfg.packs=0 then
  1461. begin
  1462. MessageBox ('No pack set found!', nil,
  1463. mfError + mfOkButton);
  1464. if CreateLog then
  1465. begin
  1466. WriteLn (Log, 'No pack set');
  1467. close(Log);
  1468. end;
  1469. halt(1);
  1470. end;
  1471. cfg.pack[cfg.packs].defcfgfile:=s
  1472. end
  1473. else
  1474. if item='IDECFGFILE' then
  1475. begin
  1476. if cfg.packs=0 then
  1477. begin
  1478. MessageBox ('No pack set found!', nil,
  1479. mfError + mfOkButton);
  1480. if CreateLog then
  1481. begin
  1482. WriteLn (Log, 'No pack set');
  1483. Close(Log);
  1484. end;
  1485. halt(1);
  1486. end;
  1487. cfg.pack[cfg.packs].defidecfgfile:=s
  1488. end
  1489. else
  1490. if item='SETPATHFILE' then
  1491. begin
  1492. if cfg.packs=0 then
  1493. begin
  1494. MessageBox ('No pack set found!', nil,
  1495. mfError + mfOkButton);
  1496. if CreateLog then
  1497. begin
  1498. WriteLn (Log, 'No pack set');
  1499. close(Log);
  1500. end;
  1501. halt(1);
  1502. end;
  1503. cfg.pack[cfg.packs].setpathfile:=s
  1504. end
  1505. else
  1506. if item='IDEINIFILE' then
  1507. begin
  1508. if cfg.packs=0 then
  1509. begin
  1510. MessageBox ('No pack set found!', nil,
  1511. mfError + mfOkButton);
  1512. if CreateLog then
  1513. begin
  1514. WriteLn (Log, 'No pack set');
  1515. Close(Log);
  1516. end;
  1517. halt(1);
  1518. end;
  1519. cfg.pack[cfg.packs].defideinifile:=s
  1520. end
  1521. else
  1522. if item='PPC386' then
  1523. begin
  1524. if cfg.packs=0 then
  1525. begin
  1526. MessageBox ('No pack set found!', nil,
  1527. mfError + mfOkButton);
  1528. if CreateLog then
  1529. begin
  1530. WriteLn (Log, 'No pack set');
  1531. Close(Log);
  1532. end;
  1533. halt(1);
  1534. end;
  1535. cfg.pack[cfg.packs].ppc386:=s;
  1536. end
  1537. else
  1538. if item='BINSUB' then
  1539. begin
  1540. if cfg.packs=0 then
  1541. begin
  1542. MessageBox ('No pack set found!', nil,
  1543. mfError + mfOkButton);
  1544. if CreateLog then
  1545. begin
  1546. WriteLn (Log, 'No pack set');
  1547. Close(Log);
  1548. end;
  1549. halt(1);
  1550. end;
  1551. cfg.pack[cfg.packs].binsub:=s;
  1552. end
  1553. {else: Obsolete PM }
  1554. { if item='FILECHECK' then
  1555. begin
  1556. if cfg.packs=0 then
  1557. begin
  1558. MessageBox ('No pack set found!', nil,
  1559. mfError + mfOkButton);
  1560. if CreateLog then
  1561. WriteLn (Log, 'No pack set');
  1562. halt(1);
  1563. end;
  1564. cfg.pack[cfg.packs].filechk:=s;
  1565. end }
  1566. else
  1567. if item='TARGETNAME' then
  1568. begin
  1569. if cfg.packs=0 then
  1570. begin
  1571. MessageBox ('No pack set found!', nil,
  1572. mfError + mfOkButton);
  1573. if CreateLog then
  1574. begin
  1575. WriteLn (Log, 'No pack set');
  1576. Close(Log);
  1577. end;
  1578. halt(1);
  1579. end;
  1580. cfg.pack[cfg.packs].targetname:=s;
  1581. end
  1582. else
  1583. if item='PACKAGE' then
  1584. begin
  1585. if cfg.packs=0 then
  1586. begin
  1587. MessageBox ('No pack set found!', nil,
  1588. mfError + mfOkButton);
  1589. if CreateLog then
  1590. begin
  1591. WriteLn (Log, 'No pack set');
  1592. Close(Log);
  1593. end;
  1594. halt(1);
  1595. end;
  1596. with cfg.pack[cfg.packs] do
  1597. begin
  1598. j:=pos(',',s);
  1599. if (j>0) and (packages<maxpackages) then
  1600. begin
  1601. inc(packages);
  1602. hs:=copy(s,1,j-1);
  1603. k:=pos('[',hs);
  1604. if (k>0) then
  1605. begin
  1606. package[packages].zip:=Copy(hs,1,k-1);
  1607. package[packages].zipshort:=Copy(hs,k+1,length(hs)-k-1);
  1608. end
  1609. else
  1610. package[packages].zip:=hs;
  1611. package[packages].name:=copy(s,j+1,255);
  1612. end;
  1613. package[packages].diskspace:=-1;
  1614. end;
  1615. end
  1616. end;
  1617. end;
  1618. end;
  1619. close(t);
  1620. end;
  1621. procedure tapp.checkavailpack;
  1622. var
  1623. i, j : longint;
  1624. one_found : boolean;
  1625. begin
  1626. { check the packages }
  1627. j:=0;
  1628. while (j<cfg.packs) do
  1629. begin
  1630. inc(j);
  1631. one_found:=false;
  1632. {if cfg.pack[j].filechk<>'' then}
  1633. for i:=1 to cfg.pack[j].packages do
  1634. begin
  1635. if file_exists(cfg.pack[j].package[i].zip,startpath) or
  1636. file_exists(cfg.pack[j].package[i].zipshort,startpath) then
  1637. begin
  1638. one_found:=true;
  1639. break;
  1640. end;
  1641. end;
  1642. if not one_found then
  1643. begin
  1644. { remove the package }
  1645. move(cfg.pack[j+1],cfg.pack[j],sizeof(tpack)*(cfg.packs-j));
  1646. dec(cfg.packs);
  1647. dec(j);
  1648. end;
  1649. end;
  1650. end;
  1651. procedure tapp.initmenubar;
  1652. var
  1653. r : trect;
  1654. begin
  1655. getextent(r);
  1656. r.b.y:=r.a.y+1;
  1657. menubar:=new(pmenubar,init(r,newmenu(
  1658. newsubmenu('Free Pascal Installer',hcnocontext,newmenu(nil
  1659. ),
  1660. nil))));
  1661. end;
  1662. procedure tapp.handleevent(var event : tevent);
  1663. begin
  1664. inherited handleevent(event);
  1665. if event.what=evcommand then
  1666. if event.command=cmstart then
  1667. begin
  1668. clearevent(event);
  1669. do_installdialog;
  1670. if successfull then
  1671. begin
  1672. event.what:=evcommand;
  1673. event.command:=cmquit;
  1674. handleevent(event);
  1675. end;
  1676. end;
  1677. end;
  1678. {$IFDEF DOSSTUB}
  1679. function CheckOS2: boolean;
  1680. var
  1681. OwnName: PathStr;
  1682. OwnDir: DirStr;
  1683. Name: NameStr;
  1684. Ext: ExtStr;
  1685. DosV, W: word;
  1686. P: PChar;
  1687. const
  1688. Title: string [15] = 'FPC Installer'#0;
  1689. RunBlock: TRunBlock = (Length: $32;
  1690. Dependent: 0;
  1691. Background: 0;
  1692. TraceLevel: 0;
  1693. PrgTitle: @Title [1];
  1694. PrgName: nil;
  1695. Args: nil;
  1696. TermQ: 0;
  1697. Environment: nil;
  1698. Inheritance: 0;
  1699. SesType: 2;
  1700. Icon: nil;
  1701. PgmHandle: 0;
  1702. PgmControl: 2;
  1703. Column: 0;
  1704. Row: 0;
  1705. Width: 80;
  1706. Height: 25);
  1707. begin
  1708. CheckOS2 := false;
  1709. asm
  1710. mov ah, 30h
  1711. int 21h
  1712. xchg ah, al
  1713. mov DosV, ax
  1714. mov ax, 4010h
  1715. int 2Fh
  1716. cmp ax, 4010h
  1717. jnz @0
  1718. xor bx, bx
  1719. @0:
  1720. mov W, bx
  1721. end;
  1722. if DosV > 3 shl 8 then
  1723. begin
  1724. OwnName := FExpand (ParamStr (0));
  1725. FSplit (OwnName, OwnDir, Name, Ext);
  1726. if (DosV >= 20 shl 8 + 10) and (W >= 20 shl 8 + 10) then
  1727. (* OS/2 version 2.1 or later running (double-checked) *)
  1728. begin
  1729. OwnName [Succ (byte (OwnName [0]))] := #0;
  1730. RunBlock.PrgName := @OwnName [1];
  1731. P := Ptr (PrefixSeg, $80);
  1732. if PByte (P)^ <> 0 then
  1733. begin
  1734. Inc (P);
  1735. RunBlock.Args := Ptr (PrefixSeg, $81);
  1736. end;
  1737. asm
  1738. mov ax, 6400h
  1739. mov bx, 0025h
  1740. mov cx, 636Ch
  1741. mov si, offset RunBlock
  1742. int 21h
  1743. jc @0
  1744. mov DosV, 0
  1745. @0:
  1746. end;
  1747. CheckOS2 := DosV = 0;
  1748. end;
  1749. end;
  1750. end;
  1751. {$ENDIF}
  1752. procedure usagescreen;
  1753. begin
  1754. writeln('FPC Installer ',installerversion,' ',installercopyright);
  1755. writeln('Command line options:');
  1756. writeln(' -l create log file');
  1757. {$ifdef MAYBE_LFN}
  1758. writeln(' --nolfn force installation with short file names');
  1759. {$endif MAYBE_LFN}
  1760. writeln;
  1761. writeln(' -h displays this help');
  1762. end;
  1763. var
  1764. OldExit: pointer;
  1765. procedure NewExit;
  1766. begin
  1767. ExitProc := OldExit;
  1768. if CreateLog then
  1769. begin
  1770. {$I-}
  1771. if ErrorAddr <> nil then
  1772. begin
  1773. WriteLn (Log, 'Installer crashed with RTE ', ExitCode);
  1774. Close (Log);
  1775. end
  1776. else
  1777. if ExitCode <> 0 then
  1778. begin
  1779. WriteLn (Log, 'Installer ended with non-zero exit code ', ExitCode);
  1780. Close (Log);
  1781. end
  1782. {$I+}
  1783. end;
  1784. end;
  1785. var
  1786. i : longint;
  1787. { vm : tvideomode;}
  1788. begin
  1789. OldExit := ExitProc;
  1790. ExitProc := @NewExit;
  1791. { register objects for help streaming }
  1792. RegisterWHTMLScan;
  1793. {$IFDEF OS2}
  1794. { TH - no error boxes if checking an inaccessible disk etc. }
  1795. {$IFDEF FPC}
  1796. DosCalls.DosError (0);
  1797. {$ELSE FPC}
  1798. {$IFDEF VirtualPascal}
  1799. OS2Base.DosError (ferr_DisableHardErr);
  1800. {$ELSE VirtualPascal}
  1801. BseDos.DosError (0);
  1802. {$ENDIF VirtualPascal}
  1803. {$ENDIF FPC}
  1804. {$ENDIF}
  1805. {$IFDEF DOSSTUB}
  1806. if CheckOS2 then Halt;
  1807. {$ENDIF}
  1808. createlog:=false;
  1809. {$ifdef MAYBE_LFN}
  1810. locallfnsupport:=system.lfnsupport;
  1811. {$endif MAYBE_LFN}
  1812. for i:=1 to paramcount do
  1813. begin
  1814. if paramstr(i)='-l' then
  1815. createlog:=true
  1816. {$ifdef MAYBE_LFN}
  1817. else if paramstr(i)='--nolfn' then
  1818. begin
  1819. locallfnsupport:=false;
  1820. {$ifdef GO32V2}
  1821. { lfnsupport is a const in win32 RTL }
  1822. system.lfnsupport:=locallfnsupport;
  1823. {$endif GO32V2}
  1824. end
  1825. {$endif MAYBE_LFN}
  1826. else if paramstr(i)='-h' then
  1827. begin
  1828. usagescreen;
  1829. halt(0);
  1830. end
  1831. else
  1832. begin
  1833. usagescreen;
  1834. halt(1);
  1835. end;
  1836. end;
  1837. if createlog then
  1838. begin
  1839. assign(log,'install.log');
  1840. rewrite(log);
  1841. {$ifdef MAYBE_LFN}
  1842. if not(locallfnsupport) then
  1843. WriteLog ('OS doesn''t have LFN support');
  1844. {$endif}
  1845. end;
  1846. getdir(0,startpath);
  1847. successfull:=false;
  1848. fillchar(cfg, SizeOf(cfg), 0);
  1849. fillchar(data, SizeOf(data), 0);
  1850. installapp.init;
  1851. { vm.col:=80;
  1852. vm.row:=25;
  1853. vm.color:=true;
  1854. installapp.SetScreenVideoMode(vm);
  1855. }
  1856. FSplit (FExpand (ParamStr (0)), DStr, CfgName, EStr);
  1857. installapp.readcfg(CfgName + CfgExt);
  1858. installapp.checkavailpack;
  1859. { installapp.readcfg(startpath+dirsep+cfgfile);}
  1860. {$ifdef GO32V2}
  1861. if not(lfnsupport) then
  1862. MessageBox('The operating system doesn''t support LFN (long file names),'+
  1863. ' so some packages will get shorten filenames when installed',nil,mfinformation or mfokbutton);
  1864. {$endif}
  1865. installapp.do_installdialog;
  1866. installapp.done;
  1867. if createlog then
  1868. close(log);
  1869. end.