fputils.pas 15 KB

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