install.pas 55 KB

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