wutils.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  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. GetFTime(f,T);
  313. Close(f);
  314. {$I+}
  315. if (EatIO<>0) or (DosError<>0) then T:=-1;
  316. FileMode:=FM;
  317. end;
  318. GetFileTime:=T;
  319. end;
  320. function GetShortName(const n:string):string;
  321. {$ifdef win32}
  322. var
  323. hs,hs2 : string;
  324. i : longint;
  325. {$endif}
  326. {$ifdef go32v2}
  327. var
  328. hs : string;
  329. {$endif}
  330. begin
  331. GetShortName:=n;
  332. {$ifdef win32}
  333. hs:=n+#0;
  334. i:=Windows.GetShortPathName(@hs[1],@hs2[1],high(hs2));
  335. if (i>0) and (i<=high(hs2)) then
  336. begin
  337. hs2[0]:=chr(strlen(@hs2[1]));
  338. GetShortName:=hs2;
  339. end;
  340. {$endif}
  341. {$ifdef go32v2}
  342. hs:=n;
  343. if Dos.GetShortName(hs) then
  344. GetShortName:=hs;
  345. {$endif}
  346. end;
  347. function EatIO: integer;
  348. begin
  349. EatIO:=IOResult;
  350. end;
  351. function LowCase(C: char): char;
  352. begin
  353. if ('A'<=C) and (C<='Z') then C:=chr(ord(C)+32);
  354. LowCase:=C;
  355. end;
  356. function LowcaseStr(S: string): string;
  357. var I: Longint;
  358. begin
  359. for I:=1 to length(S) do
  360. S[I]:=Lowcase(S[I]);
  361. LowcaseStr:=S;
  362. end;
  363. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  364. begin
  365. if B then BoolToStr:=TrueS else BoolToStr:=FalseS;
  366. end;
  367. procedure TNoDisposeCollection.FreeItem(Item: Pointer);
  368. begin
  369. { don't do anything here }
  370. end;
  371. constructor TUnsortedStringCollection.CreateFrom(ALines: PUnsortedStringCollection);
  372. begin
  373. if Assigned(ALines)=false then Fail;
  374. inherited Init(ALines^.Count,ALines^.Count div 10);
  375. Assign(ALines);
  376. end;
  377. procedure TUnsortedStringCollection.Assign(ALines: PUnsortedStringCollection);
  378. procedure AddIt(P: PString); {$ifndef FPC}far;{$endif}
  379. begin
  380. Insert(NewStr(GetStr(P)));
  381. end;
  382. begin
  383. FreeAll;
  384. if Assigned(ALines) then
  385. ALines^.ForEach(@AddIt);
  386. end;
  387. function TUnsortedStringCollection.At(Index: Integer): PString;
  388. begin
  389. At:=inherited At(Index);
  390. end;
  391. procedure TUnsortedStringCollection.FreeItem(Item: Pointer);
  392. begin
  393. if Item<>nil then DisposeStr(Item);
  394. end;
  395. function TUnsortedStringCollection.GetItem(var S: TStream): Pointer;
  396. begin
  397. GetItem:=S.ReadStr;
  398. end;
  399. procedure TUnsortedStringCollection.PutItem(var S: TStream; Item: Pointer);
  400. begin
  401. S.WriteStr(Item);
  402. end;
  403. constructor TNulStream.Init;
  404. begin
  405. inherited Init;
  406. Position:=0;
  407. end;
  408. function TNulStream.GetPos: Longint;
  409. begin
  410. GetPos:=Position;
  411. end;
  412. function TNulStream.GetSize: Longint;
  413. begin
  414. GetSize:=Position;
  415. end;
  416. procedure TNulStream.Read(var Buf; Count: Word);
  417. begin
  418. Error(stReadError,0);
  419. end;
  420. procedure TNulStream.Seek(Pos: Longint);
  421. begin
  422. if Pos<=Position then
  423. Position:=Pos;
  424. end;
  425. procedure TNulStream.Write(var Buf; Count: Word);
  426. begin
  427. Inc(Position,Count);
  428. end;
  429. constructor TSubStream.Init(AStream: PStream; AStartPos, ASize: longint);
  430. begin
  431. inherited Init;
  432. if Assigned(AStream)=false then Fail;
  433. S:=AStream; StartPos:=AStartPos; StreamSize:=ASize;
  434. Seek(0);
  435. end;
  436. function TSubStream.GetPos: Longint;
  437. var Pos: longint;
  438. begin
  439. Pos:=S^.GetPos; Dec(Pos,StartPos);
  440. GetPos:=Pos;
  441. end;
  442. function TSubStream.GetSize: Longint;
  443. begin
  444. GetSize:=StreamSize;
  445. end;
  446. procedure TSubStream.Read(var Buf; Count: Word);
  447. var Pos: longint;
  448. RCount: word;
  449. begin
  450. Pos:=GetPos;
  451. if Pos+Count>StreamSize then RCount:=StreamSize-Pos else RCount:=Count;
  452. S^.Read(Buf,RCount);
  453. if RCount<Count then
  454. Error(stReadError,0);
  455. end;
  456. procedure TSubStream.Seek(Pos: Longint);
  457. var RPos: longint;
  458. begin
  459. if (Pos<=StreamSize) then RPos:=Pos else RPos:=StreamSize;
  460. S^.Seek(StartPos+RPos);
  461. end;
  462. procedure TSubStream.Write(var Buf; Count: Word);
  463. begin
  464. S^.Write(Buf,Count);
  465. end;
  466. function TTextCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
  467. var K1: PString absolute Key1;
  468. K2: PString absolute Key2;
  469. R: Sw_integer;
  470. S1,S2: string;
  471. begin
  472. S1:=UpCaseStr(K1^);
  473. S2:=UpCaseStr(K2^);
  474. if S1<S2 then R:=-1 else
  475. if S1>S2 then R:=1 else
  476. R:=0;
  477. Compare:=R;
  478. end;
  479. function TTextCollection.LookUp(const S: string; var Idx: sw_integer): string;
  480. var OLI,ORI,Left,Right,Mid: integer;
  481. LeftP,RightP,MidP: PString;
  482. RL: integer;
  483. LeftS,MidS,RightS: string;
  484. FoundS: string;
  485. UpS : string;
  486. begin
  487. Idx:=-1; FoundS:='';
  488. Left:=0; Right:=Count-1;
  489. UpS:=UpCaseStr(S);
  490. if Left<Right then
  491. begin
  492. while (Left<Right) do
  493. begin
  494. OLI:=Left; ORI:=Right;
  495. Mid:=Left+(Right-Left) div 2;
  496. LeftP:=At(Left); RightP:=At(Right); MidP:=At(Mid);
  497. LeftS:=UpCaseStr(LeftP^); MidS:=UpCaseStr(MidP^);
  498. RightS:=UpCaseStr(RightP^);
  499. if copy(MidS,1,length(UpS))=UpS then
  500. begin
  501. Idx:=Mid; FoundS:=GetStr(MidP);
  502. end;
  503. { else}
  504. if UpS<MidS then
  505. Right:=Mid
  506. else
  507. Left:=Mid;
  508. if (OLI=Left) and (ORI=Right) then
  509. Break;
  510. end;
  511. end;
  512. LookUp:=FoundS;
  513. end;
  514. procedure GiveUpTimeSlice;
  515. {$ifdef GO32V2}{$define DOS}{$endif}
  516. {$ifdef TP}{$define DOS}{$endif}
  517. {$ifdef DOS}
  518. var r: registers;
  519. begin
  520. r.ax:=$1680;
  521. intr($2f,r);
  522. end;
  523. {$endif}
  524. {$ifdef Linux}
  525. begin
  526. end;
  527. {$endif}
  528. {$ifdef Win32}
  529. begin
  530. end;
  531. {$endif}
  532. {$undef DOS}
  533. procedure RegisterWUtils;
  534. begin
  535. {$ifndef NOOBJREG}
  536. RegisterType(RUnsortedStringCollection);
  537. {$endif}
  538. end;
  539. END.
  540. {
  541. $Log$
  542. Revision 1.15 2000-02-07 11:45:11 pierre
  543. + TUnsortedStringCollection CreateFrom/Assign/GetItem/PutItem from Gabor
  544. Revision 1.14 2000/01/20 00:30:32 pierre
  545. * Result of GetShortPathName is checked
  546. Revision 1.13 2000/01/17 12:20:03 pierre
  547. * uses windows needed for GetShortName
  548. Revision 1.12 2000/01/14 15:36:43 pierre
  549. + GetShortFileName used for tcodeeditor file opening
  550. Revision 1.11 2000/01/05 17:27:20 pierre
  551. + linecomplete arg for ReadlnFromStream
  552. Revision 1.10 2000/01/03 11:38:35 michael
  553. Changes from Gabor
  554. Revision 1.9 1999/12/01 16:19:46 pierre
  555. + GetFileTime moved here
  556. Revision 1.8 1999/10/25 16:39:03 pierre
  557. + GetPChar to avoid nil pointer problems
  558. Revision 1.7 1999/09/13 11:44:00 peter
  559. * fixes from gabor, idle event, html fix
  560. Revision 1.6 1999/08/24 22:01:48 pierre
  561. * readlnfromstream length check added
  562. Revision 1.5 1999/08/03 20:22:45 peter
  563. + TTab acts now on Ctrl+Tab and Ctrl+Shift+Tab...
  564. + Desktop saving should work now
  565. - History saved
  566. - Clipboard content saved
  567. - Desktop saved
  568. - Symbol info saved
  569. * syntax-highlight bug fixed, which compared special keywords case sensitive
  570. (for ex. 'asm' caused asm-highlighting, while 'ASM' didn't)
  571. * with 'whole words only' set, the editor didn't found occourences of the
  572. searched text, if the text appeared previously in the same line, but didn't
  573. satisfied the 'whole-word' condition
  574. * ^QB jumped to (SelStart.X,SelEnd.X) instead of (SelStart.X,SelStart.Y)
  575. (ie. the beginning of the selection)
  576. * when started typing in a new line, but not at the start (X=0) of it,
  577. the editor inserted the text one character more to left as it should...
  578. * TCodeEditor.HideSelection (Ctrl-K+H) didn't update the screen
  579. * Shift shouldn't cause so much trouble in TCodeEditor now...
  580. * Syntax highlight had problems recognizing a special symbol if it was
  581. prefixed by another symbol character in the source text
  582. * Auto-save also occours at Dos shell, Tool execution, etc. now...
  583. Revision 1.4 1999/04/07 21:56:06 peter
  584. + object support for browser
  585. * html help fixes
  586. * more desktop saving things
  587. * NODEBUG directive to exclude debugger
  588. Revision 1.2 1999/03/08 14:58:22 peter
  589. + prompt with dialogs for tools
  590. Revision 1.1 1999/03/01 15:51:43 peter
  591. + Log
  592. }