install.pas 58 KB

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