install.pas 58 KB

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