install.pas 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  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. include : boolean;
  86. filechk : string[40];
  87. packages : longint;
  88. package : array[1..maxpackages] of tpackage;
  89. end;
  90. cfgrec=record
  91. title : string[80];
  92. version : string[20];
  93. basepath : DirStr;
  94. binsub : string[12];
  95. ppc386 : string[12];
  96. packs : word;
  97. pack : array[1..maxpacks] of tpack;
  98. defcfgfile : string[12];
  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. S: string;
  413. WPath: boolean;
  414. {$ENDIF}
  415. {$IFDEF OS2}
  416. ErrPath: array [0..259] of char;
  417. Handle: longint;
  418. WLibPath: boolean;
  419. const
  420. EMXName: array [1..4] of char = 'EMX'#0;
  421. {$ENDIF}
  422. begin
  423. YB := 14;
  424. {$IFNDEF LINUX}
  425. S := Data.BasePath + Cfg.BinSub;
  426. if Pos (Upper (S), Upper (GetEnv ('PATH'))) = 0 then
  427. begin
  428. WPath := true;
  429. Inc (YB, 2);
  430. end else WPath := false;
  431. {$IFDEF OS2}
  432. if DosLoadModule (@ErrPath, SizeOf (ErrPath), @EMXName, Handle) = 0 then
  433. begin
  434. WLibPath := false;
  435. DosFreeModule (Handle);
  436. end else
  437. begin
  438. WLibPath := true;
  439. Inc (YB, 2);
  440. end;
  441. {$ENDIF}
  442. {$ENDIF}
  443. R.Assign(6, 6, 74, YB);
  444. inherited init(r,'Installation Successfull');
  445. {$IFNDEF LINUX}
  446. if WPath then
  447. begin
  448. R.Assign(2, 3, 64, 5);
  449. P:=new(pstatictext,init(r,'Extend your PATH variable with '''+S+''''));
  450. insert(P);
  451. end;
  452. {$IFDEF OS2}
  453. if WLibPath then
  454. begin
  455. if WPath then S := 'and your LIBPATH with ''' + S + '\dll''' else
  456. S := 'Extend your LIBPATH with ''' + S + '\dll''';
  457. R.Assign (2, YB - 13, 64, YB - 11);
  458. P := New (PStaticText, Init (R, S));
  459. Insert (P);
  460. end;
  461. {$ENDIF}
  462. {$ENDIF}
  463. R.Assign(2, YB - 11, 64, YB - 10);
  464. P:=new(pstatictext,init(r,'To compile files enter '''+cfg.ppc386+' [file]'''));
  465. insert(P);
  466. R.Assign (29, YB - 9, 39, YB - 7);
  467. Control := New (PButton, Init (R,'~O~k', cmOK, bfDefault));
  468. Insert (Control);
  469. end;
  470. {*****************************************************************************
  471. TInstallDialog
  472. *****************************************************************************}
  473. constructor tinstalldialog.init;
  474. const
  475. width = 76;
  476. height = 20;
  477. x1 = (79-width) div 2;
  478. y1 = (23-height) div 2;
  479. x2 = x1+width;
  480. y2 = y1+height;
  481. var
  482. tabr,tabir,r : trect;
  483. packmask : array[1..maxpacks] of longint;
  484. i,line,j : integer;
  485. items : array[1..maxpacks] of psitem;
  486. f : pview;
  487. found : boolean;
  488. okbut,cancelbut : pbutton;
  489. firstitem : array[1..maxpacks] of integer;
  490. packcbs : array[1..maxpacks] of pcheckboxes;
  491. packtd : ptabdef;
  492. labpath : plabel;
  493. ilpath : pinputline;
  494. tab : ptab;
  495. titletext : pcoloredtext;
  496. labcfg : plabel;
  497. cfgcb : pcheckboxes;
  498. begin
  499. f:=nil;
  500. { walk packages reverse and insert a newsitem for each, and set the mask }
  501. for j:=1to cfg.packs do
  502. with cfg.pack[j] do
  503. begin
  504. firstitem[j]:=0;
  505. items[j]:=nil;
  506. packmask[j]:=0;
  507. for i:=packages downto 1 do
  508. begin
  509. if file_exists(package[i].zip,startpath) then
  510. begin
  511. items[j]:=newsitem(package[i].name+diskspace(startpath+DirSep+package[i].zip),items[j]);
  512. packmask[j]:=packmask[j] or packagemask(i);
  513. firstitem[j]:=i;
  514. end
  515. else
  516. items[j]:=newsitem(package[i].name,items[j]);
  517. end;
  518. end;
  519. { If no component found abort }
  520. found:=false;
  521. for j:=1to cfg.packs do
  522. if packmask[j]<>0 then
  523. found:=true;
  524. if not found then
  525. begin
  526. messagebox('No components found to install, aborting.',nil,mferror+mfokbutton);
  527. errorhalt;
  528. end;
  529. r.assign(x1,y1,x2,y2);
  530. inherited init(r,'');
  531. GetExtent(R);
  532. R.Grow(-2,-1);
  533. Dec(R.B.Y,2);
  534. TabR.Copy(R);
  535. TabIR.Copy(R);
  536. TabIR.Grow(-2,-2);
  537. TabIR.Move(-2,0);
  538. {-------- General Sheets ----------}
  539. R.Copy(TabIR);
  540. r.move(0,1);
  541. r.b.x:=r.a.x+40;
  542. r.b.y:=r.a.y+1;
  543. new(titletext,init(r,cfg.title,$71));
  544. r.move(0,2);
  545. r.b.x:=r.a.x+40;
  546. new(labpath,init(r,'~B~ase path',f));
  547. r.move(0,1);
  548. r.b.x:=r.a.x+40;
  549. r.b.y:=r.a.y+1;
  550. new(ilpath,init(r,high(DirStr)));
  551. r.move(0,2);
  552. r.b.x:=r.a.x+40;
  553. new(labcfg,init(r,'Con~f~ig',f));
  554. r.move(0,1);
  555. r.b.x:=r.a.x+40;
  556. r.b.y:=r.a.y+1;
  557. new(cfgcb,init(r,newsitem('create ppc386.cfg',nil)));
  558. data.cfgval:=1;
  559. {-------- Pack Sheets ----------}
  560. for j:=1to cfg.packs do
  561. begin
  562. R.Copy(TabIR);
  563. new(packcbs[j],init(r,items[j]));
  564. if data.packmask[j]=$ffff then
  565. data.packmask[j]:=packmask[j];
  566. packcbs[j]^.enablemask:=packmask[j];
  567. packcbs[j]^.movedto(firstitem[j]);
  568. end;
  569. {--------- Main ---------}
  570. packtd:=nil;
  571. for j:=cfg.packs downto 1 do
  572. packtd:=NewTabDef(cfg.pack[j].name,PackCbs[j],NewTabItem(PackCbs[j],nil),packtd);
  573. New(Tab, Init(TabR,
  574. NewTabDef('~G~eneral',IlPath,
  575. NewTabItem(TitleText,
  576. NewTabItem(LabPath,
  577. NewTabItem(ILPath,
  578. NewTabItem(LabCfg,
  579. NewTabItem(CfgCB,
  580. nil))))),
  581. packtd)
  582. ));
  583. Tab^.GrowMode:=0;
  584. Insert(Tab);
  585. line:=tabr.b.y;
  586. r.assign((width div 2)-18,line,(width div 2)-4,line+2);
  587. new(okbut,init(r,'~C~ontinue',cmok,bfdefault));
  588. Insert(OkBut);
  589. r.assign((width div 2)+4,line,(width div 2)+14,line+2);
  590. new(cancelbut,init(r,'~Q~uit',cmcancel,bfnormal));
  591. Insert(CancelBut);
  592. Tab^.Select;
  593. end;
  594. {*****************************************************************************
  595. TApp
  596. *****************************************************************************}
  597. const
  598. cmstart = 1000;
  599. procedure tapp.do_installdialog;
  600. var
  601. p : pinstalldialog;
  602. p2 : punzipdialog;
  603. p3 : penddialog;
  604. r : trect;
  605. result,
  606. c : word;
  607. i,j : longint;
  608. found : boolean;
  609. {$ifndef linux}
  610. DSize,Space : longint;
  611. S: DirStr;
  612. {$endif}
  613. begin
  614. data.basepath:=cfg.basepath;
  615. data.cfgval:=0;
  616. for j:=1to cfg.packs do
  617. data.packmask[j]:=$ffff;
  618. repeat
  619. { select components }
  620. p:=new(pinstalldialog,init);
  621. c:=executedialog(p,@data);
  622. if (c=cmok) then
  623. begin
  624. if Data.BasePath = '' then
  625. messagebox('Please, choose the directory for installation first.',nil,mferror+mfokbutton)
  626. else
  627. begin
  628. found:=false;
  629. for j:=1to cfg.packs do
  630. if data.packmask[j]>0 then
  631. found:=true;
  632. if found then
  633. begin
  634. {$IFNDEF LINUX}
  635. { TH - check the available disk space here }
  636. DSize := 0;
  637. for j:=1to cfg.packs do
  638. with cfg.pack[j] do
  639. begin
  640. for i:=1 to packages do
  641. begin
  642. if data.packmask[j] and packagemask(i)<>0 then
  643. Inc (DSize, DiskSpaceN(package[i].zip));
  644. end;
  645. end;
  646. S := FExpand (Data.BasePath);
  647. if S [Length (S)] = DirSep then
  648. Dec (S [0]);
  649. Space := DiskFree (byte (Upcase(S [1])) - 64) shr 10;
  650. if Space < DSize then
  651. S := 'is not'
  652. else
  653. S := '';
  654. if (Space < DSize + 500) then
  655. begin
  656. if S = '' then
  657. S := 'might not be';
  658. if messagebox('There ' + S + ' enough space on the target ' +
  659. 'drive for all the selected components. Do you ' +
  660. 'want to change the installation path?',nil,
  661. mferror+mfyesbutton+mfnobutton) = cmYes then
  662. Continue;
  663. end;
  664. {$ENDIF}
  665. if createinstalldir(data.basepath) then
  666. break;
  667. end
  668. else
  669. begin
  670. { maybe only config }
  671. if (data.cfgval and 1)<>0 then
  672. begin
  673. result:=messagebox('No components selected.'#13#13'Create a configfile ?',nil,
  674. mfinformation+mfyesbutton+mfnobutton);
  675. if (result=cmYes) and createinstalldir(data.basepath) then
  676. writedefcfg(data.basepath+cfg.binsub+DirSep+cfg.defcfgfile);
  677. exit;
  678. end
  679. else
  680. begin
  681. result:=messagebox('No components selected.'#13#13'Abort installation?',nil,
  682. mferror+mfyesbutton+mfnobutton);
  683. if result=cmYes then
  684. exit;
  685. end;
  686. end;
  687. end;
  688. end
  689. else
  690. exit;
  691. until false;
  692. { extract packages }
  693. for j:=1 to cfg.packs do
  694. with cfg.pack[j] do
  695. begin
  696. r.assign(20,7,60,16);
  697. p2:=new(punzipdialog,init(r,'Extracting Packages'));
  698. desktop^.insert(p2);
  699. for i:=1 to packages do
  700. begin
  701. if data.packmask[j] and packagemask(i)<>0 then
  702. p2^.do_unzip(package[i].zip,data.basepath);
  703. end;
  704. desktop^.delete(p2);
  705. dispose(p2,done);
  706. end;
  707. { write config }
  708. if (data.cfgval and 1)<>0 then
  709. writedefcfg(data.basepath+cfg.binsub+DirSep+cfg.defcfgfile);
  710. { show end message }
  711. p3:=new(penddialog,init);
  712. executedialog(p3,nil);
  713. end;
  714. procedure tapp.readcfg(const fn:string);
  715. var
  716. t : text;
  717. i,j,
  718. line : longint;
  719. item,
  720. s : string;
  721. params : array[0..0] of pointer;
  722. {$ifndef FPC}
  723. procedure readln(var t:text;var s:string);
  724. var
  725. c : char;
  726. i : longint;
  727. begin
  728. c:=#0;
  729. i:=0;
  730. while (not eof(t)) and (c<>#10) do
  731. begin
  732. read(t,c);
  733. if c<>#10 then
  734. begin
  735. inc(i);
  736. s[i]:=c;
  737. end;
  738. end;
  739. if (i>0) and (s[i]=#13) then
  740. dec(i);
  741. s[0]:=chr(i);
  742. end;
  743. {$endif}
  744. begin
  745. assign(t,StartPath + DirSep + fn);
  746. {$I-}
  747. reset(t);
  748. {$I+}
  749. if ioresult<>0 then
  750. begin
  751. StartPath := GetProgDir;
  752. assign(t,StartPath + DirSep + fn);
  753. {$I-}
  754. reset(t);
  755. {$I+}
  756. if ioresult<>0 then
  757. begin
  758. params[0]:=@fn;
  759. messagebox('File %s not found!',@params,mferror+mfokbutton);
  760. errorhalt;
  761. end;
  762. end;
  763. line:=0;
  764. while not eof(t) do
  765. begin
  766. readln(t,s);
  767. inc(line);
  768. if (s<>'') and not(s[1] in ['#',';']) then
  769. begin
  770. i:=pos('=',s);
  771. if i>0 then
  772. begin
  773. item:=upper(Copy(s,1,i-1));
  774. system.delete(s,1,i);
  775. if item='VERSION' then
  776. cfg.version:=s
  777. else
  778. if item='TITLE' then
  779. cfg.title:=s
  780. else
  781. if item='BASEPATH' then
  782. cfg.basepath:=s
  783. else
  784. if item='PPC386' then
  785. cfg.ppc386:=s
  786. else
  787. if item='BINSUB' then
  788. cfg.binsub:=s
  789. else
  790. if item='CFGFILE' then
  791. cfg.defcfgfile:=s
  792. else
  793. if item='DEFAULTCFG' then
  794. begin
  795. repeat
  796. readln(t,s);
  797. if upper(s)='ENDCFG' then
  798. break;
  799. if cfg.defcfgs<maxdefcfgs then
  800. begin
  801. inc(cfg.defcfgs);
  802. cfg.defcfg[cfg.defcfgs]:=newstr(s);
  803. end;
  804. until false;
  805. end
  806. else
  807. if item='PACK' then
  808. begin
  809. inc(cfg.packs);
  810. if cfg.packs>maxpacks then
  811. begin
  812. writeln('Too much packs');
  813. halt(1);
  814. end;
  815. cfg.pack[cfg.packs].name:=s;
  816. end
  817. else
  818. if item='FILECHECK' then
  819. begin
  820. if cfg.packs=0 then
  821. begin
  822. writeln('No pack set');
  823. halt(1);
  824. end;
  825. cfg.pack[cfg.packs].filechk:=s;
  826. end
  827. else
  828. if item='PACKAGE' then
  829. begin
  830. if cfg.packs=0 then
  831. begin
  832. writeln('No pack set');
  833. halt(1);
  834. end;
  835. with cfg.pack[cfg.packs] do
  836. begin
  837. j:=pos(',',s);
  838. if (j>0) and (packages<maxpackages) then
  839. begin
  840. inc(packages);
  841. package[packages].zip:=copy(s,1,j-1);
  842. package[packages].name:=copy(s,j+1,255);
  843. end;
  844. end;
  845. end
  846. end;
  847. end;
  848. end;
  849. close(t);
  850. end;
  851. procedure tapp.checkavailpack;
  852. var
  853. j : longint;
  854. dir : searchrec;
  855. begin
  856. { check the packages }
  857. j:=0;
  858. while (j<cfg.packs) do
  859. begin
  860. inc(j);
  861. if cfg.pack[j].filechk<>'' then
  862. begin
  863. findfirst(cfg.pack[j].filechk,$20,dir);
  864. if doserror<>0 then
  865. begin
  866. { remove the package }
  867. move(cfg.pack[j+1],cfg.pack[j],sizeof(tpack)*(cfg.packs-j));
  868. dec(cfg.packs);
  869. dec(j);
  870. end;
  871. {$IFNDEF TP}
  872. findclose(dir);
  873. {$ENDIF}
  874. end;
  875. end;
  876. end;
  877. procedure tapp.initmenubar;
  878. var
  879. r : trect;
  880. begin
  881. getextent(r);
  882. r.b.y:=r.a.y+1;
  883. menubar:=new(pmenubar,init(r,newmenu(
  884. newsubmenu('Free Pascal Installer',hcnocontext,newmenu(nil
  885. ),
  886. nil))));
  887. end;
  888. procedure tapp.handleevent(var event : tevent);
  889. begin
  890. inherited handleevent(event);
  891. if event.what=evcommand then
  892. if event.command=cmstart then
  893. begin
  894. clearevent(event);
  895. do_installdialog;
  896. if successfull then
  897. begin
  898. event.what:=evcommand;
  899. event.command:=cmquit;
  900. handleevent(event);
  901. end;
  902. end;
  903. end;
  904. {$IFDEF DOSSTUB}
  905. function CheckOS2: boolean;
  906. var
  907. OwnName: PathStr;
  908. OwnDir: DirStr;
  909. Name: NameStr;
  910. Ext: ExtStr;
  911. DosV, W: word;
  912. P: PChar;
  913. const
  914. Title: string [15] = 'FPC Installer'#0;
  915. RunBlock: TRunBlock = (Length: $32;
  916. Dependent: 0;
  917. Background: 0;
  918. TraceLevel: 0;
  919. PrgTitle: @Title [1];
  920. PrgName: nil;
  921. Args: nil;
  922. TermQ: 0;
  923. Environment: nil;
  924. Inheritance: 0;
  925. SesType: 2;
  926. Icon: nil;
  927. PgmHandle: 0;
  928. PgmControl: 2;
  929. Column: 0;
  930. Row: 0;
  931. Width: 80;
  932. Height: 25);
  933. begin
  934. CheckOS2 := false;
  935. asm
  936. mov ah, 30h
  937. int 21h
  938. xchg ah, al
  939. mov DosV, ax
  940. mov ax, 4010h
  941. int 2Fh
  942. cmp ax, 4010h
  943. jnz @0
  944. xor bx, bx
  945. @0:
  946. mov W, bx
  947. end;
  948. if DosV > 3 shl 8 then
  949. begin
  950. OwnName := FExpand (ParamStr (0));
  951. FSplit (OwnName, OwnDir, Name, Ext);
  952. if (DosV >= 20 shl 8 + 10) and (W >= 20 shl 8 + 10) then
  953. (* OS/2 version 2.1 or later running (double-checked) *)
  954. begin
  955. OwnName [Succ (byte (OwnName [0]))] := #0;
  956. RunBlock.PrgName := @OwnName [1];
  957. P := Ptr (PrefixSeg, $80);
  958. if PByte (P)^ <> 0 then
  959. begin
  960. Inc (P);
  961. RunBlock.Args := Ptr (PrefixSeg, $81);
  962. end;
  963. asm
  964. mov ax, 6400h
  965. mov bx, 0025h
  966. mov cx, 636Ch
  967. mov si, offset RunBlock
  968. int 21h
  969. jc @0
  970. mov DosV, 0
  971. @0:
  972. end;
  973. CheckOS2 := DosV = 0;
  974. end;
  975. end;
  976. end;
  977. {$ENDIF}
  978. begin
  979. {$ifdef FPC}
  980. {$ifdef win32}
  981. Dos.Exec(GetEnv('COMSPEC'),'/C echo This dummy call gets the mouse to become visible');
  982. {$endif win32}
  983. {$endif FPC}
  984. (* TH - no error boxes if checking an inaccessible disk etc. *)
  985. {$IFDEF OS2}
  986. {$IFDEF FPC}
  987. DosCalls.DosError (0);
  988. {$ELSE FPC}
  989. {$IFDEF VirtualPascal}
  990. OS2Base.DosError (ferr_DisableHardErr);
  991. {$ELSE VirtualPascal}
  992. BseDos.DosError (0);
  993. {$ENDIF VirtualPascal}
  994. {$ENDIF FPC}
  995. {$ENDIF}
  996. {$IFDEF DOSSTUB}
  997. if CheckOS2 then Halt;
  998. {$ENDIF}
  999. getdir(0,startpath);
  1000. successfull:=false;
  1001. fillchar(cfg, SizeOf(cfg), 0);
  1002. fillchar(data, SizeOf(data), 0);
  1003. installapp.init;
  1004. FSplit (FExpand (ParamStr (0)), DStr, CfgName, EStr);
  1005. installapp.readcfg(CfgName + CfgExt);
  1006. installapp.checkavailpack;
  1007. { installapp.readcfg(startpath+dirsep+cfgfile);}
  1008. installapp.do_installdialog;
  1009. installapp.done;
  1010. end.
  1011. {
  1012. $Log$
  1013. Revision 1.16 2000-02-06 12:59:39 peter
  1014. * change upper -> upcase
  1015. * fixed stupid debugging leftover with diskspace check
  1016. Revision 1.15 2000/02/02 17:19:10 pierre
  1017. * avoid diskfree problem and get mouse visible
  1018. Revision 1.14 2000/02/02 15:21:31 peter
  1019. * show errorcode in message when error in unzipping
  1020. Revision 1.13 2000/01/26 21:49:33 peter
  1021. * install.pas compilable by FPC again
  1022. * removed some notes from unzip.pas
  1023. * support installer creation under linux (install has name conflict)
  1024. Revision 1.12 2000/01/26 21:15:59 hajny
  1025. * compilable with TP again (lines < 127install.pas, ifdef around findclose)
  1026. Revision 1.11 2000/01/24 22:21:48 peter
  1027. * new install version (keys not wrong correct yet)
  1028. Revision 1.10 2000/01/18 00:22:48 peter
  1029. * fixed uninited local var
  1030. Revision 1.9 1999/08/03 20:21:53 peter
  1031. * fixed sources mask which was not set correctly
  1032. Revision 1.7 1999/07/01 07:56:58 hajny
  1033. * installation to root fixed
  1034. Revision 1.6 1999/06/29 22:20:19 peter
  1035. * updated to use tab pages
  1036. Revision 1.5 1999/06/25 07:06:30 hajny
  1037. + searching for installation script updated
  1038. Revision 1.4 1999/06/10 20:01:23 peter
  1039. + fcl,fv,gtk support
  1040. Revision 1.3 1999/06/10 15:00:14 peter
  1041. * fixed to compile for not os2
  1042. * update install.dat
  1043. Revision 1.2 1999/06/10 07:28:27 hajny
  1044. * compilable with TP again
  1045. Revision 1.1 1999/02/19 16:45:26 peter
  1046. * moved to fpinst/ directory
  1047. + makefile
  1048. Revision 1.15 1999/02/17 22:34:08 peter
  1049. * updates from TH for OS2
  1050. Revision 1.14 1998/12/22 22:47:34 peter
  1051. * updates for OS2
  1052. * small fixes
  1053. Revision 1.13 1998/12/21 13:11:39 peter
  1054. * updates for 0.99.10
  1055. Revision 1.12 1998/12/16 00:25:34 peter
  1056. * updated for 0.99.10
  1057. * new end dialogbox
  1058. Revision 1.11 1998/11/01 20:32:25 peter
  1059. * packed record
  1060. Revision 1.10 1998/10/25 23:38:35 peter
  1061. * removed warnings
  1062. Revision 1.9 1998/10/23 16:57:40 pierre
  1063. * compiles without -So option
  1064. * the main dialog init was buggy !!
  1065. Revision 1.8 1998/09/22 21:10:31 jonas
  1066. * initialize cfg and data with 0 at startup
  1067. Revision 1.7 1998/09/16 16:46:37 peter
  1068. + updates
  1069. Revision 1.6 1998/09/15 13:11:14 pierre
  1070. small fix to cleanup if no package
  1071. Revision 1.5 1998/09/15 12:06:06 peter
  1072. * install updated to support w32 and dos and config file
  1073. Revision 1.4 1998/09/10 10:50:49 florian
  1074. * DOS install program updated
  1075. Revision 1.3 1998/09/09 13:39:58 peter
  1076. + internal unzip
  1077. * dialog is showed automaticly
  1078. Revision 1.2 1998/04/07 22:47:57 florian
  1079. + version/release/patch numbers as string added
  1080. }