wutils.pas 31 KB

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