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