install.pas 32 KB

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