{ $Id$ This file is part of the Free Pascal Integrated Development Environment Copyright (c) 1998 by Berczi Gabor Utilility routines used by the IDE 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. **********************************************************************} unit FPUtils; interface uses Objects; const {$ifdef Unix} dirsep = '/'; listsep = [';',':']; exeext = ''; pasext = '.pas'; ppext = '.pp'; {$else} dirsep = '\'; listsep = [';']; exeext = '.exe'; pasext = '.pas'; ppext = '.pp'; {$endif} function SmartPath(Path: string): string; Function FixPath(s:string;allowdot:boolean):string; function FixFileName(const s:string):string; function MakeExeName(const fn:string):string; function Center(const S: string; Len: byte): string; function FitStr(const S: string; Len: byte): string; function KillTilde(S: string): string; function LowercaseStr(const S: string): string; function DirOf(const S: string): string; function ExtOf(const S: string): string; function NameOf(const S: string): string; function NameAndExtOf(const S: string): string; function StrToExtended(S: string): Extended; function Power(const A,B: double): double; function MatchesMask(What, Mask: string): boolean; function MatchesMaskList(What, MaskList: string): boolean; function MatchesFileList(What, FileList: string): boolean; function EatIO: integer; function RenameFile(const OldFileName,NewFileName: string): boolean; function LocateFile(FileList: string): string; function LocatePasFile(const FileName:string):string; function LocateExeFile(var FileName:string): boolean; function EraseFile(FileName: string): boolean; function GetStr(const P: PString): string; procedure ReplaceStr(var S: string; const What,NewS: string); procedure ReplaceStrI(var S: string; What: string; const NewS: string); const ListSeparator : char = ';'; implementation uses Dos, WUtils, FPVars,FPSwitch; function IntToStr(L: longint): string; var S: string; begin Str(L,S); IntToStr:=S; end; function IntToStrZ(L: longint; MinLen: byte): string; var S: string; begin S:=IntToStr(L); if length(S)DirSep then S:=S+DirSep; if (copy(Path,1,length(S))=S) {and (Pos('\',copy(Path,length(S)+1,High(S)))=0)} then system.Delete(Path,1,length(S)); SmartPath:=Path; end; Function FixPath(s:string;allowdot:boolean):string; var i : longint; begin for i:=1 to length(s) do if s[i] in ['/','\'] then s[i]:=DirSep; if (length(s)>0) and (s[length(s)]<>DirSep) and (s[length(s)]<>':') then s:=s+DirSep; if (not allowdot) and (s='.'+DirSep) then s:=''; FixPath:=s; end; function FixFileName(const s:string):string; var i : longint; {$ifdef Unix} NoPath : boolean; {$endif} begin {$ifdef Unix}NoPath:=true;{$endif} for i:=length(s) downto 1 do begin case s[i] of {$ifdef Unix} '/','\' : begin FixFileName[i]:='/'; NoPath:=false; {Skip lowercasing path: 'X11'<>'x11' } end; 'A'..'Z' : if NoPath then FixFileName[i]:=char(byte(s[i])+32) else FixFileName[i]:=s[i]; {$else} '/' : FixFileName[i]:='\'; 'A'..'Z' : FixFileName[i]:=char(byte(s[i])+32); {$endif} else FixFileName[i]:=s[i]; end; end; FixFileName[0]:=s[0]; end; function MakeExeName(const fn:string):string; var d : DirStr; n : NameStr; e : ExtStr; begin FSplit(fn,d,n,e); MakeExeName:=d+n+ExeExt; end; function Center(const S: string; Len: byte): string; begin Center:=LExpand(S+CharStr(' ',Max(0,(Len-length(S)) div 2)),Len); end; function FitStr(const S: string; Len: byte): string; begin FitStr:=RExpand(copy(S,1,Len),Len); end; function KillTilde(S: string): string; var P: longint; begin repeat P:=Pos('~',S); if P>0 then Delete(S,P,1); until P=0; KillTilde:=S; end; function LowerCaseStr(const S: string): string; var I: Longint; begin for I:=1 to length(S) do if S[I] in ['A'..'Z'] then LowerCaseStr[I]:=chr(ord(S[I])+32) else LowerCaseStr[I]:=S[I]; LowercaseStr[0]:=S[0]; end; function DirOf(const S: string): string; var D: DirStr; E: ExtStr; N: NameStr; begin FSplit(S,D,N,E); if (D<>'') and (D[Length(D)]<>DirSep) then DirOf:=D+DirSep else DirOf:=D; end; function ExtOf(const S: string): string; var D: DirStr; E: ExtStr; N: NameStr; begin FSplit(S,D,N,E); ExtOf:=E; end; function NameOf(const S: string): string; var D: DirStr; E: ExtStr; N: NameStr; begin FSplit(S,D,N,E); NameOf:=N; end; function NameAndExtOf(const S: string): string; var D: DirStr; E: ExtStr; N: NameStr; begin FSplit(S,D,N,E); NameAndExtOf:=N+E; end; function StrToExtended(S: string): Extended; var R : Extended; C : integer; begin Val(S,R,C); StrToExtended:=R; end; function Power(const A,B: double): double; begin if A=0 then Power:=0 else Power:=exp(B*ln(A)); end; function MatchesMask(What, Mask: string): boolean; function upper(const s : string) : string; var i : Sw_integer; begin for i:=1 to length(s) do if s[i] in ['a'..'z'] then upper[i]:=char(byte(s[i])-32) else upper[i]:=s[i]; upper[0]:=s[0]; end; Function CmpStr(const hstr1,hstr2:string):boolean; var found : boolean; i1,i2 : Sw_integer; begin i1:=0; i2:=0; found:=true; while found and (i1hstr2[i2]) then begin if i21 then dec(i2); end; else found:=(hstr1[i1]=hstr2[i2]) or (hstr2[i2]='?'); end; end; if found then found:=(i1>=length(hstr1)) and (i2>=length(hstr2)); CmpStr:=found; end; var D1,D2 : DirStr; N1,N2 : NameStr; E1,E2 : Extstr; begin {$ifdef Unix} FSplit(What,D1,N1,E1); FSplit(Mask,D2,N2,E2); {$else} FSplit(Upper(What),D1,N1,E1); FSplit(Upper(Mask),D2,N2,E2); {$endif} MatchesMask:=CmpStr(N2,N1) and CmpStr(E2,E1); end; function MatchesMaskList(What, MaskList: string): boolean; var P: integer; Match: boolean; begin Match:=false; if What<>'' then repeat P:=Pos(ListSeparator, MaskList); if P=0 then P:=length(MaskList)+1; Match:=MatchesMask(What,copy(MaskList,1,P-1)); Delete(MaskList,1,P); until Match or (MaskList=''); MatchesMaskList:=Match; end; function MatchesFileList(What, FileList: string): boolean; var P: integer; Match: boolean; WD,FD : record D: DirStr; N: NameStr; E: ExtStr; end; F: string; begin Match:=false; FSplit(What,WD.D,WD.N,WD.E); if What<>'' then repeat P:=Pos(ListSeparator, FileList); if P=0 then P:=length(FileList)+1; F:=copy(FileList,1,P-1); FSplit(F,FD.D,FD.N,FD.E); Match:=MatchesMask(WD.D+WD.N,FD.D+FD.N) and MatchesMask(WD.E,FD.E); Delete(FileList,1,P); until Match or (FileList=''); MatchesFileList:=Match; end; function EatIO: integer; begin EatIO:=IOResult; end; function RenameFile(const OldFileName,NewFileName: string): boolean; var f: file; begin Assign(f,OldFileName); Rename(f,NewFileName); RenameFile:=(EatIO=0); end; function LocateFile(FileList: string): string; var FilePath: string; function CheckFile(Path,Name: string): boolean; var OK: boolean; begin Path:=CompleteDir(Path); Path:=Path+Name; OK:=ExistsFile(Path); if OK then FilePath:=Path; CheckFile:=OK; end; function LocateSingleFile(FileName: string): boolean; var OK: boolean; begin OK:=CheckFile(FExpand('.'),FileName); if OK=false then OK:=CheckFile(StartupDir,FileName); if OK=false then OK:=CheckFile(IDEDir,FileName); LocateSingleFile:=OK; end; var P: integer; begin FilePath:=''; if FileList<>'' then repeat P:=Pos(ListSeparator,FileList); if P=0 then P:=length(FileList)+1; LocateSingleFile(copy(FileList,1,P-1)); Delete(FileList,1,P); until (FilePath<>'') or (FileList=''); LocateFile:=FilePath; end; function LocatePasFile(const FileName:string):string; var s : string; begin LocatePasFile:=FileName; if ExistsFile(FileName) or (ExtOf(FileName)<>'') then exit; S:=FileName+PPExt; if ExistsFile(S) then begin LocatePasFile:=S; exit; end; S:=FileName+PasExt; if ExistsFile(S) then begin LocatePasFile:=S; exit; end; end; function LocateExeFile(var FileName:string): boolean; var dir,s : string; i : longint; begin LocateExeFile:=False; if ExistsFile(FileName) then begin LocateExeFile:=true; Exit; end; S:=GetEnv('PATH'); While Length(S)>0 do begin i:=1; While (i<=Length(S)) and not (S[i] in ListSep) do Inc(i); Dir:=CompleteDir(Copy(S,1,i-1)); if i0 then begin Delete(S,I,length(What)); Insert(NewS,S,I); end; until I=0; end; procedure ReplaceStrI(var S: string; What: string; const NewS: string); var I : integer; UpcaseS: string; begin UpcaseS:=UpcaseStr(S); What:=UpcaseStr(What); repeat I:=Pos(What,UpcaseS); if I>0 then begin Delete(S,I,length(What)); Insert(NewS,S,I); end; until I=0; end; END. { $Log$ Revision 1.5 2000-11-15 00:14:10 pierre new merge Revision 1.1.2.5 2000/11/14 09:23:56 marco * Second batch Revision 1.4 2000/11/13 17:37:42 pierre merges from fixes branch Revision 1.1.2.4 2000/11/13 16:59:09 pierre * some function in double removed from fputils unit Revision 1.3 2000/11/03 16:05:38 pierre * (merged) Revision 1.1.2.3 2000/11/03 15:45:57 pierre * fix LTrim for AnsiStrings Revision 1.2 2000/08/22 09:41:41 pierre * first big merge from fixes branch Revision 1.1.2.2 2000/08/15 03:40:53 peter [*] no more fatal exits when the IDE can't find the error file (containing the redirected assembler/linker output) after compilation [*] hidden windows are now added always at the end of the Window List [*] TINIFile parsed entries encapsulated in string delimiters incorrectly [*] selection was incorrectly adjusted when typing in overwrite mode [*] the line wasn't expanded when it's end was reached in overw. mode [*] the IDE now tries to locate source files also in the user specified unit dirs (for ex. as a response to 'Open at cursor' (Ctrl+Enter) ) [*] 'Open at cursor' is now aware of the extension (if specified) Revision 1.1.2.1 2000/07/20 11:02:15 michael + Fixes from gabor. See fixes.txt Revision 1.1 2000/07/13 09:48:36 michael + Initial import Revision 1.16 2000/06/22 09:07:13 pierre * Gabor changes: see fixes.txt Revision 1.15 2000/04/18 11:42:37 pierre lot of Gabor changes : see fixes.txt Revision 1.14 2000/01/03 11:38:34 michael Changes from Gabor Revision 1.13 1999/04/15 08:58:07 peter * syntax highlight fixes * browser updates Revision 1.12 1999/04/07 21:55:55 peter + object support for browser * html help fixes * more desktop saving things * NODEBUG directive to exclude debugger Revision 1.11 1999/03/19 16:04:31 peter * new compiler dialog Revision 1.10 1999/03/08 14:58:14 peter + prompt with dialogs for tools Revision 1.9 1999/03/01 15:42:06 peter + Added dummy entries for functions not yet implemented * MenuBar didn't update itself automatically on command-set changes * Fixed Debugging/Profiling options dialog * TCodeEditor converts spaces to tabs at save only if efUseTabChars is set * efBackSpaceUnindents works correctly + 'Messages' window implemented + Added '$CAP MSG()' and '$CAP EDIT' to available tool-macros + Added TP message-filter support (for ex. you can call GREP thru GREP2MSG and view the result in the messages window - just like in TP) * A 'var' was missing from the param-list of THelpFacility.TopicSearch, so topic search didn't work... * In FPHELP.PAS there were still context-variables defined as word instead of THelpCtx * StdStatusKeys() was missing from the statusdef for help windows + Topic-title for index-table can be specified when adding a HTML-files Revision 1.8 1999/02/22 02:15:20 peter + default extension for save in the editor + Separate Text to Find for the grep dialog * fixed redir crash with tp7 Revision 1.7 1999/02/16 17:13:55 pierre + findclose added for FPC Revision 1.6 1999/02/05 12:12:01 pierre + SourceDir that stores directories for sources that the compiler should not know about Automatically asked for addition when a new file that needed filedialog to be found is in an unknown directory Stored and retrieved from INIFile + Breakpoints conditions added to INIFile * Breakpoints insterted and removed at debin and end of debug session Revision 1.5 1999/02/02 16:41:43 peter + automatic .pas/.pp adding by opening of file * better debuggerscreen changes Revision 1.4 1999/01/21 11:54:25 peter + tools menu + speedsearch in symbolbrowser * working run command Revision 1.3 1999/01/12 14:29:40 peter + Implemented still missing 'switch' entries in Options menu + Pressing Ctrl-B sets ASCII mode in editor, after which keypresses (even ones with ASCII < 32 ; entered with Alt+<###>) are interpreted always as ASCII chars and inserted directly in the text. + Added symbol browser * splitted fp.pas to fpide.pas Revision 1.2 1998/12/28 15:47:53 peter + Added user screen support, display & window + Implemented Editor,Mouse Options dialog + Added location of .INI and .CFG file + Option (INI) file managment implemented (see bottom of Options Menu) + Switches updated + Run program Revision 1.31 1998/12/27 11:25:37 gabor + MatchesMask(), MatchesMaskList() and MatchesFileList() added + NameAndExtOf() added Revision 1.3 1998/12/22 10:39:52 peter + options are now written/read + find and replace routines }