wutils.pas 33 KB

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