install.pas 57 KB

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