whlpview.pas 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998 by Berczi Gabor
  5. Help display objects
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit WHlpView;
  13. interface
  14. uses
  15. Objects,Drivers,Commands,Views,
  16. {$ifdef EDITORS}
  17. Editors,
  18. {$else}
  19. WEditor,
  20. {$endif}
  21. WUtils,WHelp;
  22. {$IFNDEF EDITORS}
  23. type
  24. TEditor = TCodeEditor; PEditor = PCodeEditor;
  25. {$ENDIF}
  26. const
  27. cmPrevTopic = 90;
  28. HistorySize = 30;
  29. CHelpViewer = #33#34#35#36;
  30. CHelpFrame = #37#37#38#38#39;
  31. cmHelpFilesChanged = 57340;
  32. type
  33. PHelpLink = ^THelpLink;
  34. THelpLink = record
  35. Bounds : TRect;
  36. FileID : longint;
  37. Context : THelpCtx;
  38. end;
  39. PHelpColorArea = ^THelpColorArea;
  40. THelpColorArea = record
  41. Color : byte;
  42. Bounds : TRect;
  43. end;
  44. PHelpKeyword = ^THelpKeyword;
  45. THelpKeyword = record
  46. KWord : PString;
  47. Index : sw_integer;
  48. end;
  49. PLinkCollection = ^TLinkCollection;
  50. TLinkCollection = object(TCollection)
  51. procedure FreeItem(Item: Pointer); virtual;
  52. end;
  53. PColorAreaCollection = ^TColorAreaCollection;
  54. TColorAreaCollection = object(TCollection)
  55. procedure FreeItem(Item: Pointer); virtual;
  56. end;
  57. PKeywordCollection = ^TKeywordCollection;
  58. TKeywordCollection = object({TSorted}TCollection)
  59. function At(Index: sw_Integer): PHelpKeyword;
  60. procedure FreeItem(Item: Pointer); virtual;
  61. function Compare(Key1, Key2: Pointer): sw_Integer; virtual;
  62. end;
  63. { TSearchRelation = (srEqual,srGreater,srLess,srGreatEqu,srLessEqu);
  64. PAdvancedStringCollection = ^TAdvancedStringCollection;
  65. TAdvancedStringCollection = object(TStringCollection)
  66. function SearchItem(Key: pointer; Rel: TSearchRelation; var Index: integer): boolean; virtual;
  67. end;}
  68. PHelpTopic = ^THelpTopic;
  69. THelpTopic = object(TObject)
  70. Topic: PTopic;
  71. Lines: PUnsortedStringCollection;
  72. Links: PLinkCollection;
  73. ColorAreas: PColorAreaCollection;
  74. constructor Init(ATopic: PTopic);
  75. procedure SetParams(AMargin, AWidth: sw_integer); virtual;
  76. function GetLineCount: sw_integer; virtual;
  77. function GetLineText(Line: sw_integer): string; virtual;
  78. function GetLinkCount: sw_integer; virtual;
  79. procedure GetLinkBounds(Index: sw_integer; var R: TRect); virtual;
  80. function GetLinkFileID(Index: sw_integer): word; virtual;
  81. function GetLinkContext(Index: sw_integer): THelpCtx; virtual;
  82. function GetColorAreaCount: sw_integer; virtual;
  83. procedure GetColorAreaBounds(Index: sw_integer; var R: TRect); virtual;
  84. function GetColorAreaColor(Index: sw_integer): word; virtual;
  85. destructor Done; virtual;
  86. private
  87. Width,Margin: sw_integer;
  88. StockItem: boolean;
  89. procedure ReBuild;
  90. end;
  91. THelpHistoryEntry = record
  92. Context_ : THelpCtx;
  93. Delta_ : TPoint;
  94. CurPos_ : TPoint;
  95. CurLink_ : sw_integer;
  96. FileID_ : word;
  97. end;
  98. PHelpViewer = ^THelpViewer;
  99. THelpViewer = object(TEditor)
  100. Margin: sw_integer;
  101. HelpTopic: PHelpTopic;
  102. CurLink: sw_integer;
  103. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  104. procedure ChangeBounds(var Bounds: TRect); virtual;
  105. procedure Draw; virtual;
  106. procedure HandleEvent(var Event: TEvent); virtual;
  107. procedure SetCurPtr(X,Y: sw_integer); virtual;
  108. function GetLineCount: sw_integer; virtual;
  109. function GetLineText(Line: sw_integer): string; virtual;
  110. function GetLinkCount: sw_integer; virtual;
  111. procedure GetLinkBounds(Index: sw_integer; var R: TRect); virtual;
  112. function GetLinkFileID(Index: sw_integer): word; virtual;
  113. function GetLinkContext(Index: sw_integer): THelpCtx; virtual;
  114. function GetLinkText(Index: sw_integer): string; virtual;
  115. function GetColorAreaCount: sw_integer; virtual;
  116. procedure GetColorAreaBounds(Index: sw_integer; var R: TRect); virtual;
  117. function GetColorAreaColor(Index: sw_integer): word; virtual;
  118. procedure SelectNextLink(ANext: boolean); virtual;
  119. procedure SwitchToIndex; virtual;
  120. procedure SwitchToTopic(SourceFileID: word; Context: THelpCtx); virtual;
  121. procedure SetTopic(Topic: PTopic); virtual;
  122. procedure SetCurLink(Link: sw_integer); virtual;
  123. procedure SelectLink(Index: sw_integer); virtual;
  124. procedure PrevTopic; virtual;
  125. procedure RenderTopic; virtual;
  126. procedure Lookup(S: string); virtual;
  127. function GetPalette: PPalette; virtual;
  128. constructor Load(var S: TStream);
  129. procedure Store(var S: TStream);
  130. destructor Done; virtual;
  131. private
  132. History : array[0..HistorySize] of THelpHistoryEntry;
  133. HistoryPtr : integer;
  134. WordList : PKeywordCollection;
  135. Lookupword : string;
  136. InLookUp : boolean;
  137. IndexTopic : PTopic;
  138. IndexHelpTopic: PHelpTopic;
  139. function LinkContainsPoint(var R: TRect; var P: TPoint): boolean;
  140. procedure ISwitchToTopic(SourceFileID: word; Context: THelpCtx; RecordInHistory: boolean);
  141. procedure ISwitchToTopicPtr(P: PTopic; RecordInHistory: boolean);
  142. procedure BuildTopicWordList;
  143. end;
  144. PHelpFrame = ^THelpFrame;
  145. THelpFrame = object(TFrame)
  146. function GetPalette: PPalette; virtual;
  147. end;
  148. PHelpWindow = ^THelpWindow;
  149. THelpWindow = object(TWindow)
  150. HSB,VSB : PScrollBar;
  151. HelpView: PHelpViewer;
  152. HideOnClose: boolean;
  153. constructor Init(var Bounds: TRect; ATitle: TTitleStr; ASourceFileID: word; AContext: THelpCtx; ANumber: Integer);
  154. procedure InitFrame; virtual;
  155. procedure InitScrollBars; virtual;
  156. procedure InitHelpView; virtual;
  157. procedure ShowIndex; virtual;
  158. procedure ShowTopic(SourceFileID: word; Context: THelpCtx); virtual;
  159. procedure HandleEvent(var Event: TEvent); virtual;
  160. procedure Close; virtual;
  161. function GetPalette: PPalette; virtual; { needs to be overriden }
  162. end;
  163. implementation
  164. uses
  165. Video,
  166. WViews;
  167. const CommentColor = Blue;
  168. function NewLink(FileID: longint; Topic: THelpCtx; StartP, EndP: TPoint): PHelpLink;
  169. var P: PHelpLink;
  170. begin
  171. New(P); FillChar(P^, SizeOf(P^), 0);
  172. P^.FileID:=FileID;
  173. P^.Context:=Topic; P^.Bounds.A:=StartP; P^.Bounds.B:=EndP;
  174. NewLink:=P;
  175. end;
  176. procedure DisposeLink(P: PHelpLink);
  177. begin
  178. if P<>nil then Dispose(P);
  179. end;
  180. function NewColorArea(Color: byte; StartP, EndP: TPoint): PHelpColorArea;
  181. var P: PHelpColorArea;
  182. begin
  183. New(P); FillChar(P^, SizeOf(P^), 0);
  184. P^.Color:=Color; P^.Bounds.A:=StartP; P^.Bounds.B:=EndP;
  185. NewColorArea:=P;
  186. end;
  187. procedure DisposeColorArea(P: PHelpColorArea);
  188. begin
  189. if P<>nil then Dispose(P);
  190. end;
  191. function NewKeyword(Index: sw_integer; KWord: string): PHelpKeyword;
  192. var P: PHelpKeyword;
  193. begin
  194. New(P); FillChar(P^, SizeOf(P^), 0);
  195. P^.Index:=Index; P^.KWord:=NewStr(KWord);
  196. NewKeyword:=P;
  197. end;
  198. procedure DisposeKeyword(P: PHelpKeyword);
  199. begin
  200. if P<>nil then
  201. begin
  202. if P^.KWord<>nil then DisposeStr(P^.KWord);
  203. Dispose(P);
  204. end;
  205. end;
  206. procedure TLinkCollection.FreeItem(Item: Pointer);
  207. begin
  208. if Item<>nil then DisposeLink(Item);
  209. end;
  210. procedure TColorAreaCollection.FreeItem(Item: Pointer);
  211. begin
  212. if Item<>nil then DisposeColorArea(Item);
  213. end;
  214. function TKeywordCollection.At(Index: sw_Integer): PHelpKeyword;
  215. begin
  216. At:=inherited At(Index);
  217. end;
  218. procedure TKeywordCollection.FreeItem(Item: Pointer);
  219. begin
  220. if Item<>nil then DisposeKeyword(Item);
  221. end;
  222. function TKeywordCollection.Compare(Key1, Key2: Pointer): sw_Integer;
  223. var R: sw_integer;
  224. K1: PHelpKeyword absolute Key1;
  225. K2: PHelpKeyword absolute Key2;
  226. S1,S2: string;
  227. begin
  228. S1:=UpcaseStr(K1^.KWord^); S2:=UpcaseStr(K2^.KWord^);
  229. if S1<S2 then R:=-1 else
  230. if S1>S2 then R:=1 else
  231. R:=0;
  232. Compare:=R;
  233. end;
  234. {function TAdvancedStringCollection.SearchItem(Key: pointer; Rel: TSearchRelation; var Index: sw_integer): boolean;
  235. var
  236. L, H, I, C: sw_Integer;
  237. const resSmaller = -1; resEqual = 0; resGreater = 1;
  238. begin
  239. Index:=-1;
  240. case Rel of
  241. srEqual :
  242. while (L <= H) and (Index=-1) do
  243. begin
  244. I := (L + H) shr 1;
  245. C := Compare(KeyOf(Items^[I]), Key);
  246. if C = resSmaller then L := I + 1 else
  247. begin
  248. H := I - 1;
  249. if C = resEqual then
  250. begin
  251. if not Duplicates then L := I;
  252. Index := L;
  253. end;
  254. end;
  255. end;
  256. srGreater :
  257. begin
  258. end;
  259. srLess :
  260. ;
  261. srGreatEqu :
  262. ;
  263. srLessEqu :
  264. ;
  265. else Exit;
  266. end;
  267. Search:=Index<>-1;
  268. end;}
  269. constructor THelpTopic.Init(ATopic: PTopic);
  270. begin
  271. inherited Init;
  272. Topic:=ATopic;
  273. New(Lines, Init(100,100)); New(Links, Init(50,50)); New(ColorAreas, Init(50,50));
  274. end;
  275. procedure THelpTopic.SetParams(AMargin, AWidth: sw_integer);
  276. begin
  277. if Width<>AWidth then
  278. begin
  279. Width:=AWidth; Margin:=AMargin;
  280. ReBuild;
  281. end;
  282. end;
  283. procedure THelpTopic.ReBuild;
  284. var TextPos,LinkNo: sw_word;
  285. Line,CurWord: string;
  286. C: char;
  287. InLink,InColorArea: boolean;
  288. LinkStart,LinkEnd,ColorAreaStart,ColorAreaEnd: TPoint;
  289. CurPos: TPoint;
  290. ZeroLevel: sw_integer;
  291. LineStart,NextLineStart: sw_integer;
  292. LineAlign : (laLeft,laCenter,laRight);
  293. FirstLink,LastLink: sw_integer;
  294. procedure ClearLine;
  295. begin
  296. Line:='';
  297. end;
  298. procedure AddWord(TheWord: string); forward;
  299. procedure NextLine;
  300. var P: sw_integer;
  301. I,Delta: sw_integer;
  302. begin
  303. Line:=CharStr(' ',Margin)+Line;
  304. repeat
  305. P:=Pos(#255,Line);
  306. if P>0 then Line[P]:=#32;
  307. until P=0;
  308. while copy(Line,length(Line),1)=' ' do Delete(Line,length(Line),1);
  309. Delta:=0;
  310. if Line<>'' then
  311. case LineAlign of
  312. laLeft : ;
  313. laCenter : if Margin+length(Line)+Margin<Width then
  314. begin
  315. Delta:=(Width-(Margin+length(Line)+Margin)) div 2;
  316. Line:=CharStr(' ',Delta)+Line;
  317. end;
  318. laRight : if Margin+length(Line)+Margin<Width then
  319. begin
  320. Delta:=Width-(Margin+length(Line)+Margin);
  321. Line:=CharStr(' ',Delta)+Line;
  322. end;
  323. end;
  324. if (Delta>0) and (FirstLink<>LastLink) then
  325. for I:=FirstLink to LastLink-1 do
  326. with PHelpLink(Links^.At(I))^ do
  327. Bounds.Move(Delta,0);
  328. if Line='' then Line:=' ';
  329. Lines^.Insert(NewStr(Line));
  330. ClearLine;
  331. LineStart:=NextLineStart;
  332. CurPos.X:=Margin+LineStart; Line:=CharStr(#255,LineStart); Inc(CurPos.Y);
  333. if InLink then LinkStart:=CurPos;
  334. FirstLink:=LastLink;
  335. end;
  336. procedure FlushLine;
  337. var W: string;
  338. begin
  339. if CurWord<>'' then begin W:=CurWord; CurWord:=''; AddWord(W); end;
  340. NextLine;
  341. end;
  342. procedure AddWord(TheWord: string);
  343. var W: string;
  344. begin
  345. W:=TheWord;
  346. while (length(W)>0) and (W[length(W)] in [' ',#255]) do
  347. Delete(W,length(W),1);
  348. if (copy(Line+TheWord,1,1)<>' ') then
  349. if (Line<>'') and (Margin+length(Line)+length(W)+Margin>Width) then
  350. NextLine;
  351. Line:=Line+TheWord;
  352. CurPos.X:=Margin+length(Line);
  353. end;
  354. procedure CheckZeroLevel;
  355. begin
  356. if ZeroLevel<>0 then
  357. begin
  358. if CurWord<>'' then AddWord(CurWord+' ');
  359. CurWord:='';
  360. ZeroLevel:=0;
  361. end;
  362. end;
  363. begin
  364. Lines^.FreeAll; Links^.FreeAll;
  365. if Topic=nil then Lines^.Insert(NewStr('No help available for this topic.')) else
  366. begin
  367. LineStart:=0; NextLineStart:=0;
  368. TextPos:=0; ClearLine; CurWord:=''; Line:='';
  369. CurPos.X:=Margin+LineStart; CurPos.Y:=0; LinkNo:=0;
  370. InLink:=false; InColorArea:=false; ZeroLevel:=0;
  371. LineAlign:=laLeft;
  372. FirstLink:=0; LastLink:=0;
  373. while (TextPos<Topic^.TextSize) do
  374. begin
  375. C:=chr(PByteArray(Topic^.Text)^[TextPos]);
  376. case C of
  377. hscLineBreak :
  378. {if ZeroLevel=0 then ZeroLevel:=1 else
  379. begin FlushLine; FlushLine; ZeroLevel:=0; end;}
  380. if InLink then CurWord:=CurWord+' ' else
  381. begin
  382. NextLineStart:=0;
  383. FlushLine;
  384. LineStart:=0;
  385. LineAlign:=laLeft;
  386. end;
  387. #1 : Break;
  388. hscLink :
  389. begin
  390. CheckZeroLevel;
  391. if InLink=false then
  392. begin LinkStart:=CurPos; InLink:=true; end else
  393. begin
  394. if CurWord<>'' then AddWord(CurWord); CurWord:='';
  395. LinkEnd:=CurPos; Dec(LinkEnd.X);
  396. if Topic^.Links<>nil then
  397. begin
  398. Inc(LastLink);
  399. if LinkNo<Topic^.LinkCount then
  400. Links^.Insert(NewLink(Topic^.Links^[LinkNo].FileID,
  401. Topic^.Links^[LinkNo].Context,LinkStart,LinkEnd));
  402. Inc(LinkNo);
  403. end;
  404. InLink:=false;
  405. end;
  406. end;
  407. hscLineStart :
  408. begin
  409. NextLineStart:=length(Line)+length(CurWord);
  410. { LineStart:=LineStart+(NextLineStart-LineStart);}
  411. end;
  412. hscCode :
  413. begin
  414. if InColorArea=false then
  415. ColorAreaStart:=CurPos else
  416. begin
  417. if CurWord<>'' then AddWord(CurWord); CurWord:='';
  418. ColorAreaEnd:=CurPos; Dec(ColorAreaEnd.X);
  419. ColorAreas^.Insert(NewColorArea(CommentColor,ColorAreaStart,ColorAreaEnd));
  420. end;
  421. InColorArea:=not InColorArea;
  422. end;
  423. hscCenter :
  424. LineAlign:=laCenter;
  425. hscRight :
  426. LineAlign:=laCenter;
  427. #32: if InLink then CurWord:=CurWord+C else
  428. begin CheckZeroLevel; AddWord(CurWord+C); CurWord:=''; end;
  429. else begin CheckZeroLevel; CurWord:=CurWord+C; end;
  430. end;
  431. CurPos.X:=Margin+length(Line)+length(CurWord);
  432. Inc(TextPos);
  433. end;
  434. if (Line<>'') or (CurWord<>'') then FlushLine;
  435. end;
  436. end;
  437. function THelpTopic.GetLineCount: sw_integer;
  438. begin
  439. GetLineCount:=Lines^.Count;
  440. end;
  441. function THelpTopic.GetLineText(Line: sw_integer): string;
  442. var S: string;
  443. begin
  444. if Line<GetLineCount then S:=PString(Lines^.At(Line))^ else S:='';
  445. GetLineText:=S;
  446. end;
  447. function THelpTopic.GetLinkCount: sw_integer;
  448. begin
  449. GetLinkCount:=Links^.Count;
  450. end;
  451. procedure THelpTopic.GetLinkBounds(Index: sw_integer; var R: TRect);
  452. var P: PHelpLink;
  453. begin
  454. P:=Links^.At(Index);
  455. R:=P^.Bounds;
  456. end;
  457. function THelpTopic.GetLinkFileID(Index: sw_integer): word;
  458. var P: PHelpLink;
  459. begin
  460. P:=Links^.At(Index);
  461. GetLinkFileID:=P^.FileID;
  462. end;
  463. function THelpTopic.GetLinkContext(Index: sw_integer): THelpCtx;
  464. var P: PHelpLink;
  465. begin
  466. P:=Links^.At(Index);
  467. GetLinkContext:=P^.Context;
  468. end;
  469. function THelpTopic.GetColorAreaCount: sw_integer;
  470. begin
  471. GetColorAreaCount:=ColorAreas^.Count;
  472. end;
  473. procedure THelpTopic.GetColorAreaBounds(Index: sw_integer; var R: TRect);
  474. var P: PHelpColorArea;
  475. begin
  476. P:=ColorAreas^.At(Index);
  477. R:=P^.Bounds;
  478. end;
  479. function THelpTopic.GetColorAreaColor(Index: sw_integer): word;
  480. var P: PHelpColorArea;
  481. begin
  482. P:=ColorAreas^.At(Index);
  483. GetColorAreaColor:=P^.Color;
  484. end;
  485. destructor THelpTopic.Done;
  486. begin
  487. inherited Done;
  488. Dispose(Lines, Done); Dispose(Links, Done); Dispose(ColorAreas, Done);
  489. if (Topic<>nil) then DisposeTopic(Topic);
  490. end;
  491. constructor THelpViewer.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  492. begin
  493. inherited Init(Bounds, AHScrollBar, AVScrollBar, nil, 0);
  494. Flags:=efInsertMode; IsReadOnly:=true;
  495. New(WordList, Init(50,50));
  496. Margin:=1; CurLink:=-1;
  497. end;
  498. procedure THelpViewer.ChangeBounds(var Bounds: TRect);
  499. begin
  500. if Owner<>nil then Owner^.Lock;
  501. inherited ChangeBounds(Bounds);
  502. if (HelpTopic<>nil) and (HelpTopic^.Topic<>nil) and
  503. (HelpTopic^.Topic^.FileID<>0) then RenderTopic;
  504. if Owner<>nil then Owner^.UnLock;
  505. end;
  506. procedure THelpViewer.RenderTopic;
  507. begin
  508. if HelpTopic<>nil then
  509. HelpTopic^.SetParams(Margin,Size.X);
  510. {$ifndef EDITORS}
  511. SetLimit(255,GetLineCount);
  512. {$endif}
  513. DrawView;
  514. end;
  515. function THelpViewer.LinkContainsPoint(var R: TRect; var P: TPoint): boolean;
  516. var OK: boolean;
  517. begin
  518. if (R.A.Y=R.B.Y) then
  519. OK:= (P.Y=R.A.Y) and (R.A.X<=P.X) and (P.X<=R.B.X) else
  520. OK:=
  521. ( (R.A.Y=P.Y) and (R.A.X<=P.X) ) or
  522. ( (R.A.Y<P.Y) and (P.Y<R.B.Y) ) or
  523. ( (R.B.Y=P.Y) and (P.X<=R.B.X) );
  524. LinkContainsPoint:=OK;
  525. end;
  526. procedure THelpViewer.SetCurPtr(X,Y: sw_integer);
  527. var OldCurLink,I: sw_integer;
  528. OldPos,P: TPoint;
  529. R: TRect;
  530. begin
  531. OldPos:=CurPos;
  532. OldCurLink:=CurLink;
  533. inherited SetCurPtr(X,Y);
  534. CurLink:=-1;
  535. P:=CurPos;
  536. for I:=0 to GetLinkCount-1 do
  537. begin
  538. GetLinkBounds(I,R);
  539. if LinkContainsPoint(R,P) then
  540. begin CurLink:=I; Break; end;
  541. end;
  542. if OldCurLink<>CurLink then DrawView;
  543. if ((OldPos.X<>CurPos.X) or (OldPos.Y<>CurPos.Y)) and (InLookup=false) then
  544. Lookup('');
  545. end;
  546. function THelpViewer.GetLineCount: sw_integer;
  547. var Count: sw_integer;
  548. begin
  549. if HelpTopic=nil then Count:=0 else Count:=HelpTopic^.GetLineCount;
  550. GetLineCount:=Count;
  551. end;
  552. function THelpViewer.GetLineText(Line: sw_integer): string;
  553. var S: string;
  554. begin
  555. if HelpTopic=nil then S:='' else S:=HelpTopic^.GetLineText(Line);
  556. GetLineText:=S;
  557. end;
  558. function THelpViewer.GetLinkCount: sw_integer;
  559. var Count: sw_integer;
  560. begin
  561. if HelpTopic=nil then Count:=0 else Count:=HelpTopic^.GetLinkCount;
  562. GetLinkCount:=Count;
  563. end;
  564. procedure THelpViewer.GetLinkBounds(Index: sw_integer; var R: TRect);
  565. begin
  566. HelpTopic^.GetLinkBounds(Index,R);
  567. end;
  568. function THelpViewer.GetLinkFileID(Index: sw_integer): word;
  569. begin
  570. GetLinkFileID:=HelpTopic^.GetLinkFileID(Index);
  571. end;
  572. function THelpViewer.GetLinkContext(Index: sw_integer): THelpCtx;
  573. begin
  574. GetLinkContext:=HelpTopic^.GetLinkContext(Index);
  575. end;
  576. function THelpViewer.GetLinkText(Index: sw_integer): string;
  577. var S: string;
  578. R: TRect;
  579. Y,StartX,EndX: sw_integer;
  580. begin
  581. S:=''; GetLinkBounds(Index,R);
  582. Y:=R.A.Y;
  583. while (Y<=R.B.Y) do
  584. begin
  585. if Y=R.A.Y then StartX:=R.A.X else StartX:=Margin;
  586. if Y=R.B.Y then EndX:=R.B.X else EndX:=255;
  587. S:=S+copy(GetLineText(Y),StartX+1,EndX-StartX+1);
  588. Inc(Y);
  589. end;
  590. GetLinkText:=S;
  591. end;
  592. function THelpViewer.GetColorAreaCount: sw_integer;
  593. var Count: sw_integer;
  594. begin
  595. if HelpTopic=nil then Count:=0 else Count:=HelpTopic^.GetColorAreaCount;
  596. GetColorAreaCount:=Count;
  597. end;
  598. procedure THelpViewer.GetColorAreaBounds(Index: sw_integer; var R: TRect);
  599. begin
  600. HelpTopic^.GetColorAreaBounds(Index,R);
  601. end;
  602. function THelpViewer.GetColorAreaColor(Index: sw_integer): word;
  603. begin
  604. GetColorAreaColor:=HelpTopic^.GetColorAreaColor(Index);
  605. end;
  606. procedure THelpViewer.SelectNextLink(ANext: boolean);
  607. var I,Link: sw_integer;
  608. R: TRect;
  609. begin
  610. if HelpTopic=nil then Exit;
  611. Link:=CurLink;
  612. if Link<>-1 then
  613. begin
  614. if ANext then
  615. begin Inc(Link); if Link>=GetLinkCount then Link:=0; end else
  616. begin Dec(Link); if Link=-1 then Link:=GetLinkCount-1; end;
  617. end else
  618. for I:=0 to GetLinkCount-1 do
  619. begin
  620. GetLinkBounds(I,R);
  621. if (R.A.Y>CurPos.Y) or
  622. (R.A.Y=CurPos.Y) and (R.A.X>CurPos.X) then
  623. begin Link:=I; Break; end;
  624. end;
  625. if (Link=-1) and (GetLinkCount>0) then
  626. if ANext then Link:=0
  627. else Link:=GetLinkCount-1;
  628. SetCurLink(Link);
  629. end;
  630. procedure THelpViewer.SetCurLink(Link: sw_integer);
  631. var R: TRect;
  632. begin
  633. if Link<>-1 then
  634. begin
  635. GetLinkBounds(Link,R);
  636. SetCurPtr(R.A.X,R.A.Y);
  637. TrackCursor(true);
  638. end;
  639. end;
  640. procedure THelpViewer.SwitchToIndex;
  641. begin
  642. if IndexTopic=nil then
  643. IndexTopic:=HelpFacility^.BuildIndexTopic;
  644. ISwitchToTopicPtr(IndexTopic,true);
  645. end;
  646. procedure THelpViewer.SwitchToTopic(SourceFileID: word; Context: THelpCtx);
  647. begin
  648. ISwitchToTopic(SourceFileID,Context,true);
  649. end;
  650. procedure THelpViewer.ISwitchToTopic(SourceFileID: word; Context: THelpCtx; RecordInHistory: boolean);
  651. var P: PTopic;
  652. begin
  653. if HelpFacility=nil then P:=nil else
  654. if (SourceFileID=0) and (Context=0) and (HelpTopic<>nil) then
  655. P:=IndexTopic else
  656. P:=HelpFacility^.LoadTopic(SourceFileID, Context);
  657. ISwitchToTopicPtr(P,RecordInHistory);
  658. end;
  659. procedure THelpViewer.ISwitchToTopicPtr(P: PTopic; RecordInHistory: boolean);
  660. var HistoryFull: boolean;
  661. begin
  662. if (P<>nil) and RecordInHistory and (HelpTopic<>nil) then
  663. begin
  664. HistoryFull:=HistoryPtr>=HistorySize;
  665. if HistoryFull then
  666. Move(History[1],History[0],SizeOf(History)-SizeOf(History[0]));
  667. with History[HistoryPtr] do
  668. begin
  669. {SourceTopic_:=SourceTopic; }Context_:=HelpTopic^.Topic^.HelpCtx;
  670. FileID_:=HelpTopic^.Topic^.FileID;
  671. Delta_:=Delta; CurPos_:=CurPos; CurLink_:=CurLink;
  672. end;
  673. if HistoryFull=false then Inc(HistoryPtr);
  674. end;
  675. if Owner<>nil then Owner^.Lock;
  676. SetTopic(P);
  677. DrawView;
  678. if Owner<>nil then Owner^.UnLock;
  679. end;
  680. procedure THelpViewer.PrevTopic;
  681. begin
  682. if HistoryPtr>0 then
  683. begin
  684. if Owner<>nil then Owner^.Lock;
  685. Dec(HistoryPtr);
  686. with History[HistoryPtr] do
  687. begin
  688. ISwitchToTopic(FileID_,Context_,false);
  689. ScrollTo(Delta_.X,Delta_.Y);
  690. SetCurPtr(CurPos_.X,CurPos_.Y);
  691. TrackCursor(false);
  692. if CurLink<>CurLink_ then SetCurLink(CurLink_);
  693. end;
  694. DrawView;
  695. if Owner<>nil then Owner^.UnLock;
  696. end;
  697. end;
  698. procedure THelpViewer.SetTopic(Topic: PTopic);
  699. begin
  700. CurLink:=-1;
  701. if (HelpTopic=nil) or (Topic<>HelpTopic^.Topic) then
  702. begin
  703. if (HelpTopic<>nil) and (HelpTopic<>IndexHelpTopic) then
  704. Dispose(HelpTopic, Done);
  705. HelpTopic:=nil;
  706. if Topic<>nil then
  707. begin
  708. if (Topic=IndexTopic) and (IndexHelpTopic<>nil) then
  709. HelpTopic:=IndexHelpTopic else
  710. New(HelpTopic, Init(Topic));
  711. if Topic=IndexTopic then
  712. IndexHelpTopic:=HelpTopic;
  713. end;
  714. end;
  715. if Owner<>nil then Owner^.Lock;
  716. SetCurPtr(0,0); TrackCursor(false);
  717. RenderTopic;
  718. BuildTopicWordList;
  719. Lookup('');
  720. SetSelection(CurPos,CurPos);
  721. DrawView;
  722. if Owner<>nil then Owner^.UnLock;
  723. end;
  724. procedure THelpViewer.BuildTopicWordList;
  725. var I: sw_integer;
  726. begin
  727. WordList^.FreeAll;
  728. for I:=0 to GetLinkCount-1 do
  729. WordList^.Insert(NewKeyword(I,Trim(GetLinkText(I))));
  730. end;
  731. procedure THelpViewer.Lookup(S: string);
  732. var Index, I: Sw_integer;
  733. W: string;
  734. OldLookup: string;
  735. R: TRect;
  736. P: PHelpKeyword;
  737. begin
  738. InLookup:=true;
  739. OldLookup:=LookupWord;
  740. S:=UpcaseStr(S);
  741. Index:=-1;
  742. I:=0; {J:=0;
  743. while (J<GetLinkCount) do
  744. begin
  745. GetLinkBounds(J,R);
  746. if (R.A.Y<CurPos.Y) or ((R.A.Y=CurPos.Y) and (R.B.X<CurPos.X))
  747. then Inc(J) else
  748. begin I:=J; Break; end;
  749. end;}
  750. if S='' then LookupWord:='' else
  751. begin
  752. while (Index=-1) and (I<WordList^.Count) do
  753. begin
  754. P:=WordList^.At(I);
  755. if P^.KWord<>nil then
  756. begin
  757. W:=UpcaseStr(Trim(P^.KWord^));
  758. if copy(W,1,length(S))=S then Index:=I;
  759. end;
  760. { if W>S then Break else}
  761. Inc(I);
  762. end;
  763. if Index<>-1 then
  764. begin
  765. W:=Trim(WordList^.At(Index)^.KWord^);
  766. LookupWord:=copy(W,1,length(S));
  767. end;
  768. end;
  769. if LookupWord<>OldLookup then
  770. begin
  771. if Index=-1 then SetCurLink(CurLink) else
  772. begin
  773. if Owner<>nil then Owner^.Lock;
  774. P:=WordList^.At(Index);
  775. S:=GetLinkText(P^.Index);
  776. I:=Pos(LookupWord,S); if I=0 then I:=1;
  777. GetLinkBounds(P^.Index,R);
  778. SetCurPtr(R.A.X+(I-1)+length(Lookupword),R.A.Y);
  779. CurLink:=P^.Index; DrawView;
  780. TrackCursor(true);
  781. if Owner<>nil then Owner^.UnLock;
  782. end;
  783. end;
  784. InLookup:=false;
  785. end;
  786. procedure THelpViewer.SelectLink(Index: sw_integer);
  787. var ID: word;
  788. Ctx: THelpCtx;
  789. begin
  790. if Index=-1 then Exit;
  791. if HelpTopic=nil then begin ID:=0; Ctx:=0; end else
  792. begin
  793. ID:=GetLinkFileID(Index);
  794. Ctx:=GetLinkContext(Index);
  795. end;
  796. SwitchToTopic(ID,Ctx);
  797. end;
  798. procedure THelpViewer.HandleEvent(var Event: TEvent);
  799. var DontClear: boolean;
  800. procedure GetMousePos(var P: TPoint);
  801. begin
  802. MakeLocal(Event.Where,P);
  803. Inc(P.X,Delta.X); Inc(P.Y,Delta.Y);
  804. end;
  805. begin
  806. case Event.What of
  807. evMouseDown :
  808. if MouseInView(Event.Where) then
  809. if (Event.Buttons=mbLeftButton) and (Event.Double) then
  810. begin
  811. inherited HandleEvent(Event);
  812. if CurLink<>-1 then
  813. SelectLink(CurLink);
  814. end;
  815. evBroadcast :
  816. case Event.Command of
  817. cmHelpFilesChanged :
  818. begin
  819. if HelpTopic=IndexHelpTopic then HelpTopic:=nil;
  820. IndexTopic:=nil;
  821. if IndexHelpTopic<>nil then Dispose(IndexHelpTopic, Done);
  822. IndexHelpTopic:=nil;
  823. end;
  824. end;
  825. evCommand :
  826. begin
  827. DontClear:=false;
  828. case Event.Command of
  829. cmPrevTopic :
  830. PrevTopic;
  831. else DontClear:=true;
  832. end;
  833. if DontClear=false then ClearEvent(Event);
  834. end;
  835. evKeyDown :
  836. begin
  837. DontClear:=false;
  838. case Event.KeyCode of
  839. kbTab :
  840. SelectNextLink(true);
  841. kbShiftTab :
  842. begin NoSelect:=true; SelectNextLink(false); NoSelect:=false; end;
  843. kbEnter :
  844. if CurLink<>-1 then
  845. SelectLink(CurLink);
  846. else
  847. case Event.CharCode of
  848. #32..#255 :
  849. begin NoSelect:=true; Lookup(LookupWord+Event.CharCode); NoSelect:=false; end;
  850. else DontClear:=true;
  851. end;
  852. end;
  853. TrackCursor(false);
  854. if DontClear=false then ClearEvent(Event);
  855. end;
  856. end;
  857. inherited HandleEvent(Event);
  858. end;
  859. procedure THelpViewer.Draw;
  860. var NormalColor, LinkColor,
  861. SelectColor, SelectionColor: word;
  862. B: TDrawBuffer;
  863. DX,DY,X,Y,I,MinX,MaxX,ScreenX: sw_integer;
  864. LastLinkDrawn,LastColorAreaDrawn: sw_integer;
  865. S: string;
  866. R: TRect;
  867. {$ifndef EDITORS}
  868. SelR : TRect;
  869. {$endif}
  870. C: word;
  871. CurP: TPoint;
  872. begin
  873. NormalColor:=GetColor(1); LinkColor:=GetColor(2);
  874. SelectColor:=GetColor(3); SelectionColor:=GetColor(4);
  875. {$ifndef EDITORS}
  876. SelR.A:=SelStart; SelR.B:=SelEnd;
  877. {$endif}
  878. LastLinkDrawn:=0; LastColorAreaDrawn:=0;
  879. for DY:=0 to Size.Y-1 do
  880. begin
  881. Y:=Delta.Y+DY;
  882. MoveChar(B,' ',NormalColor,Size.X);
  883. if Y<GetLineCount then
  884. begin
  885. S:=copy(GetLineText(Y),Delta.X+1,255);
  886. S:=copy(S,1,MaxViewWidth);
  887. MoveStr(B,S,NormalColor);
  888. for I:=LastColorAreaDrawn to GetColorAreaCount-1 do
  889. begin
  890. GetColorAreaBounds(I,R);
  891. if R.A.Y>Y then Break;
  892. LastColorAreaDrawn:=I;
  893. if Y=R.B.Y then MaxX:=R.B.X else MaxX:=(length(S)-1);
  894. if Y=R.A.Y then MinX:=R.A.X else MinX:=0;
  895. if (R.A.Y<=Y) and (Y<=R.B.Y) then
  896. begin
  897. C:=GetColorAreaColor(I);
  898. for DX:=MinX to MaxX do
  899. begin
  900. X:=DX;
  901. ScreenX:=X-(Delta.X);
  902. if (ScreenX>0) and (ScreenX<=High(B)) then
  903. begin
  904. { CurP.X:=X; CurP.Y:=Y;
  905. if LinkAreaContainsPoint(R,CurP) then}
  906. B[ScreenX]:=(B[ScreenX] and $f0ff) or (C shl 8);
  907. end;
  908. end;
  909. end;
  910. end;
  911. for I:=LastLinkDrawn to GetLinkCount-1 do
  912. begin
  913. GetLinkBounds(I,R);
  914. if R.A.Y>Y then Break;
  915. LastLinkDrawn:=I;
  916. if Y=R.B.Y then MaxX:=R.B.X else MaxX:=(length(S)-1);
  917. if Y=R.A.Y then MinX:=R.A.X else MinX:=0;
  918. if (R.A.Y<=Y) and (Y<=R.B.Y) then
  919. for DX:=MinX to MaxX do
  920. begin
  921. X:=DX;
  922. ScreenX:=X-(Delta.X);
  923. if (ScreenX>=0) and (ScreenX<=High(B)) then
  924. begin
  925. CurP.X:=X; CurP.Y:=Y;
  926. if LinkContainsPoint(R,CurP) then
  927. if I=CurLink then C:=SelectColor else C:=LinkColor;
  928. B[ScreenX]:=(B[ScreenX] and $ff) or (C shl 8);
  929. end;
  930. end;
  931. end;
  932. {$ifndef EDITORS}
  933. if ((SelR.A.X<>SelR.B.X) or (SelR.A.Y<>SelR.B.Y)) and (SelR.A.Y<=Y) and (Y<=SelR.B.Y) then
  934. begin
  935. if Y=SelR.A.Y then MinX:=SelR.A.X else MinX:=0;
  936. if Y=SelR.B.Y then MaxX:=SelR.B.X-1 else MaxX:=255;
  937. for DX:=MinX to MaxX do
  938. begin
  939. X:=DX;
  940. ScreenX:=X-(Delta.X);
  941. if (ScreenX>=0) and (ScreenX<High(B)) then
  942. B[ScreenX]:=(B[ScreenX] and $0fff) or ((SelectionColor and $f0) shl 8);
  943. end;
  944. end;
  945. {$endif}
  946. end;
  947. WriteLine(0,DY,Size.X,1,B);
  948. end;
  949. DrawCursor;
  950. end;
  951. function THelpViewer.GetPalette: PPalette;
  952. const P: string[length(CHelpViewer)] = CHelpViewer;
  953. begin
  954. GetPalette:=@P;
  955. end;
  956. constructor THelpViewer.Load(var S: TStream);
  957. begin
  958. inherited Load(S);
  959. end;
  960. procedure THelpViewer.Store(var S: TStream);
  961. begin
  962. inherited Store(S);
  963. end;
  964. destructor THelpViewer.Done;
  965. begin
  966. inherited Done;
  967. if assigned(WordList) then
  968. Dispose(WordList, Done);
  969. end;
  970. function THelpFrame.GetPalette: PPalette;
  971. const P: string[length(CHelpFrame)] = CHelpFrame;
  972. begin
  973. GetPalette:=@P;
  974. end;
  975. constructor THelpWindow.Init(var Bounds: TRect; ATitle: TTitleStr; ASourceFileID: word; AContext: THelpCtx; ANumber: Integer);
  976. begin
  977. inherited Init(Bounds, ATitle, ANumber);
  978. InitScrollBars;
  979. if Assigned(HSB) then Insert(HSB);
  980. if Assigned(VSB) then Insert(VSB);
  981. InitHelpView;
  982. if Assigned(HelpView) then
  983. begin
  984. if (ASourceFileID<>0) or (AContext<>0) then
  985. ShowTopic(ASourceFileID, AContext);
  986. Insert(HelpView);
  987. end;
  988. end;
  989. procedure THelpWindow.InitScrollBars;
  990. var R: TRect;
  991. begin
  992. GetExtent(R); R.Grow(0,-1); R.A.X:=R.B.X-1;
  993. New(VSB, Init(R)); VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  994. GetExtent(R); R.Grow(-1,0); R.A.Y:=R.B.Y-1;
  995. New(HSB, Init(R)); HSB^.GrowMode:=gfGrowLoY+gfGrowHiX+gfGrowHiY;
  996. end;
  997. procedure THelpWindow.InitHelpView;
  998. var R: TRect;
  999. begin
  1000. GetExtent(R); R.Grow(-1,-1);
  1001. New(HelpView, Init(R, HSB, VSB));
  1002. HelpView^.GrowMode:=gfGrowHiX+gfGrowHiY;
  1003. end;
  1004. procedure THelpWindow.InitFrame;
  1005. var R: TRect;
  1006. begin
  1007. GetExtent(R);
  1008. Frame:=New(PHelpFrame, Init(R));
  1009. end;
  1010. procedure THelpWindow.ShowIndex;
  1011. begin
  1012. HelpView^.SwitchToIndex;
  1013. end;
  1014. procedure THelpWindow.ShowTopic(SourceFileID: word; Context: THelpCtx);
  1015. begin
  1016. HelpView^.SwitchToTopic(SourceFileID, Context);
  1017. end;
  1018. procedure THelpWindow.HandleEvent(var Event: TEvent);
  1019. begin
  1020. case Event.What of
  1021. evKeyDown :
  1022. case Event.KeyCode of
  1023. kbEsc :
  1024. begin
  1025. Event.What:=evCommand; Event.Command:=cmClose;
  1026. end;
  1027. end;
  1028. end;
  1029. inherited HandleEvent(Event);
  1030. end;
  1031. procedure THelpWindow.Close;
  1032. begin
  1033. if HideOnClose then Hide else inherited Close;
  1034. end;
  1035. function THelpWindow.GetPalette: PPalette;
  1036. begin
  1037. GetPalette:=nil;
  1038. end;
  1039. END.
  1040. {
  1041. $Log$
  1042. Revision 1.11 2000-02-07 08:29:13 michael
  1043. [*] the fake (!) TOKENS.PAS still contained the typo bug
  1044. FSplit(,n,d,e) (correctly FSplit(,d,n,e))
  1045. [*] CodeComplete had a very ugly bug - coordinates were document-relative
  1046. (instead of being screen-relative)
  1047. [*] TResourceStream didn't count the size of the resource names when
  1048. determining the file size and this could lead to the last resources not
  1049. loaded correctly
  1050. [+] Ctrl-Enter in editor now tries to open the file at cursor
  1051. [+] CodeComplete option added to Options|Environment|Editor
  1052. [+] user interface for managing CodeComplete implemented
  1053. [+] user interface for CodeTemplates implemented
  1054. [+] CodeComplete wordlist and CodeTemplates stored in desktop file
  1055. [+] help topic size no longer limited to 64KB when compiled with FPC
  1056. Revision 1.10 1999/08/16 18:25:31 peter
  1057. * Adjusting the selection when the editor didn't contain any line.
  1058. * Reserved word recognition redesigned, but this didn't affect the overall
  1059. syntax highlight speed remarkably (at least not on my Amd-K6/350).
  1060. The syntax scanner loop is a bit slow but the main problem is the
  1061. recognition of special symbols. Switching off symbol processing boosts
  1062. the performance up to ca. 200%...
  1063. * The editor didn't allow copying (for ex to clipboard) of a single character
  1064. * 'File|Save as' caused permanently run-time error 3. Not any more now...
  1065. * Compiler Messages window (actually the whole desktop) did not act on any
  1066. keypress when compilation failed and thus the window remained visible
  1067. + Message windows are now closed upon pressing Esc
  1068. + At 'Run' the IDE checks whether any sources are modified, and recompiles
  1069. only when neccessary
  1070. + BlockRead and BlockWrite (Ctrl+K+R/W) implemented in TCodeEditor
  1071. + LineSelect (Ctrl+K+L) implemented
  1072. * The IDE had problems closing help windows before saving the desktop
  1073. Revision 1.9 1999/06/28 19:32:35 peter
  1074. * fixes from gabor
  1075. Revision 1.8 1999/04/07 21:56:02 peter
  1076. + object support for browser
  1077. * html help fixes
  1078. * more desktop saving things
  1079. * NODEBUG directive to exclude debugger
  1080. Revision 1.7 1999/03/08 14:58:20 peter
  1081. + prompt with dialogs for tools
  1082. Revision 1.6 1999/03/01 15:42:13 peter
  1083. + Added dummy entries for functions not yet implemented
  1084. * MenuBar didn't update itself automatically on command-set changes
  1085. * Fixed Debugging/Profiling options dialog
  1086. * TCodeEditor converts spaces to tabs at save only if efUseTabChars is set
  1087. * efBackSpaceUnindents works correctly
  1088. + 'Messages' window implemented
  1089. + Added '$CAP MSG()' and '$CAP EDIT' to available tool-macros
  1090. + Added TP message-filter support (for ex. you can call GREP thru
  1091. GREP2MSG and view the result in the messages window - just like in TP)
  1092. * A 'var' was missing from the param-list of THelpFacility.TopicSearch,
  1093. so topic search didn't work...
  1094. * In FPHELP.PAS there were still context-variables defined as word instead
  1095. of THelpCtx
  1096. * StdStatusKeys() was missing from the statusdef for help windows
  1097. + Topic-title for index-table can be specified when adding a HTML-files
  1098. Revision 1.5 1999/02/18 13:44:38 peter
  1099. * search fixed
  1100. + backward search
  1101. * help fixes
  1102. * browser updates
  1103. Revision 1.4 1999/02/08 10:37:47 peter
  1104. + html helpviewer
  1105. Revision 1.3 1999/01/21 11:54:32 peter
  1106. + tools menu
  1107. + speedsearch in symbolbrowser
  1108. * working run command
  1109. Revision 1.2 1998/12/28 15:47:57 peter
  1110. + Added user screen support, display & window
  1111. + Implemented Editor,Mouse Options dialog
  1112. + Added location of .INI and .CFG file
  1113. + Option (INI) file managment implemented (see bottom of Options Menu)
  1114. + Switches updated
  1115. + Run program
  1116. Revision 1.31 1998/12/27 12:07:30 gabor
  1117. * changed THelpViewer.Init to reflect changes in WEDITOR
  1118. Revision 1.3 1998/12/22 10:39:56 peter
  1119. + options are now written/read
  1120. + find and replace routines
  1121. }