wutils.pas 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267
  1. {
  2. This file is part of the Free Pascal Integrated Development Environment
  3. Copyright (c) 1998 by Berczi Gabor
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit WUtils;
  11. interface
  12. {$ifndef FPC}
  13. {$define TPUNIXLF}
  14. {$endif}
  15. uses
  16. {$ifdef Windows}
  17. windows,
  18. {$endif Windows}
  19. {$ifdef netwlibc}
  20. libc,
  21. {$else}
  22. {$ifdef netware}
  23. nwserv,
  24. {$endif}
  25. {$endif}
  26. {$ifdef Unix}
  27. {$ifdef VER1_0}
  28. linux,
  29. {$else}
  30. baseunix,
  31. unix,
  32. {$endif}
  33. {$endif Unix}
  34. Dos,Objects;
  35. const
  36. kbCtrlGrayPlus = $9000;
  37. kbCtrlGrayMinus = $8e00;
  38. kbCtrlGrayMul = $9600;
  39. TempFirstChar = {$ifndef Unix}'~'{$else}'_'{$endif};
  40. TempExt = '.tmp';
  41. TempNameLen = 8;
  42. EOL : String[2] = {$ifdef Unix}#10;{$else}#13#10;{$endif}
  43. type
  44. PByteArray = ^TByteArray;
  45. TByteArray = array[0..MaxBytes] of byte;
  46. PNoDisposeCollection = ^TNoDisposeCollection;
  47. TNoDisposeCollection = object(TCollection)
  48. procedure FreeItem(Item: Pointer); virtual;
  49. end;
  50. PUnsortedStringCollection = ^TUnsortedStringCollection;
  51. TUnsortedStringCollection = object(TCollection)
  52. constructor CreateFrom(ALines: PUnsortedStringCollection);
  53. procedure Assign(ALines: PUnsortedStringCollection);
  54. function At(Index: Sw_Integer): PString;
  55. procedure FreeItem(Item: Pointer); virtual;
  56. function GetItem(var S: TStream): Pointer; virtual;
  57. procedure PutItem(var S: TStream; Item: Pointer); virtual;
  58. procedure InsertStr(const S: string);
  59. end;
  60. PNulStream = ^TNulStream;
  61. TNulStream = object(TStream)
  62. constructor Init;
  63. function GetPos: Longint; virtual;
  64. function GetSize: Longint; virtual;
  65. procedure Read(var Buf; Count: Word); virtual;
  66. procedure Seek(Pos: Longint); virtual;
  67. procedure Write(var Buf; Count: Word); virtual;
  68. end;
  69. PSubStream = ^TSubStream;
  70. TSubStream = object(TStream)
  71. constructor Init(AStream: PStream; AStartPos, ASize: longint);
  72. function GetPos: Longint; virtual;
  73. function GetSize: Longint; virtual;
  74. procedure Read(var Buf; Count: Word); virtual;
  75. procedure Seek(Pos: Longint); virtual;
  76. procedure Write(var Buf; Count: Word); virtual;
  77. private
  78. StartPos: longint;
  79. S : PStream;
  80. end;
  81. PFastBufStream = ^TFastBufStream;
  82. TFastBufStream = object(TBufStream)
  83. constructor Init (FileName: FNameStr; Mode, Size: Word);
  84. procedure Seek(Pos: Longint); virtual;
  85. procedure Readline(var s:string;var linecomplete,hasCR : boolean);
  86. private
  87. BasePos: longint;
  88. end;
  89. PTextCollection = ^TTextCollection;
  90. TTextCollection = object(TStringCollection)
  91. function LookUp(const S: string; var Idx: sw_integer): string;
  92. function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
  93. end;
  94. PIntCollection = ^TIntCollection;
  95. TIntCollection = object(TSortedCollection)
  96. function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
  97. procedure FreeItem(Item: Pointer); virtual;
  98. procedure Add(Item: ptrint);
  99. function Contains(Item: ptrint): boolean;
  100. function AtInt(Index: sw_integer): ptrint;
  101. end;
  102. {$ifdef TPUNIXLF}
  103. procedure readln(var t:text;var s:string);
  104. {$endif}
  105. procedure ReadlnFromStream(Stream: PStream; var s:string;var linecomplete,hasCR : boolean);
  106. function eofstream(s: pstream): boolean;
  107. function Min(A,B: longint): longint;
  108. function Max(A,B: longint): longint;
  109. function CharStr(C: char; Count: integer): string;
  110. function UpcaseStr(const S: string): string;
  111. function LowCase(C: char): char;
  112. function LowcaseStr(S: string): string;
  113. function RExpand(const S: string; MinLen: byte): string;
  114. function LExpand(const S: string; MinLen: byte): string;
  115. function LTrim(const S: string): string;
  116. function RTrim(const S: string): string;
  117. function Trim(const S: string): string;
  118. function IntToStr(L: longint): string;
  119. function IntToStrL(L: longint; MinLen: sw_integer): string;
  120. function IntToStrZ(L: longint; MinLen: sw_integer): string;
  121. function StrToInt(const S: string): longint;
  122. function StrToCard(const S: string): cardinal;
  123. function FloatToStr(D: Double; Decimals: byte): string;
  124. function FloatToStrL(D: Double; Decimals: byte; MinLen: byte): string;
  125. function GetStr(P: PString): string;
  126. function GetPChar(P: PChar): string;
  127. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  128. function LExtendString(S: string; MinLen: byte): string;
  129. function DirOf(const S: string): string;
  130. function ExtOf(const S: string): string;
  131. function NameOf(const S: string): string;
  132. function NameAndExtOf(const S: string): string;
  133. function DirAndNameOf(const S: string): string;
  134. { return Dos GetFTime value or -1 if the file does not exist }
  135. function GetFileTime(const FileName: string): longint;
  136. { copied from compiler global unit }
  137. function GetShortName(const n:string):string;
  138. function GetLongName(const n:string):string;
  139. function TrimEndSlash(const Path: string): string;
  140. function CompleteDir(const Path: string): string;
  141. function GetCurDir: string;
  142. function OptimizePath(Path: string; MaxLen: integer): string;
  143. function CompareText(S1, S2: string): integer;
  144. function ExistsDir(const DirName: string): boolean;
  145. function ExistsFile(const FileName: string): boolean;
  146. function SizeOfFile(const FileName: string): longint;
  147. function DeleteFile(const FileName: string): integer;
  148. function CopyFile(const SrcFileName, DestFileName: string): boolean;
  149. function GenTempFileName: string;
  150. function FormatPath(Path: string): string;
  151. function CompletePath(const Base, InComplete: string): string;
  152. function CompleteURL(const Base, URLRef: string): string;
  153. function EatIO: integer;
  154. function Now: longint;
  155. function FormatDateTimeL(L: longint; const Format: string): string;
  156. function FormatDateTime(const D: DateTime; const Format: string): string;
  157. {$ifdef TP}
  158. function StrPas(C: PChar): string;
  159. {$endif}
  160. function MemToStr(var B; Count: byte): string;
  161. procedure StrToMem(S: string; var B);
  162. const LastStrToIntResult : integer = 0;
  163. LastHexToIntResult : integer = 0;
  164. LastStrToCardResult : integer = 0;
  165. LastHexToCardResult : integer = 0;
  166. DirSep : char = {$ifdef Unix}'/'{$else}'\'{$endif};
  167. UseOldBufStreamMethod : boolean = false;
  168. procedure RegisterWUtils;
  169. implementation
  170. uses
  171. {$IFDEF OS2}
  172. DosCalls,
  173. {$ENDIF OS2}
  174. Strings;
  175. {$ifndef NOOBJREG}
  176. const
  177. SpaceStr = ' '+
  178. ' '+
  179. ' '+
  180. ' ' ;
  181. RUnsortedStringCollection: TStreamRec = (
  182. ObjType: 22500;
  183. VmtLink: Ofs(TypeOf(TUnsortedStringCollection)^);
  184. Load: @TUnsortedStringCollection.Load;
  185. Store: @TUnsortedStringCollection.Store
  186. );
  187. {$endif}
  188. {$ifdef TPUNIXLF}
  189. procedure readln(var t:text;var s:string);
  190. var
  191. c : char;
  192. i : longint;
  193. begin
  194. if TextRec(t).UserData[1]=2 then
  195. system.readln(t,s)
  196. else
  197. begin
  198. c:=#0;
  199. i:=0;
  200. while (not eof(t)) and (c<>#10) and (i<High(S)) do
  201. begin
  202. read(t,c);
  203. if c<>#10 then
  204. begin
  205. inc(i);
  206. s[i]:=c;
  207. end;
  208. end;
  209. if (i>0) and (s[i]=#13) then
  210. begin
  211. dec(i);
  212. TextRec(t).UserData[1]:=2;
  213. end;
  214. s[0]:=chr(i);
  215. end;
  216. end;
  217. {$endif}
  218. function eofstream(s: pstream): boolean;
  219. begin
  220. eofstream:=(s^.getpos>=s^.getsize);
  221. end;
  222. procedure ReadlnFromStream(Stream: PStream; var S:string;var linecomplete,hasCR : boolean);
  223. var
  224. c : char;
  225. i,pos : longint;
  226. begin
  227. linecomplete:=false;
  228. c:=#0;
  229. i:=0;
  230. { this created problems for lines longer than 255 characters
  231. now those lines are cutted into pieces without warning PM }
  232. { changed implicit 255 to High(S), so it will be automatically extended
  233. when longstrings eventually become default - Gabor }
  234. while (not eofstream(stream)) and (c<>#10) and (i<High(S)) do
  235. begin
  236. stream^.read(c,sizeof(c));
  237. if c<>#10 then
  238. begin
  239. inc(i);
  240. s[i]:=c;
  241. end;
  242. end;
  243. { if there was a CR LF then remove the CR Dos newline style }
  244. if (i>0) and (s[i]=#13) then
  245. begin
  246. dec(i);
  247. end;
  248. if (c=#13) and (not eofstream(stream)) then
  249. stream^.read(c,sizeof(c));
  250. if (i=High(S)) and not eofstream(stream) then
  251. begin
  252. pos:=stream^.getpos;
  253. stream^.read(c,sizeof(c));
  254. if (c=#13) and not eofstream(stream) then
  255. stream^.read(c,sizeof(c));
  256. if c<>#10 then
  257. stream^.seek(pos);
  258. end;
  259. if (c=#10) or eofstream(stream) then
  260. linecomplete:=true;
  261. if (c=#10) then
  262. hasCR:=true;
  263. s[0]:=chr(i);
  264. end;
  265. {$ifdef TP}
  266. { TP's own StrPas() is buggy, because it causes GPF with strings longer than
  267. 255 chars }
  268. function StrPas(C: PChar): string;
  269. var S: string;
  270. I: longint;
  271. begin
  272. if Assigned(C)=false then
  273. S:=''
  274. else
  275. begin
  276. I:=StrLen(C); if I>High(S) then I:=High(S);
  277. S[0]:=chr(I); Move(C^,S[1],I);
  278. end;
  279. StrPas:=S;
  280. end;
  281. {$endif}
  282. function MemToStr(var B; Count: byte): string;
  283. var S: string;
  284. begin
  285. S[0]:=chr(Count);
  286. if Count>0 then Move(B,S[1],Count);
  287. MemToStr:=S;
  288. end;
  289. procedure StrToMem(S: string; var B);
  290. begin
  291. if length(S)>0 then Move(S[1],B,length(S));
  292. end;
  293. function Max(A,B: longint): longint;
  294. begin
  295. if A>B then Max:=A else Max:=B;
  296. end;
  297. function Min(A,B: longint): longint;
  298. begin
  299. if A<B then Min:=A else Min:=B;
  300. end;
  301. function CharStr(C: char; Count: integer): string;
  302. {$ifndef FPC}
  303. var S: string;
  304. {$endif}
  305. begin
  306. if Count<=0 then
  307. begin
  308. CharStr:='';
  309. exit;
  310. end
  311. else if Count>255 then
  312. Count:=255;
  313. {$ifdef FPC}
  314. CharStr[0]:=chr(Count);
  315. FillChar(CharStr[1],Count,C);
  316. {$else}
  317. S[0]:=chr(Count);
  318. FillChar(S[1],Count,C);
  319. CharStr:=S;
  320. {$endif}
  321. end;
  322. function UpcaseStr(const S: string): string;
  323. var
  324. I: Longint;
  325. begin
  326. for I:=1 to length(S) do
  327. if S[I] in ['a'..'z'] then
  328. UpCaseStr[I]:=chr(ord(S[I])-32)
  329. else
  330. UpCaseStr[I]:=S[I];
  331. UpcaseStr[0]:=S[0];
  332. end;
  333. function RExpand(const S: string; MinLen: byte): string;
  334. begin
  335. if length(S)<MinLen then
  336. RExpand:=S+CharStr(' ',MinLen-length(S))
  337. else
  338. RExpand:=S;
  339. end;
  340. function LExpand(const S: string; MinLen: byte): string;
  341. begin
  342. if length(S)<MinLen then
  343. LExpand:=CharStr(' ',MinLen-length(S))+S
  344. else
  345. LExpand:=S;
  346. end;
  347. function LTrim(const S: string): string;
  348. var
  349. i : longint;
  350. begin
  351. i:=1;
  352. while (i<length(s)) and (s[i]=' ') do
  353. inc(i);
  354. LTrim:=Copy(s,i,High(S));
  355. end;
  356. function RTrim(const S: string): string;
  357. var
  358. i : longint;
  359. begin
  360. i:=length(s);
  361. while (i>0) and (s[i]=' ') do
  362. dec(i);
  363. RTrim:=Copy(s,1,i);
  364. end;
  365. function Trim(const S: string): string;
  366. var
  367. i,j : longint;
  368. begin
  369. i:=1;
  370. while (i<length(s)) and (s[i]=' ') do
  371. inc(i);
  372. j:=length(s);
  373. while (j>0) and (s[j]=' ') do
  374. dec(j);
  375. Trim:=Copy(S,i,j-i+1);
  376. end;
  377. function IntToStr(L: longint): string;
  378. var S: string;
  379. begin
  380. Str(L,S);
  381. IntToStr:=S;
  382. end;
  383. function IntToStrL(L: longint; MinLen: sw_integer): string;
  384. begin
  385. IntToStrL:=LExpand(IntToStr(L),MinLen);
  386. end;
  387. function IntToStrZ(L: longint; MinLen: sw_integer): string;
  388. var S: string;
  389. begin
  390. S:=IntToStr(L);
  391. if length(S)<MinLen then
  392. S:=CharStr('0',MinLen-length(S))+S;
  393. IntToStrZ:=S;
  394. end;
  395. function StrToInt(const S: string): longint;
  396. var L: longint;
  397. C: integer;
  398. begin
  399. Val(S,L,C); if C<>0 then L:=-1;
  400. LastStrToIntResult:=C;
  401. StrToInt:=L;
  402. end;
  403. function StrToCard(const S: string): cardinal;
  404. var L: cardinal;
  405. C: integer;
  406. begin
  407. Val(S,L,C); if C<>0 then L:=$ffffffff;
  408. LastStrToCardResult:=C;
  409. StrToCard:=L;
  410. end;
  411. function FloatToStr(D: Double; Decimals: byte): string;
  412. var S: string;
  413. L: byte;
  414. begin
  415. Str(D:0:Decimals,S);
  416. if length(S)>0 then
  417. while (S[1]=' ') do Delete(S,1,1);
  418. FloatToStr:=S;
  419. end;
  420. function FloatToStrL(D: Double; Decimals: byte; MinLen: byte): string;
  421. begin
  422. FloatToStrL:=LExtendString(FloatToStr(D,Decimals),MinLen);
  423. end;
  424. function LExtendString(S: string; MinLen: byte): string;
  425. begin
  426. LExtendString:=copy(SpaceStr,1,MinLen-length(S))+S;
  427. end;
  428. function GetStr(P: PString): string;
  429. begin
  430. if P=nil then GetStr:='' else GetStr:=P^;
  431. end;
  432. function GetPChar(P: PChar): string;
  433. begin
  434. if P=nil then GetPChar:='' else GetPChar:=StrPas(P);
  435. end;
  436. function DirOf(const S: string): string;
  437. var D: DirStr; E: ExtStr; N: NameStr;
  438. begin
  439. FSplit(S,D,N,E);
  440. if (D<>'') and (D[Length(D)]<>DirSep) then
  441. DirOf:=D+DirSep
  442. else
  443. DirOf:=D;
  444. end;
  445. function ExtOf(const S: string): string;
  446. var D: DirStr; E: ExtStr; N: NameStr;
  447. begin
  448. FSplit(S,D,N,E);
  449. ExtOf:=E;
  450. end;
  451. function NameOf(const S: string): string;
  452. var D: DirStr; E: ExtStr; N: NameStr;
  453. begin
  454. FSplit(S,D,N,E);
  455. NameOf:=N;
  456. end;
  457. function NameAndExtOf(const S: string): string;
  458. var D: DirStr; E: ExtStr; N: NameStr;
  459. begin
  460. FSplit(S,D,N,E);
  461. NameAndExtOf:=N+E;
  462. end;
  463. function DirAndNameOf(const S: string): string;
  464. var D: DirStr; E: ExtStr; N: NameStr;
  465. begin
  466. FSplit(S,D,N,E);
  467. DirAndNameOf:=D+N;
  468. end;
  469. { return Dos GetFTime value or -1 if the file does not exist }
  470. function GetFileTime(const FileName: string): longint;
  471. var T: longint;
  472. f: file;
  473. FM: integer;
  474. begin
  475. if FileName='' then
  476. T:=-1
  477. else
  478. begin
  479. FM:=FileMode; FileMode:=0;
  480. EatIO; Dos.DosError:=0;
  481. Assign(f,FileName);
  482. {$I-}
  483. Reset(f);
  484. if InOutRes=0 then
  485. begin
  486. GetFTime(f,T);
  487. Close(f);
  488. end;
  489. {$I+}
  490. if (EatIO<>0) or (Dos.DosError<>0) then T:=-1;
  491. FileMode:=FM;
  492. end;
  493. GetFileTime:=T;
  494. end;
  495. function GetShortName(const n:string):string;
  496. {$ifdef Windows}
  497. var
  498. hs,hs2 : string;
  499. i : longint;
  500. {$endif}
  501. {$ifdef go32v2}
  502. var
  503. hs : string;
  504. {$endif}
  505. begin
  506. GetShortName:=n;
  507. {$ifdef Windows}
  508. hs:=n+#0;
  509. i:=Windows.GetShortPathName(@hs[1],@hs2[1],high(hs2));
  510. if (i>0) and (i<=high(hs2)) then
  511. begin
  512. hs2[0]:=chr(strlen(@hs2[1]));
  513. GetShortName:=hs2;
  514. end;
  515. {$endif}
  516. {$ifdef go32v2}
  517. hs:=n;
  518. if Dos.GetShortName(hs) then
  519. GetShortName:=hs;
  520. {$endif}
  521. end;
  522. function GetLongName(const n:string):string;
  523. {$ifdef Windows}
  524. var
  525. hs : string;
  526. hs2 : Array [0..255] of char;
  527. i : longint;
  528. j : pchar;
  529. {$endif}
  530. {$ifdef go32v2}
  531. var
  532. hs : string;
  533. {$endif}
  534. begin
  535. GetLongName:=n;
  536. {$ifdef Windows}
  537. hs:=n+#0;
  538. i:=Windows.GetFullPathName(@hs[1],256,hs2,j);
  539. if (i>0) and (i<=high(hs)) then
  540. begin
  541. hs:=strpas(hs2);
  542. GetLongName:=hs;
  543. end;
  544. {$endif}
  545. {$ifdef go32v2}
  546. hs:=n;
  547. if Dos.GetLongName(hs) then
  548. GetLongName:=hs;
  549. {$endif}
  550. end;
  551. function EatIO: integer;
  552. begin
  553. EatIO:=IOResult;
  554. end;
  555. function LowCase(C: char): char;
  556. begin
  557. if ('A'<=C) and (C<='Z') then C:=chr(ord(C)+32);
  558. LowCase:=C;
  559. end;
  560. function LowcaseStr(S: string): string;
  561. var I: Longint;
  562. begin
  563. for I:=1 to length(S) do
  564. S[I]:=Lowcase(S[I]);
  565. LowcaseStr:=S;
  566. end;
  567. function BoolToStr(B: boolean; const TrueS, FalseS: string): string;
  568. begin
  569. if B then BoolToStr:=TrueS else BoolToStr:=FalseS;
  570. end;
  571. procedure TNoDisposeCollection.FreeItem(Item: Pointer);
  572. begin
  573. { don't do anything here }
  574. end;
  575. constructor TUnsortedStringCollection.CreateFrom(ALines: PUnsortedStringCollection);
  576. begin
  577. if Assigned(ALines)=false then Fail;
  578. inherited Init(ALines^.Count,ALines^.Count div 10);
  579. Assign(ALines);
  580. end;
  581. procedure TUnsortedStringCollection.Assign(ALines: PUnsortedStringCollection);
  582. procedure AddIt(P: PString); {$ifndef FPC}far;{$endif}
  583. begin
  584. Insert(NewStr(GetStr(P)));
  585. end;
  586. begin
  587. FreeAll;
  588. if Assigned(ALines) then
  589. ALines^.ForEach(@AddIt);
  590. end;
  591. procedure TUnsortedStringCollection.InsertStr(const S: string);
  592. begin
  593. Insert(NewStr(S));
  594. end;
  595. function TUnsortedStringCollection.At(Index: Sw_Integer): PString;
  596. begin
  597. At:=inherited At(Index);
  598. end;
  599. procedure TUnsortedStringCollection.FreeItem(Item: Pointer);
  600. begin
  601. if Item<>nil then DisposeStr(Item);
  602. end;
  603. function TUnsortedStringCollection.GetItem(var S: TStream): Pointer;
  604. begin
  605. GetItem:=S.ReadStr;
  606. end;
  607. procedure TUnsortedStringCollection.PutItem(var S: TStream; Item: Pointer);
  608. begin
  609. S.WriteStr(Item);
  610. end;
  611. function TIntCollection.Contains(Item: ptrint): boolean;
  612. var Index: sw_integer;
  613. begin
  614. Contains:=Search(pointer(Item),Index);
  615. end;
  616. function TIntCollection.AtInt(Index: sw_integer): ptrint;
  617. begin
  618. AtInt:=longint(At(Index));
  619. end;
  620. procedure TIntCollection.Add(Item: ptrint);
  621. begin
  622. Insert(pointer(Item));
  623. end;
  624. function TIntCollection.Compare(Key1, Key2: Pointer): sw_Integer;
  625. var K1: longint absolute Key1;
  626. K2: longint absolute Key2;
  627. R: integer;
  628. begin
  629. if K1<K2 then R:=-1 else
  630. if K1>K2 then R:= 1 else
  631. R:=0;
  632. Compare:=R;
  633. end;
  634. procedure TIntCollection.FreeItem(Item: Pointer);
  635. begin
  636. { do nothing here }
  637. end;
  638. constructor TNulStream.Init;
  639. begin
  640. inherited Init;
  641. Position:=0;
  642. end;
  643. function TNulStream.GetPos: Longint;
  644. begin
  645. GetPos:=Position;
  646. end;
  647. function TNulStream.GetSize: Longint;
  648. begin
  649. GetSize:=Position;
  650. end;
  651. procedure TNulStream.Read(var Buf; Count: Word);
  652. begin
  653. Error(stReadError,0);
  654. end;
  655. procedure TNulStream.Seek(Pos: Longint);
  656. begin
  657. if Pos<=Position then
  658. Position:=Pos;
  659. end;
  660. procedure TNulStream.Write(var Buf; Count: Word);
  661. begin
  662. Inc(Position,Count);
  663. end;
  664. constructor TSubStream.Init(AStream: PStream; AStartPos, ASize: longint);
  665. begin
  666. inherited Init;
  667. if Assigned(AStream)=false then Fail;
  668. S:=AStream; StartPos:=AStartPos; StreamSize:=ASize;
  669. Seek(0);
  670. end;
  671. function TSubStream.GetPos: Longint;
  672. var Pos: longint;
  673. begin
  674. Pos:=S^.GetPos; Dec(Pos,StartPos);
  675. GetPos:=Pos;
  676. end;
  677. function TSubStream.GetSize: Longint;
  678. begin
  679. GetSize:=StreamSize;
  680. end;
  681. procedure TSubStream.Read(var Buf; Count: Word);
  682. var Pos: longint;
  683. RCount: word;
  684. begin
  685. Pos:=GetPos;
  686. if Pos+Count>StreamSize then RCount:=StreamSize-Pos else RCount:=Count;
  687. S^.Read(Buf,RCount);
  688. if RCount<Count then
  689. Error(stReadError,0);
  690. end;
  691. procedure TSubStream.Seek(Pos: Longint);
  692. var RPos: longint;
  693. begin
  694. if (Pos<=StreamSize) then RPos:=Pos else RPos:=StreamSize;
  695. S^.Seek(StartPos+RPos);
  696. end;
  697. procedure TSubStream.Write(var Buf; Count: Word);
  698. begin
  699. S^.Write(Buf,Count);
  700. end;
  701. constructor TFastBufStream.Init (FileName: FNameStr; Mode, Size: Word);
  702. begin
  703. Inherited Init(FileName,Mode,Size);
  704. BasePos:=0;
  705. end;
  706. procedure TFastBufStream.Seek(Pos: Longint);
  707. var RelOfs: longint;
  708. begin
  709. RelOfs:=Pos-BasePos;
  710. if (RelOfs<0) or (RelOfs>=BufEnd) or (BufEnd=0) then
  711. begin
  712. inherited Seek(Pos);
  713. BasePos:=Pos-BufPtr;
  714. end
  715. else
  716. begin
  717. BufPtr:=RelOfs;
  718. Position:=Pos;
  719. end;
  720. end;
  721. procedure TFastBufStream.Readline(var s:string;var linecomplete,hasCR : boolean);
  722. var
  723. c : char;
  724. i,pos,StartPos : longint;
  725. charsInS : boolean;
  726. begin
  727. linecomplete:=false;
  728. c:=#0;
  729. i:=0;
  730. { this created problems for lines longer than 255 characters
  731. now those lines are cutted into pieces without warning PM }
  732. { changed implicit 255 to High(S), so it will be automatically extended
  733. when longstrings eventually become default - Gabor }
  734. if (bufend-bufptr>=High(S)) and (getpos+High(S)<getsize) then
  735. begin
  736. StartPos:=GetPos;
  737. //read(S[1],High(S));
  738. system.move(buffer^[bufptr],S[1],High(S));
  739. charsInS:=true;
  740. end
  741. else
  742. CharsInS:=false;
  743. while (CharsInS or not (getpos>=getsize)) and
  744. (c<>#10) and (i<High(S)) do
  745. begin
  746. if CharsInS then
  747. c:=s[i+1]
  748. else
  749. read(c,sizeof(c));
  750. if c<>#10 then
  751. begin
  752. inc(i);
  753. if not CharsInS then
  754. s[i]:=c;
  755. end;
  756. end;
  757. if CharsInS then
  758. begin
  759. if c=#10 then
  760. Seek(StartPos+i+1)
  761. else
  762. Seek(StartPos+i);
  763. end;
  764. { if there was a CR LF then remove the CR Dos newline style }
  765. if (i>0) and (s[i]=#13) then
  766. begin
  767. dec(i);
  768. end;
  769. if (c=#13) and (not (getpos>=getsize)) then
  770. begin
  771. read(c,sizeof(c));
  772. end;
  773. if (i=High(S)) and not (getpos>=getsize) then
  774. begin
  775. pos:=getpos;
  776. read(c,sizeof(c));
  777. if (c=#13) and not (getpos>=getsize) then
  778. read(c,sizeof(c));
  779. if c<>#10 then
  780. seek(pos);
  781. end;
  782. if (c=#10) or (getpos>=getsize) then
  783. linecomplete:=true;
  784. if (c=#10) then
  785. hasCR:=true;
  786. s[0]:=chr(i);
  787. end;
  788. function TTextCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
  789. var K1: PString absolute Key1;
  790. K2: PString absolute Key2;
  791. R: Sw_integer;
  792. S1,S2: string;
  793. begin
  794. S1:=UpCaseStr(K1^);
  795. S2:=UpCaseStr(K2^);
  796. if S1<S2 then R:=-1 else
  797. if S1>S2 then R:=1 else
  798. R:=0;
  799. Compare:=R;
  800. end;
  801. function TTextCollection.LookUp(const S: string; var Idx: sw_integer): string;
  802. var OLI,ORI,Left,Right,Mid: integer;
  803. {LeftP,RightP,}MidP: PString;
  804. {LeftS,}MidS{,RightS}: string;
  805. FoundS: string;
  806. UpS : string;
  807. begin
  808. Idx:=-1; FoundS:='';
  809. Left:=0; Right:=Count-1;
  810. UpS:=UpCaseStr(S);
  811. while Left<=Right do
  812. begin
  813. OLI:=Left; ORI:=Right;
  814. Mid:=Left+(Right-Left) div 2;
  815. MidP:=At(Mid);
  816. MidS:=UpCaseStr(MidP^);
  817. if copy(MidS,1,length(UpS))=UpS then
  818. begin
  819. Idx:=Mid; FoundS:=GetStr(MidP);
  820. { exit immediately if exact match PM }
  821. If Length(MidS)=Length(UpS) then
  822. break;
  823. end;
  824. if UpS<MidS then
  825. Right:=Mid
  826. else
  827. Left:=Mid;
  828. if (OLI=Left) and (ORI=Right) then
  829. begin
  830. if (Left<Right) then
  831. Left:=Right
  832. else
  833. Break;
  834. end;
  835. end;
  836. LookUp:=FoundS;
  837. end;
  838. function TrimEndSlash(const Path: string): string;
  839. var S: string;
  840. begin
  841. S:=Path;
  842. if (length(S)>0) and (S<>DirSep) and (copy(S,length(S),1)=DirSep) and
  843. (S[length(S)-1]<>':') then
  844. S:=copy(S,1,length(S)-1);
  845. TrimEndSlash:=S;
  846. end;
  847. function CompareText(S1, S2: string): integer;
  848. var R: integer;
  849. begin
  850. S1:=UpcaseStr(S1); S2:=UpcaseStr(S2);
  851. if S1<S2 then R:=-1 else
  852. if S1>S2 then R:= 1 else
  853. R:=0;
  854. CompareText:=R;
  855. end;
  856. function FormatPath(Path: string): string;
  857. var P: sw_integer;
  858. SC: char;
  859. begin
  860. if ord(DirSep)=ord('/') then
  861. SC:='\'
  862. else
  863. SC:='/';
  864. repeat
  865. P:=Pos(SC,Path);
  866. if P>0 then Path[P]:=DirSep;
  867. until P=0;
  868. FormatPath:=Path;
  869. end;
  870. function CompletePath(const Base, InComplete: string): string;
  871. var Drv,BDrv: string[40]; D,BD: DirStr; N,BN: NameStr; E,BE: ExtStr;
  872. P: sw_integer;
  873. Complete: string;
  874. begin
  875. Complete:=FormatPath(InComplete);
  876. FSplit(FormatPath(InComplete),D,N,E);
  877. P:=Pos(':',D); if P=0 then Drv:='' else begin Drv:=copy(D,1,P); Delete(D,1,P); end;
  878. FSplit(FormatPath(Base),BD,BN,BE);
  879. P:=Pos(':',BD); if P=0 then BDrv:='' else begin BDrv:=copy(BD,1,P); Delete(BD,1,P); end;
  880. if copy(D,1,1)<>DirSep then
  881. Complete:=BD+D+N+E;
  882. if Drv='' then
  883. Complete:=BDrv+Complete;
  884. Complete:=FExpand(Complete);
  885. CompletePath:=Complete;
  886. end;
  887. function CompleteURL(const Base, URLRef: string): string;
  888. var P: integer;
  889. Drive: string[20];
  890. IsComplete: boolean;
  891. S: string;
  892. Ref: string;
  893. Bookmark: string;
  894. begin
  895. IsComplete:=false; Ref:=URLRef;
  896. P:=Pos(':',Ref);
  897. if P=0 then Drive:='' else Drive:=UpcaseStr(copy(Ref,1,P-1));
  898. if Drive<>'' then
  899. if (Drive='MAILTO') or (Drive='FTP') or (Drive='HTTP') or
  900. (Drive='GOPHER') or (Drive='FILE') then
  901. IsComplete:=true;
  902. if IsComplete then S:=Ref else
  903. begin
  904. P:=Pos('#',Ref);
  905. if P=0 then
  906. Bookmark:=''
  907. else
  908. begin
  909. Bookmark:=copy(Ref,P+1,length(Ref));
  910. Ref:=copy(Ref,1,P-1);
  911. end;
  912. S:=CompletePath(Base,Ref);
  913. if Bookmark<>'' then
  914. S:=S+'#'+Bookmark;
  915. end;
  916. CompleteURL:=S;
  917. end;
  918. function OptimizePath(Path: string; MaxLen: integer): string;
  919. var i : integer;
  920. BackSlashs : array[1..20] of integer;
  921. BSCount : integer;
  922. Jobbra : boolean;
  923. Jobb, Bal : byte;
  924. Hiba : boolean;
  925. begin
  926. if length(Path)>MaxLen then
  927. begin
  928. BSCount:=0; Jobbra:=true;
  929. for i:=1 to length(Path) do if Path[i]=DirSep then
  930. begin
  931. Inc(BSCount);
  932. BackSlashs[BSCount]:=i;
  933. end;
  934. i:=BSCount div 2;
  935. Hiba:=false;
  936. Bal:=i; Jobb:=i+1;
  937. case i of 0 : ;
  938. 1 : Path:=copy(Path, 1, BackSlashs[1])+'..'+
  939. copy(Path, BackSlashs[2], length(Path));
  940. else begin
  941. while (BackSlashs[Bal]+(length(Path)-BackSlashs[Jobb]) >=
  942. MaxLen) and not Hiba do
  943. begin
  944. if Jobbra then begin
  945. if Jobb<BSCount then inc(Jobb)
  946. else Hiba:=true;
  947. Jobbra:=false;
  948. end
  949. else begin
  950. if Bal>1 then dec(Bal)
  951. else Hiba:=true;
  952. Jobbra:=true;
  953. end;
  954. end;
  955. Path:=copy(Path, 1, BackSlashs[Bal])+'..'+
  956. copy(Path, BackSlashs[Jobb], length(Path));
  957. end;
  958. end;
  959. end;
  960. if length(Path)>MaxLen then
  961. begin
  962. i:=Pos('\..\',Path);
  963. if i>0 then Path:=copy(Path,1,i-1)+'..'+copy(Path,i+length('\..\'),length(Path));
  964. end;
  965. OptimizePath:=Path;
  966. end;
  967. function Now: longint;
  968. var D: DateTime;
  969. W: word;
  970. L: longint;
  971. begin
  972. FillChar(D,sizeof(D),0);
  973. GetDate(D.Year,D.Month,D.Day,W);
  974. GetTime(D.Hour,D.Min,D.Sec,W);
  975. PackTime(D,L);
  976. Now:=L;
  977. end;
  978. function FormatDateTimeL(L: longint; const Format: string): string;
  979. var D: DateTime;
  980. begin
  981. UnpackTime(L,D);
  982. FormatDateTimeL:=FormatDateTime(D,Format);
  983. end;
  984. function FormatDateTime(const D: DateTime; const Format: string): string;
  985. var I: sw_integer;
  986. CurCharStart: sw_integer;
  987. CurChar: char;
  988. CurCharCount: integer;
  989. DateS: string;
  990. C: char;
  991. procedure FlushChars;
  992. var S: string;
  993. I: sw_integer;
  994. begin
  995. S:='';
  996. for I:=1 to CurCharCount do
  997. S:=S+CurChar;
  998. case CurChar of
  999. 'y' : S:=IntToStrL(D.Year,length(S));
  1000. 'm' : S:=IntToStrZ(D.Month,length(S));
  1001. 'd' : S:=IntToStrZ(D.Day,length(S));
  1002. 'h' : S:=IntToStrZ(D.Hour,length(S));
  1003. 'n' : S:=IntToStrZ(D.Min,length(S));
  1004. 's' : S:=IntToStrZ(D.Sec,length(S));
  1005. end;
  1006. DateS:=DateS+S;
  1007. end;
  1008. begin
  1009. DateS:='';
  1010. CurCharStart:=-1; CurCharCount:=0; CurChar:=#0;
  1011. for I:=1 to length(Format) do
  1012. begin
  1013. C:=Format[I];
  1014. if (C<>CurChar) or (CurCharStart=-1) then
  1015. begin
  1016. if CurCharStart<>-1 then FlushChars;
  1017. CurCharCount:=1; CurCharStart:=I;
  1018. end
  1019. else
  1020. Inc(CurCharCount);
  1021. CurChar:=C;
  1022. end;
  1023. FlushChars;
  1024. FormatDateTime:=DateS;
  1025. end;
  1026. function DeleteFile(const FileName: string): integer;
  1027. var f: file;
  1028. begin
  1029. {$I-}
  1030. Assign(f,FileName);
  1031. Erase(f);
  1032. DeleteFile:=EatIO;
  1033. {$I+}
  1034. end;
  1035. function ExistsFile(const FileName: string): boolean;
  1036. var
  1037. Dir : SearchRec;
  1038. begin
  1039. Dos.FindFirst(FileName,Archive+ReadOnly,Dir);
  1040. ExistsFile:=(Dos.DosError=0);
  1041. {$ifdef FPC}
  1042. Dos.FindClose(Dir);
  1043. {$endif def FPC}
  1044. end;
  1045. { returns zero for empty and non existant files }
  1046. function SizeOfFile(const FileName: string): longint;
  1047. var
  1048. Dir : SearchRec;
  1049. begin
  1050. Dos.FindFirst(FileName,Archive+ReadOnly,Dir);
  1051. if (Dos.DosError=0) then
  1052. SizeOfFile:=Dir.Size
  1053. else
  1054. SizeOfFile:=0;
  1055. {$ifdef FPC}
  1056. Dos.FindClose(Dir);
  1057. {$endif def FPC}
  1058. end;
  1059. function ExistsDir(const DirName: string): boolean;
  1060. var
  1061. Dir : SearchRec;
  1062. begin
  1063. Dos.FindFirst(TrimEndSlash(DirName),Directory,Dir);
  1064. { if a file is found it is also reported
  1065. at least for some Dos version
  1066. so we need to check the attributes PM }
  1067. ExistsDir:=(Dos.DosError=0) and ((Dir.attr and Directory) <> 0);
  1068. {$ifdef FPC}
  1069. Dos.FindClose(Dir);
  1070. {$endif def FPC}
  1071. end;
  1072. function CompleteDir(const Path: string): string;
  1073. begin
  1074. { keep c: untouched PM }
  1075. if (Path<>'') and (Path[Length(Path)]<>DirSep) and
  1076. (Path[Length(Path)]<>':') then
  1077. CompleteDir:=Path+DirSep
  1078. else
  1079. CompleteDir:=Path;
  1080. end;
  1081. function GetCurDir: string;
  1082. var S: string;
  1083. begin
  1084. GetDir(0,S);
  1085. if copy(S,length(S),1)<>DirSep then S:=S+DirSep;
  1086. GetCurDir:=S;
  1087. end;
  1088. function GenTempFileName: string;
  1089. var Dir: string;
  1090. Name: string;
  1091. I: integer;
  1092. OK: boolean;
  1093. Path: string;
  1094. begin
  1095. Dir:=GetEnv('TEMP');
  1096. if Dir='' then Dir:=GetEnv('TMP');
  1097. if (Dir<>'') then if not ExistsDir(Dir) then Dir:='';
  1098. if Dir='' then Dir:=GetCurDir;
  1099. repeat
  1100. Name:=TempFirstChar;
  1101. for I:=2 to TempNameLen do
  1102. Name:=Name+chr(ord('a')+random(ord('z')-ord('a')+1));
  1103. Name:=Name+TempExt;
  1104. Path:=CompleteDir(Dir)+Name;
  1105. OK:=not ExistsFile(Path);
  1106. until OK;
  1107. GenTempFileName:=Path;
  1108. end;
  1109. function CopyFile(const SrcFileName, DestFileName: string): boolean;
  1110. var SrcF,DestF: PBufStream;
  1111. OK: boolean;
  1112. begin
  1113. SrcF:=nil; DestF:=nil;
  1114. New(SrcF, Init(SrcFileName,stOpenRead,4096));
  1115. OK:=Assigned(SrcF) and (SrcF^.Status=stOK);
  1116. if OK then
  1117. begin
  1118. New(DestF, Init(DestFileName,stCreate,1024));
  1119. OK:=Assigned(DestF) and (DestF^.Status=stOK);
  1120. end;
  1121. if OK then DestF^.CopyFrom(SrcF^,SrcF^.GetSize);
  1122. if Assigned(DestF) then Dispose(DestF, Done);
  1123. if Assigned(SrcF) then Dispose(SrcF, Done);
  1124. CopyFile:=OK;
  1125. end;
  1126. procedure RegisterWUtils;
  1127. begin
  1128. {$ifndef NOOBJREG}
  1129. RegisterType(RUnsortedStringCollection);
  1130. {$endif}
  1131. end;
  1132. BEGIN
  1133. Randomize;
  1134. END.