wutils.pas 36 KB

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