wutils.pas 30 KB

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