wutils.pas 33 KB

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