{ $Id$ This file is part of Free Pascal Copyright (c) 1993-2000 by Florian Klaempfl member of the Free Pascal development team This is the install program for Free Pascal See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} program install; {$DEFINE FV} (* TH - added to make use of the original Turbo Vision possible. *) { $DEFINE DLL} (* TH - if defined, UNZIP32.DLL library is used to unpack. *) { $DEFINE DOSSTUB} (* TH - should _not_ be defined unless creating a bound DOS and OS/2 installer!!! *) (* Defining DOSSTUB causes adding a small piece of code *) (* for starting the OS/2 part from the DOS part of a bound *) (* application if running in OS/2 VDM (DOS) window. Used *) (* only if compiling with TP/BP (see conditionals below). *) {$IFDEF VER60} {$DEFINE TP} {$ENDIF} {$IFDEF VER70} {$DEFINE TP} {$ENDIF} {$IFNDEF TP} {$UNDEF DOSSTUB} {$ELSE} {$IFDEF OS2} {$UNDEF DOSSTUB} {$ENDIF} {$ENDIF} {$IFDEF DPMI} {$UNDEF DOSSTUB} {$ENDIF} uses {$IFDEF OS2} {$IFDEF FPC} DosCalls, {$ELSE FPC} {$IFDEF VirtualPascal} OS2Base, {$ELSE VirtualPascal} BseDos, {$ENDIF VirtualPascal} {$ENDIF FPC} {$ENDIF OS2} {$IFDEF GO32V2} emu387, {$ENDIF} {$ifdef HEAPTRC} heaptrc, {$endif HEAPTRC} strings,dos,objects,drivers, {$IFDEF FV} commands, {$ENDIF} {$IFDEF DLL} unzipdll, {$ENDIF} unzip,ziptypes, app,dialogs,views,menus,msgbox,colortxt,tabs,inststr,scroll, HelpCtx,WHTMLScn; const installerversion='1.0.2'; {$ifdef TP}lfnsupport=false;{$endif} maxpacks=10; maxpackages=20; maxdefcfgs=1024; HTMLIndexExt = '.htx'; CfgExt = '.dat'; MaxStatusPos = 4; StatusChars: string [MaxStatusPos] = '/-\|'; StatusPos: byte = 1; { this variable is set to true if an ide is installed } haside : boolean = false; hashtmlhelp : boolean = false; {$IFDEF LINUX} DirSep='/'; {$ELSE} {$IFDEF UNIX} DirSep='/'; {$ELSE} DirSep='\'; {$ENDIF} {$ENDIF} {$IFNDEF GO32V2} {$IFDEF GO32V1} LFNSupport = false; {$ELSE} {$IFDEF TP} LFNSupport = false; {$ELSE} LFNSupport = true; {$ENDIF} {$ENDIF} {$ENDIF} type tpackage=record name : string[60]; zip : string[12]; end; tpack=record name : string[12]; binsub : string[40]; ppc386 : string[20]; defidecfgfile, defideinifile, defcfgfile : string[12]; include : boolean; filechk : string[40]; packages : longint; package : array[1..maxpackages] of tpackage; end; tcfgarray = array[1..maxdefcfgs] of pstring; cfgrec=record title : string[80]; version : string[20]; language : string[30]; helpidx, docsub, basepath : DirStr; packs : word; pack : array[1..maxpacks] of tpack; defideinis, defidecfgs, defcfgs : longint; defideini, defidecfg, defcfg : tcfgarray; end; datarec=packed record basepath : DirStr; cfgval : word; packmask : array[1..maxpacks] of word; end; punzipdialog=^tunzipdialog; tunzipdialog=object(tdialog) filetext : pstatictext; extractfiletext : pstatictext; constructor Init(var Bounds: TRect; ATitle: TTitleStr); procedure do_unzip(s,topath:string); end; penddialog = ^tenddialog; tenddialog = object(tdialog) constructor init; end; pinstalldialog = ^tinstalldialog; tinstalldialog = object(tdialog) constructor init; end; planguagedialog = ^tlanguagedialog; tlanguagedialog = object(tdialog) constructor init; end; PFPHTMLFileLinkScanner = ^TFPHTMLFileLinkScanner; TFPHTMLFileLinkScanner = object(THTMLFileLinkScanner) function CheckURL(const URL: string): boolean; virtual; function CheckText(const Text: string): boolean; virtual; procedure ProcessDoc(Doc: PHTMLLinkScanFile); virtual; end; phtmlindexdialog = ^thtmlindexdialog; thtmlindexdialog = object(tdialog) text : pstatictext; constructor init(var Bounds: TRect; ATitle: TTitleStr); end; tapp = object(tapplication) procedure initmenubar;virtual; procedure handleevent(var event : tevent);virtual; procedure do_installdialog; procedure do_languagedialog; procedure readcfg(const fn:string); procedure checkavailpack; end; {$IFDEF DOSSTUB} PByte = ^byte; PRunBlock = ^TRunBlock; TRunBlock = record Length: word; Dependent: word; Background: word; TraceLevel: word; PrgTitle: PChar; PrgName: PChar; Args: PChar; TermQ: longint; Environment: pointer; Inheritance: word; SesType: word; Icon: pointer; PgmHandle: longint; PgmControl: word; Column: word; Row: word; Width: word; Height: word; end; {$ENDIF} var installapp : tapp; startpath : string; successfull : boolean; cfg : cfgrec; data : datarec; CfgName: NameStr; DStr: DirStr; EStr: ExtStr; UnzDlg : punzipdialog; log : text; createlog : boolean; msgfile : string; {$IFNDEF DLL} const UnzipErr: longint = 0; {$ENDIF} {***************************************************************************** Helpers *****************************************************************************} procedure errorhalt; begin installapp.done; halt(1); end; function packagemask(i:longint):longint; begin packagemask:=1 shl (i-1); end; function upper(const s : string):string; var i : integer; begin for i:=1 to length(s) do if s[i] in ['a'..'z'] then upper[i]:=chr(ord(s[i])-32) else upper[i]:=s[i]; upper[0]:=s[0]; end; function Replace(var s:string;const s1,s2:string) : boolean; var i : longint; begin Replace:=false; repeat i:=pos(s1,s); if i>0 then begin Delete(s,i,length(s1)); Insert(s2,s,i); Replace:=true; end; until i=0; end; function file_exists(const f : string;const path : string) : boolean; begin file_exists:=fsearch(f,path)<>''; end; function createdir(s:string):boolean; var s1,start : string; err : boolean; i : longint; begin err:=false; {$I-} getdir(0,start); {$ifndef linux} if (s[2]=':') and (s[3]=DirSep) then begin chdir(Copy(s,1,3)); Delete(S,1,3); end; {$endif} repeat i:=Pos(DirSep,s); if i=0 then i:=255; s1:=Copy(s,1,i-1); Delete(s,1,i); ChDir(s1); if ioresult<>0 then begin mkdir(s1); chdir(s1); if ioresult<>0 then begin err:=true; break; end; end; until s=''; chdir(start); {$I+} createdir:=err; end; function DiskSpaceN(const zipfile : string) : longint; var compressed,uncompressed : longint; s : string; begin s:=zipfile+#0; if not (IsZip (@S [1])) then DiskSpaceN := -1 else begin Uncompressed:=UnzipSize(@s[1],compressed); DiskSpaceN:=uncompressed shr 10; end; end; function diskspace(const zipfile : string) : string; var uncompressed : longint; s : string; begin uncompressed:=DiskSpaceN (zipfile); if Uncompressed = -1 then DiskSpace := str_invalid else begin str(uncompressed,s); diskspace:=' ('+s+' KB)'; end; end; function createinstalldir(s : string) : boolean; var err : boolean; dir : searchrec; params : array[0..0] of pointer; begin if s[length(s)]=DirSep then dec(s[0]); FindFirst(s,AnyFile,dir); if doserror=0 then begin if Dir.Attr and Directory = 0 then begin messagebox(msg_problems_create_dir,nil, mferror+mfokbutton); createinstalldir:=false; end else createinstalldir:=messagebox(msg_install_dir_exists,nil, mferror+mfyesbutton+mfnobutton)=cmYes; exit; end; err:=Createdir(s); if err then begin params[0]:=@s; messagebox(msg_install_cant_be_created, @params,mferror+mfokbutton); createinstalldir:=false; exit; end; {$ifndef TP} {$IFNDEF OS2} FindClose (dir); {$ENDIF} {$endif} createinstalldir:=true; end; function GetProgDir: DirStr; var D: DirStr; N: NameStr; E: ExtStr; begin FSplit (FExpand (ParamStr (0)), D, N, E); if (D [0] <> #0) and (D [byte (D [0])] = '\') then Dec (D [0]); GetProgDir := D; end; function RTrim(const S: string): string; var i : longint; begin i:=length(s); while (i>0) and (s[i]=' ') do dec(i); RTrim:=Copy(s,1,i); end; function LTrim(const S: string): string; var i : longint; begin i:=1; while (iS2 then R:= 1 else R:=0; CompareText:=R; end; function ExtOf(const S: string): string; var D: DirStr; E: ExtStr; N: NameStr; begin FSplit(S,D,N,E); ExtOf:=E; end; function DirAndNameOf(const S: string): string; var D: DirStr; E: ExtStr; N: NameStr; begin FSplit(S,D,N,E); DirAndNameOf:=D+N; end; {***************************************************************************** HTML-Index Generation *****************************************************************************} var indexdlg : phtmlindexdialog; constructor thtmlindexdialog.Init(var Bounds: TRect; ATitle: TTitleStr); var r : trect; begin inherited init(bounds,atitle); R.Assign (4, 2,bounds.B.X-Bounds.A.X-2, 4); text:=new(pstatictext,init(r,'Please wait ...')); insert(text); end; procedure TFPHTMLFileLinkScanner.ProcessDoc(Doc: PHTMLLinkScanFile); var oldtext : pstring; begin oldtext:=indexdlg^.text^.text; indexdlg^.text^.text:=newstr('Processing '+Doc^.GetDocumentURL); indexdlg^.text^.drawview; inherited ProcessDoc(Doc); disposestr(indexdlg^.text^.text); indexdlg^.text^.text:=oldtext; indexdlg^.text^.drawview; end; function TFPHTMLFileLinkScanner.CheckURL(const URL: string): boolean; var OK: boolean; const HTTPPrefix = 'http:'; FTPPrefix = 'ftp:'; begin OK:=inherited CheckURL(URL); if OK then OK:=DirAndNameOf(URL)<>''; if OK then OK:=CompareText(copy(ExtOf(URL),1,4),'.HTM')=0; if OK then OK:=CompareText(copy(URL,1,length(HTTPPrefix)),HTTPPrefix)<>0; if OK then OK:=CompareText(copy(URL,1,length(FTPPrefix)),FTPPrefix)<>0; CheckURL:=OK; end; function TFPHTMLFileLinkScanner.CheckText(const Text: string): boolean; var OK: boolean; S: string; begin S:=Trim(Text); OK:=(S<>'') and (copy(S,1,1)<>'['); CheckText:=OK; end; procedure writehlpindex(filename : string); var LS : PFPHTMLFileLinkScanner; BS : PBufStream; S : String; Re : Word; params : array[0..0] of pointer; dir : searchrec; r : trect; begin S:='HTML Index'; r.assign(10,10,70,15); indexdlg:=new(phtmlindexdialog,init(r,'Creating HTML index file, please wait ...')); desktop^.insert(indexdlg); New(LS, Init); LS^.ProcessDocument(FileName,[soSubDocsOnly]); if LS^.GetDocumentCount=0 then begin params[0]:=@filename; MessageBox('Problem creating help index %1, aborting',@params, mferror+mfokbutton); end else begin FileName:=DirAndNameOf(FileName)+HTMLIndexExt; findfirst(filename,AnyFile,dir); if doserror=0 then begin params[0]:=@filename; Re:=MessageBox('Help index %s already exists, overwrite it?',@params, mfinformation+mfyesbutton+mfnobutton); end; if Re<>cmNo then begin New(BS, Init(FileName, stCreate, 4096)); if Assigned(BS)=false then begin MessageBox('Error while writing help index! '+ 'No help index is created',@params, mferror+mfokbutton); Re:=cmCancel; end else begin LS^.StoreDocuments(BS^); if BS^.Status<>stOK then begin MessageBox('Error while writing help index!'#13+ 'No help index is created',@params, mferror+mfokbutton); Re:=cmCancel; end; Dispose(BS, Done); end; end; end; Dispose(LS, Done); desktop^.delete(indexdlg); dispose(indexdlg,done); end; {***************************************************************************** Writing of ppc386.cfg *****************************************************************************} procedure writedefcfg(const fn:string;const cfgdata : tcfgarray;count : longint); var t : text; i : longint; s : string; dir : searchrec; params : array[0..0] of pointer; d : dirstr; n : namestr; e : extstr; begin { already exists } findfirst(fn,AnyFile,dir); if doserror=0 then begin params[0]:=@fn; if MessageBox(msg_overwrite_cfg,@params, mfinformation+mfyesbutton+mfnobutton)=cmNo then exit; end; { create directory } fsplit(fn,d,n,e); createdir(d); { create the ppc386.cfg } assign(t,fn); {$I-} rewrite(t); {$I+} if ioresult<>0 then begin params[0]:=@fn; MessageBox(msg_problems_writing_cfg,@params,mfinformation+mfokbutton); exit; end; for i:=1 to count do if assigned(cfgdata[i]) then begin s:=cfgdata[i]^; Replace(s,'$1',data.basepath); { error msg file entry? } if Replace(s,'$L',msgfile) then begin { if we've to set an error msg file, we } { write it else we discard the line } if msgfile<>'' then writeln(t,s); end else writeln(t,s); end else writeln(t,''); close(t); end; {***************************************************************************** TUnZipDialog *****************************************************************************} constructor tunzipdialog.Init(var Bounds: TRect; ATitle: TTitleStr); var r : trect; begin inherited init(bounds,atitle); (* R.Assign (11, 4, 38, 6);*) R.Assign (1, 4,bounds.B.X-Bounds.A.X-2, 6); filetext:=new(pstatictext,init(r,#3'File: ')); insert(filetext); R.Assign (1, 7,bounds.B.X-Bounds.A.X-2, 9); extractfiletext:=new(pstatictext,init(r,#3' ')); insert(extractfiletext); end; {$IFNDEF DLL} procedure UnzipCheckFn (Retcode: longint; Rec: pReportRec );{$ifdef Delphi32}STDCALL;{$endif} {$IFNDEF BIT32} FAR;{$ENDIF BIT32} var name : string; begin case Rec^.Status of unzip_starting: UnzipErr := 0; file_starting: begin with UnzDlg^.extractfiletext^ do begin Disposestr(text); name:=Strpas(Rec^.FileName); Text:=NewStr(#3+name); DrawView; end; end; file_failure: UnzipErr := RetCode; file_unzipping: begin with UnzDlg^.FileText^ do begin Inc (StatusPos); if StatusPos > MaxStatusPos then StatusPos := 1; Text^ [Length (Text^)] := StatusChars [StatusPos]; DrawView; end; end; end; end; {$ENDIF} procedure tunzipdialog.do_unzip(s,topath : string); var again : boolean; fn,dir,wild : string; Cnt: integer; params : array[0..0] of pointer; begin Disposestr(filetext^.text); filetext^.Text:=NewStr(#3+str_file+s+ #13#3' '); filetext^.drawview; if not(file_exists(s,startpath)) then begin params[0]:=@s; messagebox(msg_file_missing,@params,mferror+mfokbutton); errorhalt; end; {$IFNDEF DLL} {$IFDEF FPC} SetUnzipReportProc (@UnzipCheckFn); {$ELSE FPC} SetUnzipReportProc (UnzipCheckFn); {$ENDIF FPC} {$ENDIF DLL} repeat fn:=startpath+DirSep+s+#0; dir:=topath+#0; wild:=AllFiles + #0; again:=false; FileUnzipEx(@fn[1],@dir[1],@wild[1]); if (UnzipErr <> 0) then begin Str(UnzipErr,s); params[0]:=@s; if messagebox(msg_extraction_error,@params,mferror+mfyesbutton+mfnobutton)=cmNo then errorhalt else again:=true; end; until not again; end; {***************************************************************************** TEndDialog *****************************************************************************} constructor tenddialog.init; var R : TRect; P : PStaticText; Control : PButton; YB: word; {$IFNDEF LINUX} i : longint; S: string; WPath: boolean; {$ENDIF} {$IFDEF OS2} ErrPath: array [0..259] of char; Handle: longint; WLibPath: boolean; const EMXName: array [1..4] of char = 'EMX'#0; {$ENDIF} begin if haside then YB := 15 else YB := 14; {$IFNDEF LINUX} s:=''; for i:=1 to cfg.packs do if cfg.pack[i].binsub<>'' then begin if s<>'' then s:=s+';'; S := s+Data.BasePath + Cfg.pack[i].BinSub; end; if Pos (Upper (S), Upper (GetEnv ('PATH'))) = 0 then begin WPath := true; Inc (YB, 2); end else WPath := false; {$IFDEF OS2} if DosLoadModule (@ErrPath, SizeOf (ErrPath), @EMXName, Handle) = 0 then begin WLibPath := false; DosFreeModule (Handle); end else begin WLibPath := true; Inc (YB, 2); end; {$ENDIF} {$ENDIF} R.Assign(6, 6, 74, YB); inherited init(r,dialog_enddialog_title); {$IFNDEF LINUX} if WPath then begin R.Assign(2, 3, 64, 5); P:=new(pstatictext,init(r,str_extend_path+''''+S+'''')); insert(P); end; {$IFDEF OS2} if WLibPath then begin if WPath then S := str_libpath+'''' + S + '\'+str_dll+'''' else S := str_extend_libpath+'''' + S + '\'+str_dll+''''; R.Assign (2, YB - 14, 64, YB - 12); P := New (PStaticText, Init (R, S)); Insert (P); end; {$ENDIF} {$ENDIF} R.Assign(2, YB - 13, 64, YB - 12); P:=new(pstatictext,init(r,str_to_compile+''''+cfg.pack[1].ppc386+str_file2+'''')); insert(P); if haside then begin R.Assign(2, YB - 12, 64, YB - 10); P:=new(pstatictext,init(r,str_start_ide)); insert(P); end; R.Assign (29, YB - 9, 39, YB - 7); Control := New (PButton, Init (R,str_ok, cmOK, bfDefault)); Insert (Control); end; {***************************************************************************** TInstallDialog *****************************************************************************} var islfn : boolean; procedure lfnreport( Retcode : longint;Rec : pReportRec ); {$IFDEF TP} far; {$ENDIF} var p : pathstr; n : namestr; e : extstr; begin fsplit(strpas(rec^.Filename),p,n,e); if length(n)>8 then islfn:=true; end; function haslfn(const zipfile,path : string) : boolean; var buf : array[0..255] of char; begin strpcopy(buf,path+DirSep+zipfile); islfn:=false; {$ifdef FPC} ViewZip(buf,AllFiles,@lfnreport); {$else FPC} ViewZip(buf,AllFiles,lfnreport); {$endif FPC} haslfn:=islfn; end; constructor tlanguagedialog.init; const languages = 8; width = 40; height = languages+6; x1 = (79-width) div 2; y1 = (23-height) div 2; x2 = x1+width; y2 = y1+height; var r : trect; okbut : pbutton; line : longint; rb : PRadioButtons; begin r.assign(x1,y1,x2,y2); inherited init(r,dialog_language_title); GetExtent(R); R.Grow(-2,-1); line:=r.a.y+1; r.assign((width div 2)-15,line,(width div 2)+15,line+languages); New(rb, Init(r, NewSItem(dialog_language_english, NewSItem(dialog_language_dutch, NewSItem(dialog_language_french, NewSItem(dialog_language_russian, NewSItem(dialog_language_hungarian, NewSItem(dialog_language_spanish, NewSItem(dialog_language_german, NewSItem(dialog_language_russian_win, nil)))))))))); insert(rb); inc(line,languages); inc(line,1); r.assign((width div 2)-5,line,(width div 2)+5,line+2); new(okbut,init(r,str_ok,cmok,bfdefault)); Insert(OkBut); end; constructor tinstalldialog.init; const width = 76; height = 20; x1 = (79-width) div 2; y1 = (23-height) div 2; x2 = x1+width; y2 = y1+height; var tabr,tabir,r : trect; packmask : array[1..maxpacks] of longint; i,line,j : integer; items : array[1..maxpacks] of psitem; f : pview; found : boolean; okbut,cancelbut : pbutton; firstitem : array[1..maxpacks] of integer; packcbs : array[1..maxpacks] of pcheckboxes; packtd : ptabdef; labpath : plabel; ilpath : pinputline; tab : ptab; titletext : pcoloredtext; labcfg : plabel; cfgcb : pcheckboxes; scrollbox: pscrollbox; sbr,sbsbr: trect; sbsb: pscrollbar; begin f:=nil; { walk packages reverse and insert a newsitem for each, and set the mask } for j:=1 to cfg.packs do with cfg.pack[j] do begin firstitem[j]:=0; items[j]:=nil; packmask[j]:=0; for i:=packages downto 1 do begin if file_exists(package[i].zip,startpath) then begin {$ifdef go32v2} if not(lfnsupport) then begin if not(haslfn(package[i].zip,startpath)) then begin items[j]:=newsitem(package[i].name+diskspace(startpath+DirSep+package[i].zip),items[j]); packmask[j]:=packmask[j] or packagemask(i); firstitem[j]:=i; if createlog then writeln(log,str_checking_lfn,startpath+DirSep+package[i].zip,' ... no lfn'); end else begin items[j]:=newsitem(package[i].name+str_requires_lfn,items[j]); if createlog then writeln(log,str_checking_lfn,startpath+DirSep+package[i].zip,' ... uses lfn'); end; end else {$endif go32v2} begin items[j]:=newsitem(package[i].name+diskspace(startpath+DirSep+package[i].zip),items[j]); packmask[j]:=packmask[j] or packagemask(i); firstitem[j]:=i; end; end else items[j]:=newsitem(package[i].name,items[j]); end; end; { If no component found abort } found:=false; for j:=1 to cfg.packs do if packmask[j]<>0 then found:=true; if not found then begin messagebox(msg_no_components_found,nil,mferror+mfokbutton); errorhalt; end; r.assign(x1,y1,x2,y2); inherited init(r,''); GetExtent(R); R.Grow(-2,-1); Dec(R.B.Y,2); TabR.Copy(R); TabIR.Copy(R); TabIR.Grow(-2,-2); TabIR.Move(-2,0); {-------- General Sheets ----------} R.Copy(TabIR); r.move(0,1); r.b.x:=r.a.x+40; r.b.y:=r.a.y+1; new(titletext,init(r,cfg.title,$71)); r.move(0,2); r.b.x:=r.a.x+40; new(labpath,init(r,dialog_install_basepath,f)); r.move(0,1); r.b.x:=r.a.x+40; r.b.y:=r.a.y+1; new(ilpath,init(r,high(DirStr))); r.move(0,2); r.b.x:=r.a.x+40; new(labcfg,init(r,dialog_install_config,f)); r.move(0,1); r.b.x:=r.a.x+40; r.b.y:=r.a.y+1; new(cfgcb,init(r,newsitem(dialog_install_createppc386cfg,nil))); data.cfgval:=1; {-------- Pack Sheets ----------} for j:=1 to cfg.packs do begin R.Copy(TabIR); if R.A.Y+cfg.pack[j].packages>R.B.Y then R.B.Y:=R.A.Y+cfg.pack[j].packages; new(packcbs[j],init(r,items[j])); if data.packmask[j]=$ffff then data.packmask[j]:=packmask[j]; packcbs[j]^.enablemask:={$ifdef DEV}$7fffffff{$else}packmask[j]{$endif}; packcbs[j]^.movedto(firstitem[j]); end; {--------- Main ---------} packtd:=nil; sbr.assign(1,3,tabr.b.x-tabr.a.x-3,tabr.b.y-tabr.a.y-1); for j:=cfg.packs downto 1 do begin if (sbr.b.y-sbr.a.y)'' then writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defcfgfile,cfg.defcfg,cfg.defcfgs); if haside then begin for i:=1 to cfg.packs do if cfg.pack[i].defidecfgfile<>'' then writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defidecfgfile,cfg.defidecfg,cfg.defidecfgs); for i:=1 to cfg.packs do if cfg.pack[i].defideinifile<>'' then writedefcfg(data.basepath+cfg.pack[i].binsub+DirSep+cfg.pack[i].defideinifile,cfg.defideini,cfg.defideinis); if hashtmlhelp then writehlpindex(data.basepath+DirSep+cfg.DocSub+DirSep+cfg.helpidx); end; end; begin data.basepath:=cfg.basepath; data.cfgval:=0; for j:=1 to cfg.packs do data.packmask[j]:=$ffff; repeat { select components } p:=new(pinstalldialog,init); c:=executedialog(p,@data); if (c=cmok) then begin if Data.BasePath = '' then messagebox(msg_select_dir,nil,mferror+mfokbutton) else begin found:=false; for j:=1 to cfg.packs do if data.packmask[j]>0 then found:=true; if found then begin {$IFNDEF LINUX} { TH - check the available disk space here } DSize := 0; for j:=1 to cfg.packs do with cfg.pack[j] do begin for i:=1 to packages do begin if data.packmask[j] and packagemask(i)<>0 then begin ASpace := DiskSpaceN (package[i].zip); if ASpace = -1 then begin params[0]:=@package[i].zip; MessageBox (msg_corrupt_zip, @params,mferror + mfokbutton); end else Inc (DSize, ASpace); end; end; end; S := FExpand (Data.BasePath); if S [Length (S)] = DirSep then Dec (S [0]); Space := DiskFree (byte (Upcase(S [1])) - 64) shr 10; if Space < DSize then S := str_is_not else S := ''; if (Space < DSize + 500) then begin if S = '' then S := str_might_not_be; params[0]:=@s; if messagebox(msg_space_warning,@params, mferror+mfyesbutton+mfnobutton) = cmYes then Continue; end; {$ENDIF} if createinstalldir(data.basepath) then break; end else begin { maybe only config } if (data.cfgval and 1)<>0 then begin result:=messagebox(msg_no_components_selected,nil, mfinformation+mfyesbutton+mfnobutton); if (result=cmYes) and createinstalldir(data.basepath) then doconfigwrite; exit; end else begin result:=messagebox(msg_nocomponents,nil, mferror+mfyesbutton+mfnobutton); if result=cmYes then exit; end; end; end; end else exit; until false; { extract packages } for j:=1 to cfg.packs do with cfg.pack[j] do begin r.assign(10,7,70,18); UnzDlg:=new(punzipdialog,init(r,dialog_unzipdialog_title)); desktop^.insert(UnzDlg); for i:=1 to packages do begin if data.packmask[j] and packagemask(i)<>0 then begin UnzDlg^.do_unzip(package[i].zip,data.basepath); { gather some information about the installed files } if copy(package[i].zip,1,3)='ide' then haside:=true; if copy(package[i].zip,1,7)='doc-htm' then hashtmlhelp:=true; end; end; desktop^.delete(UnzDlg); dispose(UnzDlg,done); end; { write config } if (data.cfgval and 1)<>0 then doconfigwrite; { show end message } p3:=new(penddialog,init); executedialog(p3,nil); end; procedure tapp.readcfg(const fn:string); var t : text; i,j, line : longint; item, s : string; params : array[0..0] of pointer; {$ifndef FPC} procedure readln(var t:text;var s:string); var c : char; i : longint; begin c:=#0; i:=0; while (not eof(t)) and (c<>#10) do begin read(t,c); if c<>#10 then begin inc(i); s[i]:=c; end; end; if (i>0) and (s[i]=#13) then dec(i); s[0]:=chr(i); end; {$endif} begin assign(t,StartPath + DirSep + fn); {$I-} reset(t); {$I+} if ioresult<>0 then begin StartPath := GetProgDir; assign(t,StartPath + DirSep + fn); {$I-} reset(t); {$I+} if ioresult<>0 then begin params[0]:=@fn; messagebox(msg_file_not_found,@params,mferror+mfokbutton); errorhalt; end; end; line:=0; while not eof(t) do begin readln(t,s); inc(line); if (s<>'') and not(s[1] in ['#',';']) then begin i:=pos('=',s); if i>0 then begin item:=upper(Copy(s,1,i-1)); system.delete(s,1,i); if item='VERSION' then cfg.version:=s else if item='TITLE' then cfg.title:=s else if item='LANGUAGE' then cfg.language:=s else if item='BASEPATH' then cfg.basepath:=s else if item='HELPIDX' then cfg.helpidx:=s else if item='DOCSUB' then cfg.docsub:=s else if item='DEFAULTCFG' then begin repeat readln(t,s); if upper(s)='ENDCFG' then break; if cfg.defcfgsmaxpacks then begin writeln('Too many packs'); halt(1); end; cfg.pack[cfg.packs].name:=s; end else if item='CFGFILE' then begin if cfg.packs=0 then begin writeln('No pack set'); halt(1); end; cfg.pack[cfg.packs].defcfgfile:=s end else if item='IDECFGFILE' then begin if cfg.packs=0 then begin writeln('No pack set'); halt(1); end; cfg.pack[cfg.packs].defidecfgfile:=s end else if item='IDEINIFILE' then begin if cfg.packs=0 then begin writeln('No pack set'); halt(1); end; cfg.pack[cfg.packs].defideinifile:=s end else if item='PPC386' then begin if cfg.packs=0 then begin writeln('No pack set'); halt(1); end; cfg.pack[cfg.packs].ppc386:=s; end else if item='BINSUB' then begin if cfg.packs=0 then begin writeln('No pack set'); halt(1); end; cfg.pack[cfg.packs].binsub:=s; end else if item='FILECHECK' then begin if cfg.packs=0 then begin writeln('No pack set'); halt(1); end; cfg.pack[cfg.packs].filechk:=s; end else if item='PACKAGE' then begin if cfg.packs=0 then begin writeln('No pack set'); halt(1); end; with cfg.pack[cfg.packs] do begin j:=pos(',',s); if (j>0) and (packages'' then begin findfirst(cfg.pack[j].filechk,$20,dir); if doserror<>0 then begin { remove the package } move(cfg.pack[j+1],cfg.pack[j],sizeof(tpack)*(cfg.packs-j)); dec(cfg.packs); dec(j); end; {$IFNDEF TP} findclose(dir); {$ENDIF} end; end; end; procedure tapp.initmenubar; var r : trect; begin getextent(r); r.b.y:=r.a.y+1; menubar:=new(pmenubar,init(r,newmenu( newsubmenu(menu_install,hcnocontext,newmenu(nil ), nil)))); end; procedure tapp.handleevent(var event : tevent); begin inherited handleevent(event); if event.what=evcommand then if event.command=cmstart then begin clearevent(event); do_installdialog; if successfull then begin event.what:=evcommand; event.command:=cmquit; handleevent(event); end; end; end; {$IFDEF DOSSTUB} function CheckOS2: boolean; var OwnName: PathStr; OwnDir: DirStr; Name: NameStr; Ext: ExtStr; DosV, W: word; P: PChar; const Title: string [15] = 'FPC Installer'#0; RunBlock: TRunBlock = (Length: $32; Dependent: 0; Background: 0; TraceLevel: 0; PrgTitle: @Title [1]; PrgName: nil; Args: nil; TermQ: 0; Environment: nil; Inheritance: 0; SesType: 2; Icon: nil; PgmHandle: 0; PgmControl: 2; Column: 0; Row: 0; Width: 80; Height: 25); begin CheckOS2 := false; asm mov ah, 30h int 21h xchg ah, al mov DosV, ax mov ax, 4010h int 2Fh cmp ax, 4010h jnz @0 xor bx, bx @0: mov W, bx end; if DosV > 3 shl 8 then begin OwnName := FExpand (ParamStr (0)); FSplit (OwnName, OwnDir, Name, Ext); if (DosV >= 20 shl 8 + 10) and (W >= 20 shl 8 + 10) then (* OS/2 version 2.1 or later running (double-checked) *) begin OwnName [Succ (byte (OwnName [0]))] := #0; RunBlock.PrgName := @OwnName [1]; P := Ptr (PrefixSeg, $80); if PByte (P)^ <> 0 then begin Inc (P); RunBlock.Args := Ptr (PrefixSeg, $81); end; asm mov ax, 6400h mov bx, 0025h mov cx, 636Ch mov si, offset RunBlock int 21h jc @0 mov DosV, 0 @0: end; CheckOS2 := DosV = 0; end; end; end; {$ENDIF} var i : longint; begin { register objects for help streaming } RegisterWHTMLScan; {$ifdef FPC} {$ifdef win32} Dos.Exec(GetEnv('COMSPEC'),'/C echo This dummy call gets the mouse to become visible'); {$endif win32} {$endif FPC} (* TH - no error boxes if checking an inaccessible disk etc. *) {$IFDEF OS2} {$IFDEF FPC} DosCalls.DosError (0); {$ELSE FPC} {$IFDEF VirtualPascal} OS2Base.DosError (ferr_DisableHardErr); {$ELSE VirtualPascal} BseDos.DosError (0); {$ENDIF VirtualPascal} {$ENDIF FPC} {$ENDIF} {$IFDEF DOSSTUB} if CheckOS2 then Halt; {$ENDIF} createlog:=false; for i:=1 to paramcount do begin if paramstr(i)='-l' then createlog:=true else if paramstr(i)='-h' then begin writeln('FPC Installer Copyright (c) 1993-2000 Florian Klaempfl'); writeln('Command line options:'); writeln(' -l create log file'); writeln; writeln(' -h displays this help'); halt(0); end else begin writeln('Illegal command line parameter: ',paramstr(i)); halt(1); end; end; if createlog then begin assign(log,'install.log'); rewrite(log); if not(lfnsupport) then writeln(log,'OS doesn''t have LFN support'); end; getdir(0,startpath); successfull:=false; fillchar(cfg, SizeOf(cfg), 0); fillchar(data, SizeOf(data), 0); { set a default language } cfg.language:='English'; { don't use a message file by default } msgfile:=''; installapp.init; FSplit (FExpand (ParamStr (0)), DStr, CfgName, EStr); installapp.readcfg(CfgName + CfgExt); installapp.checkavailpack; installapp.do_languagedialog; { installapp.readcfg(startpath+dirsep+cfgfile);} if not(lfnsupport) then MessageBox(msg_no_lfn,nil,mfinformation or mfokbutton); installapp.do_installdialog; installapp.done; if createlog then close(log); end. { $Log$ Revision 1.12 2000-11-26 19:00:44 hajny * English correction Revision 1.11 2000/10/11 17:16:01 peter * fixed a typo and the setting of haside and hashtmlhelp (merged) Revision 1.10 2000/10/11 15:57:47 peter * merged ide additions Revision 1.9 2000/10/08 18:43:17 hajny * the language dialog repaired Revision 1.8 2000/09/24 10:52:36 peter * smaller window Revision 1.7 2000/09/22 23:13:37 pierre * add emulation for go32v2 and display currently extraced file and changes by Gabor for scrolling support (merged) Revision 1.6 2000/09/22 12:15:49 florian + support of Russian (Windows) Revision 1.5 2000/09/22 11:07:51 florian + all language dependend strings are now resource strings + the -Fr switch is now set in the ppc386.cfg Revision 1.4 2000/09/21 22:09:23 florian + start of multilanguage support Revision 1.3 2000/09/17 14:44:12 hajny * compilable with TP again Revision 1.2 2000/07/21 10:43:01 florian + added for lfn support Revision 1.1 2000/07/13 06:30:21 michael + Initial import }