install.pas 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515
  1. {
  2. $Id$
  3. This file is part of Free Pascal
  4. Copyright (c) 1993-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. This is the install program for 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 DPMI}
  35. {$UNDEF DOSSTUB}
  36. {$ENDIF}
  37. uses
  38. {$IFDEF OS2}
  39. {$IFDEF FPC}
  40. DosCalls,
  41. {$ELSE FPC}
  42. {$IFDEF VirtualPascal}
  43. OS2Base,
  44. {$ELSE VirtualPascal}
  45. BseDos,
  46. {$ENDIF VirtualPascal}
  47. {$ENDIF FPC}
  48. {$ENDIF OS2}
  49. {$IFDEF GO32V2}
  50. emu387,
  51. {$ENDIF}
  52. {$ifdef HEAPTRC}
  53. heaptrc,
  54. {$endif HEAPTRC}
  55. strings,dos,objects,drivers,
  56. {$IFDEF FV}
  57. commands,
  58. {$ENDIF}
  59. unzip,ziptypes,
  60. {$IFDEF DLL}
  61. unzipdll,
  62. {$ENDIF}
  63. app,dialogs,views,menus,msgbox,colortxt,tabs,inststr,scroll;
  64. const
  65. installerversion='1.02';
  66. {$ifdef TP}lfnsupport=false;{$endif}
  67. maxpacks=10;
  68. maxpackages=20;
  69. maxdefcfgs=1024;
  70. CfgExt = '.dat';
  71. MaxStatusPos = 4;
  72. StatusChars: string [MaxStatusPos] = '/-\|';
  73. StatusPos: byte = 1;
  74. {$IFDEF LINUX}
  75. DirSep='/';
  76. {$ELSE}
  77. {$IFDEF UNIX}
  78. DirSep='/';
  79. {$ELSE}
  80. DirSep='\';
  81. {$ENDIF}
  82. {$ENDIF}
  83. {$IFNDEF GO32V2}
  84. {$IFDEF GO32V1}
  85. LFNSupport = false;
  86. {$ELSE}
  87. {$IFDEF TP}
  88. LFNSupport = false;
  89. {$ELSE}
  90. LFNSupport = true;
  91. {$ENDIF}
  92. {$ENDIF}
  93. {$ENDIF}
  94. type
  95. tpackage=record
  96. name : string[60];
  97. zip : string[12];
  98. end;
  99. tpack=record
  100. name : string[12];
  101. binsub : string[40];
  102. ppc386 : string[20];
  103. defcfgfile : string[12];
  104. include : boolean;
  105. filechk : string[40];
  106. packages : longint;
  107. package : array[1..maxpackages] of tpackage;
  108. end;
  109. cfgrec=record
  110. title : string[80];
  111. version : string[20];
  112. language : string[30];
  113. basepath : DirStr;
  114. packs : word;
  115. pack : array[1..maxpacks] of tpack;
  116. defcfgs : longint;
  117. defcfg : array[1..maxdefcfgs] of pstring;
  118. end;
  119. datarec=packed record
  120. basepath : DirStr;
  121. cfgval : word;
  122. packmask : array[1..maxpacks] of word;
  123. end;
  124. punzipdialog=^tunzipdialog;
  125. tunzipdialog=object(tdialog)
  126. filetext : pstatictext;
  127. extractfiletext : pstatictext;
  128. constructor Init(var Bounds: TRect; ATitle: TTitleStr);
  129. procedure do_unzip(s,topath:string);
  130. end;
  131. penddialog = ^tenddialog;
  132. tenddialog = object(tdialog)
  133. constructor init;
  134. end;
  135. pinstalldialog = ^tinstalldialog;
  136. tinstalldialog = object(tdialog)
  137. constructor init;
  138. end;
  139. planguagedialog = ^tlanguagedialog;
  140. tlanguagedialog = object(tdialog)
  141. constructor init;
  142. end;
  143. tapp = object(tapplication)
  144. procedure initmenubar;virtual;
  145. procedure handleevent(var event : tevent);virtual;
  146. procedure do_installdialog;
  147. procedure do_languagedialog;
  148. procedure readcfg(const fn:string);
  149. procedure checkavailpack;
  150. end;
  151. {$IFDEF DOSSTUB}
  152. PByte = ^byte;
  153. PRunBlock = ^TRunBlock;
  154. TRunBlock = record
  155. Length: word;
  156. Dependent: word;
  157. Background: word;
  158. TraceLevel: word;
  159. PrgTitle: PChar;
  160. PrgName: PChar;
  161. Args: PChar;
  162. TermQ: longint;
  163. Environment: pointer;
  164. Inheritance: word;
  165. SesType: word;
  166. Icon: pointer;
  167. PgmHandle: longint;
  168. PgmControl: word;
  169. Column: word;
  170. Row: word;
  171. Width: word;
  172. Height: word;
  173. end;
  174. {$ENDIF}
  175. var
  176. installapp : tapp;
  177. startpath : string;
  178. successfull : boolean;
  179. cfg : cfgrec;
  180. data : datarec;
  181. CfgName: NameStr;
  182. DStr: DirStr;
  183. EStr: ExtStr;
  184. UnzDlg : punzipdialog;
  185. log : text;
  186. createlog : boolean;
  187. msgfile : string;
  188. {$IFNDEF DLL}
  189. const
  190. UnzipErr: longint = 0;
  191. {$ENDIF}
  192. {*****************************************************************************
  193. Helpers
  194. *****************************************************************************}
  195. procedure errorhalt;
  196. begin
  197. installapp.done;
  198. halt(1);
  199. end;
  200. function packagemask(i:longint):longint;
  201. begin
  202. packagemask:=1 shl (i-1);
  203. end;
  204. function upper(const s : string):string;
  205. var
  206. i : integer;
  207. begin
  208. for i:=1 to length(s) do
  209. if s[i] in ['a'..'z'] then
  210. upper[i]:=chr(ord(s[i])-32)
  211. else
  212. upper[i]:=s[i];
  213. upper[0]:=s[0];
  214. end;
  215. function Replace(var s:string;const s1,s2:string) : boolean;
  216. var
  217. i : longint;
  218. begin
  219. Replace:=false;
  220. repeat
  221. i:=pos(s1,s);
  222. if i>0 then
  223. begin
  224. Delete(s,i,length(s1));
  225. Insert(s2,s,i);
  226. Replace:=true;
  227. end;
  228. until i=0;
  229. end;
  230. function file_exists(const f : string;const path : string) : boolean;
  231. begin
  232. file_exists:=fsearch(f,path)<>'';
  233. end;
  234. function createdir(s:string):boolean;
  235. var
  236. s1,start : string;
  237. err : boolean;
  238. i : longint;
  239. begin
  240. err:=false;
  241. {$I-}
  242. getdir(0,start);
  243. {$ifndef linux}
  244. if (s[2]=':') and (s[3]=DirSep) then
  245. begin
  246. chdir(Copy(s,1,3));
  247. Delete(S,1,3);
  248. end;
  249. {$endif}
  250. repeat
  251. i:=Pos(DirSep,s);
  252. if i=0 then
  253. i:=255;
  254. s1:=Copy(s,1,i-1);
  255. Delete(s,1,i);
  256. ChDir(s1);
  257. if ioresult<>0 then
  258. begin
  259. mkdir(s1);
  260. chdir(s1);
  261. if ioresult<>0 then
  262. begin
  263. err:=true;
  264. break;
  265. end;
  266. end;
  267. until s='';
  268. chdir(start);
  269. {$I+}
  270. createdir:=err;
  271. end;
  272. function DiskSpaceN(const zipfile : string) : longint;
  273. var
  274. compressed,uncompressed : longint;
  275. s : string;
  276. begin
  277. s:=zipfile+#0;
  278. if not (IsZip (@S [1])) then DiskSpaceN := -1 else
  279. begin
  280. Uncompressed:=UnzipSize(@s[1],compressed);
  281. DiskSpaceN:=uncompressed shr 10;
  282. end;
  283. end;
  284. function diskspace(const zipfile : string) : string;
  285. var
  286. uncompressed : longint;
  287. s : string;
  288. begin
  289. uncompressed:=DiskSpaceN (zipfile);
  290. if Uncompressed = -1 then DiskSpace := str_invalid else
  291. begin
  292. str(uncompressed,s);
  293. diskspace:=' ('+s+' KB)';
  294. end;
  295. end;
  296. function createinstalldir(s : string) : boolean;
  297. var
  298. err : boolean;
  299. dir : searchrec;
  300. params : array[0..0] of pointer;
  301. begin
  302. if s[length(s)]=DirSep then
  303. dec(s[0]);
  304. FindFirst(s,AnyFile,dir);
  305. if doserror=0 then
  306. begin
  307. if Dir.Attr and Directory = 0 then
  308. begin
  309. messagebox(msg_problems_create_dir,nil,
  310. mferror+mfokbutton);
  311. createinstalldir:=false;
  312. end else
  313. createinstalldir:=messagebox(msg_install_dir_exists,nil,
  314. mferror+mfyesbutton+mfnobutton)=cmYes;
  315. exit;
  316. end;
  317. err:=Createdir(s);
  318. if err then
  319. begin
  320. params[0]:=@s;
  321. messagebox(msg_install_cant_be_created,
  322. @params,mferror+mfokbutton);
  323. createinstalldir:=false;
  324. exit;
  325. end;
  326. {$ifndef TP}
  327. {$IFNDEF OS2}
  328. FindClose (dir);
  329. {$ENDIF}
  330. {$endif}
  331. createinstalldir:=true;
  332. end;
  333. function GetProgDir: DirStr;
  334. var
  335. D: DirStr;
  336. N: NameStr;
  337. E: ExtStr;
  338. begin
  339. FSplit (FExpand (ParamStr (0)), D, N, E);
  340. if (D [0] <> #0) and (D [byte (D [0])] = '\') then Dec (D [0]);
  341. GetProgDir := D;
  342. end;
  343. {*****************************************************************************
  344. Writing of ppc386.cfg
  345. *****************************************************************************}
  346. procedure writedefcfg(const fn:string);
  347. var
  348. t : text;
  349. i : longint;
  350. s : string;
  351. dir : searchrec;
  352. params : array[0..0] of pointer;
  353. d : dirstr;
  354. n : namestr;
  355. e : extstr;
  356. begin
  357. { already exists }
  358. findfirst(fn,AnyFile,dir);
  359. if doserror=0 then
  360. begin
  361. params[0]:=@fn;
  362. if MessageBox(msg_overwrite_cfg,@params,
  363. mfinformation+mfyesbutton+mfnobutton)=cmNo then
  364. exit;
  365. end;
  366. { create directory }
  367. fsplit(fn,d,n,e);
  368. createdir(d);
  369. { create the ppc386.cfg }
  370. assign(t,fn);
  371. {$I-}
  372. rewrite(t);
  373. {$I+}
  374. if ioresult<>0 then
  375. begin
  376. params[0]:=@fn;
  377. MessageBox(msg_problems_writing_cfg,@params,mfinformation+mfokbutton);
  378. exit;
  379. end;
  380. for i:=1 to cfg.defcfgs do
  381. if assigned(cfg.defcfg[i]) then
  382. begin
  383. s:=cfg.defcfg[i]^;
  384. Replace(s,'$1',data.basepath);
  385. { error msg file entry? }
  386. if Replace(s,'$L',msgfile) then
  387. begin
  388. { if we've to set an error msg file, we }
  389. { write it else we discard the line }
  390. if msgfile<>'' then
  391. writeln(t,s);
  392. end
  393. else
  394. writeln(t,s);
  395. end
  396. else
  397. writeln(t,'');
  398. close(t);
  399. end;
  400. {*****************************************************************************
  401. TUnZipDialog
  402. *****************************************************************************}
  403. constructor tunzipdialog.Init(var Bounds: TRect; ATitle: TTitleStr);
  404. var
  405. r : trect;
  406. begin
  407. inherited init(bounds,atitle);
  408. (* R.Assign (11, 4, 38, 6);*)
  409. R.Assign (1, 4,bounds.B.X-Bounds.A.X-2, 6);
  410. filetext:=new(pstatictext,init(r,#3'File: '));
  411. insert(filetext);
  412. R.Assign (1, 7,bounds.B.X-Bounds.A.X-2, 9);
  413. extractfiletext:=new(pstatictext,init(r,#3' '));
  414. insert(extractfiletext);
  415. end;
  416. {$IFNDEF DLL}
  417. procedure UnzipCheckFn (Retcode: longint; Rec: pReportRec );{$ifdef Delphi32}STDCALL;{$endif}
  418. {$IFNDEF BIT32} FAR;{$ENDIF BIT32}
  419. var
  420. name : string;
  421. begin
  422. case Rec^.Status of
  423. unzip_starting:
  424. UnzipErr := 0;
  425. file_starting:
  426. begin
  427. with UnzDlg^.extractfiletext^ do
  428. begin
  429. Disposestr(text);
  430. name:=Strpas(Rec^.FileName);
  431. Text:=NewStr(#3+name);
  432. DrawView;
  433. end;
  434. end;
  435. file_failure: UnzipErr := RetCode;
  436. file_unzipping:
  437. begin
  438. with UnzDlg^.FileText^ do
  439. begin
  440. Inc (StatusPos);
  441. if StatusPos > MaxStatusPos then StatusPos := 1;
  442. Text^ [Length (Text^)] := StatusChars [StatusPos];
  443. DrawView;
  444. end;
  445. end;
  446. end;
  447. end;
  448. {$ENDIF}
  449. procedure tunzipdialog.do_unzip(s,topath : string);
  450. var
  451. again : boolean;
  452. fn,dir,wild : string;
  453. Cnt: integer;
  454. params : array[0..0] of pointer;
  455. begin
  456. Disposestr(filetext^.text);
  457. filetext^.Text:=NewStr(#3+str_file+s+ #13#3' ');
  458. filetext^.drawview;
  459. if not(file_exists(s,startpath)) then
  460. begin
  461. params[0]:=@s;
  462. messagebox(msg_file_missing,@params,mferror+mfokbutton);
  463. errorhalt;
  464. end;
  465. {$IFNDEF DLL}
  466. {$IFDEF FPC}
  467. SetUnzipReportProc (@UnzipCheckFn);
  468. {$ELSE FPC}
  469. SetUnzipReportProc (UnzipCheckFn);
  470. {$ENDIF FPC}
  471. {$ENDIF DLL}
  472. repeat
  473. fn:=startpath+DirSep+s+#0;
  474. dir:=topath+#0;
  475. wild:=AllFiles + #0;
  476. again:=false;
  477. FileUnzipEx(@fn[1],@dir[1],@wild[1]);
  478. if (UnzipErr <> 0) then
  479. begin
  480. Str(UnzipErr,s);
  481. params[0]:=@s;
  482. if messagebox(msg_extraction_error,@params,mferror+mfyesbutton+mfnobutton)=cmNo then
  483. errorhalt
  484. else
  485. again:=true;
  486. end;
  487. until not again;
  488. end;
  489. {*****************************************************************************
  490. TEndDialog
  491. *****************************************************************************}
  492. constructor tenddialog.init;
  493. var
  494. R : TRect;
  495. P : PStaticText;
  496. Control : PButton;
  497. YB: word;
  498. {$IFNDEF LINUX}
  499. i : longint;
  500. S: string;
  501. WPath: boolean;
  502. {$ENDIF}
  503. {$IFDEF OS2}
  504. ErrPath: array [0..259] of char;
  505. Handle: longint;
  506. WLibPath: boolean;
  507. const
  508. EMXName: array [1..4] of char = 'EMX'#0;
  509. {$ENDIF}
  510. begin
  511. YB := 14;
  512. {$IFNDEF LINUX}
  513. s:='';
  514. for i:=1 to cfg.packs do
  515. if cfg.pack[i].binsub<>'' then
  516. begin
  517. if s<>'' then
  518. s:=s+';';
  519. S := s+Data.BasePath + Cfg.pack[i].BinSub;
  520. end;
  521. if Pos (Upper (S), Upper (GetEnv ('PATH'))) = 0 then
  522. begin
  523. WPath := true;
  524. Inc (YB, 2);
  525. end
  526. else
  527. WPath := false;
  528. {$IFDEF OS2}
  529. if DosLoadModule (@ErrPath, SizeOf (ErrPath), @EMXName, Handle) = 0 then
  530. begin
  531. WLibPath := false;
  532. DosFreeModule (Handle);
  533. end
  534. else
  535. begin
  536. WLibPath := true;
  537. Inc (YB, 2);
  538. end;
  539. {$ENDIF}
  540. {$ENDIF}
  541. R.Assign(6, 6, 74, YB);
  542. inherited init(r,dialog_enddialog_title);
  543. {$IFNDEF LINUX}
  544. if WPath then
  545. begin
  546. R.Assign(2, 3, 64, 5);
  547. P:=new(pstatictext,init(r,str_extend_path+''''+S+''''));
  548. insert(P);
  549. end;
  550. {$IFDEF OS2}
  551. if WLibPath then
  552. begin
  553. if WPath then
  554. S := str_libpath+'''' + S + '\'+str_dll+''''
  555. else
  556. S := str_extend_libpath+'''' + S + '\'+str_dll+'''';
  557. R.Assign (2, YB - 13, 64, YB - 11);
  558. P := New (PStaticText, Init (R, S));
  559. Insert (P);
  560. end;
  561. {$ENDIF}
  562. {$ENDIF}
  563. R.Assign(2, YB - 11, 64, YB - 10);
  564. P:=new(pstatictext,init(r,str_to_compile+''''+cfg.pack[1].ppc386+str_file2+''''));
  565. insert(P);
  566. R.Assign (29, YB - 9, 39, YB - 7);
  567. Control := New (PButton, Init (R,str_ok, cmOK, bfDefault));
  568. Insert (Control);
  569. end;
  570. {*****************************************************************************
  571. TInstallDialog
  572. *****************************************************************************}
  573. var
  574. islfn : boolean;
  575. procedure lfnreport( Retcode : longint;Rec : pReportRec );
  576. {$IFDEF TP}
  577. far;
  578. {$ENDIF}
  579. var
  580. p : pathstr;
  581. n : namestr;
  582. e : extstr;
  583. begin
  584. fsplit(strpas(rec^.Filename),p,n,e);
  585. if length(n)>8 then
  586. islfn:=true;
  587. end;
  588. function haslfn(const zipfile,path : string) : boolean;
  589. var
  590. buf : array[0..255] of char;
  591. begin
  592. strpcopy(buf,path+DirSep+zipfile);
  593. islfn:=false;
  594. {$ifdef FPC}
  595. ViewZip(buf,AllFiles,@lfnreport);
  596. {$else FPC}
  597. ViewZip(buf,AllFiles,lfnreport);
  598. {$endif FPC}
  599. haslfn:=islfn;
  600. end;
  601. constructor tlanguagedialog.init;
  602. const
  603. languages = 8;
  604. width = 40;
  605. height = languages+6;
  606. x1 = (79-width) div 2;
  607. y1 = (23-height) div 2;
  608. x2 = x1+width;
  609. y2 = y1+height;
  610. var
  611. r : trect;
  612. okbut : pbutton;
  613. line : longint;
  614. rb : PRadioButtons;
  615. begin
  616. r.assign(x1,y1,x2,y2);
  617. inherited init(r,dialog_language_title);
  618. GetExtent(R);
  619. R.Grow(-2,-1);
  620. line:=r.a.y+1;
  621. r.assign((width div 2)-15,line,(width div 2)+15,line+languages);
  622. New(rb, Init(r,
  623. NewSItem(dialog_language_english,
  624. NewSItem(dialog_language_dutch,
  625. NewSItem(dialog_language_french,
  626. NewSItem(dialog_language_russian,
  627. NewSItem(dialog_language_hungarian,
  628. NewSItem(dialog_language_spanish,
  629. NewSItem(dialog_language_german,
  630. NewSItem(dialog_language_russian_win,
  631. nil))))))))));
  632. insert(rb);
  633. inc(line,languages);
  634. inc(line,1);
  635. r.assign((width div 2)-5,line,(width div 2)+5,line+2);
  636. new(okbut,init(r,str_ok,cmok,bfdefault));
  637. Insert(OkBut);
  638. end;
  639. constructor tinstalldialog.init;
  640. const
  641. width = 76;
  642. height = 20;
  643. x1 = (79-width) div 2;
  644. y1 = (23-height) div 2;
  645. x2 = x1+width;
  646. y2 = y1+height;
  647. var
  648. tabr,tabir,r : trect;
  649. packmask : array[1..maxpacks] of longint;
  650. i,line,j : integer;
  651. items : array[1..maxpacks] of psitem;
  652. f : pview;
  653. found : boolean;
  654. okbut,cancelbut : pbutton;
  655. firstitem : array[1..maxpacks] of integer;
  656. packcbs : array[1..maxpacks] of pcheckboxes;
  657. packtd : ptabdef;
  658. labpath : plabel;
  659. ilpath : pinputline;
  660. tab : ptab;
  661. titletext : pcoloredtext;
  662. labcfg : plabel;
  663. cfgcb : pcheckboxes;
  664. scrollbox: pscrollbox;
  665. sbr,sbsbr: trect;
  666. sbsb: pscrollbar;
  667. begin
  668. f:=nil;
  669. { walk packages reverse and insert a newsitem for each, and set the mask }
  670. for j:=1 to cfg.packs do
  671. with cfg.pack[j] do
  672. begin
  673. firstitem[j]:=0;
  674. items[j]:=nil;
  675. packmask[j]:=0;
  676. for i:=packages downto 1 do
  677. begin
  678. if file_exists(package[i].zip,startpath) then
  679. begin
  680. {$ifdef go32v2}
  681. if not(lfnsupport) then
  682. begin
  683. if not(haslfn(package[i].zip,startpath)) then
  684. begin
  685. items[j]:=newsitem(package[i].name+diskspace(startpath+DirSep+package[i].zip),items[j]);
  686. packmask[j]:=packmask[j] or packagemask(i);
  687. firstitem[j]:=i;
  688. if createlog then
  689. writeln(log,str_checking_lfn,startpath+DirSep+package[i].zip,' ... no lfn');
  690. end
  691. else
  692. begin
  693. items[j]:=newsitem(package[i].name+str_requires_lfn,items[j]);
  694. if createlog then
  695. writeln(log,str_checking_lfn,startpath+DirSep+package[i].zip,' ... uses lfn');
  696. end;
  697. end
  698. else
  699. {$endif go32v2}
  700. begin
  701. items[j]:=newsitem(package[i].name+diskspace(startpath+DirSep+package[i].zip),items[j]);
  702. packmask[j]:=packmask[j] or packagemask(i);
  703. firstitem[j]:=i;
  704. end;
  705. end
  706. else
  707. items[j]:=newsitem(package[i].name,items[j]);
  708. end;
  709. end;
  710. { If no component found abort }
  711. found:=false;
  712. for j:=1 to cfg.packs do
  713. if packmask[j]<>0 then
  714. found:=true;
  715. if not found then
  716. begin
  717. messagebox(msg_no_components_found,nil,mferror+mfokbutton);
  718. errorhalt;
  719. end;
  720. r.assign(x1,y1,x2,y2);
  721. inherited init(r,'');
  722. GetExtent(R);
  723. R.Grow(-2,-1);
  724. Dec(R.B.Y,2);
  725. TabR.Copy(R);
  726. TabIR.Copy(R);
  727. TabIR.Grow(-2,-2);
  728. TabIR.Move(-2,0);
  729. {-------- General Sheets ----------}
  730. R.Copy(TabIR);
  731. r.move(0,1);
  732. r.b.x:=r.a.x+40;
  733. r.b.y:=r.a.y+1;
  734. new(titletext,init(r,cfg.title,$71));
  735. r.move(0,2);
  736. r.b.x:=r.a.x+40;
  737. new(labpath,init(r,dialog_install_basepath,f));
  738. r.move(0,1);
  739. r.b.x:=r.a.x+40;
  740. r.b.y:=r.a.y+1;
  741. new(ilpath,init(r,high(DirStr)));
  742. r.move(0,2);
  743. r.b.x:=r.a.x+40;
  744. new(labcfg,init(r,dialog_install_config,f));
  745. r.move(0,1);
  746. r.b.x:=r.a.x+40;
  747. r.b.y:=r.a.y+1;
  748. new(cfgcb,init(r,newsitem(dialog_install_createppc386cfg,nil)));
  749. data.cfgval:=1;
  750. {-------- Pack Sheets ----------}
  751. for j:=1 to cfg.packs do
  752. begin
  753. R.Copy(TabIR);
  754. if R.A.Y+cfg.pack[j].packages>R.B.Y then
  755. R.B.Y:=R.A.Y+cfg.pack[j].packages;
  756. new(packcbs[j],init(r,items[j]));
  757. if data.packmask[j]=$ffff then
  758. data.packmask[j]:=packmask[j];
  759. packcbs[j]^.enablemask:={$ifdef DEV}$7fffffff{$else}packmask[j]{$endif};
  760. packcbs[j]^.movedto(firstitem[j]);
  761. end;
  762. {--------- Main ---------}
  763. packtd:=nil;
  764. sbr.assign(1,3,tabr.b.x-tabr.a.x-3,tabr.b.y-tabr.a.y-1);
  765. for j:=cfg.packs downto 1 do
  766. begin
  767. if (sbr.b.y-sbr.a.y)<cfg.pack[j].packages then
  768. begin
  769. sbsbr.assign(sbr.b.x,sbr.a.y,sbr.b.x+1,sbr.b.y);
  770. New(sbsb, init(sbsbr));
  771. end
  772. else
  773. sbsb:=nil;
  774. New(ScrollBox, Init(sbr, nil, sbsb));
  775. PackCbs[j]^.MoveTo(0,0);
  776. ScrollBox^.Insert(PackCbs[j]);
  777. packtd:=NewTabDef(
  778. cfg.pack[j].name,ScrollBox,
  779. NewTabItem(sbsb,
  780. NewTabItem(ScrollBox,
  781. nil)),
  782. packtd);
  783. end;
  784. New(Tab, Init(TabR,
  785. NewTabDef(dialog_install_general,IlPath,
  786. NewTabItem(TitleText,
  787. NewTabItem(LabPath,
  788. NewTabItem(ILPath,
  789. NewTabItem(LabCfg,
  790. NewTabItem(CfgCB,
  791. nil))))),
  792. packtd)
  793. ));
  794. Tab^.GrowMode:=0;
  795. Insert(Tab);
  796. line:=tabr.b.y;
  797. r.assign((width div 2)-18,line,(width div 2)-4,line+2);
  798. new(okbut,init(r,str_continue,cmok,bfdefault));
  799. Insert(OkBut);
  800. r.assign((width div 2)+4,line,(width div 2)+14,line+2);
  801. new(cancelbut,init(r,str_quit,cmcancel,bfnormal));
  802. Insert(CancelBut);
  803. Tab^.Select;
  804. end;
  805. {*****************************************************************************
  806. TUnZipDialog
  807. *****************************************************************************}
  808. procedure tapp.do_languagedialog;
  809. var
  810. p : planguagedialog;
  811. langdata : longint;
  812. c : word;
  813. begin
  814. { select components }
  815. new(p,init);
  816. langdata:=0;
  817. c:=executedialog(p,@langdata);
  818. writeln(langdata);
  819. if c=cmok then
  820. begin
  821. case langdata of
  822. 0:
  823. cfg.language:='English';
  824. 1:
  825. begin
  826. cfg.language:='Dutch';
  827. msgfile:='errorn.msg';
  828. end;
  829. 2:
  830. begin
  831. cfg.language:='French';
  832. msgfile:='errorf.msg';
  833. end;
  834. 3:
  835. begin
  836. cfg.language:='Russian';
  837. msgfile:='errorr.msg';
  838. end;
  839. 4:
  840. cfg.language:='Hungarian';
  841. 5:
  842. begin
  843. cfg.language:='Spanish';
  844. msgfile:='errors.msg';
  845. end;
  846. 6:
  847. begin
  848. cfg.language:='German';
  849. msgfile:='errord.msg';
  850. end;
  851. 7:
  852. begin
  853. cfg.language:='RussianWin';
  854. msgfile:='errorrw.msg';
  855. end;
  856. end;
  857. end;
  858. end;
  859. {*****************************************************************************
  860. TApp
  861. *****************************************************************************}
  862. const
  863. cmstart = 1000;
  864. procedure tapp.do_installdialog;
  865. var
  866. p : pinstalldialog;
  867. p3 : penddialog;
  868. r : trect;
  869. result,
  870. c : word;
  871. i,j : longint;
  872. found : boolean;
  873. params : array[0..0] of pointer;
  874. {$ifndef linux}
  875. DSize,Space,ASpace : longint;
  876. S: DirStr;
  877. {$endif}
  878. begin
  879. data.basepath:=cfg.basepath;
  880. data.cfgval:=0;
  881. for j:=1 to cfg.packs do
  882. data.packmask[j]:=$ffff;
  883. repeat
  884. { select components }
  885. p:=new(pinstalldialog,init);
  886. c:=executedialog(p,@data);
  887. if (c=cmok) then
  888. begin
  889. if Data.BasePath = '' then
  890. messagebox(msg_select_dir,nil,mferror+mfokbutton)
  891. else
  892. begin
  893. found:=false;
  894. for j:=1 to cfg.packs do
  895. if data.packmask[j]>0 then
  896. found:=true;
  897. if found then
  898. begin
  899. {$IFNDEF LINUX}
  900. { TH - check the available disk space here }
  901. DSize := 0;
  902. for j:=1 to cfg.packs do
  903. with cfg.pack[j] do
  904. begin
  905. for i:=1 to packages do
  906. begin
  907. if data.packmask[j] and packagemask(i)<>0 then
  908. begin
  909. ASpace := DiskSpaceN (package[i].zip);
  910. if ASpace = -1 then
  911. begin
  912. params[0]:=@package[i].zip;
  913. MessageBox (msg_corrupt_zip,
  914. @params,mferror + mfokbutton);
  915. end
  916. else Inc (DSize, ASpace);
  917. end;
  918. end;
  919. end;
  920. S := FExpand (Data.BasePath);
  921. if S [Length (S)] = DirSep then
  922. Dec (S [0]);
  923. Space := DiskFree (byte (Upcase(S [1])) - 64) shr 10;
  924. if Space < DSize then
  925. S := str_is_not
  926. else
  927. S := '';
  928. if (Space < DSize + 500) then
  929. begin
  930. if S = '' then
  931. S := str_might_not_be;
  932. params[0]:=@s;
  933. if messagebox(msg_space_warning,@params,
  934. mferror+mfyesbutton+mfnobutton) = cmYes then
  935. Continue;
  936. end;
  937. {$ENDIF}
  938. if createinstalldir(data.basepath) then
  939. break;
  940. end
  941. else
  942. begin
  943. { maybe only config }
  944. if (data.cfgval and 1)<>0 then
  945. begin
  946. result:=messagebox(msg_no_components_selected,nil,
  947. mfinformation+mfyesbutton+mfnobutton);
  948. if (result=cmYes) and createinstalldir(data.basepath) then
  949. begin
  950. for i:=1 to cfg.packs do
  951. if cfg.pack[i].defcfgfile<>'' then
  952. writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defcfgfile);
  953. end;
  954. exit;
  955. end
  956. else
  957. begin
  958. result:=messagebox(msg_nocomponents,nil,
  959. mferror+mfyesbutton+mfnobutton);
  960. if result=cmYes then
  961. exit;
  962. end;
  963. end;
  964. end;
  965. end
  966. else
  967. exit;
  968. until false;
  969. { extract packages }
  970. for j:=1 to cfg.packs do
  971. with cfg.pack[j] do
  972. begin
  973. r.assign(10,7,70,18);
  974. UnzDlg:=new(punzipdialog,init(r,dialog_unzipdialog_title));
  975. desktop^.insert(UnzDlg);
  976. for i:=1 to packages do
  977. begin
  978. if data.packmask[j] and packagemask(i)<>0 then
  979. UnzDlg^.do_unzip(package[i].zip,data.basepath);
  980. end;
  981. desktop^.delete(UnzDlg);
  982. dispose(UnzDlg,done);
  983. end;
  984. { write config }
  985. if (data.cfgval and 1)<>0 then
  986. begin
  987. for i:=1 to cfg.packs do
  988. if cfg.pack[i].defcfgfile<>'' then
  989. writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defcfgfile);
  990. end;
  991. { show end message }
  992. p3:=new(penddialog,init);
  993. executedialog(p3,nil);
  994. end;
  995. procedure tapp.readcfg(const fn:string);
  996. var
  997. t : text;
  998. i,j,
  999. line : longint;
  1000. item,
  1001. s : string;
  1002. params : array[0..0] of pointer;
  1003. {$ifndef FPC}
  1004. procedure readln(var t:text;var s:string);
  1005. var
  1006. c : char;
  1007. i : longint;
  1008. begin
  1009. c:=#0;
  1010. i:=0;
  1011. while (not eof(t)) and (c<>#10) do
  1012. begin
  1013. read(t,c);
  1014. if c<>#10 then
  1015. begin
  1016. inc(i);
  1017. s[i]:=c;
  1018. end;
  1019. end;
  1020. if (i>0) and (s[i]=#13) then
  1021. dec(i);
  1022. s[0]:=chr(i);
  1023. end;
  1024. {$endif}
  1025. begin
  1026. assign(t,StartPath + DirSep + fn);
  1027. {$I-}
  1028. reset(t);
  1029. {$I+}
  1030. if ioresult<>0 then
  1031. begin
  1032. StartPath := GetProgDir;
  1033. assign(t,StartPath + DirSep + fn);
  1034. {$I-}
  1035. reset(t);
  1036. {$I+}
  1037. if ioresult<>0 then
  1038. begin
  1039. params[0]:=@fn;
  1040. messagebox(msg_file_not_found,@params,mferror+mfokbutton);
  1041. errorhalt;
  1042. end;
  1043. end;
  1044. line:=0;
  1045. while not eof(t) do
  1046. begin
  1047. readln(t,s);
  1048. inc(line);
  1049. if (s<>'') and not(s[1] in ['#',';']) then
  1050. begin
  1051. i:=pos('=',s);
  1052. if i>0 then
  1053. begin
  1054. item:=upper(Copy(s,1,i-1));
  1055. system.delete(s,1,i);
  1056. if item='VERSION' then
  1057. cfg.version:=s
  1058. else
  1059. if item='TITLE' then
  1060. cfg.title:=s
  1061. else
  1062. if item='LANGUAGE' then
  1063. cfg.language:=s
  1064. else
  1065. if item='BASEPATH' then
  1066. cfg.basepath:=s
  1067. else
  1068. if item='DEFAULTCFG' then
  1069. begin
  1070. repeat
  1071. readln(t,s);
  1072. if upper(s)='ENDCFG' then
  1073. break;
  1074. if cfg.defcfgs<maxdefcfgs then
  1075. begin
  1076. inc(cfg.defcfgs);
  1077. cfg.defcfg[cfg.defcfgs]:=newstr(s);
  1078. end;
  1079. until false;
  1080. end
  1081. else
  1082. if item='PACK' then
  1083. begin
  1084. inc(cfg.packs);
  1085. if cfg.packs>maxpacks then
  1086. begin
  1087. writeln('Too much packs');
  1088. halt(1);
  1089. end;
  1090. cfg.pack[cfg.packs].name:=s;
  1091. end
  1092. else
  1093. if item='CFGFILE' then
  1094. begin
  1095. if cfg.packs=0 then
  1096. begin
  1097. writeln('No pack set');
  1098. halt(1);
  1099. end;
  1100. cfg.pack[cfg.packs].defcfgfile:=s
  1101. end
  1102. else
  1103. if item='PPC386' then
  1104. begin
  1105. if cfg.packs=0 then
  1106. begin
  1107. writeln('No pack set');
  1108. halt(1);
  1109. end;
  1110. cfg.pack[cfg.packs].ppc386:=s;
  1111. end
  1112. else
  1113. if item='BINSUB' then
  1114. begin
  1115. if cfg.packs=0 then
  1116. begin
  1117. writeln('No pack set');
  1118. halt(1);
  1119. end;
  1120. cfg.pack[cfg.packs].binsub:=s;
  1121. end
  1122. else
  1123. if item='FILECHECK' then
  1124. begin
  1125. if cfg.packs=0 then
  1126. begin
  1127. writeln('No pack set');
  1128. halt(1);
  1129. end;
  1130. cfg.pack[cfg.packs].filechk:=s;
  1131. end
  1132. else
  1133. if item='PACKAGE' then
  1134. begin
  1135. if cfg.packs=0 then
  1136. begin
  1137. writeln('No pack set');
  1138. halt(1);
  1139. end;
  1140. with cfg.pack[cfg.packs] do
  1141. begin
  1142. j:=pos(',',s);
  1143. if (j>0) and (packages<maxpackages) then
  1144. begin
  1145. inc(packages);
  1146. package[packages].zip:=copy(s,1,j-1);
  1147. package[packages].name:=copy(s,j+1,255);
  1148. end;
  1149. end;
  1150. end
  1151. end;
  1152. end;
  1153. end;
  1154. close(t);
  1155. end;
  1156. procedure tapp.checkavailpack;
  1157. var
  1158. j : longint;
  1159. dir : searchrec;
  1160. begin
  1161. { check the packages }
  1162. j:=0;
  1163. while (j<cfg.packs) do
  1164. begin
  1165. inc(j);
  1166. if cfg.pack[j].filechk<>'' then
  1167. begin
  1168. findfirst(cfg.pack[j].filechk,$20,dir);
  1169. if doserror<>0 then
  1170. begin
  1171. { remove the package }
  1172. move(cfg.pack[j+1],cfg.pack[j],sizeof(tpack)*(cfg.packs-j));
  1173. dec(cfg.packs);
  1174. dec(j);
  1175. end;
  1176. {$IFNDEF TP}
  1177. findclose(dir);
  1178. {$ENDIF}
  1179. end;
  1180. end;
  1181. end;
  1182. procedure tapp.initmenubar;
  1183. var
  1184. r : trect;
  1185. begin
  1186. getextent(r);
  1187. r.b.y:=r.a.y+1;
  1188. menubar:=new(pmenubar,init(r,newmenu(
  1189. newsubmenu(menu_install,hcnocontext,newmenu(nil
  1190. ),
  1191. nil))));
  1192. end;
  1193. procedure tapp.handleevent(var event : tevent);
  1194. begin
  1195. inherited handleevent(event);
  1196. if event.what=evcommand then
  1197. if event.command=cmstart then
  1198. begin
  1199. clearevent(event);
  1200. do_installdialog;
  1201. if successfull then
  1202. begin
  1203. event.what:=evcommand;
  1204. event.command:=cmquit;
  1205. handleevent(event);
  1206. end;
  1207. end;
  1208. end;
  1209. {$IFDEF DOSSTUB}
  1210. function CheckOS2: boolean;
  1211. var
  1212. OwnName: PathStr;
  1213. OwnDir: DirStr;
  1214. Name: NameStr;
  1215. Ext: ExtStr;
  1216. DosV, W: word;
  1217. P: PChar;
  1218. const
  1219. Title: string [15] = 'FPC Installer'#0;
  1220. RunBlock: TRunBlock = (Length: $32;
  1221. Dependent: 0;
  1222. Background: 0;
  1223. TraceLevel: 0;
  1224. PrgTitle: @Title [1];
  1225. PrgName: nil;
  1226. Args: nil;
  1227. TermQ: 0;
  1228. Environment: nil;
  1229. Inheritance: 0;
  1230. SesType: 2;
  1231. Icon: nil;
  1232. PgmHandle: 0;
  1233. PgmControl: 2;
  1234. Column: 0;
  1235. Row: 0;
  1236. Width: 80;
  1237. Height: 25);
  1238. begin
  1239. CheckOS2 := false;
  1240. asm
  1241. mov ah, 30h
  1242. int 21h
  1243. xchg ah, al
  1244. mov DosV, ax
  1245. mov ax, 4010h
  1246. int 2Fh
  1247. cmp ax, 4010h
  1248. jnz @0
  1249. xor bx, bx
  1250. @0:
  1251. mov W, bx
  1252. end;
  1253. if DosV > 3 shl 8 then
  1254. begin
  1255. OwnName := FExpand (ParamStr (0));
  1256. FSplit (OwnName, OwnDir, Name, Ext);
  1257. if (DosV >= 20 shl 8 + 10) and (W >= 20 shl 8 + 10) then
  1258. (* OS/2 version 2.1 or later running (double-checked) *)
  1259. begin
  1260. OwnName [Succ (byte (OwnName [0]))] := #0;
  1261. RunBlock.PrgName := @OwnName [1];
  1262. P := Ptr (PrefixSeg, $80);
  1263. if PByte (P)^ <> 0 then
  1264. begin
  1265. Inc (P);
  1266. RunBlock.Args := Ptr (PrefixSeg, $81);
  1267. end;
  1268. asm
  1269. mov ax, 6400h
  1270. mov bx, 0025h
  1271. mov cx, 636Ch
  1272. mov si, offset RunBlock
  1273. int 21h
  1274. jc @0
  1275. mov DosV, 0
  1276. @0:
  1277. end;
  1278. CheckOS2 := DosV = 0;
  1279. end;
  1280. end;
  1281. end;
  1282. {$ENDIF}
  1283. var
  1284. i : longint;
  1285. begin
  1286. {$ifdef FPC}
  1287. {$ifdef win32}
  1288. Dos.Exec(GetEnv('COMSPEC'),'/C echo This dummy call gets the mouse to become visible');
  1289. {$endif win32}
  1290. {$endif FPC}
  1291. (* TH - no error boxes if checking an inaccessible disk etc. *)
  1292. {$IFDEF OS2}
  1293. {$IFDEF FPC}
  1294. DosCalls.DosError (0);
  1295. {$ELSE FPC}
  1296. {$IFDEF VirtualPascal}
  1297. OS2Base.DosError (ferr_DisableHardErr);
  1298. {$ELSE VirtualPascal}
  1299. BseDos.DosError (0);
  1300. {$ENDIF VirtualPascal}
  1301. {$ENDIF FPC}
  1302. {$ENDIF}
  1303. {$IFDEF DOSSTUB}
  1304. if CheckOS2 then Halt;
  1305. {$ENDIF}
  1306. createlog:=false;
  1307. for i:=1 to paramcount do
  1308. begin
  1309. if paramstr(i)='-l' then
  1310. createlog:=true
  1311. else if paramstr(i)='-h' then
  1312. begin
  1313. writeln('FPC Installer Copyright (c) 1993-2000 Florian Klaempfl');
  1314. writeln('Command line options:');
  1315. writeln(' -l create log file');
  1316. writeln;
  1317. writeln(' -h displays this help');
  1318. halt(0);
  1319. end
  1320. else
  1321. begin
  1322. writeln('Illegal command line parameter: ',paramstr(i));
  1323. halt(1);
  1324. end;
  1325. end;
  1326. if createlog then
  1327. begin
  1328. assign(log,'install.log');
  1329. rewrite(log);
  1330. if not(lfnsupport) then
  1331. writeln(log,'OS doesn''t have LFN support');
  1332. end;
  1333. getdir(0,startpath);
  1334. successfull:=false;
  1335. fillchar(cfg, SizeOf(cfg), 0);
  1336. fillchar(data, SizeOf(data), 0);
  1337. { set a default language }
  1338. cfg.language:='English';
  1339. { don't use a message file by default }
  1340. msgfile:='';
  1341. installapp.init;
  1342. FSplit (FExpand (ParamStr (0)), DStr, CfgName, EStr);
  1343. installapp.readcfg(CfgName + CfgExt);
  1344. installapp.checkavailpack;
  1345. installapp.do_languagedialog;
  1346. { installapp.readcfg(startpath+dirsep+cfgfile);}
  1347. if not(lfnsupport) then
  1348. MessageBox(msg_no_lfn,nil,mfinformation or mfokbutton);
  1349. installapp.do_installdialog;
  1350. installapp.done;
  1351. if createlog then
  1352. close(log);
  1353. end.
  1354. {
  1355. $Log$
  1356. Revision 1.9 2000-10-08 18:43:17 hajny
  1357. * the language dialog repaired
  1358. Revision 1.8 2000/09/24 10:52:36 peter
  1359. * smaller window
  1360. Revision 1.7 2000/09/22 23:13:37 pierre
  1361. * add emulation for go32v2 and display currently extraced file
  1362. and changes by Gabor for scrolling support (merged)
  1363. Revision 1.6 2000/09/22 12:15:49 florian
  1364. + support of Russian (Windows)
  1365. Revision 1.5 2000/09/22 11:07:51 florian
  1366. + all language dependend strings are now resource strings
  1367. + the -Fr switch is now set in the ppc386.cfg
  1368. Revision 1.4 2000/09/21 22:09:23 florian
  1369. + start of multilanguage support
  1370. Revision 1.3 2000/09/17 14:44:12 hajny
  1371. * compilable with TP again
  1372. Revision 1.2 2000/07/21 10:43:01 florian
  1373. + added for lfn support
  1374. Revision 1.1 2000/07/13 06:30:21 michael
  1375. + Initial import
  1376. }