fputils.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998 by Berczi Gabor
  5. Utilility routines used by the IDE
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit FPUtils;
  13. interface
  14. uses Objects;
  15. const
  16. {$ifdef Unix}
  17. dirsep = '/';
  18. listsep = [';',':'];
  19. exeext = '';
  20. pasext = '.pas';
  21. ppext = '.pp';
  22. {$else}
  23. dirsep = '\';
  24. listsep = [';'];
  25. exeext = '.exe';
  26. pasext = '.pas';
  27. ppext = '.pp';
  28. {$endif}
  29. function SmartPath(Path: string): string;
  30. Function FixPath(s:string;allowdot:boolean):string;
  31. function FixFileName(const s:string):string;
  32. function MakeExeName(const fn:string):string;
  33. function Center(const S: string; Len: byte): string;
  34. function FitStr(const S: string; Len: byte): string;
  35. function KillTilde(S: string): string;
  36. function LowercaseStr(const S: string): string;
  37. {function DirOf(const S: string): string;
  38. function ExtOf(const S: string): string;
  39. function NameOf(const S: string): string;
  40. function NameAndExtOf(const S: string): string;}
  41. function StrToExtended(S: string): Extended;
  42. function Power(const A,B: double): double;
  43. function MatchesMask(What, Mask: string): boolean;
  44. function MatchesMaskList(What, MaskList: string): boolean;
  45. function MatchesFileList(What, FileList: string): boolean;
  46. function EatIO: integer;
  47. function RenameFile(const OldFileName,NewFileName: string): boolean;
  48. function LocateFile(FileList: string): string;
  49. function LocatePasFile(const FileName:string):string;
  50. function LocateExeFile(var FileName:string): boolean;
  51. function EraseFile(FileName: string): boolean;
  52. function GetStr(const P: PString): string;
  53. procedure ReplaceStr(var S: string; const What,NewS: string);
  54. procedure ReplaceStrI(var S: string; What: string; const NewS: string);
  55. const ListSeparator : char = ';';
  56. implementation
  57. uses Dos,
  58. WUtils,
  59. FPVars,FPSwitch;
  60. function IntToStr(L: longint): string;
  61. var S: string;
  62. begin
  63. Str(L,S);
  64. IntToStr:=S;
  65. end;
  66. function IntToStrZ(L: longint; MinLen: byte): string;
  67. var S: string;
  68. begin
  69. S:=IntToStr(L);
  70. if length(S)<MinLen then S:=CharStr('0',MinLen-length(S))+S;
  71. IntToStrZ:=S;
  72. end;
  73. function IntToStrL(L: longint; MinLen: byte): string;
  74. var S: string;
  75. begin
  76. S:=IntToStr(L);
  77. if length(S)<MinLen then S:=CharStr(' ',MinLen-length(S))+S;
  78. IntToStrL:=S;
  79. end;
  80. function SmartPath(Path: string): string;
  81. var S: string;
  82. begin
  83. GetDir(0,S);
  84. if copy(S,length(S),1)<>DirSep then S:=S+DirSep;
  85. {$ifdef FSCaseInsensitive}
  86. if (LowerCaseStr(copy(Path,1,length(S)))=LowerCaseStr(S)) {and (Pos('\',copy(Path,length(S)+1,High(S)))=0)} then
  87. {$else}
  88. if (copy(Path,1,length(S))=S) {and (Pos('\',copy(Path,length(S)+1,High(S)))=0)} then
  89. {$endif}
  90. system.Delete(Path,1,length(S));
  91. SmartPath:=Path;
  92. end;
  93. Function FixPath(s:string;allowdot:boolean):string;
  94. var
  95. i : longint;
  96. begin
  97. for i:=1 to length(s) do
  98. if s[i] in ['/','\'] then
  99. s[i]:=DirSep;
  100. if (length(s)>0) and (s[length(s)]<>DirSep) and
  101. (s[length(s)]<>':') then
  102. s:=s+DirSep;
  103. if (not allowdot) and (s='.'+DirSep) then
  104. s:='';
  105. FixPath:=s;
  106. end;
  107. function FixFileName(const s:string):string;
  108. var
  109. i : longint;
  110. {$ifdef Unix}
  111. NoPath : boolean;
  112. {$endif}
  113. begin
  114. {$ifdef Unix}NoPath:=true;{$endif}
  115. for i:=length(s) downto 1 do
  116. begin
  117. case s[i] of
  118. {$ifdef Unix}
  119. '/','\' : begin
  120. FixFileName[i]:='/';
  121. NoPath:=false; {Skip lowercasing path: 'X11'<>'x11' }
  122. end;
  123. 'A'..'Z' : if NoPath then
  124. FixFileName[i]:=char(byte(s[i])+ord('a')-ord('A'))
  125. else
  126. FixFileName[i]:=s[i];
  127. {$else}
  128. '/' : FixFileName[i]:='\';
  129. 'A'..'Z' : FixFileName[i]:=char(byte(s[i])+32);
  130. {$endif}
  131. else
  132. FixFileName[i]:=s[i];
  133. end;
  134. end;
  135. FixFileName[0]:=s[0];
  136. end;
  137. function MakeExeName(const fn:string):string;
  138. var
  139. d : DirStr;
  140. n : NameStr;
  141. e : ExtStr;
  142. begin
  143. FSplit(fn,d,n,e);
  144. MakeExeName:=d+n+ExeExt;
  145. end;
  146. function Center(const S: string; Len: byte): string;
  147. begin
  148. Center:=LExpand(S+CharStr(' ',Max(0,(Len-length(S)) div 2)),Len);
  149. end;
  150. function FitStr(const S: string; Len: byte): string;
  151. begin
  152. FitStr:=RExpand(copy(S,1,Len),Len);
  153. end;
  154. function KillTilde(S: string): string;
  155. var P: longint;
  156. begin
  157. repeat
  158. P:=Pos('~',S);
  159. if P>0 then
  160. Delete(S,P,1);
  161. until P=0;
  162. KillTilde:=S;
  163. end;
  164. function LowerCaseStr(const S: string): string;
  165. var
  166. I: Longint;
  167. begin
  168. for I:=1 to length(S) do
  169. if S[I] in ['A'..'Z'] then
  170. LowerCaseStr[I]:=chr(ord(S[I])+32)
  171. else
  172. LowerCaseStr[I]:=S[I];
  173. LowercaseStr[0]:=S[0];
  174. end;
  175. {function DirOf(const S: string): string;
  176. var D: DirStr; E: ExtStr; N: NameStr;
  177. begin
  178. FSplit(S,D,N,E);
  179. if (D<>'') and (D[Length(D)]<>DirSep) then
  180. DirOf:=D+DirSep
  181. else
  182. DirOf:=D;
  183. end;
  184. function ExtOf(const S: string): string;
  185. var D: DirStr; E: ExtStr; N: NameStr;
  186. begin
  187. FSplit(S,D,N,E);
  188. ExtOf:=E;
  189. end;
  190. function NameOf(const S: string): string;
  191. var D: DirStr; E: ExtStr; N: NameStr;
  192. begin
  193. FSplit(S,D,N,E);
  194. NameOf:=N;
  195. end;
  196. function NameAndExtOf(const S: string): string;
  197. var D: DirStr; E: ExtStr; N: NameStr;
  198. begin
  199. FSplit(S,D,N,E);
  200. NameAndExtOf:=N+E;
  201. end; }
  202. function StrToExtended(S: string): Extended;
  203. var R : Extended;
  204. C : integer;
  205. begin
  206. Val(S,R,C);
  207. StrToExtended:=R;
  208. end;
  209. function Power(const A,B: double): double;
  210. begin
  211. if A=0 then Power:=0
  212. else Power:=exp(B*ln(A));
  213. end;
  214. function MatchesMask(What, Mask: string): boolean;
  215. function upper(const s : string) : string;
  216. var
  217. i : Sw_integer;
  218. begin
  219. for i:=1 to length(s) do
  220. if s[i] in ['a'..'z'] then
  221. upper[i]:=char(byte(s[i])-32)
  222. else
  223. upper[i]:=s[i];
  224. upper[0]:=s[0];
  225. end;
  226. Function CmpStr(const hstr1,hstr2:string):boolean;
  227. var
  228. found : boolean;
  229. i1,i2 : Sw_integer;
  230. begin
  231. i1:=0;
  232. i2:=0;
  233. found:=true;
  234. while found and (i1<length(hstr1)) and (i2<=length(hstr2)) do
  235. begin
  236. if found then
  237. inc(i2);
  238. inc(i1);
  239. case hstr1[i1] of
  240. '?' :
  241. found:=true;
  242. '*' :
  243. begin
  244. found:=true;
  245. if (i1=length(hstr1)) then
  246. i2:=length(hstr2)
  247. else
  248. if (i1<length(hstr1)) and (hstr1[i1+1]<>hstr2[i2]) then
  249. begin
  250. if i2<length(hstr2) then
  251. dec(i1)
  252. end
  253. else
  254. if i2>1 then
  255. dec(i2);
  256. end;
  257. else
  258. found:=(hstr1[i1]=hstr2[i2]) or (hstr2[i2]='?');
  259. end;
  260. end;
  261. if found then
  262. found:=(i1>=length(hstr1)) and (i2>=length(hstr2));
  263. CmpStr:=found;
  264. end;
  265. var
  266. D1,D2 : DirStr;
  267. N1,N2 : NameStr;
  268. E1,E2 : Extstr;
  269. begin
  270. {$ifdef Unix}
  271. FSplit(What,D1,N1,E1);
  272. FSplit(Mask,D2,N2,E2);
  273. {$else}
  274. FSplit(Upper(What),D1,N1,E1);
  275. FSplit(Upper(Mask),D2,N2,E2);
  276. {$endif}
  277. MatchesMask:=CmpStr(N2,N1) and CmpStr(E2,E1);
  278. end;
  279. function MatchesMaskList(What, MaskList: string): boolean;
  280. var P: integer;
  281. Match: boolean;
  282. begin
  283. Match:=false;
  284. if What<>'' then
  285. repeat
  286. P:=Pos(ListSeparator, MaskList);
  287. if P=0 then
  288. P:=length(MaskList)+1;
  289. Match:=MatchesMask(What,copy(MaskList,1,P-1));
  290. Delete(MaskList,1,P);
  291. until Match or (MaskList='');
  292. MatchesMaskList:=Match;
  293. end;
  294. function MatchesFileList(What, FileList: string): boolean;
  295. var P: integer;
  296. Match: boolean;
  297. WD,FD : record D: DirStr; N: NameStr; E: ExtStr; end;
  298. F: string;
  299. begin
  300. Match:=false;
  301. FSplit(What,WD.D,WD.N,WD.E);
  302. if What<>'' then
  303. repeat
  304. P:=Pos(ListSeparator, FileList);
  305. if P=0 then P:=length(FileList)+1;
  306. F:=copy(FileList,1,P-1);
  307. FSplit(F,FD.D,FD.N,FD.E);
  308. Match:=MatchesMask(WD.D+WD.N,FD.D+FD.N) and
  309. MatchesMask(WD.E,FD.E);
  310. Delete(FileList,1,P);
  311. until Match or (FileList='');
  312. MatchesFileList:=Match;
  313. end;
  314. function EatIO: integer;
  315. begin
  316. EatIO:=IOResult;
  317. end;
  318. function RenameFile(const OldFileName,NewFileName: string): boolean;
  319. var f: file;
  320. begin
  321. Assign(f,OldFileName);
  322. Rename(f,NewFileName);
  323. RenameFile:=(EatIO=0);
  324. end;
  325. function LocateFile(FileList: string): string;
  326. var FilePath: string;
  327. function CheckFile(Path,Name: string): boolean;
  328. var OK: boolean;
  329. begin
  330. Path:=CompleteDir(Path);
  331. Path:=Path+Name;
  332. OK:=ExistsFile(Path);
  333. if OK then FilePath:=Path;
  334. CheckFile:=OK;
  335. end;
  336. function LocateSingleFile(FileName: string): boolean;
  337. var OK: boolean;
  338. begin
  339. OK:=CheckFile(FExpand('.'),FileName);
  340. if OK=false then OK:=CheckFile(StartupDir,FileName);
  341. if OK=false then OK:=CheckFile(IDEDir,FileName);
  342. LocateSingleFile:=OK;
  343. end;
  344. var P: integer;
  345. begin
  346. FilePath:='';
  347. if FileList<>'' then
  348. repeat
  349. P:=Pos(ListSeparator,FileList); if P=0 then P:=length(FileList)+1;
  350. LocateSingleFile(copy(FileList,1,P-1));
  351. Delete(FileList,1,P);
  352. until (FilePath<>'') or (FileList='');
  353. LocateFile:=FilePath;
  354. end;
  355. function LocatePasFile(const FileName:string):string;
  356. var
  357. s : string;
  358. begin
  359. LocatePasFile:=FileName;
  360. if ExistsFile(FileName) or (ExtOf(FileName)<>'') then
  361. exit;
  362. S:=FileName+PPExt;
  363. if ExistsFile(S) then
  364. begin
  365. LocatePasFile:=S;
  366. exit;
  367. end;
  368. S:=FileName+PasExt;
  369. if ExistsFile(S) then
  370. begin
  371. LocatePasFile:=S;
  372. exit;
  373. end;
  374. end;
  375. function LocateExeFile(var FileName:string): boolean;
  376. var
  377. dir,s : string;
  378. i : longint;
  379. begin
  380. LocateExeFile:=False;
  381. if ExistsFile(FileName) then
  382. begin
  383. LocateExeFile:=true;
  384. Exit;
  385. end;
  386. S:=GetEnv('PATH');
  387. While Length(S)>0 do
  388. begin
  389. i:=1;
  390. While (i<=Length(S)) and not (S[i] in ListSep) do
  391. Inc(i);
  392. Dir:=CompleteDir(Copy(S,1,i-1));
  393. if i<Length(S) then
  394. Delete(S,1,i)
  395. else
  396. S:='';
  397. if ExistsFile(Dir+FileName) then
  398. Begin
  399. FileName:=Dir+FileName;
  400. LocateExeFile:=true;
  401. Exit;
  402. End;
  403. end;
  404. end;
  405. function GetStr(const P: PString): string;
  406. begin
  407. if P=nil then GetStr:='' else GetStr:=P^;
  408. end;
  409. function EraseFile(FileName: string): boolean;
  410. var f: file;
  411. begin
  412. if FileName='' then Exit;
  413. {$I-}
  414. Assign(f,FileName);
  415. Erase(f);
  416. {$I+}
  417. EraseFile:=(EatIO=0);
  418. end;
  419. procedure ReplaceStr(var S: string; const What,NewS: string);
  420. var I : Sw_integer;
  421. begin
  422. repeat
  423. I:=Pos(What,S);
  424. if I>0 then
  425. begin
  426. Delete(S,I,length(What));
  427. Insert(NewS,S,I);
  428. end;
  429. until I=0;
  430. end;
  431. procedure ReplaceStrI(var S: string; What: string; const NewS: string);
  432. var I : integer;
  433. UpcaseS: string;
  434. begin
  435. UpcaseS:=UpcaseStr(S); What:=UpcaseStr(What);
  436. repeat
  437. I:=Pos(What,UpcaseS);
  438. if I>0 then
  439. begin
  440. Delete(S,I,length(What));
  441. Insert(NewS,S,I);
  442. end;
  443. until I=0;
  444. end;
  445. END.
  446. {
  447. $Log$
  448. Revision 1.1 2001-08-04 11:30:24 peter
  449. * ide works now with both compiler versions
  450. Revision 1.1.2.7 2001/03/06 21:57:29 pierre
  451. * some more generic code
  452. Revision 1.1.2.6 2000/11/27 11:57:29 pierre
  453. * some duplicates with wutils commented out
  454. Revision 1.1.2.5 2000/11/14 09:23:56 marco
  455. * Second batch
  456. Revision 1.1.2.4 2000/11/13 16:59:09 pierre
  457. * some function in double removed from fputils unit
  458. Revision 1.1.2.3 2000/11/03 15:45:57 pierre
  459. * fix LTrim for AnsiStrings
  460. Revision 1.1.2.2 2000/08/15 03:40:53 peter
  461. [*] no more fatal exits when the IDE can't find the error file (containing
  462. the redirected assembler/linker output) after compilation
  463. [*] hidden windows are now added always at the end of the Window List
  464. [*] TINIFile parsed entries encapsulated in string delimiters incorrectly
  465. [*] selection was incorrectly adjusted when typing in overwrite mode
  466. [*] the line wasn't expanded when it's end was reached in overw. mode
  467. [*] the IDE now tries to locate source files also in the user specified
  468. unit dirs (for ex. as a response to 'Open at cursor' (Ctrl+Enter) )
  469. [*] 'Open at cursor' is now aware of the extension (if specified)
  470. Revision 1.1.2.1 2000/07/20 11:02:15 michael
  471. + Fixes from gabor. See fixes.txt
  472. Revision 1.1 2000/07/13 09:48:36 michael
  473. + Initial import
  474. Revision 1.16 2000/06/22 09:07:13 pierre
  475. * Gabor changes: see fixes.txt
  476. Revision 1.15 2000/04/18 11:42:37 pierre
  477. lot of Gabor changes : see fixes.txt
  478. Revision 1.14 2000/01/03 11:38:34 michael
  479. Changes from Gabor
  480. Revision 1.13 1999/04/15 08:58:07 peter
  481. * syntax highlight fixes
  482. * browser updates
  483. Revision 1.12 1999/04/07 21:55:55 peter
  484. + object support for browser
  485. * html help fixes
  486. * more desktop saving things
  487. * NODEBUG directive to exclude debugger
  488. Revision 1.11 1999/03/19 16:04:31 peter
  489. * new compiler dialog
  490. Revision 1.10 1999/03/08 14:58:14 peter
  491. + prompt with dialogs for tools
  492. Revision 1.9 1999/03/01 15:42:06 peter
  493. + Added dummy entries for functions not yet implemented
  494. * MenuBar didn't update itself automatically on command-set changes
  495. * Fixed Debugging/Profiling options dialog
  496. * TCodeEditor converts spaces to tabs at save only if efUseTabChars is
  497. set
  498. * efBackSpaceUnindents works correctly
  499. + 'Messages' window implemented
  500. + Added '$CAP MSG()' and '$CAP EDIT' to available tool-macros
  501. + Added TP message-filter support (for ex. you can call GREP thru
  502. GREP2MSG and view the result in the messages window - just like in TP)
  503. * A 'var' was missing from the param-list of THelpFacility.TopicSearch,
  504. so topic search didn't work...
  505. * In FPHELP.PAS there were still context-variables defined as word instead
  506. of THelpCtx
  507. * StdStatusKeys() was missing from the statusdef for help windows
  508. + Topic-title for index-table can be specified when adding a HTML-files
  509. Revision 1.8 1999/02/22 02:15:20 peter
  510. + default extension for save in the editor
  511. + Separate Text to Find for the grep dialog
  512. * fixed redir crash with tp7
  513. Revision 1.7 1999/02/16 17:13:55 pierre
  514. + findclose added for FPC
  515. Revision 1.6 1999/02/05 12:12:01 pierre
  516. + SourceDir that stores directories for sources that the
  517. compiler should not know about
  518. Automatically asked for addition when a new file that
  519. needed filedialog to be found is in an unknown directory
  520. Stored and retrieved from INIFile
  521. + Breakpoints conditions added to INIFile
  522. * Breakpoints insterted and removed at debin and end of debug session
  523. Revision 1.5 1999/02/02 16:41:43 peter
  524. + automatic .pas/.pp adding by opening of file
  525. * better debuggerscreen changes
  526. Revision 1.4 1999/01/21 11:54:25 peter
  527. + tools menu
  528. + speedsearch in symbolbrowser
  529. * working run command
  530. Revision 1.3 1999/01/12 14:29:40 peter
  531. + Implemented still missing 'switch' entries in Options menu
  532. + Pressing Ctrl-B sets ASCII mode in editor, after which keypresses (even
  533. ones with ASCII < 32 ; entered with Alt+<###>) are interpreted always as
  534. ASCII chars and inserted directly in the text.
  535. + Added symbol browser
  536. * splitted fp.pas to fpide.pas
  537. Revision 1.2 1998/12/28 15:47:53 peter
  538. + Added user screen support, display & window
  539. + Implemented Editor,Mouse Options dialog
  540. + Added location of .INI and .CFG file
  541. + Option (INI) file managment implemented (see bottom of Options Menu)
  542. + Switches updated
  543. + Run program
  544. Revision 1.31 1998/12/27 11:25:37 gabor
  545. + MatchesMask(), MatchesMaskList() and MatchesFileList() added
  546. + NameAndExtOf() added
  547. Revision 1.3 1998/12/22 10:39:52 peter
  548. + options are now written/read
  549. + find and replace routines
  550. }