wutils.pas 32 KB

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