wutils.pas 31 KB

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