wutils.pas 13 KB

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