install.pas 58 KB

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