wutils.pas 16 KB

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