wutils.pas 30 KB

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