wutils.pas 32 KB

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