whlpview.pas 34 KB

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