wutils.pas 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  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. Dos,Objects;
  18. type
  19. PByteArray = ^TByteArray;
  20. TByteArray = array[0..MaxBytes] 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. procedure InsertStr(const S: string);
  34. end;
  35. PNulStream = ^TNulStream;
  36. TNulStream = object(TStream)
  37. constructor Init;
  38. function GetPos: Longint; virtual;
  39. function GetSize: Longint; virtual;
  40. procedure Read(var Buf; Count: Word); virtual;
  41. procedure Seek(Pos: Longint); virtual;
  42. procedure Write(var Buf; Count: Word); virtual;
  43. end;
  44. PSubStream = ^TSubStream;
  45. TSubStream = object(TStream)
  46. constructor Init(AStream: PStream; AStartPos, ASize: longint);
  47. function GetPos: Longint; virtual;
  48. function GetSize: Longint; virtual;
  49. procedure Read(var Buf; Count: Word); virtual;
  50. procedure Seek(Pos: Longint); virtual;
  51. procedure Write(var Buf; Count: Word); virtual;
  52. private
  53. StartPos: longint;
  54. S : PStream;
  55. end;
  56. PFastBufStream = ^TFastBufStream;
  57. TFastBufStream = object(TBufStream)
  58. procedure Seek(Pos: Longint); virtual;
  59. private
  60. BasePos: longint;
  61. end;
  62. PTextCollection = ^TTextCollection;
  63. TTextCollection = object(TStringCollection)
  64. function LookUp(const S: string; var Idx: sw_integer): string;
  65. function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
  66. end;
  67. PIntCollection = ^TIntCollection;
  68. TIntCollection = object(TSortedCollection)
  69. function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
  70. procedure FreeItem(Item: Pointer); virtual;
  71. procedure Add(Item: longint);
  72. function Contains(Item: longint): boolean;
  73. function AtInt(Index: sw_integer): longint;
  74. end;
  75. {$ifdef TPUNIXLF}
  76. procedure readln(var t:text;var s:string);
  77. {$endif}
  78. procedure ReadlnFromStream(Stream: PStream; var s:string;var linecomplete : boolean);
  79. function eofstream(s: pstream): boolean;
  80. function Min(A,B: longint): longint;
  81. function Max(A,B: longint): longint;
  82. function CharStr(C: char; Count: integer): string;
  83. function UpcaseStr(const S: string): string;
  84. function LowCase(C: char): char;
  85. function LowcaseStr(S: string): string;
  86. function RExpand(const S: string; MinLen: byte): string;
  87. function LExpand(const S: string; MinLen: byte): string;
  88. function LTrim(const S: string): string;
  89. function RTrim(const S: string): string;
  90. function Trim(const S: string): string;
  91. function IntToStr(L: longint): string;
  92. function IntToStrL(L: longint; MinLen: sw_integer): string;
  93. function IntToStrZ(L: longint; MinLen: sw_integer): string;
  94. function StrToInt(const S: string): longint;
  95. function IntToHex(L: longint; MinLen: integer): string;
  96. function GetStr(P: PString): string;
  97. function GetPChar(P: PChar): string;
  98. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  99. function DirOf(const S: string): string;
  100. function ExtOf(const S: string): string;
  101. function NameOf(const S: string): string;
  102. function NameAndExtOf(const S: string): string;
  103. function DirAndNameOf(const S: string): string;
  104. { return Dos GetFTime value or -1 if the file does not exist }
  105. function GetFileTime(const FileName: string): longint;
  106. { copied from compiler global unit }
  107. function GetShortName(const n:string):string;
  108. function GetLongName(const n:string):string;
  109. function TrimEndSlash(const Path: string): string;
  110. function OptimizePath(Path: string; MaxLen: integer): string;
  111. function CompareText(S1, S2: string): integer;
  112. function FormatPath(Path: string): string;
  113. function CompletePath(const Base, InComplete: string): string;
  114. function CompleteURL(const Base, URLRef: string): string;
  115. function DeleteFile(const FileName: string): integer;
  116. function EatIO: integer;
  117. function Now: longint;
  118. function FormatDateTimeL(L: longint; const Format: string): string;
  119. function FormatDateTime(const D: DateTime; const Format: string): string;
  120. {$ifdef TP}
  121. function StrPas(C: PChar): string;
  122. {$endif}
  123. function MemToStr(var B; Count: byte): string;
  124. procedure StrToMem(S: string; var B);
  125. procedure GiveUpTimeSlice;
  126. const LastStrToIntResult : integer = 0;
  127. DirSep : char = {$ifdef Linux}'/'{$else}'\'{$endif};
  128. procedure RegisterWUtils;
  129. implementation
  130. uses
  131. {$ifdef win32}
  132. windows,
  133. {$endif win32}
  134. Strings;
  135. {$ifndef NOOBJREG}
  136. const
  137. RUnsortedStringCollection: TStreamRec = (
  138. ObjType: 22500;
  139. VmtLink: Ofs(TypeOf(TUnsortedStringCollection)^);
  140. Load: @TUnsortedStringCollection.Load;
  141. Store: @TUnsortedStringCollection.Store
  142. );
  143. {$endif}
  144. {$ifdef TPUNIXLF}
  145. procedure readln(var t:text;var s:string);
  146. var
  147. c : char;
  148. i : longint;
  149. begin
  150. if TextRec(t).UserData[1]=2 then
  151. system.readln(t,s)
  152. else
  153. begin
  154. c:=#0;
  155. i:=0;
  156. while (not eof(t)) and (c<>#10) and (i<High(S)) do
  157. begin
  158. read(t,c);
  159. if c<>#10 then
  160. begin
  161. inc(i);
  162. s[i]:=c;
  163. end;
  164. end;
  165. if (i>0) and (s[i]=#13) then
  166. begin
  167. dec(i);
  168. TextRec(t).UserData[1]:=2;
  169. end;
  170. s[0]:=chr(i);
  171. end;
  172. end;
  173. {$endif}
  174. function eofstream(s: pstream): boolean;
  175. begin
  176. eofstream:=(s^.getpos>=s^.getsize);
  177. end;
  178. procedure ReadlnFromStream(Stream: PStream; var S:string;var linecomplete : boolean);
  179. var
  180. c : char;
  181. i,pos : longint;
  182. begin
  183. linecomplete:=false;
  184. c:=#0;
  185. i:=0;
  186. { this created problems for lines longer than 255 characters
  187. now those lines are cutted into pieces without warning PM }
  188. { changed implicit 255 to High(S), so it will be automatically extended
  189. when longstrings eventually become default - Gabor }
  190. while (not eofstream(stream)) and (c<>#10) and (i<High(S)) do
  191. begin
  192. stream^.read(c,sizeof(c));
  193. if c<>#10 then
  194. begin
  195. inc(i);
  196. s[i]:=c;
  197. end;
  198. end;
  199. { if there was a CR LF then remove the CR Dos newline style }
  200. if (i>0) and (s[i]=#13) then
  201. begin
  202. dec(i);
  203. end;
  204. if (c=#13) and (not eofstream(stream)) then
  205. stream^.read(c,sizeof(c));
  206. if (i=High(S)) and not eofstream(stream) then
  207. begin
  208. pos:=stream^.getpos;
  209. stream^.read(c,sizeof(c));
  210. if (c=#13) and not eofstream(stream) then
  211. stream^.read(c,sizeof(c));
  212. if c<>#10 then
  213. stream^.seek(pos);
  214. end;
  215. if (c=#10) or eofstream(stream) then
  216. linecomplete:=true;
  217. s[0]:=chr(i);
  218. end;
  219. {$ifdef TP}
  220. { TP's own StrPas() is buggy, because it causes GPF with strings longer than
  221. 255 chars }
  222. function StrPas(C: PChar): string;
  223. var S: string;
  224. I: longint;
  225. begin
  226. if Assigned(C)=false then
  227. S:=''
  228. else
  229. begin
  230. I:=StrLen(C); if I>High(S) then I:=High(S);
  231. S[0]:=chr(I); Move(C^,S[1],I);
  232. end;
  233. StrPas:=S;
  234. end;
  235. {$endif}
  236. function MemToStr(var B; Count: byte): string;
  237. var S: string;
  238. begin
  239. S[0]:=chr(Count);
  240. if Count>0 then Move(B,S[1],Count);
  241. MemToStr:=S;
  242. end;
  243. procedure StrToMem(S: string; var B);
  244. begin
  245. if length(S)>0 then Move(S[1],B,length(S));
  246. end;
  247. function Max(A,B: longint): longint;
  248. begin
  249. if A>B then Max:=A else Max:=B;
  250. end;
  251. function Min(A,B: longint): longint;
  252. begin
  253. if A<B then Min:=A else Min:=B;
  254. end;
  255. function CharStr(C: char; Count: integer): string;
  256. {$ifndef FPC}
  257. var S: string;
  258. {$endif}
  259. begin
  260. {$ifdef FPC}
  261. CharStr[0]:=chr(Count);
  262. FillChar(CharStr[1],Count,C);
  263. {$else}
  264. S[0]:=chr(Count);
  265. FillChar(S[1],Count,C);
  266. CharStr:=S;
  267. {$endif}
  268. end;
  269. function UpcaseStr(const S: string): string;
  270. var
  271. I: Longint;
  272. begin
  273. for I:=1 to length(S) do
  274. if S[I] in ['a'..'z'] then
  275. UpCaseStr[I]:=chr(ord(S[I])-32)
  276. else
  277. UpCaseStr[I]:=S[I];
  278. UpcaseStr[0]:=S[0];
  279. end;
  280. function RExpand(const S: string; MinLen: byte): string;
  281. begin
  282. if length(S)<MinLen then
  283. RExpand:=S+CharStr(' ',MinLen-length(S))
  284. else
  285. RExpand:=S;
  286. end;
  287. function LExpand(const S: string; MinLen: byte): string;
  288. begin
  289. if length(S)<MinLen then
  290. LExpand:=CharStr(' ',MinLen-length(S))+S
  291. else
  292. LExpand:=S;
  293. end;
  294. function LTrim(const S: string): string;
  295. var
  296. i : longint;
  297. begin
  298. i:=1;
  299. while (i<length(s)) and (s[i]=' ') do
  300. inc(i);
  301. LTrim:=Copy(s,i,High(S));
  302. end;
  303. function RTrim(const S: string): string;
  304. var
  305. i : longint;
  306. begin
  307. i:=length(s);
  308. while (i>0) and (s[i]=' ') do
  309. dec(i);
  310. RTrim:=Copy(s,1,i);
  311. end;
  312. function Trim(const S: string): string;
  313. begin
  314. Trim:=RTrim(LTrim(S));
  315. end;
  316. function IntToStr(L: longint): string;
  317. var S: string;
  318. begin
  319. Str(L,S);
  320. IntToStr:=S;
  321. end;
  322. function IntToStrL(L: longint; MinLen: sw_integer): string;
  323. begin
  324. IntToStrL:=LExpand(IntToStr(L),MinLen);
  325. end;
  326. function IntToStrZ(L: longint; MinLen: sw_integer): string;
  327. var S: string;
  328. begin
  329. S:=IntToStr(L);
  330. if length(S)<MinLen then
  331. S:=CharStr('0',MinLen-length(S))+S;
  332. IntToStrZ:=S;
  333. end;
  334. function StrToInt(const S: string): longint;
  335. var L: longint;
  336. C: integer;
  337. begin
  338. Val(S,L,C); if C<>0 then L:=-1;
  339. LastStrToIntResult:=C;
  340. StrToInt:=L;
  341. end;
  342. function IntToHex(L: longint; MinLen: integer): string;
  343. const HexNums : string[16] = '0123456789ABCDEF';
  344. var S: string;
  345. R: real;
  346. function DivF(Mit,Mivel: real): longint;
  347. begin
  348. DivF:=trunc(Mit/Mivel);
  349. end;
  350. function ModF(Mit,Mivel: real): longint;
  351. begin
  352. ModF:=trunc(Mit-DivF(Mit,Mivel)*Mivel);
  353. end;
  354. begin
  355. S:='';
  356. R:=L; if R<0 then begin R:=R+2147483647+2147483647+2; end;
  357. repeat
  358. S:=HexNums[ModF(R,16)+1]+S;
  359. R:=DivF(R,16);
  360. until R=0;
  361. while length(S)<MinLen do S:='0'+S;
  362. IntToHex:=S;
  363. end;
  364. function GetStr(P: PString): string;
  365. begin
  366. if P=nil then GetStr:='' else GetStr:=P^;
  367. end;
  368. function GetPChar(P: PChar): string;
  369. begin
  370. if P=nil then GetPChar:='' else GetPChar:=StrPas(P);
  371. end;
  372. function DirOf(const S: string): string;
  373. var D: DirStr; E: ExtStr; N: NameStr;
  374. begin
  375. FSplit(S,D,N,E);
  376. if (D<>'') and (D[Length(D)]<>DirSep) then
  377. DirOf:=D+DirSep
  378. else
  379. DirOf:=D;
  380. end;
  381. function ExtOf(const S: string): string;
  382. var D: DirStr; E: ExtStr; N: NameStr;
  383. begin
  384. FSplit(S,D,N,E);
  385. ExtOf:=E;
  386. end;
  387. function NameOf(const S: string): string;
  388. var D: DirStr; E: ExtStr; N: NameStr;
  389. begin
  390. FSplit(S,D,N,E);
  391. NameOf:=N;
  392. end;
  393. function NameAndExtOf(const S: string): string;
  394. var D: DirStr; E: ExtStr; N: NameStr;
  395. begin
  396. FSplit(S,D,N,E);
  397. NameAndExtOf:=N+E;
  398. end;
  399. function DirAndNameOf(const S: string): string;
  400. var D: DirStr; E: ExtStr; N: NameStr;
  401. begin
  402. FSplit(S,D,N,E);
  403. DirAndNameOf:=D+N;
  404. end;
  405. { return Dos GetFTime value or -1 if the file does not exist }
  406. function GetFileTime(const FileName: string): longint;
  407. var T: longint;
  408. f: file;
  409. FM: integer;
  410. begin
  411. if FileName='' then
  412. T:=-1
  413. else
  414. begin
  415. FM:=FileMode; FileMode:=0;
  416. EatIO; DosError:=0;
  417. Assign(f,FileName);
  418. {$I-}
  419. Reset(f);
  420. if InOutRes=0 then
  421. begin
  422. GetFTime(f,T);
  423. Close(f);
  424. end;
  425. {$I+}
  426. if (EatIO<>0) or (DosError<>0) then T:=-1;
  427. FileMode:=FM;
  428. end;
  429. GetFileTime:=T;
  430. end;
  431. function GetShortName(const n:string):string;
  432. {$ifdef win32}
  433. var
  434. hs,hs2 : string;
  435. i : longint;
  436. {$endif}
  437. {$ifdef go32v2}
  438. var
  439. hs : string;
  440. {$endif}
  441. begin
  442. GetShortName:=n;
  443. {$ifdef win32}
  444. hs:=n+#0;
  445. i:=Windows.GetShortPathName(@hs[1],@hs2[1],high(hs2));
  446. if (i>0) and (i<=high(hs2)) then
  447. begin
  448. hs2[0]:=chr(strlen(@hs2[1]));
  449. GetShortName:=hs2;
  450. end;
  451. {$endif}
  452. {$ifdef go32v2}
  453. hs:=n;
  454. if Dos.GetShortName(hs) then
  455. GetShortName:=hs;
  456. {$endif}
  457. end;
  458. function GetLongName(const n:string):string;
  459. {$ifdef win32}
  460. var
  461. hs : string;
  462. hs2 : Array [0..255] of char;
  463. i : longint;
  464. j : pchar;
  465. {$endif}
  466. {$ifdef go32v2}
  467. var
  468. hs : string;
  469. {$endif}
  470. begin
  471. GetLongName:=n;
  472. {$ifdef win32}
  473. hs:=n+#0;
  474. i:=Windows.GetFullPathName(@hs[1],256,hs2,j);
  475. if (i>0) and (i<=high(hs)) then
  476. begin
  477. hs:=strpas(hs2);
  478. GetLongName:=hs;
  479. end;
  480. {$endif}
  481. {$ifdef go32v2}
  482. hs:=n;
  483. if Dos.GetLongName(hs) then
  484. GetLongName:=hs;
  485. {$endif}
  486. end;
  487. function EatIO: integer;
  488. begin
  489. EatIO:=IOResult;
  490. end;
  491. function LowCase(C: char): char;
  492. begin
  493. if ('A'<=C) and (C<='Z') then C:=chr(ord(C)+32);
  494. LowCase:=C;
  495. end;
  496. function LowcaseStr(S: string): string;
  497. var I: Longint;
  498. begin
  499. for I:=1 to length(S) do
  500. S[I]:=Lowcase(S[I]);
  501. LowcaseStr:=S;
  502. end;
  503. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  504. begin
  505. if B then BoolToStr:=TrueS else BoolToStr:=FalseS;
  506. end;
  507. procedure TNoDisposeCollection.FreeItem(Item: Pointer);
  508. begin
  509. { don't do anything here }
  510. end;
  511. constructor TUnsortedStringCollection.CreateFrom(ALines: PUnsortedStringCollection);
  512. begin
  513. if Assigned(ALines)=false then Fail;
  514. inherited Init(ALines^.Count,ALines^.Count div 10);
  515. Assign(ALines);
  516. end;
  517. procedure TUnsortedStringCollection.Assign(ALines: PUnsortedStringCollection);
  518. procedure AddIt(P: PString); {$ifndef FPC}far;{$endif}
  519. begin
  520. Insert(NewStr(GetStr(P)));
  521. end;
  522. begin
  523. FreeAll;
  524. if Assigned(ALines) then
  525. ALines^.ForEach(@AddIt);
  526. end;
  527. procedure TUnsortedStringCollection.InsertStr(const S: string);
  528. begin
  529. Insert(NewStr(S));
  530. end;
  531. function TUnsortedStringCollection.At(Index: Integer): PString;
  532. begin
  533. At:=inherited At(Index);
  534. end;
  535. procedure TUnsortedStringCollection.FreeItem(Item: Pointer);
  536. begin
  537. if Item<>nil then DisposeStr(Item);
  538. end;
  539. function TUnsortedStringCollection.GetItem(var S: TStream): Pointer;
  540. begin
  541. GetItem:=S.ReadStr;
  542. end;
  543. procedure TUnsortedStringCollection.PutItem(var S: TStream; Item: Pointer);
  544. begin
  545. S.WriteStr(Item);
  546. end;
  547. function TIntCollection.Contains(Item: longint): boolean;
  548. var Index: sw_integer;
  549. begin
  550. Contains:=Search(pointer(Item),Index);
  551. end;
  552. function TIntCollection.AtInt(Index: sw_integer): longint;
  553. begin
  554. AtInt:=longint(At(Index));
  555. end;
  556. procedure TIntCollection.Add(Item: longint);
  557. begin
  558. Insert(pointer(Item));
  559. end;
  560. function TIntCollection.Compare(Key1, Key2: Pointer): sw_Integer;
  561. var K1: longint absolute Key1;
  562. K2: longint absolute Key2;
  563. R: integer;
  564. begin
  565. if K1<K2 then R:=-1 else
  566. if K1>K2 then R:= 1 else
  567. R:=0;
  568. Compare:=R;
  569. end;
  570. procedure TIntCollection.FreeItem(Item: Pointer);
  571. begin
  572. { do nothing here }
  573. end;
  574. constructor TNulStream.Init;
  575. begin
  576. inherited Init;
  577. Position:=0;
  578. end;
  579. function TNulStream.GetPos: Longint;
  580. begin
  581. GetPos:=Position;
  582. end;
  583. function TNulStream.GetSize: Longint;
  584. begin
  585. GetSize:=Position;
  586. end;
  587. procedure TNulStream.Read(var Buf; Count: Word);
  588. begin
  589. Error(stReadError,0);
  590. end;
  591. procedure TNulStream.Seek(Pos: Longint);
  592. begin
  593. if Pos<=Position then
  594. Position:=Pos;
  595. end;
  596. procedure TNulStream.Write(var Buf; Count: Word);
  597. begin
  598. Inc(Position,Count);
  599. end;
  600. constructor TSubStream.Init(AStream: PStream; AStartPos, ASize: longint);
  601. begin
  602. inherited Init;
  603. if Assigned(AStream)=false then Fail;
  604. S:=AStream; StartPos:=AStartPos; StreamSize:=ASize;
  605. Seek(0);
  606. end;
  607. function TSubStream.GetPos: Longint;
  608. var Pos: longint;
  609. begin
  610. Pos:=S^.GetPos; Dec(Pos,StartPos);
  611. GetPos:=Pos;
  612. end;
  613. function TSubStream.GetSize: Longint;
  614. begin
  615. GetSize:=StreamSize;
  616. end;
  617. procedure TSubStream.Read(var Buf; Count: Word);
  618. var Pos: longint;
  619. RCount: word;
  620. begin
  621. Pos:=GetPos;
  622. if Pos+Count>StreamSize then RCount:=StreamSize-Pos else RCount:=Count;
  623. S^.Read(Buf,RCount);
  624. if RCount<Count then
  625. Error(stReadError,0);
  626. end;
  627. procedure TSubStream.Seek(Pos: Longint);
  628. var RPos: longint;
  629. begin
  630. if (Pos<=StreamSize) then RPos:=Pos else RPos:=StreamSize;
  631. S^.Seek(StartPos+RPos);
  632. end;
  633. procedure TSubStream.Write(var Buf; Count: Word);
  634. begin
  635. S^.Write(Buf,Count);
  636. end;
  637. procedure TFastBufStream.Seek(Pos: Longint);
  638. function BufStartPos: longint;
  639. begin
  640. BufStartPos:=Position-BufPtr;
  641. end;
  642. var RelOfs: longint;
  643. begin
  644. RelOfs:=Pos-{BufStartPos}BasePos;
  645. if (RelOfs<0) or (RelOfs>=BufEnd) or (BufEnd=0) then
  646. begin
  647. inherited Seek(Pos);
  648. BasePos:=Pos;
  649. end
  650. else
  651. begin
  652. BufPtr:=RelOfs;
  653. Position:=Pos;
  654. end;
  655. end;
  656. function TTextCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
  657. var K1: PString absolute Key1;
  658. K2: PString absolute Key2;
  659. R: Sw_integer;
  660. S1,S2: string;
  661. begin
  662. S1:=UpCaseStr(K1^);
  663. S2:=UpCaseStr(K2^);
  664. if S1<S2 then R:=-1 else
  665. if S1>S2 then R:=1 else
  666. R:=0;
  667. Compare:=R;
  668. end;
  669. function TTextCollection.LookUp(const S: string; var Idx: sw_integer): string;
  670. var OLI,ORI,Left,Right,Mid: integer;
  671. {LeftP,RightP,}MidP: PString;
  672. {LeftS,}MidS{,RightS}: string;
  673. FoundS: string;
  674. UpS : string;
  675. begin
  676. Idx:=-1; FoundS:='';
  677. Left:=0; Right:=Count-1;
  678. UpS:=UpCaseStr(S);
  679. if Left<Right then
  680. begin
  681. while (Left<Right) do
  682. begin
  683. OLI:=Left; ORI:=Right;
  684. Mid:=Left+(Right-Left) div 2;
  685. { LeftP:=At(Left); RightP:=At(Right); }MidP:=At(Mid);
  686. { LeftS:=UpCaseStr(LeftP^); }MidS:=UpCaseStr(MidP^);
  687. { RightS:=UpCaseStr(RightP^);}
  688. if copy(MidS,1,length(UpS))=UpS then
  689. begin
  690. Idx:=Mid; FoundS:=GetStr(MidP);
  691. end;
  692. { else}
  693. if UpS<MidS then
  694. Right:=Mid
  695. else
  696. Left:=Mid;
  697. if (OLI=Left) and (ORI=Right) then
  698. Break;
  699. end;
  700. end;
  701. LookUp:=FoundS;
  702. end;
  703. function TrimEndSlash(const Path: string): string;
  704. var S: string;
  705. begin
  706. S:=Path;
  707. if (length(S)>0) and (S<>DirSep) and (copy(S,length(S),1)=DirSep) and
  708. (S[length(S)-1]<>':') then
  709. S:=copy(S,1,length(S)-1);
  710. TrimEndSlash:=S;
  711. end;
  712. function CompareText(S1, S2: string): integer;
  713. var R: integer;
  714. begin
  715. S1:=UpcaseStr(S1); S2:=UpcaseStr(S2);
  716. if S1<S2 then R:=-1 else
  717. if S1>S2 then R:= 1 else
  718. R:=0;
  719. CompareText:=R;
  720. end;
  721. function FormatPath(Path: string): string;
  722. var P: sw_integer;
  723. SC: char;
  724. begin
  725. if ord(DirSep)=ord('/') then
  726. SC:='\'
  727. else
  728. SC:='/';
  729. repeat
  730. P:=Pos(SC,Path);
  731. if P>0 then Path[P]:=DirSep;
  732. until P=0;
  733. FormatPath:=Path;
  734. end;
  735. function CompletePath(const Base, InComplete: string): string;
  736. var Drv,BDrv: string[40]; D,BD: DirStr; N,BN: NameStr; E,BE: ExtStr;
  737. P: sw_integer;
  738. Complete: string;
  739. begin
  740. Complete:=FormatPath(InComplete);
  741. FSplit(FormatPath(InComplete),D,N,E);
  742. P:=Pos(':',D); if P=0 then Drv:='' else begin Drv:=copy(D,1,P); Delete(D,1,P); end;
  743. FSplit(FormatPath(Base),BD,BN,BE);
  744. P:=Pos(':',BD); if P=0 then BDrv:='' else begin BDrv:=copy(BD,1,P); Delete(BD,1,P); end;
  745. if copy(D,1,1)<>DirSep then
  746. Complete:=BD+D+N+E;
  747. if Drv='' then
  748. Complete:=BDrv+Complete;
  749. Complete:=FExpand(Complete);
  750. CompletePath:=Complete;
  751. end;
  752. function CompleteURL(const Base, URLRef: string): string;
  753. var P: integer;
  754. Drive: string[20];
  755. IsComplete: boolean;
  756. S: string;
  757. Ref: string;
  758. Bookmark: string;
  759. begin
  760. IsComplete:=false; Ref:=URLRef;
  761. P:=Pos(':',Ref);
  762. if P=0 then Drive:='' else Drive:=UpcaseStr(copy(Ref,1,P-1));
  763. if Drive<>'' then
  764. if (Drive='MAILTO') or (Drive='FTP') or (Drive='HTTP') or
  765. (Drive='GOPHER') or (Drive='FILE') then
  766. IsComplete:=true;
  767. if IsComplete then S:=Ref else
  768. begin
  769. P:=Pos('#',Ref);
  770. if P=0 then
  771. Bookmark:=''
  772. else
  773. begin
  774. Bookmark:=copy(Ref,P+1,length(Ref));
  775. Ref:=copy(Ref,1,P-1);
  776. end;
  777. S:=CompletePath(Base,Ref);
  778. if Bookmark<>'' then
  779. S:=S+'#'+Bookmark;
  780. end;
  781. CompleteURL:=S;
  782. end;
  783. function OptimizePath(Path: string; MaxLen: integer): string;
  784. var i : integer;
  785. BackSlashs : array[1..20] of integer;
  786. BSCount : integer;
  787. Jobbra : boolean;
  788. Jobb, Bal : byte;
  789. Hiba : boolean;
  790. begin
  791. if length(Path)>MaxLen then
  792. begin
  793. BSCount:=0; Jobbra:=true;
  794. for i:=1 to length(Path) do if Path[i]=DirSep then
  795. begin
  796. Inc(BSCount);
  797. BackSlashs[BSCount]:=i;
  798. end;
  799. i:=BSCount div 2;
  800. Hiba:=false;
  801. Bal:=i; Jobb:=i+1;
  802. case i of 0 : ;
  803. 1 : Path:=copy(Path, 1, BackSlashs[1])+'..'+
  804. copy(Path, BackSlashs[2], length(Path));
  805. else begin
  806. while (BackSlashs[Bal]+(length(Path)-BackSlashs[Jobb]) >=
  807. MaxLen) and not Hiba do
  808. begin
  809. if Jobbra then begin
  810. if Jobb<BSCount then inc(Jobb)
  811. else Hiba:=true;
  812. Jobbra:=false;
  813. end
  814. else begin
  815. if Bal>1 then dec(Bal)
  816. else Hiba:=true;
  817. Jobbra:=true;
  818. end;
  819. end;
  820. Path:=copy(Path, 1, BackSlashs[Bal])+'..'+
  821. copy(Path, BackSlashs[Jobb], length(Path));
  822. end;
  823. end;
  824. end;
  825. if length(Path)>MaxLen then
  826. begin
  827. i:=Pos('\..\',Path);
  828. if i>0 then Path:=copy(Path,1,i-1)+'..'+copy(Path,i+length('\..\'),length(Path));
  829. end;
  830. OptimizePath:=Path;
  831. end;
  832. function Now: longint;
  833. var D: DateTime;
  834. W: word;
  835. L: longint;
  836. begin
  837. FillChar(D,sizeof(D),0);
  838. GetDate(D.Year,D.Month,D.Day,W);
  839. GetTime(D.Hour,D.Min,D.Sec,W);
  840. PackTime(D,L);
  841. Now:=L;
  842. end;
  843. function FormatDateTimeL(L: longint; const Format: string): string;
  844. var D: DateTime;
  845. begin
  846. UnpackTime(L,D);
  847. FormatDateTimeL:=FormatDateTime(D,Format);
  848. end;
  849. function FormatDateTime(const D: DateTime; const Format: string): string;
  850. var I: sw_integer;
  851. CurCharStart: sw_integer;
  852. CurChar: char;
  853. CurCharCount: integer;
  854. DateS: string;
  855. C: char;
  856. procedure FlushChars;
  857. var S: string;
  858. I: sw_integer;
  859. begin
  860. S:='';
  861. for I:=1 to CurCharCount do
  862. S:=S+CurChar;
  863. case CurChar of
  864. 'y' : S:=IntToStrL(D.Year,length(S));
  865. 'm' : S:=IntToStrZ(D.Month,length(S));
  866. 'd' : S:=IntToStrZ(D.Day,length(S));
  867. 'h' : S:=IntToStrZ(D.Hour,length(S));
  868. 'n' : S:=IntToStrZ(D.Min,length(S));
  869. 's' : S:=IntToStrZ(D.Sec,length(S));
  870. end;
  871. DateS:=DateS+S;
  872. end;
  873. begin
  874. DateS:='';
  875. CurCharStart:=-1; CurCharCount:=0; CurChar:=#0;
  876. for I:=1 to length(Format) do
  877. begin
  878. C:=Format[I];
  879. if (C<>CurChar) or (CurCharStart=-1) then
  880. begin
  881. if CurCharStart<>-1 then FlushChars;
  882. CurCharCount:=1; CurCharStart:=I;
  883. end
  884. else
  885. Inc(CurCharCount);
  886. CurChar:=C;
  887. end;
  888. FlushChars;
  889. FormatDateTime:=DateS;
  890. end;
  891. function DeleteFile(const FileName: string): integer;
  892. var f: file;
  893. begin
  894. {$I-}
  895. Assign(f,FileName);
  896. Erase(f);
  897. DeleteFile:=EatIO;
  898. {$I+}
  899. end;
  900. procedure GiveUpTimeSlice;
  901. {$ifdef GO32V2}{$define DOS}{$endif}
  902. {$ifdef TP}{$define DOS}{$endif}
  903. {$ifdef DOS}
  904. var r: registers;
  905. begin
  906. r.ax:=$1680;
  907. intr($2f,r);
  908. end;
  909. {$endif}
  910. {$ifdef Linux}
  911. begin
  912. end;
  913. {$endif}
  914. {$ifdef Win32}
  915. begin
  916. end;
  917. {$endif}
  918. {$undef DOS}
  919. procedure RegisterWUtils;
  920. begin
  921. {$ifndef NOOBJREG}
  922. RegisterType(RUnsortedStringCollection);
  923. {$endif}
  924. end;
  925. END.
  926. {
  927. $Log$
  928. Revision 1.1 2000-07-13 09:48:37 michael
  929. + Initial import
  930. Revision 1.27 2000/07/03 08:54:54 pierre
  931. * Some enhancements for WinHelp support by G abor
  932. Revision 1.26 2000/06/26 07:29:23 pierre
  933. * new bunch of Gabor's changes
  934. Revision 1.25 2000/06/22 09:07:15 pierre
  935. * Gabor changes: see fixes.txt
  936. Revision 1.24 2000/06/16 21:16:41 pierre
  937. * allow to read until 255 chars per line
  938. Revision 1.23 2000/06/16 08:50:45 pierre
  939. + new bunch of Gabor's changes
  940. Revision 1.22 2000/05/29 11:09:14 pierre
  941. + New bunch of Gabor's changes: see fixes.txt
  942. Revision 1.21 2000/05/02 08:42:29 pierre
  943. * new set of Gabor changes: see fixes.txt
  944. Revision 1.20 2000/04/25 08:42:36 pierre
  945. * New Gabor changes : see fixes.txt
  946. Revision 1.19 2000/04/18 11:42:39 pierre
  947. lot of Gabor changes : see fixes.txt
  948. Revision 1.18 2000/03/21 23:19:13 pierre
  949. + TrimEndSlash and CompareText by Gabor
  950. Revision 1.17 2000/03/20 19:19:45 pierre
  951. * LFN support in streams
  952. Revision 1.16 2000/03/14 13:36:12 pierre
  953. * error for unexistant file in GetFileTime fixed
  954. Revision 1.15 2000/02/07 11:45:11 pierre
  955. + TUnsortedStringCollection CreateFrom/Assign/GetItem/PutItem from Gabor
  956. Revision 1.14 2000/01/20 00:30:32 pierre
  957. * Result of GetShortPathName is checked
  958. Revision 1.13 2000/01/17 12:20:03 pierre
  959. * uses windows needed for GetShortName
  960. Revision 1.12 2000/01/14 15:36:43 pierre
  961. + GetShortFileName used for tcodeeditor file opening
  962. Revision 1.11 2000/01/05 17:27:20 pierre
  963. + linecomplete arg for ReadlnFromStream
  964. Revision 1.10 2000/01/03 11:38:35 michael
  965. Changes from Gabor
  966. Revision 1.9 1999/12/01 16:19:46 pierre
  967. + GetFileTime moved here
  968. Revision 1.8 1999/10/25 16:39:03 pierre
  969. + GetPChar to avoid nil pointer problems
  970. Revision 1.7 1999/09/13 11:44:00 peter
  971. * fixes from gabor, idle event, html fix
  972. Revision 1.6 1999/08/24 22:01:48 pierre
  973. * readlnfromstream length check added
  974. Revision 1.5 1999/08/03 20:22:45 peter
  975. + TTab acts now on Ctrl+Tab and Ctrl+Shift+Tab...
  976. + Desktop saving should work now
  977. - History saved
  978. - Clipboard content saved
  979. - Desktop saved
  980. - Symbol info saved
  981. * syntax-highlight bug fixed, which compared special keywords case sensitive
  982. (for ex. 'asm' caused asm-highlighting, while 'ASM' didn't)
  983. * with 'whole words only' set, the editor didn't found occourences of the
  984. searched text, if the text appeared previously in the same line, but didn't
  985. satisfied the 'whole-word' condition
  986. * ^QB jumped to (SelStart.X,SelEnd.X) instead of (SelStart.X,SelStart.Y)
  987. (ie. the beginning of the selection)
  988. * when started typing in a new line, but not at the start (X=0) of it,
  989. the editor inserted the text one character more to left as it should...
  990. * TCodeEditor.HideSelection (Ctrl-K+H) didn't update the screen
  991. * Shift shouldn't cause so much trouble in TCodeEditor now...
  992. * Syntax highlight had problems recognizing a special symbol if it was
  993. prefixed by another symbol character in the source text
  994. * Auto-save also occours at Dos shell, Tool execution, etc. now...
  995. Revision 1.4 1999/04/07 21:56:06 peter
  996. + object support for browser
  997. * html help fixes
  998. * more desktop saving things
  999. * NODEBUG directive to exclude debugger
  1000. Revision 1.2 1999/03/08 14:58:22 peter
  1001. + prompt with dialogs for tools
  1002. Revision 1.1 1999/03/01 15:51:43 peter
  1003. + Log
  1004. }