wutils.pas 29 KB

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