wutils.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998 by Berczi Gabor
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit WUtils;
  12. interface
  13. {$ifndef FPC}
  14. {$define TPUNIXLF}
  15. {$endif}
  16. uses
  17. Objects;
  18. type
  19. PByteArray = ^TByteArray;
  20. TByteArray = array[0..65520] of byte;
  21. PNoDisposeCollection = ^TNoDisposeCollection;
  22. TNoDisposeCollection = object(TCollection)
  23. procedure FreeItem(Item: Pointer); virtual;
  24. end;
  25. PUnsortedStringCollection = ^TUnsortedStringCollection;
  26. TUnsortedStringCollection = object(TCollection)
  27. function At(Index: Integer): PString;
  28. procedure FreeItem(Item: Pointer); virtual;
  29. end;
  30. PNulStream = ^TNulStream;
  31. TNulStream = object(TStream)
  32. constructor Init;
  33. function GetPos: Longint; virtual;
  34. function GetSize: Longint; virtual;
  35. procedure Read(var Buf; Count: Word); virtual;
  36. procedure Seek(Pos: Longint); virtual;
  37. procedure Write(var Buf; Count: Word); virtual;
  38. end;
  39. PSubStream = ^TSubStream;
  40. TSubStream = object(TStream)
  41. constructor Init(AStream: PStream; AStartPos, ASize: longint);
  42. function GetPos: Longint; virtual;
  43. function GetSize: Longint; virtual;
  44. procedure Read(var Buf; Count: Word); virtual;
  45. procedure Seek(Pos: Longint); virtual;
  46. procedure Write(var Buf; Count: Word); virtual;
  47. private
  48. StartPos: longint;
  49. S : PStream;
  50. end;
  51. PTextCollection = ^TTextCollection;
  52. TTextCollection = object(TStringCollection)
  53. function LookUp(const S: string; var Idx: sw_integer): string;
  54. function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
  55. end;
  56. {$ifdef TPUNIXLF}
  57. procedure readln(var t:text;var s:string);
  58. {$endif}
  59. procedure ReadlnFromStream(Stream: PStream; var s:string;var linecomplete : boolean);
  60. function eofstream(s: pstream): boolean;
  61. function Min(A,B: longint): longint;
  62. function Max(A,B: longint): longint;
  63. function CharStr(C: char; Count: byte): string;
  64. function UpcaseStr(const S: string): string;
  65. function LowCase(C: char): char;
  66. function LowcaseStr(S: string): string;
  67. function RExpand(const S: string; MinLen: byte): string;
  68. function LTrim(const S: string): string;
  69. function RTrim(const S: string): string;
  70. function Trim(const S: string): string;
  71. function IntToStr(L: longint): string;
  72. function StrToInt(const S: string): longint;
  73. function GetStr(P: PString): string;
  74. function GetPChar(P: PChar): string;
  75. function DirOf(const S: string): string;
  76. function ExtOf(const S: string): string;
  77. function NameOf(const S: string): string;
  78. function NameAndExtOf(const S: string): string;
  79. function DirAndNameOf(const S: string): string;
  80. { return Dos GetFTime value or -1 if the file does not exist }
  81. function GetFileTime(const FileName: string): longint;
  82. { copied from compiler global unit }
  83. function GetShortName(const n:string):string;
  84. function EatIO: integer;
  85. procedure GiveUpTimeSlice;
  86. const LastStrToIntResult : integer = 0;
  87. DirSep : char = {$ifdef Linux}'/'{$else}'\'{$endif};
  88. implementation
  89. uses
  90. {$ifdef win32}
  91. windows,
  92. {$endif win32}
  93. Strings, Dos;
  94. {$ifdef TPUNIXLF}
  95. procedure readln(var t:text;var s:string);
  96. var
  97. c : char;
  98. i : longint;
  99. begin
  100. if TextRec(t).UserData[1]=2 then
  101. system.readln(t,s)
  102. else
  103. begin
  104. c:=#0;
  105. i:=0;
  106. while (not eof(t)) and (c<>#10) do
  107. begin
  108. read(t,c);
  109. if c<>#10 then
  110. begin
  111. inc(i);
  112. s[i]:=c;
  113. end;
  114. end;
  115. if (i>0) and (s[i]=#13) then
  116. begin
  117. dec(i);
  118. TextRec(t).UserData[1]:=2;
  119. end;
  120. s[0]:=chr(i);
  121. end;
  122. end;
  123. {$endif}
  124. function eofstream(s: pstream): boolean;
  125. begin
  126. eofstream:=(s^.getpos>=s^.getsize);
  127. end;
  128. procedure ReadlnFromStream(Stream: PStream; var S:string;var linecomplete : boolean);
  129. var
  130. c : char;
  131. i : longint;
  132. begin
  133. linecomplete:=false;
  134. c:=#0;
  135. i:=0;
  136. { this created problems for lines longer than 255 characters
  137. now those lines are cutted into pieces without warning PM }
  138. while (not eofstream(stream)) and (c<>#10) and (i<255) do
  139. begin
  140. stream^.read(c,sizeof(c));
  141. if c<>#10 then
  142. begin
  143. inc(i);
  144. s[i]:=c;
  145. end;
  146. end;
  147. if (c=#10) or eofstream(stream) then
  148. linecomplete:=true;
  149. { if there was a CR LF then remove the CR Dos newline style }
  150. if (i>0) and (s[i]=#13) then
  151. dec(i);
  152. s[0]:=chr(i);
  153. end;
  154. function Max(A,B: longint): longint;
  155. begin
  156. if A>B then Max:=A else Max:=B;
  157. end;
  158. function Min(A,B: longint): longint;
  159. begin
  160. if A<B then Min:=A else Min:=B;
  161. end;
  162. function CharStr(C: char; Count: byte): string;
  163. {$ifndef FPC}
  164. var S: string;
  165. {$endif}
  166. begin
  167. {$ifdef FPC}
  168. CharStr[0]:=chr(Count);
  169. FillChar(CharStr[1],Count,C);
  170. {$else}
  171. S[0]:=chr(Count);
  172. FillChar(S[1],Count,C);
  173. CharStr:=S;
  174. {$endif}
  175. end;
  176. function UpcaseStr(const S: string): string;
  177. var
  178. I: Longint;
  179. begin
  180. for I:=1 to length(S) do
  181. if S[I] in ['a'..'z'] then
  182. UpCaseStr[I]:=chr(ord(S[I])-32)
  183. else
  184. UpCaseStr[I]:=S[I];
  185. UpcaseStr[0]:=S[0];
  186. end;
  187. function LowerCaseStr(S: string): string;
  188. var
  189. I: Longint;
  190. begin
  191. for I:=1 to length(S) do
  192. if S[I] in ['A'..'Z'] then
  193. LowerCaseStr[I]:=chr(ord(S[I])+32)
  194. else
  195. LowerCaseStr[I]:=S[I];
  196. LowercaseStr[0]:=S[0];
  197. end;
  198. function RExpand(const S: string; MinLen: byte): string;
  199. begin
  200. if length(S)<MinLen then
  201. RExpand:=S+CharStr(' ',MinLen-length(S))
  202. else
  203. RExpand:=S;
  204. end;
  205. function LTrim(const S: string): string;
  206. var
  207. i : longint;
  208. begin
  209. i:=1;
  210. while (i<length(s)) and (s[i]=' ') do
  211. inc(i);
  212. LTrim:=Copy(s,i,255);
  213. end;
  214. function RTrim(const S: string): string;
  215. var
  216. i : longint;
  217. begin
  218. i:=length(s);
  219. while (i>0) and (s[i]=' ') do
  220. dec(i);
  221. RTrim:=Copy(s,1,i);
  222. end;
  223. function Trim(const S: string): string;
  224. begin
  225. Trim:=RTrim(LTrim(S));
  226. end;
  227. function IntToStr(L: longint): string;
  228. var S: string;
  229. begin
  230. Str(L,S);
  231. IntToStr:=S;
  232. end;
  233. function StrToInt(const S: string): longint;
  234. var L: longint;
  235. C: integer;
  236. begin
  237. Val(S,L,C); if C<>0 then L:=-1;
  238. LastStrToIntResult:=C;
  239. StrToInt:=L;
  240. end;
  241. function GetStr(P: PString): string;
  242. begin
  243. if P=nil then GetStr:='' else GetStr:=P^;
  244. end;
  245. function GetPChar(P: PChar): string;
  246. begin
  247. if P=nil then GetPChar:='' else GetPChar:=StrPas(P);
  248. end;
  249. function DirOf(const S: string): string;
  250. var D: DirStr; E: ExtStr; N: NameStr;
  251. begin
  252. FSplit(S,D,N,E);
  253. if (D<>'') and (D[Length(D)]<>DirSep) then
  254. DirOf:=D+DirSep
  255. else
  256. DirOf:=D;
  257. end;
  258. function ExtOf(const S: string): string;
  259. var D: DirStr; E: ExtStr; N: NameStr;
  260. begin
  261. FSplit(S,D,N,E);
  262. ExtOf:=E;
  263. end;
  264. function NameOf(const S: string): string;
  265. var D: DirStr; E: ExtStr; N: NameStr;
  266. begin
  267. FSplit(S,D,N,E);
  268. NameOf:=N;
  269. end;
  270. function NameAndExtOf(const S: string): string;
  271. var D: DirStr; E: ExtStr; N: NameStr;
  272. begin
  273. FSplit(S,D,N,E);
  274. NameAndExtOf:=N+E;
  275. end;
  276. function DirAndNameOf(const S: string): string;
  277. var D: DirStr; E: ExtStr; N: NameStr;
  278. begin
  279. FSplit(S,D,N,E);
  280. DirAndNameOf:=D+N;
  281. end;
  282. { return Dos GetFTime value or -1 if the file does not exist }
  283. function GetFileTime(const FileName: string): longint;
  284. var T: longint;
  285. f: file;
  286. FM: integer;
  287. begin
  288. if FileName='' then
  289. T:=-1
  290. else
  291. begin
  292. FM:=FileMode; FileMode:=0;
  293. EatIO; DosError:=0;
  294. Assign(f,FileName);
  295. {$I-}
  296. Reset(f);
  297. GetFTime(f,T);
  298. Close(f);
  299. {$I+}
  300. if (EatIO<>0) or (DosError<>0) then T:=-1;
  301. FileMode:=FM;
  302. end;
  303. GetFileTime:=T;
  304. end;
  305. function GetShortName(const n:string):string;
  306. {$ifdef win32}
  307. var
  308. hs,hs2 : string;
  309. i : longint;
  310. {$endif}
  311. {$ifdef go32v2}
  312. var
  313. hs : string;
  314. {$endif}
  315. begin
  316. GetShortName:=n;
  317. {$ifdef win32}
  318. hs:=n+#0;
  319. i:=Windows.GetShortPathName(@hs[1],@hs2[1],high(hs2));
  320. if (i>0) and (i<=high(hs2)) then
  321. begin
  322. hs2[0]:=chr(strlen(@hs2[1]));
  323. GetShortName:=hs2;
  324. end;
  325. {$endif}
  326. {$ifdef go32v2}
  327. hs:=n;
  328. if Dos.GetShortName(hs) then
  329. GetShortName:=hs;
  330. {$endif}
  331. end;
  332. function EatIO: integer;
  333. begin
  334. EatIO:=IOResult;
  335. end;
  336. function LowCase(C: char): char;
  337. begin
  338. if ('A'<=C) and (C<='Z') then C:=chr(ord(C)+32);
  339. LowCase:=C;
  340. end;
  341. function LowcaseStr(S: string): string;
  342. var I: Longint;
  343. begin
  344. for I:=1 to length(S) do
  345. S[I]:=Lowcase(S[I]);
  346. LowcaseStr:=S;
  347. end;
  348. procedure TNoDisposeCollection.FreeItem(Item: Pointer);
  349. begin
  350. { don't do anything here }
  351. end;
  352. function TUnsortedStringCollection.At(Index: Integer): PString;
  353. begin
  354. At:=inherited At(Index);
  355. end;
  356. procedure TUnsortedStringCollection.FreeItem(Item: Pointer);
  357. begin
  358. if Item<>nil then DisposeStr(Item);
  359. end;
  360. constructor TNulStream.Init;
  361. begin
  362. inherited Init;
  363. Position:=0;
  364. end;
  365. function TNulStream.GetPos: Longint;
  366. begin
  367. GetPos:=Position;
  368. end;
  369. function TNulStream.GetSize: Longint;
  370. begin
  371. GetSize:=Position;
  372. end;
  373. procedure TNulStream.Read(var Buf; Count: Word);
  374. begin
  375. Error(stReadError,0);
  376. end;
  377. procedure TNulStream.Seek(Pos: Longint);
  378. begin
  379. if Pos<=Position then
  380. Position:=Pos;
  381. end;
  382. procedure TNulStream.Write(var Buf; Count: Word);
  383. begin
  384. Inc(Position,Count);
  385. end;
  386. constructor TSubStream.Init(AStream: PStream; AStartPos, ASize: longint);
  387. begin
  388. inherited Init;
  389. if Assigned(AStream)=false then Fail;
  390. S:=AStream; StartPos:=AStartPos; StreamSize:=ASize;
  391. Seek(0);
  392. end;
  393. function TSubStream.GetPos: Longint;
  394. var Pos: longint;
  395. begin
  396. Pos:=S^.GetPos; Dec(Pos,StartPos);
  397. GetPos:=Pos;
  398. end;
  399. function TSubStream.GetSize: Longint;
  400. begin
  401. GetSize:=StreamSize;
  402. end;
  403. procedure TSubStream.Read(var Buf; Count: Word);
  404. var Pos: longint;
  405. RCount: word;
  406. begin
  407. Pos:=GetPos;
  408. if Pos+Count>StreamSize then RCount:=StreamSize-Pos else RCount:=Count;
  409. S^.Read(Buf,RCount);
  410. if RCount<Count then
  411. Error(stReadError,0);
  412. end;
  413. procedure TSubStream.Seek(Pos: Longint);
  414. var RPos: longint;
  415. begin
  416. if (Pos<=StreamSize) then RPos:=Pos else RPos:=StreamSize;
  417. S^.Seek(StartPos+RPos);
  418. end;
  419. procedure TSubStream.Write(var Buf; Count: Word);
  420. begin
  421. S^.Write(Buf,Count);
  422. end;
  423. function TTextCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
  424. var K1: PString absolute Key1;
  425. K2: PString absolute Key2;
  426. R: Sw_integer;
  427. S1,S2: string;
  428. begin
  429. S1:=UpCaseStr(K1^);
  430. S2:=UpCaseStr(K2^);
  431. if S1<S2 then R:=-1 else
  432. if S1>S2 then R:=1 else
  433. R:=0;
  434. Compare:=R;
  435. end;
  436. function TTextCollection.LookUp(const S: string; var Idx: sw_integer): string;
  437. var OLI,ORI,Left,Right,Mid: integer;
  438. LeftP,RightP,MidP: PString;
  439. RL: integer;
  440. LeftS,MidS,RightS: string;
  441. FoundS: string;
  442. UpS : string;
  443. begin
  444. Idx:=-1; FoundS:='';
  445. Left:=0; Right:=Count-1;
  446. UpS:=UpCaseStr(S);
  447. if Left<Right then
  448. begin
  449. while (Left<Right) do
  450. begin
  451. OLI:=Left; ORI:=Right;
  452. Mid:=Left+(Right-Left) div 2;
  453. LeftP:=At(Left); RightP:=At(Right); MidP:=At(Mid);
  454. LeftS:=UpCaseStr(LeftP^); MidS:=UpCaseStr(MidP^);
  455. RightS:=UpCaseStr(RightP^);
  456. if copy(MidS,1,length(UpS))=UpS then
  457. begin
  458. Idx:=Mid; FoundS:=GetStr(MidP);
  459. end;
  460. { else}
  461. if UpS<MidS then
  462. Right:=Mid
  463. else
  464. Left:=Mid;
  465. if (OLI=Left) and (ORI=Right) then
  466. Break;
  467. end;
  468. end;
  469. LookUp:=FoundS;
  470. end;
  471. procedure GiveUpTimeSlice;
  472. {$ifdef GO32V2}{$define DOS}{$endif}
  473. {$ifdef TP}{$define DOS}{$endif}
  474. {$ifdef DOS}
  475. var r: registers;
  476. begin
  477. r.ax:=$1680;
  478. intr($2f,r);
  479. end;
  480. {$endif}
  481. {$ifdef Linux}
  482. begin
  483. end;
  484. {$endif}
  485. {$ifdef Win32}
  486. begin
  487. end;
  488. {$endif}
  489. {$undef DOS}
  490. END.
  491. {
  492. $Log$
  493. Revision 1.14 2000-01-20 00:30:32 pierre
  494. * Result of GetShortPathName is checked
  495. Revision 1.13 2000/01/17 12:20:03 pierre
  496. * uses windows needed for GetShortName
  497. Revision 1.12 2000/01/14 15:36:43 pierre
  498. + GetShortFileName used for tcodeeditor file opening
  499. Revision 1.11 2000/01/05 17:27:20 pierre
  500. + linecomplete arg for ReadlnFromStream
  501. Revision 1.10 2000/01/03 11:38:35 michael
  502. Changes from Gabor
  503. Revision 1.9 1999/12/01 16:19:46 pierre
  504. + GetFileTime moved here
  505. Revision 1.8 1999/10/25 16:39:03 pierre
  506. + GetPChar to avoid nil pointer problems
  507. Revision 1.7 1999/09/13 11:44:00 peter
  508. * fixes from gabor, idle event, html fix
  509. Revision 1.6 1999/08/24 22:01:48 pierre
  510. * readlnfromstream length check added
  511. Revision 1.5 1999/08/03 20:22:45 peter
  512. + TTab acts now on Ctrl+Tab and Ctrl+Shift+Tab...
  513. + Desktop saving should work now
  514. - History saved
  515. - Clipboard content saved
  516. - Desktop saved
  517. - Symbol info saved
  518. * syntax-highlight bug fixed, which compared special keywords case sensitive
  519. (for ex. 'asm' caused asm-highlighting, while 'ASM' didn't)
  520. * with 'whole words only' set, the editor didn't found occourences of the
  521. searched text, if the text appeared previously in the same line, but didn't
  522. satisfied the 'whole-word' condition
  523. * ^QB jumped to (SelStart.X,SelEnd.X) instead of (SelStart.X,SelStart.Y)
  524. (ie. the beginning of the selection)
  525. * when started typing in a new line, but not at the start (X=0) of it,
  526. the editor inserted the text one character more to left as it should...
  527. * TCodeEditor.HideSelection (Ctrl-K+H) didn't update the screen
  528. * Shift shouldn't cause so much trouble in TCodeEditor now...
  529. * Syntax highlight had problems recognizing a special symbol if it was
  530. prefixed by another symbol character in the source text
  531. * Auto-save also occours at Dos shell, Tool execution, etc. now...
  532. Revision 1.4 1999/04/07 21:56:06 peter
  533. + object support for browser
  534. * html help fixes
  535. * more desktop saving things
  536. * NODEBUG directive to exclude debugger
  537. Revision 1.2 1999/03/08 14:58:22 peter
  538. + prompt with dialogs for tools
  539. Revision 1.1 1999/03/01 15:51:43 peter
  540. + Log
  541. }