install.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  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 FV} (* TH - added to make use of the original Turbo Vision possible. *)
  15. { $DEFINE DLL} (* TH - if defined, UNZIP32.DLL library is used to unpack. *)
  16. { $DEFINE DOSSTUB} (* TH - should _not_ be defined unless creating a bound DOS and OS/2 installer!!! *)
  17. (* Defining DOSSTUB causes adding a small piece of code *)
  18. (* for starting the OS/2 part from the DOS part of a bound *)
  19. (* application if running in OS/2 VDM (DOS) window. Used *)
  20. (* only if compiling with TP/BP (see conditionals below). *)
  21. {$IFDEF VER60}
  22. {$DEFINE TP}
  23. {$ENDIF}
  24. {$IFDEF VER70}
  25. {$DEFINE TP}
  26. {$ENDIF}
  27. {$IFNDEF TP}
  28. {$UNDEF DOSSTUB}
  29. {$ELSE}
  30. {$IFDEF OS2}
  31. {$UNDEF DOSSTUB}
  32. {$ENDIF}
  33. {$ENDIF}
  34. {$IFDEF OS2}
  35. {$UNDEF FV}
  36. {$IFDEF VIRTUALPASCAL}
  37. {$DEFINE DLL}
  38. {$ENDIF}
  39. {$ENDIF}
  40. {$IFDEF DPMI}
  41. {$UNDEF DOSSTUB}
  42. {$ENDIF}
  43. uses
  44. {$IFDEF OS2}
  45. {$IFDEF FPC}
  46. DosCalls,
  47. {$ELSE FPC}
  48. {$IFDEF VirtualPascal}
  49. OS2Base,
  50. {$ELSE VirtualPascal}
  51. BseDos,
  52. {$ENDIF VirtualPascal}
  53. {$ENDIF FPC}
  54. {$ENDIF OS2}
  55. {$ifdef HEAPTRC}
  56. heaptrc,
  57. {$endif HEAPTRC}
  58. strings,dos,objects,drivers,
  59. {$IFDEF FV}
  60. commands,
  61. {$ENDIF}
  62. unzip,ziptypes,
  63. {$IFDEF DLL}
  64. unzipdll,
  65. {$ENDIF}
  66. app,dialogs,views,menus,msgbox,colortxt,tabs;
  67. const
  68. installerversion='0.99.14';
  69. maxpacks=10;
  70. maxpackages=20;
  71. maxdefcfgs=1024;
  72. CfgExt = '.dat';
  73. MaxStatusPos = 4;
  74. StatusChars: string [MaxStatusPos] = '/-\|';
  75. StatusPos: byte = 1;
  76. {$ifdef linux}
  77. DirSep='/';
  78. {$else}
  79. DirSep='\';
  80. {$endif}
  81. type
  82. tpackage=record
  83. name : string[60];
  84. zip : string[12];
  85. end;
  86. tpack=record
  87. name : string[12];
  88. binsub : string[40];
  89. ppc386 : string[20];
  90. defcfgfile : string[12];
  91. include : boolean;
  92. filechk : string[40];
  93. packages : longint;
  94. package : array[1..maxpackages] of tpackage;
  95. end;
  96. cfgrec=record
  97. title : string[80];
  98. version : string[20];
  99. basepath : DirStr;
  100. packs : word;
  101. pack : array[1..maxpacks] of tpack;
  102. defcfgs : longint;
  103. defcfg : array[1..maxdefcfgs] of pstring;
  104. end;
  105. datarec=packed record
  106. basepath : DirStr;
  107. cfgval : word;
  108. packmask : array[1..maxpacks] of word;
  109. end;
  110. punzipdialog=^tunzipdialog;
  111. tunzipdialog=object(tdialog)
  112. filetext : pstatictext;
  113. constructor Init(var Bounds: TRect; ATitle: TTitleStr);
  114. procedure do_unzip(s,topath:string);
  115. end;
  116. penddialog = ^tenddialog;
  117. tenddialog = object(tdialog)
  118. constructor init;
  119. end;
  120. pinstalldialog = ^tinstalldialog;
  121. tinstalldialog = object(tdialog)
  122. constructor init;
  123. end;
  124. tapp = object(tapplication)
  125. procedure initmenubar;virtual;
  126. procedure handleevent(var event : tevent);virtual;
  127. procedure do_installdialog;
  128. procedure readcfg(const fn:string);
  129. procedure checkavailpack;
  130. end;
  131. {$IFDEF DOSSTUB}
  132. PByte = ^byte;
  133. PRunBlock = ^TRunBlock;
  134. TRunBlock = record
  135. Length: word;
  136. Dependent: word;
  137. Background: word;
  138. TraceLevel: word;
  139. PrgTitle: PChar;
  140. PrgName: PChar;
  141. Args: PChar;
  142. TermQ: longint;
  143. Environment: pointer;
  144. Inheritance: word;
  145. SesType: word;
  146. Icon: pointer;
  147. PgmHandle: longint;
  148. PgmControl: word;
  149. Column: word;
  150. Row: word;
  151. Width: word;
  152. Height: word;
  153. end;
  154. {$ENDIF}
  155. var
  156. installapp : tapp;
  157. startpath : string;
  158. successfull : boolean;
  159. cfg : cfgrec;
  160. data : datarec;
  161. CfgName: NameStr;
  162. DStr: DirStr;
  163. EStr: ExtStr;
  164. UnzDlg : punzipdialog;
  165. {$IFNDEF DLL}
  166. const
  167. UnzipErr: longint = 0;
  168. {$ENDIF}
  169. {*****************************************************************************
  170. Helpers
  171. *****************************************************************************}
  172. procedure errorhalt;
  173. begin
  174. installapp.done;
  175. halt(1);
  176. end;
  177. function packagemask(i:longint):longint;
  178. begin
  179. packagemask:=1 shl (i-1);
  180. end;
  181. function upper(const s : string):string;
  182. var
  183. i : integer;
  184. begin
  185. for i:=1 to length(s) do
  186. if s[i] in ['a'..'z'] then
  187. upper[i]:=chr(ord(s[i])-32)
  188. else
  189. upper[i]:=s[i];
  190. upper[0]:=s[0];
  191. end;
  192. procedure Replace(var s:string;const s1,s2:string);
  193. var
  194. i : longint;
  195. begin
  196. repeat
  197. i:=pos(s1,s);
  198. if i>0 then
  199. begin
  200. Delete(s,i,length(s1));
  201. Insert(s2,s,i);
  202. end;
  203. until i=0;
  204. end;
  205. function file_exists(const f : string;const path : string) : boolean;
  206. begin
  207. file_exists:=fsearch(f,path)<>'';
  208. end;
  209. function createdir(s:string):boolean;
  210. var
  211. s1,start : string;
  212. err : boolean;
  213. i : longint;
  214. begin
  215. err:=false;
  216. {$I-}
  217. getdir(0,start);
  218. {$ifndef linux}
  219. if (s[2]=':') and (s[3]=DirSep) then
  220. begin
  221. chdir(Copy(s,1,3));
  222. Delete(S,1,3);
  223. end;
  224. {$endif}
  225. repeat
  226. i:=Pos(DirSep,s);
  227. if i=0 then
  228. i:=255;
  229. s1:=Copy(s,1,i-1);
  230. Delete(s,1,i);
  231. ChDir(s1);
  232. if ioresult<>0 then
  233. begin
  234. mkdir(s1);
  235. chdir(s1);
  236. if ioresult<>0 then
  237. begin
  238. err:=true;
  239. break;
  240. end;
  241. end;
  242. until s='';
  243. chdir(start);
  244. {$I+}
  245. createdir:=err;
  246. end;
  247. function DiskSpaceN(const zipfile : string) : longint;
  248. var
  249. compressed,uncompressed : longint;
  250. s : string;
  251. begin
  252. s:=zipfile+#0;
  253. if not (IsZip (@S [1])) then DiskSpaceN := -1 else
  254. begin
  255. Uncompressed:=UnzipSize(@s[1],compressed);
  256. DiskSpaceN:=uncompressed shr 10;
  257. end;
  258. end;
  259. function diskspace(const zipfile : string) : string;
  260. var
  261. uncompressed : longint;
  262. s : string;
  263. begin
  264. uncompressed:=DiskSpaceN (zipfile);
  265. if Uncompressed = -1 then DiskSpace := ' [INVALID]' else
  266. begin
  267. str(uncompressed,s);
  268. diskspace:=' ('+s+' KB)';
  269. end;
  270. end;
  271. function createinstalldir(s : string) : boolean;
  272. var
  273. err : boolean;
  274. dir : searchrec;
  275. params : array[0..0] of pointer;
  276. begin
  277. if s[length(s)]=DirSep then
  278. dec(s[0]);
  279. FindFirst(s,AnyFile,dir);
  280. if doserror=0 then
  281. begin
  282. if Dir.Attr and Directory = 0 then
  283. begin
  284. messagebox('A file with the name chosen as the installation '+
  285. 'directory exists already. Cannot create this directory!',nil,
  286. mferror+mfokbutton);
  287. createinstalldir:=false;
  288. end else
  289. createinstalldir:=messagebox('The installation directory exists already. '+
  290. 'Do you want to continue ?',nil,
  291. mferror+mfyesbutton+mfnobutton)=cmYes;
  292. exit;
  293. end;
  294. err:=Createdir(s);
  295. if err then
  296. begin
  297. params[0]:=@s;
  298. messagebox('The installation directory %s couldn''t be created',
  299. @params,mferror+mfokbutton);
  300. createinstalldir:=false;
  301. exit;
  302. end;
  303. {$ifndef TP}
  304. {$IFNDEF OS2}
  305. FindClose (dir);
  306. {$ENDIF}
  307. {$endif}
  308. createinstalldir:=true;
  309. end;
  310. function GetProgDir: DirStr;
  311. var
  312. D: DirStr;
  313. N: NameStr;
  314. E: ExtStr;
  315. begin
  316. FSplit (FExpand (ParamStr (0)), D, N, E);
  317. if (D [0] <> #0) and (D [byte (D [0])] = '\') then Dec (D [0]);
  318. GetProgDir := D;
  319. end;
  320. {*****************************************************************************
  321. Writing of ppc386.cfg
  322. *****************************************************************************}
  323. procedure writedefcfg(const fn:string);
  324. var
  325. t : text;
  326. i : longint;
  327. s : string;
  328. dir : searchrec;
  329. params : array[0..0] of pointer;
  330. d : dirstr;
  331. n : namestr;
  332. e : extstr;
  333. begin
  334. { already exists }
  335. findfirst(fn,AnyFile,dir);
  336. if doserror=0 then
  337. begin
  338. params[0]:=@fn;
  339. if MessageBox('Config %s already exists, continue writing default config?',@params,
  340. mfinformation+mfyesbutton+mfnobutton)=cmNo then
  341. exit;
  342. end;
  343. { create directory }
  344. fsplit(fn,d,n,e);
  345. createdir(d);
  346. { create the ppc386.cfg }
  347. assign(t,fn);
  348. {$I-}
  349. rewrite(t);
  350. {$I+}
  351. if ioresult<>0 then
  352. begin
  353. params[0]:=@fn;
  354. MessageBox(#3'Default config not written.'#13#3'%s'#13#3'couldn''t be created',@params,mfinformation+mfokbutton);
  355. exit;
  356. end;
  357. for i:=1 to cfg.defcfgs do
  358. if assigned(cfg.defcfg[i]) then
  359. begin
  360. s:=cfg.defcfg[i]^;
  361. Replace(s,'$1',data.basepath);
  362. writeln(t,s);
  363. end
  364. else
  365. writeln(t,'');
  366. close(t);
  367. end;
  368. {*****************************************************************************
  369. TUnZipDialog
  370. *****************************************************************************}
  371. constructor tunzipdialog.Init(var Bounds: TRect; ATitle: TTitleStr);
  372. var
  373. r : trect;
  374. begin
  375. inherited init(bounds,atitle);
  376. (* R.Assign (11, 4, 38, 6);*)
  377. R.Assign (1, 4, 39, 6);
  378. filetext:=new(pstatictext,init(r,#3'File: '));
  379. insert(filetext);
  380. end;
  381. {$IFNDEF DLL}
  382. procedure UnzipCheckFn (Retcode: longint; Rec: pReportRec );{$ifdef Delphi32}STDCALL;{$endif}
  383. {$IFNDEF BIT32} FAR;{$ENDIF BIT32}
  384. begin
  385. case Rec^.Status of
  386. unzip_starting: UnzipErr := 0;
  387. file_failure: UnzipErr := RetCode;
  388. file_unzipping:
  389. begin
  390. with UnzDlg^.FileText^ do
  391. begin
  392. Inc (StatusPos);
  393. if StatusPos > MaxStatusPos then StatusPos := 1;
  394. Text^ [Length (Text^)] := StatusChars [StatusPos];
  395. DrawView;
  396. end;
  397. end;
  398. end;
  399. end;
  400. {$ENDIF}
  401. procedure tunzipdialog.do_unzip(s,topath : string);
  402. var
  403. again : boolean;
  404. fn,dir,wild : string;
  405. Cnt: integer;
  406. begin
  407. Disposestr(filetext^.text);
  408. filetext^.Text:=NewStr(#3'File: '+s + #13#3' ');
  409. filetext^.drawview;
  410. if not(file_exists(s,startpath)) then
  411. begin
  412. messagebox('File "'+s+'" missing for the selected installation. '+
  413. 'Installation hasn''t been completed.',nil,mferror+mfokbutton);
  414. errorhalt;
  415. end;
  416. {$IFNDEF DLL}
  417. {$IFDEF FPC}
  418. SetUnzipReportProc (@UnzipCheckFn);
  419. {$ELSE FPC}
  420. SetUnzipReportProc (UnzipCheckFn);
  421. {$ENDIF FPC}
  422. {$ENDIF DLL}
  423. repeat
  424. fn:=startpath+DirSep+s+#0;
  425. dir:=topath+#0;
  426. wild:=AllFiles + #0;
  427. again:=false;
  428. FileUnzipEx(@fn[1],@dir[1],@wild[1]);
  429. if (UnzipErr <> 0) then
  430. begin
  431. Str(UnzipErr,s);
  432. if messagebox('Error (' + S + ') while extracting. Disk full?'#13+
  433. #13#3'Try again?',nil,mferror+mfyesbutton+mfnobutton)=cmNo then
  434. errorhalt
  435. else
  436. again:=true;
  437. end;
  438. until not again;
  439. end;
  440. {*****************************************************************************
  441. TEndDialog
  442. *****************************************************************************}
  443. constructor tenddialog.init;
  444. var
  445. R : TRect;
  446. P : PStaticText;
  447. Control : PButton;
  448. YB: word;
  449. {$IFNDEF LINUX}
  450. i : longint;
  451. S: string;
  452. WPath: boolean;
  453. {$ENDIF}
  454. {$IFDEF OS2}
  455. ErrPath: array [0..259] of char;
  456. Handle: longint;
  457. WLibPath: boolean;
  458. const
  459. EMXName: array [1..4] of char = 'EMX'#0;
  460. {$ENDIF}
  461. begin
  462. YB := 14;
  463. {$IFNDEF LINUX}
  464. s:='';
  465. for i:=1 to cfg.packs do
  466. if cfg.pack[i].binsub<>'' then
  467. begin
  468. if s<>'' then
  469. s:=s+';';
  470. S := s+Data.BasePath + Cfg.pack[i].BinSub;
  471. end;
  472. if Pos (Upper (S), Upper (GetEnv ('PATH'))) = 0 then
  473. begin
  474. WPath := true;
  475. Inc (YB, 2);
  476. end
  477. else
  478. WPath := false;
  479. {$IFDEF OS2}
  480. if DosLoadModule (@ErrPath, SizeOf (ErrPath), @EMXName, Handle) = 0 then
  481. begin
  482. WLibPath := false;
  483. DosFreeModule (Handle);
  484. end
  485. else
  486. begin
  487. WLibPath := true;
  488. Inc (YB, 2);
  489. end;
  490. {$ENDIF}
  491. {$ENDIF}
  492. R.Assign(6, 6, 74, YB);
  493. inherited init(r,'Installation Successfull');
  494. {$IFNDEF LINUX}
  495. if WPath then
  496. begin
  497. R.Assign(2, 3, 64, 5);
  498. P:=new(pstatictext,init(r,'Extend your PATH variable with '''+S+''''));
  499. insert(P);
  500. end;
  501. {$IFDEF OS2}
  502. if WLibPath then
  503. begin
  504. if WPath then
  505. S := 'and your LIBPATH with ''' + S + '\dll'''
  506. else
  507. S := 'Extend your LIBPATH with ''' + S + '\dll''';
  508. R.Assign (2, YB - 13, 64, YB - 11);
  509. P := New (PStaticText, Init (R, S));
  510. Insert (P);
  511. end;
  512. {$ENDIF}
  513. {$ENDIF}
  514. R.Assign(2, YB - 11, 64, YB - 10);
  515. P:=new(pstatictext,init(r,'To compile files enter '''+cfg.pack[1].ppc386+' [file]'''));
  516. insert(P);
  517. R.Assign (29, YB - 9, 39, YB - 7);
  518. Control := New (PButton, Init (R,'~O~k', cmOK, bfDefault));
  519. Insert (Control);
  520. end;
  521. {*****************************************************************************
  522. TInstallDialog
  523. *****************************************************************************}
  524. constructor tinstalldialog.init;
  525. const
  526. width = 76;
  527. height = 21;
  528. x1 = (79-width) div 2;
  529. y1 = (23-height) div 2;
  530. x2 = x1+width;
  531. y2 = y1+height;
  532. var
  533. tabr,tabir,r : trect;
  534. packmask : array[1..maxpacks] of longint;
  535. i,line,j : integer;
  536. items : array[1..maxpacks] of psitem;
  537. f : pview;
  538. found : boolean;
  539. okbut,cancelbut : pbutton;
  540. firstitem : array[1..maxpacks] of integer;
  541. packcbs : array[1..maxpacks] of pcheckboxes;
  542. packtd : ptabdef;
  543. labpath : plabel;
  544. ilpath : pinputline;
  545. tab : ptab;
  546. titletext : pcoloredtext;
  547. labcfg : plabel;
  548. cfgcb : pcheckboxes;
  549. begin
  550. f:=nil;
  551. { walk packages reverse and insert a newsitem for each, and set the mask }
  552. for j:=1 to cfg.packs do
  553. with cfg.pack[j] do
  554. begin
  555. firstitem[j]:=0;
  556. items[j]:=nil;
  557. packmask[j]:=0;
  558. for i:=packages downto 1 do
  559. begin
  560. if file_exists(package[i].zip,startpath) then
  561. begin
  562. items[j]:=newsitem(package[i].name+diskspace(startpath+DirSep+package[i].zip),items[j]);
  563. packmask[j]:=packmask[j] or packagemask(i);
  564. firstitem[j]:=i;
  565. end
  566. else
  567. items[j]:=newsitem(package[i].name,items[j]);
  568. end;
  569. end;
  570. { If no component found abort }
  571. found:=false;
  572. for j:=1 to cfg.packs do
  573. if packmask[j]<>0 then
  574. found:=true;
  575. if not found then
  576. begin
  577. messagebox('No components found to install, aborting.',nil,mferror+mfokbutton);
  578. errorhalt;
  579. end;
  580. r.assign(x1,y1,x2,y2);
  581. inherited init(r,'');
  582. GetExtent(R);
  583. R.Grow(-2,-1);
  584. Dec(R.B.Y,2);
  585. TabR.Copy(R);
  586. TabIR.Copy(R);
  587. TabIR.Grow(-2,-2);
  588. TabIR.Move(-2,0);
  589. {-------- General Sheets ----------}
  590. R.Copy(TabIR);
  591. r.move(0,1);
  592. r.b.x:=r.a.x+40;
  593. r.b.y:=r.a.y+1;
  594. new(titletext,init(r,cfg.title,$71));
  595. r.move(0,2);
  596. r.b.x:=r.a.x+40;
  597. new(labpath,init(r,'~B~ase path',f));
  598. r.move(0,1);
  599. r.b.x:=r.a.x+40;
  600. r.b.y:=r.a.y+1;
  601. new(ilpath,init(r,high(DirStr)));
  602. r.move(0,2);
  603. r.b.x:=r.a.x+40;
  604. new(labcfg,init(r,'Con~f~ig',f));
  605. r.move(0,1);
  606. r.b.x:=r.a.x+40;
  607. r.b.y:=r.a.y+1;
  608. new(cfgcb,init(r,newsitem('create ppc386.cfg',nil)));
  609. data.cfgval:=1;
  610. {-------- Pack Sheets ----------}
  611. for j:=1 to cfg.packs do
  612. begin
  613. R.Copy(TabIR);
  614. new(packcbs[j],init(r,items[j]));
  615. if data.packmask[j]=$ffff then
  616. data.packmask[j]:=packmask[j];
  617. packcbs[j]^.enablemask:=packmask[j];
  618. packcbs[j]^.movedto(firstitem[j]);
  619. end;
  620. {--------- Main ---------}
  621. packtd:=nil;
  622. for j:=cfg.packs downto 1 do
  623. packtd:=NewTabDef(cfg.pack[j].name,PackCbs[j],NewTabItem(PackCbs[j],nil),packtd);
  624. New(Tab, Init(TabR,
  625. NewTabDef('~G~eneral',IlPath,
  626. NewTabItem(TitleText,
  627. NewTabItem(LabPath,
  628. NewTabItem(ILPath,
  629. NewTabItem(LabCfg,
  630. NewTabItem(CfgCB,
  631. nil))))),
  632. packtd)
  633. ));
  634. Tab^.GrowMode:=0;
  635. Insert(Tab);
  636. line:=tabr.b.y;
  637. r.assign((width div 2)-18,line,(width div 2)-4,line+2);
  638. new(okbut,init(r,'~C~ontinue',cmok,bfdefault));
  639. Insert(OkBut);
  640. r.assign((width div 2)+4,line,(width div 2)+14,line+2);
  641. new(cancelbut,init(r,'~Q~uit',cmcancel,bfnormal));
  642. Insert(CancelBut);
  643. Tab^.Select;
  644. end;
  645. {*****************************************************************************
  646. TApp
  647. *****************************************************************************}
  648. const
  649. cmstart = 1000;
  650. procedure tapp.do_installdialog;
  651. var
  652. p : pinstalldialog;
  653. p3 : penddialog;
  654. r : trect;
  655. result,
  656. c : word;
  657. i,j : longint;
  658. found : boolean;
  659. {$ifndef linux}
  660. DSize,Space,ASpace : longint;
  661. S: DirStr;
  662. {$endif}
  663. begin
  664. data.basepath:=cfg.basepath;
  665. data.cfgval:=0;
  666. for j:=1 to cfg.packs do
  667. data.packmask[j]:=$ffff;
  668. repeat
  669. { select components }
  670. p:=new(pinstalldialog,init);
  671. c:=executedialog(p,@data);
  672. if (c=cmok) then
  673. begin
  674. if Data.BasePath = '' then
  675. messagebox('Please, choose the directory for installation first.',nil,mferror+mfokbutton)
  676. else
  677. begin
  678. found:=false;
  679. for j:=1 to cfg.packs do
  680. if data.packmask[j]>0 then
  681. found:=true;
  682. if found then
  683. begin
  684. {$IFNDEF LINUX}
  685. { TH - check the available disk space here }
  686. DSize := 0;
  687. for j:=1 to cfg.packs do
  688. with cfg.pack[j] do
  689. begin
  690. for i:=1 to packages do
  691. begin
  692. if data.packmask[j] and packagemask(i)<>0 then
  693. begin
  694. ASpace := DiskSpaceN (package[i].zip);
  695. if ASpace = -1 then
  696. MessageBox ('File ' + package[i].zip +
  697. ' is probably corrupted!', nil,
  698. mferror + mfokbutton)
  699. else Inc (DSize, ASpace);
  700. end;
  701. end;
  702. end;
  703. S := FExpand (Data.BasePath);
  704. if S [Length (S)] = DirSep then
  705. Dec (S [0]);
  706. Space := DiskFree (byte (Upcase(S [1])) - 64) shr 10;
  707. if Space < DSize then
  708. S := 'is not'
  709. else
  710. S := '';
  711. if (Space < DSize + 500) then
  712. begin
  713. if S = '' then
  714. S := 'might not be';
  715. if messagebox('There ' + S + ' enough space on the target ' +
  716. 'drive for all the selected components. Do you ' +
  717. 'want to change the installation path?',nil,
  718. mferror+mfyesbutton+mfnobutton) = cmYes then
  719. Continue;
  720. end;
  721. {$ENDIF}
  722. if createinstalldir(data.basepath) then
  723. break;
  724. end
  725. else
  726. begin
  727. { maybe only config }
  728. if (data.cfgval and 1)<>0 then
  729. begin
  730. result:=messagebox('No components selected.'#13#13'Create a configfile ?',nil,
  731. mfinformation+mfyesbutton+mfnobutton);
  732. if (result=cmYes) and createinstalldir(data.basepath) then
  733. begin
  734. for i:=1 to cfg.packs do
  735. if cfg.pack[i].defcfgfile<>'' then
  736. writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defcfgfile);
  737. end;
  738. exit;
  739. end
  740. else
  741. begin
  742. result:=messagebox('No components selected.'#13#13'Abort installation?',nil,
  743. mferror+mfyesbutton+mfnobutton);
  744. if result=cmYes then
  745. exit;
  746. end;
  747. end;
  748. end;
  749. end
  750. else
  751. exit;
  752. until false;
  753. { extract packages }
  754. for j:=1 to cfg.packs do
  755. with cfg.pack[j] do
  756. begin
  757. r.assign(20,7,60,16);
  758. UnzDlg:=new(punzipdialog,init(r,'Extracting Packages'));
  759. desktop^.insert(UnzDlg);
  760. for i:=1 to packages do
  761. begin
  762. if data.packmask[j] and packagemask(i)<>0 then
  763. UnzDlg^.do_unzip(package[i].zip,data.basepath);
  764. end;
  765. desktop^.delete(UnzDlg);
  766. dispose(UnzDlg,done);
  767. end;
  768. { write config }
  769. if (data.cfgval and 1)<>0 then
  770. begin
  771. for i:=1 to cfg.packs do
  772. if cfg.pack[i].defcfgfile<>'' then
  773. writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defcfgfile);
  774. end;
  775. { show end message }
  776. p3:=new(penddialog,init);
  777. executedialog(p3,nil);
  778. end;
  779. procedure tapp.readcfg(const fn:string);
  780. var
  781. t : text;
  782. i,j,
  783. line : longint;
  784. item,
  785. s : string;
  786. params : array[0..0] of pointer;
  787. {$ifndef FPC}
  788. procedure readln(var t:text;var s:string);
  789. var
  790. c : char;
  791. i : longint;
  792. begin
  793. c:=#0;
  794. i:=0;
  795. while (not eof(t)) and (c<>#10) do
  796. begin
  797. read(t,c);
  798. if c<>#10 then
  799. begin
  800. inc(i);
  801. s[i]:=c;
  802. end;
  803. end;
  804. if (i>0) and (s[i]=#13) then
  805. dec(i);
  806. s[0]:=chr(i);
  807. end;
  808. {$endif}
  809. begin
  810. assign(t,StartPath + DirSep + fn);
  811. {$I-}
  812. reset(t);
  813. {$I+}
  814. if ioresult<>0 then
  815. begin
  816. StartPath := GetProgDir;
  817. assign(t,StartPath + DirSep + fn);
  818. {$I-}
  819. reset(t);
  820. {$I+}
  821. if ioresult<>0 then
  822. begin
  823. params[0]:=@fn;
  824. messagebox('File %s not found!',@params,mferror+mfokbutton);
  825. errorhalt;
  826. end;
  827. end;
  828. line:=0;
  829. while not eof(t) do
  830. begin
  831. readln(t,s);
  832. inc(line);
  833. if (s<>'') and not(s[1] in ['#',';']) then
  834. begin
  835. i:=pos('=',s);
  836. if i>0 then
  837. begin
  838. item:=upper(Copy(s,1,i-1));
  839. system.delete(s,1,i);
  840. if item='VERSION' then
  841. cfg.version:=s
  842. else
  843. if item='TITLE' then
  844. cfg.title:=s
  845. else
  846. if item='BASEPATH' then
  847. cfg.basepath:=s
  848. else
  849. if item='DEFAULTCFG' then
  850. begin
  851. repeat
  852. readln(t,s);
  853. if upper(s)='ENDCFG' then
  854. break;
  855. if cfg.defcfgs<maxdefcfgs then
  856. begin
  857. inc(cfg.defcfgs);
  858. cfg.defcfg[cfg.defcfgs]:=newstr(s);
  859. end;
  860. until false;
  861. end
  862. else
  863. if item='PACK' then
  864. begin
  865. inc(cfg.packs);
  866. if cfg.packs>maxpacks then
  867. begin
  868. writeln('Too much packs');
  869. halt(1);
  870. end;
  871. cfg.pack[cfg.packs].name:=s;
  872. end
  873. else
  874. if item='CFGFILE' then
  875. begin
  876. if cfg.packs=0 then
  877. begin
  878. writeln('No pack set');
  879. halt(1);
  880. end;
  881. cfg.pack[cfg.packs].defcfgfile:=s
  882. end
  883. else
  884. if item='PPC386' then
  885. begin
  886. if cfg.packs=0 then
  887. begin
  888. writeln('No pack set');
  889. halt(1);
  890. end;
  891. cfg.pack[cfg.packs].ppc386:=s;
  892. end
  893. else
  894. if item='BINSUB' then
  895. begin
  896. if cfg.packs=0 then
  897. begin
  898. writeln('No pack set');
  899. halt(1);
  900. end;
  901. cfg.pack[cfg.packs].binsub:=s;
  902. end
  903. else
  904. if item='FILECHECK' then
  905. begin
  906. if cfg.packs=0 then
  907. begin
  908. writeln('No pack set');
  909. halt(1);
  910. end;
  911. cfg.pack[cfg.packs].filechk:=s;
  912. end
  913. else
  914. if item='PACKAGE' then
  915. begin
  916. if cfg.packs=0 then
  917. begin
  918. writeln('No pack set');
  919. halt(1);
  920. end;
  921. with cfg.pack[cfg.packs] do
  922. begin
  923. j:=pos(',',s);
  924. if (j>0) and (packages<maxpackages) then
  925. begin
  926. inc(packages);
  927. package[packages].zip:=copy(s,1,j-1);
  928. package[packages].name:=copy(s,j+1,255);
  929. end;
  930. end;
  931. end
  932. end;
  933. end;
  934. end;
  935. close(t);
  936. end;
  937. procedure tapp.checkavailpack;
  938. var
  939. j : longint;
  940. dir : searchrec;
  941. begin
  942. { check the packages }
  943. j:=0;
  944. while (j<cfg.packs) do
  945. begin
  946. inc(j);
  947. if cfg.pack[j].filechk<>'' then
  948. begin
  949. findfirst(cfg.pack[j].filechk,$20,dir);
  950. if doserror<>0 then
  951. begin
  952. { remove the package }
  953. move(cfg.pack[j+1],cfg.pack[j],sizeof(tpack)*(cfg.packs-j));
  954. dec(cfg.packs);
  955. dec(j);
  956. end;
  957. {$IFNDEF TP}
  958. findclose(dir);
  959. {$ENDIF}
  960. end;
  961. end;
  962. end;
  963. procedure tapp.initmenubar;
  964. var
  965. r : trect;
  966. begin
  967. getextent(r);
  968. r.b.y:=r.a.y+1;
  969. menubar:=new(pmenubar,init(r,newmenu(
  970. newsubmenu('Free Pascal Installer',hcnocontext,newmenu(nil
  971. ),
  972. nil))));
  973. end;
  974. procedure tapp.handleevent(var event : tevent);
  975. begin
  976. inherited handleevent(event);
  977. if event.what=evcommand then
  978. if event.command=cmstart then
  979. begin
  980. clearevent(event);
  981. do_installdialog;
  982. if successfull then
  983. begin
  984. event.what:=evcommand;
  985. event.command:=cmquit;
  986. handleevent(event);
  987. end;
  988. end;
  989. end;
  990. {$IFDEF DOSSTUB}
  991. function CheckOS2: boolean;
  992. var
  993. OwnName: PathStr;
  994. OwnDir: DirStr;
  995. Name: NameStr;
  996. Ext: ExtStr;
  997. DosV, W: word;
  998. P: PChar;
  999. const
  1000. Title: string [15] = 'FPC Installer'#0;
  1001. RunBlock: TRunBlock = (Length: $32;
  1002. Dependent: 0;
  1003. Background: 0;
  1004. TraceLevel: 0;
  1005. PrgTitle: @Title [1];
  1006. PrgName: nil;
  1007. Args: nil;
  1008. TermQ: 0;
  1009. Environment: nil;
  1010. Inheritance: 0;
  1011. SesType: 2;
  1012. Icon: nil;
  1013. PgmHandle: 0;
  1014. PgmControl: 2;
  1015. Column: 0;
  1016. Row: 0;
  1017. Width: 80;
  1018. Height: 25);
  1019. begin
  1020. CheckOS2 := false;
  1021. asm
  1022. mov ah, 30h
  1023. int 21h
  1024. xchg ah, al
  1025. mov DosV, ax
  1026. mov ax, 4010h
  1027. int 2Fh
  1028. cmp ax, 4010h
  1029. jnz @0
  1030. xor bx, bx
  1031. @0:
  1032. mov W, bx
  1033. end;
  1034. if DosV > 3 shl 8 then
  1035. begin
  1036. OwnName := FExpand (ParamStr (0));
  1037. FSplit (OwnName, OwnDir, Name, Ext);
  1038. if (DosV >= 20 shl 8 + 10) and (W >= 20 shl 8 + 10) then
  1039. (* OS/2 version 2.1 or later running (double-checked) *)
  1040. begin
  1041. OwnName [Succ (byte (OwnName [0]))] := #0;
  1042. RunBlock.PrgName := @OwnName [1];
  1043. P := Ptr (PrefixSeg, $80);
  1044. if PByte (P)^ <> 0 then
  1045. begin
  1046. Inc (P);
  1047. RunBlock.Args := Ptr (PrefixSeg, $81);
  1048. end;
  1049. asm
  1050. mov ax, 6400h
  1051. mov bx, 0025h
  1052. mov cx, 636Ch
  1053. mov si, offset RunBlock
  1054. int 21h
  1055. jc @0
  1056. mov DosV, 0
  1057. @0:
  1058. end;
  1059. CheckOS2 := DosV = 0;
  1060. end;
  1061. end;
  1062. end;
  1063. {$ENDIF}
  1064. begin
  1065. {$ifdef FPC}
  1066. {$ifdef win32}
  1067. Dos.Exec(GetEnv('COMSPEC'),'/C echo This dummy call gets the mouse to become visible');
  1068. {$endif win32}
  1069. {$endif FPC}
  1070. (* TH - no error boxes if checking an inaccessible disk etc. *)
  1071. {$IFDEF OS2}
  1072. {$IFDEF FPC}
  1073. DosCalls.DosError (0);
  1074. {$ELSE FPC}
  1075. {$IFDEF VirtualPascal}
  1076. OS2Base.DosError (ferr_DisableHardErr);
  1077. {$ELSE VirtualPascal}
  1078. BseDos.DosError (0);
  1079. {$ENDIF VirtualPascal}
  1080. {$ENDIF FPC}
  1081. {$ENDIF}
  1082. {$IFDEF DOSSTUB}
  1083. if CheckOS2 then Halt;
  1084. {$ENDIF}
  1085. getdir(0,startpath);
  1086. successfull:=false;
  1087. fillchar(cfg, SizeOf(cfg), 0);
  1088. fillchar(data, SizeOf(data), 0);
  1089. installapp.init;
  1090. FSplit (FExpand (ParamStr (0)), DStr, CfgName, EStr);
  1091. installapp.readcfg(CfgName + CfgExt);
  1092. installapp.checkavailpack;
  1093. { installapp.readcfg(startpath+dirsep+cfgfile);}
  1094. installapp.do_installdialog;
  1095. installapp.done;
  1096. end.
  1097. {
  1098. $Log$
  1099. Revision 1.19 2000-06-18 18:27:32 hajny
  1100. + archive validity checking, progress indicator, better error checking
  1101. Revision 1.18 2000/02/24 17:47:47 peter
  1102. * last fixes for 0.99.14a release
  1103. Revision 1.17 2000/02/23 17:17:56 peter
  1104. * write ppc386.cfg for all found targets
  1105. Revision 1.16 2000/02/06 12:59:39 peter
  1106. * change upper -> upcase
  1107. * fixed stupid debugging leftover with diskspace check
  1108. Revision 1.15 2000/02/02 17:19:10 pierre
  1109. * avoid diskfree problem and get mouse visible
  1110. Revision 1.14 2000/02/02 15:21:31 peter
  1111. * show errorcode in message when error in unzipping
  1112. Revision 1.13 2000/01/26 21:49:33 peter
  1113. * install.pas compilable by FPC again
  1114. * removed some notes from unzip.pas
  1115. * support installer creation under linux (install has name conflict)
  1116. Revision 1.12 2000/01/26 21:15:59 hajny
  1117. * compilable with TP again (lines < 127install.pas, ifdef around findclose)
  1118. Revision 1.11 2000/01/24 22:21:48 peter
  1119. * new install version (keys not wrong correct yet)
  1120. Revision 1.10 2000/01/18 00:22:48 peter
  1121. * fixed uninited local var
  1122. Revision 1.9 1999/08/03 20:21:53 peter
  1123. * fixed sources mask which was not set correctly
  1124. Revision 1.7 1999/07/01 07:56:58 hajny
  1125. * installation to root fixed
  1126. Revision 1.6 1999/06/29 22:20:19 peter
  1127. * updated to use tab pages
  1128. Revision 1.5 1999/06/25 07:06:30 hajny
  1129. + searching for installation script updated
  1130. Revision 1.4 1999/06/10 20:01:23 peter
  1131. + fcl,fv,gtk support
  1132. Revision 1.3 1999/06/10 15:00:14 peter
  1133. * fixed to compile for not os2
  1134. * update install.dat
  1135. Revision 1.2 1999/06/10 07:28:27 hajny
  1136. * compilable with TP again
  1137. Revision 1.1 1999/02/19 16:45:26 peter
  1138. * moved to fpinst/ directory
  1139. + makefile
  1140. Revision 1.15 1999/02/17 22:34:08 peter
  1141. * updates from TH for OS2
  1142. Revision 1.14 1998/12/22 22:47:34 peter
  1143. * updates for OS2
  1144. * small fixes
  1145. Revision 1.13 1998/12/21 13:11:39 peter
  1146. * updates for 0.99.10
  1147. Revision 1.12 1998/12/16 00:25:34 peter
  1148. * updated for 0.99.10
  1149. * new end dialogbox
  1150. Revision 1.11 1998/11/01 20:32:25 peter
  1151. * packed record
  1152. Revision 1.10 1998/10/25 23:38:35 peter
  1153. * removed warnings
  1154. Revision 1.9 1998/10/23 16:57:40 pierre
  1155. * compiles without -So option
  1156. * the main dialog init was buggy !!
  1157. Revision 1.8 1998/09/22 21:10:31 jonas
  1158. * initialize cfg and data with 0 at startup
  1159. Revision 1.7 1998/09/16 16:46:37 peter
  1160. + updates
  1161. Revision 1.6 1998/09/15 13:11:14 pierre
  1162. small fix to cleanup if no package
  1163. Revision 1.5 1998/09/15 12:06:06 peter
  1164. * install updated to support w32 and dos and config file
  1165. Revision 1.4 1998/09/10 10:50:49 florian
  1166. * DOS install program updated
  1167. Revision 1.3 1998/09/09 13:39:58 peter
  1168. + internal unzip
  1169. * dialog is showed automaticly
  1170. Revision 1.2 1998/04/07 22:47:57 florian
  1171. + version/release/patch numbers as string added
  1172. }