2
0

wutils.pas 31 KB

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