install.pas 54 KB

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