whtmlhlp.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455
  1. {
  2. This file is part of the Free Pascal Integrated Development Environment
  3. Copyright (c) 1999-2000 by Berczi Gabor
  4. See the file COPYING.FPC, included in this distribution,
  5. for details about the copyright.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. **********************************************************************}
  10. unit WHTMLHlp;
  11. interface
  12. uses Objects,WHTML,WAnsi,WHelp;
  13. const
  14. extHTML = '.htm';
  15. extHTMLIndex = '.htx';
  16. ListIndent = 2;
  17. DefIndent = 4;
  18. MaxTopicLinks = 4000; { maximum number of links on a single HTML page }
  19. type
  20. THTMLSection = (hsNone,hsHeading1,hsHeading2,hsHeading3,hsHeading4,hsHeading5,hsHeading6);
  21. PTopicLinkCollection = ^TTopicLinkCollection;
  22. TTopicLinkCollection = object(TStringCollection)
  23. procedure Insert(Item: Pointer); virtual;
  24. function At(Index: sw_Integer): PString;
  25. function AddItem(Item: string): integer;
  26. end;
  27. TParagraphAlign = (paLeft,paCenter,paRight);
  28. PTableElement = ^TTableElement;
  29. TTableElement = object(Tobject)
  30. TextBegin,TextEnd, TextLength, NumNL : sw_word;
  31. Alignment : TParagraphAlign;
  32. NextEl : PTableElement;
  33. constructor init(AAlignment : TParagraphAlign);
  34. end;
  35. PTableLine = ^TTableLine;
  36. TTableLine = object(Tobject)
  37. NumElements : sw_word;
  38. Nextline : PTableLine;
  39. FirstEl,LastEl : PTableElement;
  40. constructor Init;
  41. procedure AddElement(PTE : PTableElement);
  42. destructor Done; virtual;
  43. end;
  44. PHTMLTopicRenderer = ^THTMLTopicRenderer;
  45. PTable = ^TTable;
  46. TTable = object(Tobject)
  47. NumLines,NumCols : sw_word;
  48. GlobalOffset,
  49. GlobalTextBegin : sw_word;
  50. WithBorder : boolean;
  51. FirstLine : PTableLine;
  52. LastLine : PTableLine;
  53. PreviousTable : PTable;
  54. Renderer : PHTMLTopicRenderer;
  55. constructor Init(Previous : PTable);
  56. procedure AddLine(PL : PTableLine);
  57. procedure AddElement(PTE : PTableElement);
  58. procedure TextInsert(Pos : sw_word;const S : string);
  59. procedure FormatTable;
  60. destructor Done; virtual;
  61. end;
  62. THTMLTopicRenderer = object(THTMLParser)
  63. function BuildTopic(P: PTopic; AURL: string; HTMLFile: PTextFile; ATopicLinks: PTopicLinkCollection): boolean;
  64. public
  65. function DocAddTextChar(C: char): boolean; virtual;
  66. procedure DocSoftBreak; virtual;
  67. procedure DocTYPE; virtual;
  68. procedure DocHTML(Entered: boolean); virtual;
  69. procedure DocHEAD(Entered: boolean); virtual;
  70. procedure DocMETA; virtual;
  71. procedure DocTITLE(Entered: boolean); virtual;
  72. procedure DocBODY(Entered: boolean); virtual;
  73. procedure DocAnchor(Entered: boolean); virtual;
  74. procedure DocUnknownTag; virtual;
  75. procedure DocHeading(Level: integer; Entered: boolean); virtual;
  76. procedure DocParagraph(Entered: boolean); virtual;
  77. procedure DocBreak; virtual;
  78. procedure DocImage; virtual;
  79. procedure DocBold(Entered: boolean); virtual;
  80. procedure DocCite(Entered: boolean); virtual;
  81. procedure DocCode(Entered: boolean); virtual;
  82. procedure DocEmphasized(Entered: boolean); virtual;
  83. procedure DocItalic(Entered: boolean); virtual;
  84. procedure DocKbd(Entered: boolean); virtual;
  85. procedure DocPreformatted(Entered: boolean); virtual;
  86. procedure DocSample(Entered: boolean); virtual;
  87. procedure DocStrong(Entered: boolean); virtual;
  88. procedure DocTeleType(Entered: boolean); virtual;
  89. procedure DocVariable(Entered: boolean); virtual;
  90. procedure DocSpan(Entered: boolean); virtual;
  91. procedure DocList(Entered: boolean); virtual;
  92. procedure DocOrderedList(Entered: boolean); virtual;
  93. procedure DocListItem; virtual;
  94. procedure DocDefList(Entered: boolean); virtual;
  95. procedure DocDefTerm; virtual;
  96. procedure DocDefExp; virtual;
  97. procedure DocTable(Entered: boolean); virtual;
  98. procedure DocTableRow(Entered: boolean); virtual;
  99. procedure DocTableItem(Entered: boolean); virtual;
  100. procedure DocHorizontalRuler; virtual;
  101. public
  102. function GetSectionColor(Section: THTMLSection; var Color: byte): boolean; virtual;
  103. private
  104. URL: string;
  105. Topic: PTopic;
  106. TopicLinks: PTopicLinkCollection;
  107. TextPtr: sw_word;
  108. InTitle: boolean;
  109. InBody: boolean;
  110. InAnchor: boolean;
  111. InParagraph: boolean;
  112. InPreformatted: boolean;
  113. TopicTitle: string;
  114. Indent: integer;
  115. AnyCharsInLine: boolean;
  116. CurHeadLevel: integer;
  117. PAlign: TParagraphAlign;
  118. LinkIndexes: array[0..MaxTopicLinks] of sw_integer;
  119. LinkPtr: sw_integer;
  120. LastTextChar: char;
  121. { Anchor: TAnchor;}
  122. { Table stuff }
  123. CurrentTable : PTable;
  124. procedure AddText(const S: string);
  125. procedure AddChar(C: char);
  126. procedure AddCharAt(C: char;AtPtr : sw_word);
  127. function AddTextAt(const S: string;AtPtr : sw_word) : sw_word;
  128. function ComputeTextLength(TStart,TEnd : sw_word) : sw_word;
  129. end;
  130. PCustomHTMLHelpFile = ^TCustomHTMLHelpFile;
  131. TCustomHTMLHelpFile = object(THelpFile)
  132. constructor Init(AID: word);
  133. destructor Done; virtual;
  134. public
  135. function GetTopicInfo(T: PTopic) : string; virtual;
  136. function SearchTopic(HelpCtx: THelpCtx): PTopic; virtual;
  137. function ReadTopic(T: PTopic): boolean; virtual;
  138. private
  139. Renderer: PHTMLTopicRenderer;
  140. DefaultFileName: string;
  141. CurFileName: string;
  142. TopicLinks: PTopicLinkCollection;
  143. end;
  144. PHTMLHelpFile = ^THTMLHelpFile;
  145. THTMLHelpFile = object(TCustomHTMLHelpFile)
  146. constructor Init(AFileName: string; AID: word; ATOCEntry: string);
  147. public
  148. function LoadIndex: boolean; virtual;
  149. private
  150. TOCEntry: string;
  151. end;
  152. PHTMLIndexHelpFile = ^THTMLIndexHelpFile;
  153. THTMLIndexHelpFile = object(TCustomHTMLHelpFile)
  154. constructor Init(AFileName: string; AID: word);
  155. function LoadIndex: boolean; virtual;
  156. private
  157. IndexFileName: string;
  158. end;
  159. PHTMLAnsiView = ^THTMLAnsiView;
  160. PHTMLAnsiConsole = ^THTMLAnsiConsole;
  161. THTMLAnsiConsole = Object(TAnsiViewConsole)
  162. MaxX,MaxY : integer;
  163. procedure GotoXY(X,Y: integer); virtual;
  164. end;
  165. THTMLAnsiView = Object(TAnsiView)
  166. private
  167. HTMLOwner : PHTMLTopicRenderer;
  168. HTMLConsole : PHTMLAnsiConsole;
  169. public
  170. constructor Init(AOwner: PHTMLTopicRenderer);
  171. procedure CopyToHTML;
  172. end;
  173. THTMLGetSectionColorProc = function(Section: THTMLSection; var Color: byte): boolean;
  174. function DefHTMLGetSectionColor(Section: THTMLSection; var Color: byte): boolean;
  175. const HTMLGetSectionColor : THTMLGetSectionColorProc = {$ifdef fpc}@{$endif}DefHTMLGetSectionColor;
  176. procedure RegisterHelpType;
  177. implementation
  178. uses
  179. Views,WConsts,WUtils,WViews,WHTMLScn;
  180. constructor TTableElement.init(AAlignment : TParagraphAlign);
  181. begin
  182. Alignment:=AAlignment;
  183. NextEl:=nil;
  184. TextBegin:=0;
  185. TextEnd:=0;
  186. end;
  187. { TTableLine methods }
  188. constructor TTableLine.Init;
  189. begin
  190. NumElements:=0;
  191. NextLine:=nil;
  192. Firstel:=nil;
  193. LastEl:=nil;
  194. end;
  195. procedure TTableLine.AddElement(PTE : PTableElement);
  196. begin
  197. if not assigned(FirstEl) then
  198. FirstEl:=PTE;
  199. if assigned(LastEl) then
  200. LastEl^.NextEl:=PTE;
  201. LastEl:=PTE;
  202. Inc(NumElements);
  203. end;
  204. destructor TTableLine.Done;
  205. begin
  206. LastEl:=FirstEl;
  207. while assigned(LastEl) do
  208. begin
  209. LastEl:=FirstEl^.NextEl;
  210. Dispose(FirstEl,Done);
  211. FirstEl:=LastEl;
  212. end;
  213. inherited Done;
  214. end;
  215. { TTable methods }
  216. constructor TTable.Init(Previous : PTable);
  217. begin
  218. PreviousTable:=Previous;
  219. NumLines:=0;
  220. NumCols:=0;
  221. GlobalOffset:=0;
  222. GlobalTextBegin:=0;
  223. FirstLine:=nil;
  224. LastLine:=nil;
  225. WithBorder:=false;
  226. end;
  227. procedure TTable.AddLine(PL : PTableLine);
  228. begin
  229. If not assigned(FirstLine) then
  230. FirstLine:=PL;
  231. if Assigned(LastLine) then
  232. LastLine^.NextLine:=PL;
  233. LastLine:=PL;
  234. Inc(NumLines);
  235. end;
  236. procedure TTable.AddElement(PTE : PTableElement);
  237. begin
  238. if assigned(LastLine) then
  239. begin
  240. LastLine^.AddElement(PTE);
  241. If LastLine^.NumElements>NumCols then
  242. NumCols:=LastLine^.NumElements;
  243. end;
  244. end;
  245. procedure TTable.TextInsert(Pos : sw_word;const S : string);
  246. var
  247. i : sw_word;
  248. begin
  249. if S='' then
  250. exit;
  251. i:=Renderer^.AddTextAt(S,Pos+GlobalOffset);
  252. GlobalOffset:=GlobalOffset+i;
  253. end;
  254. procedure TTable.FormatTable;
  255. const
  256. MaxCols = 200;
  257. type
  258. TLengthArray = Array [ 1 .. MaxCols] of sw_word;
  259. PLengthArray = ^TLengthArray;
  260. var
  261. ColLengthArray : PLengthArray;
  262. RowSizeArray : PLengthArray;
  263. CurLine : PTableLine;
  264. CurEl : PTableElement;
  265. Align : TParagraphAlign;
  266. TextBegin,TextEnd : sw_word;
  267. i,j,k,Length : sw_word;
  268. begin
  269. GetMem(ColLengthArray,Sizeof(sw_word)*NumCols);
  270. FillChar(ColLengthArray^,Sizeof(sw_word)*NumCols,#0);
  271. GetMem(RowSizeArray,Sizeof(sw_word)*NumLines);
  272. FillChar(RowSizeArray^,Sizeof(sw_word)*NumLines,#0);
  273. { Compute the largest cell }
  274. CurLine:=FirstLine;
  275. For i:=1 to NumLines do
  276. begin
  277. CurEl:=CurLine^.FirstEl;
  278. RowSizeArray^[i]:=1;
  279. For j:=1 to NumCols do
  280. begin
  281. if not assigned(CurEl) then
  282. break;
  283. Length:=CurEl^.TextLength;
  284. if assigned(CurEl^.NextEl) and
  285. (CurEl^.NextEl^.TextBegin>CurEl^.TextEnd) then
  286. Inc(Length,Renderer^.ComputeTextLength(
  287. CurEl^.NextEl^.TextBegin+GlobalOffset,
  288. CurEl^.TextBegin+GlobalOffset));
  289. if Length>ColLengthArray^[j] then
  290. ColLengthArray^[j]:=Length;
  291. { We need to handle multiline cells... }
  292. if CurEl^.NumNL>=RowSizeArray^[i] then
  293. RowSizeArray^[i]:=CurEl^.NumNL;
  294. { We don't handle multiline cells yet... }
  295. if CurEl^.NumNL>=1 then
  296. begin
  297. for k:=CurEl^.TextBegin+GlobalOffset to
  298. CurEl^.TextEnd+GlobalOffset do
  299. if Renderer^.Topic^.Text^[k]=ord(hscLineBreak) then
  300. Renderer^.Topic^.Text^[k]:=ord(' ');
  301. end;
  302. CurEl:=CurEl^.NextEl;
  303. end;
  304. CurLine:=CurLine^.NextLine;
  305. end;
  306. { Adjust to largest cell }
  307. CurLine:=FirstLine;
  308. TextBegin:=GlobalTextBegin;
  309. If (NumLines>0) and WithBorder then
  310. Begin
  311. TextInsert(TextBegin,#218);
  312. For j:=1 to NumCols do
  313. begin
  314. TextInsert(TextBegin,CharStr(#196,ColLengthArray^[j]));
  315. if j<NumCols then
  316. TextInsert(TextBegin,#194);
  317. end;
  318. TextInsert(TextBegin,#191);
  319. TextInsert(TextBegin,hscLineBreak);
  320. End;
  321. For i:=1 to NumLines do
  322. begin
  323. CurEl:=CurLine^.FirstEl;
  324. For j:=1 to NumCols do
  325. begin
  326. if not assigned(CurEl) then
  327. begin
  328. Length:=0;
  329. Align:=paLeft;
  330. end
  331. else
  332. begin
  333. TextBegin:=CurEl^.TextBegin;
  334. TextEnd:=CurEl^.TextEnd;
  335. {While (TextEnd>TextBegin) and
  336. (Renderer^.Topic^.Text^[TextEnd+GlobalOffset]=ord(hscLineBreak)) do
  337. dec(TextEnd); }
  338. Length:=CurEl^.TextLength;
  339. Align:=CurEl^.Alignment;
  340. end;
  341. if WithBorder then
  342. TextInsert(TextBegin,#179)
  343. else
  344. TextInsert(TextBegin,' ');
  345. if Length<ColLengthArray^[j] then
  346. begin
  347. case Align of
  348. paLeft:
  349. TextInsert(TextEnd,CharStr(' ',ColLengthArray^[j]-Length));
  350. paRight:
  351. TextInsert(TextBegin,CharStr(' ',ColLengthArray^[j]-Length));
  352. paCenter:
  353. begin
  354. TextInsert(TextBegin,CharStr(' ',(ColLengthArray^[j]-Length) div 2));
  355. TextInsert(TextEnd,CharStr(' ',(ColLengthArray^[j]-Length)- ((ColLengthArray^[j]-Length) div 2)));
  356. end;
  357. end;
  358. end;
  359. if Assigned(CurEl) then
  360. CurEl:=CurEl^.NextEl;
  361. end;
  362. if WithBorder then
  363. TextInsert(TextEnd,#179);
  364. //TextInsert(TextEnd,hscLineBreak);
  365. CurLine:=CurLine^.NextLine;
  366. end;
  367. If (NumLines>0) and WithBorder then
  368. Begin
  369. TextInsert(TextEnd,hscLineBreak);
  370. TextInsert(TextEnd,#192);
  371. For j:=1 to NumCols do
  372. begin
  373. TextInsert(TextEnd,CharStr(#196,ColLengthArray^[j]));
  374. if j<NumCols then
  375. TextInsert(TextEnd,#193);
  376. end;
  377. TextInsert(TextEnd,#217);
  378. TextInsert(TextEnd,hscLineBreak);
  379. End;
  380. FreeMem(ColLengthArray,Sizeof(sw_word)*NumCols);
  381. FreeMem(RowSizeArray,Sizeof(sw_word)*NumLines);
  382. end;
  383. destructor TTable.Done;
  384. begin
  385. LastLine:=FirstLine;
  386. while assigned(LastLine) do
  387. begin
  388. LastLine:=FirstLine^.NextLine;
  389. Dispose(FirstLine,Done);
  390. FirstLine:=LastLine;
  391. end;
  392. if Assigned(PreviousTable) then
  393. Inc(PreviousTable^.GlobalOffset,GlobalOffset);
  394. inherited Done;
  395. end;
  396. { THTMLAnsiConsole methods }
  397. procedure THTMLAnsiConsole.GotoXY(X,Y : integer);
  398. begin
  399. if X>MaxX then MaxX:=X-1;
  400. if Y>MaxY then MaxY:=Y-1;
  401. inherited GotoXY(X,Y);
  402. end;
  403. { THTMLAnsiView methods }
  404. constructor THTMLAnsiView.Init(AOwner : PHTMLTopicRenderer);
  405. var
  406. R : TRect;
  407. begin
  408. if not assigned(AOwner) then
  409. fail;
  410. R.Assign(0,0,80,25);
  411. inherited init(R,nil,nil);
  412. HTMLOwner:=AOwner;
  413. HTMLConsole:=New(PHTMLAnsiConsole,Init(@Self));
  414. Dispose(Console,Done);
  415. Console:=HTMLConsole;
  416. HTMLConsole^.Size.X:=80;
  417. HTMLConsole^.Size.Y:=25;
  418. HTMLConsole^.ClrScr;
  419. HTMLConsole^.MaxX:=-1;
  420. HTMLConsole^.MaxY:=-1;
  421. HTMLConsole^.BoundChecks:=0;
  422. end;
  423. procedure THTMLAnsiView.CopyToHTML;
  424. var
  425. Attr,NewAttr : byte;
  426. c : char;
  427. X,Y,Pos : longint;
  428. begin
  429. Attr:=(Buffer^[1] shr 8);
  430. HTMLOwner^.AddChar(hscLineBreak);
  431. HTMLOwner^.AddText(hscTextAttr+chr(Attr));
  432. for Y:=0 to HTMLConsole^.MaxY-1 do
  433. begin
  434. for X:=0 to HTMLConsole^.MaxX-1 do
  435. begin
  436. Pos:=(Delta.Y*MaxViewWidth)+X+Y*MaxViewWidth;
  437. NewAttr:=(Buffer^[Pos] shr 8);
  438. if NewAttr <> Attr then
  439. begin
  440. Attr:=NewAttr;
  441. HTMLOwner^.AddText(hscTextAttr+chr(Attr));
  442. end;
  443. c:= chr(Buffer^[Pos] and $ff);
  444. if ord(c)>16 then
  445. HTMLOwner^.AddChar(c)
  446. else
  447. begin
  448. HTMLOwner^.AddChar(hscDirect);
  449. HTMLOwner^.AddChar(c);
  450. end;
  451. end;
  452. { Write start of next line in normal color, for correct alignment }
  453. HTMLOwner^.AddChar(hscNormText);
  454. { Force to set attr again at start of next line }
  455. Attr:=0;
  456. HTMLOwner^.AddChar(hscLineBreak);
  457. end;
  458. end;
  459. function DefHTMLGetSectionColor(Section: THTMLSection; var Color: byte): boolean;
  460. begin
  461. Color:=0;
  462. DefHTMLGetSectionColor:=false;
  463. end;
  464. function EncodeHTMLCtx(FileID: integer; LinkNo: word): longint;
  465. var Ctx: longint;
  466. begin
  467. Ctx:=(longint(FileID) shl 16)+LinkNo;
  468. EncodeHTMLCtx:=Ctx;
  469. end;
  470. procedure DecodeHTMLCtx(Ctx: longint; var FileID: word; var LinkNo: word);
  471. begin
  472. if (Ctx shr 16)=0 then
  473. begin
  474. FileID:=$ffff; LinkNo:=0;
  475. end
  476. else
  477. begin
  478. FileID:=Ctx shr 16; LinkNo:=Ctx and $ffff;
  479. end;
  480. end;
  481. function CharStr(C: char; Count: byte): string;
  482. var S: string;
  483. begin
  484. S[0]:=chr(Count);
  485. if Count>0 then FillChar(S[1],Count,C);
  486. CharStr:=S;
  487. end;
  488. procedure TTopicLinkCollection.Insert(Item: Pointer);
  489. begin
  490. AtInsert(Count,Item);
  491. end;
  492. function TTopicLinkCollection.At(Index: sw_Integer): PString;
  493. begin
  494. At:=inherited At(Index);
  495. end;
  496. function TTopicLinkCollection.AddItem(Item: string): integer;
  497. var Idx: sw_integer;
  498. begin
  499. if Item='' then Idx:=-1 else
  500. if Search(@Item,Idx)=false then
  501. begin
  502. AtInsert(Count,NewStr(Item));
  503. Idx:=Count-1;
  504. end;
  505. AddItem:=Idx;
  506. end;
  507. function THTMLTopicRenderer.DocAddTextChar(C: char): boolean;
  508. var Added: boolean;
  509. begin
  510. Added:=false;
  511. if InTitle then
  512. begin
  513. TopicTitle:=TopicTitle+C;
  514. Added:=true;
  515. end
  516. else
  517. if InBody then
  518. begin
  519. if (InPreFormatted) or (C<>#32) or (LastTextChar<>C) then
  520. if (C<>#32) or (AnyCharsInLine=true) or (InPreFormatted=true) then
  521. begin
  522. AddChar(C);
  523. LastTextChar:=C;
  524. Added:=true;
  525. end;
  526. end;
  527. DocAddTextChar:=Added;
  528. end;
  529. procedure THTMLTopicRenderer.DocSoftBreak;
  530. begin
  531. if InPreformatted then DocBreak else
  532. if AnyCharsInLine and not assigned(CurrentTable) then
  533. begin
  534. AddChar(' ');
  535. LastTextChar:=' ';
  536. end;
  537. end;
  538. procedure THTMLTopicRenderer.DocTYPE;
  539. begin
  540. end;
  541. procedure THTMLTopicRenderer.DocHTML(Entered: boolean);
  542. begin
  543. end;
  544. procedure THTMLTopicRenderer.DocHEAD(Entered: boolean);
  545. begin
  546. end;
  547. procedure THTMLTopicRenderer.DocMETA;
  548. begin
  549. end;
  550. procedure THTMLTopicRenderer.DocTITLE(Entered: boolean);
  551. begin
  552. if Entered then
  553. begin
  554. TopicTitle:='';
  555. end
  556. else
  557. begin
  558. { render topic title here }
  559. if TopicTitle<>'' then
  560. begin
  561. AddText(' '+TopicTitle+' Ü'); DocBreak;
  562. AddText(' '+CharStr('ß',length(TopicTitle)+3)); DocBreak;
  563. end;
  564. end;
  565. InTitle:=Entered;
  566. end;
  567. procedure THTMLTopicRenderer.DocBODY(Entered: boolean);
  568. begin
  569. InBody:=Entered;
  570. end;
  571. procedure THTMLTopicRenderer.DocAnchor(Entered: boolean);
  572. var HRef,Name: string;
  573. begin
  574. if Entered and InAnchor then DocAnchor(false);
  575. if Entered then
  576. begin
  577. if DocGetTagParam('HREF',HRef)=false then HRef:='';
  578. if DocGetTagParam('NAME',Name)=false then Name:='';
  579. if {(HRef='') and} (Name='') then
  580. if DocGetTagParam('ID',Name)=false then
  581. Name:='';
  582. if Name<>'' then
  583. begin
  584. Topic^.NamedMarks^.InsertStr(Name);
  585. {$ifdef DEBUG}
  586. DebugMessage('',' Adding Name '+Name,1,1);
  587. {$endif DEBUG}
  588. AddChar(hscNamedMark);
  589. end;
  590. if (HRef<>'')then
  591. begin
  592. if (LinkPtr<MaxTopicLinks){ and
  593. not DisableCrossIndexing} then
  594. begin
  595. InAnchor:=true;
  596. AddChar(hscLink);
  597. HRef:=CompleteURL(URL,HRef);
  598. LinkIndexes[LinkPtr]:=TopicLinks^.AddItem(HRef);
  599. {$ifdef DEBUG}
  600. DebugMessage('',' Adding Link '+HRef,1,1);
  601. {$endif DEBUG}
  602. Inc(LinkPtr);
  603. end;
  604. end;
  605. end
  606. else
  607. begin
  608. if InAnchor=true then AddChar(hscLink);
  609. InAnchor:=false;
  610. end;
  611. end;
  612. procedure THTMLTopicRenderer.DocUnknownTag;
  613. begin
  614. {$ifdef DEBUG}
  615. DebugMessage('',' Unknown tag "'+TagName+'" params "'+
  616. TagParams+'"',1,1);
  617. {$endif DEBUG}
  618. end;
  619. procedure DecodeAlign(Align: string; var PAlign: TParagraphAlign);
  620. begin
  621. Align:=UpcaseStr(Align);
  622. if Align='LEFT' then PAlign:=paLeft else
  623. if Align='CENTER' then PAlign:=paCenter else
  624. if Align='RIGHT' then PAlign:=paRight;
  625. end;
  626. procedure THTMLTopicRenderer.DocHeading(Level: integer; Entered: boolean);
  627. var Align: string;
  628. C: byte;
  629. SC: THTMLSection;
  630. begin
  631. if Entered then
  632. begin
  633. DocBreak;
  634. CurHeadLevel:=Level;
  635. PAlign:=paLeft;
  636. if DocGetTagParam('ALIGN',Align) then
  637. DecodeAlign(Align,PAlign);
  638. SC:=hsNone;
  639. case Level of
  640. 1: SC:=hsHeading1;
  641. 2: SC:=hsHeading2;
  642. 3: SC:=hsHeading3;
  643. 4: SC:=hsHeading4;
  644. 5: SC:=hsHeading5;
  645. 6: SC:=hsHeading6;
  646. end;
  647. if GetSectionColor(SC,C) then
  648. AddText(hscTextAttr+chr(C));
  649. end
  650. else
  651. begin
  652. AddChar(hscNormText);
  653. CurHeadLevel:=0;
  654. DocBreak;
  655. end;
  656. end;
  657. procedure THTMLTopicRenderer.DocParagraph(Entered: boolean);
  658. var Align: string;
  659. begin
  660. if Entered and InParagraph then DocParagraph(false);
  661. if Entered then
  662. begin
  663. if AnyCharsInLine then DocBreak;
  664. if DocGetTagParam('ALIGN',Align) then
  665. DecodeAlign(Align,PAlign);
  666. end
  667. else
  668. begin
  669. { if AnyCharsInLine then }DocBreak;
  670. PAlign:=paLeft;
  671. end;
  672. InParagraph:=Entered;
  673. end;
  674. procedure THTMLTopicRenderer.DocBreak;
  675. begin
  676. if (CurHeadLevel=1) or (PAlign=paCenter) then
  677. AddChar(hscCenter);
  678. if (PAlign=paRight) then
  679. AddChar(hscRight);
  680. AddChar(hscLineBreak);
  681. if Indent>0 then
  682. AddText(CharStr(#255,Indent)+hscLineStart);
  683. AnyCharsInLine:=false;
  684. end;
  685. procedure THTMLTopicRenderer.DocImage;
  686. var Src,Alt,SrcLine: string;
  687. f : text;
  688. attr : byte;
  689. PA : PHTMLAnsiView;
  690. StorePreformatted : boolean;
  691. begin
  692. if DocGetTagParam('SRC',src) then
  693. begin
  694. if src<>'' then
  695. begin
  696. src:=CompleteURL(URL,src);
  697. { this should be a image file ending by .gif or .jpg...
  698. Try to see if a file with same name and extension .git
  699. exists PM }
  700. src:=DirAndNameOf(src)+'.ans';
  701. if ExistsFile(src) then
  702. begin
  703. PA:=New(PHTMLAnsiView,init(@self));
  704. PA^.LoadFile(src);
  705. if AnyCharsInLine then DocBreak;
  706. StorePreformatted:=InPreformatted;
  707. InPreformatted:=true;
  708. {AddText('Image from '+src+hscLineBreak); }
  709. AddChar(hscInImage);
  710. PA^.CopyToHTML;
  711. InPreformatted:=StorePreformatted;
  712. AddChar(hscInImage);
  713. AddChar(hscNormText);
  714. if AnyCharsInLine then DocBreak;
  715. Dispose(PA,Done);
  716. Exit;
  717. end;
  718. { also look for a raw text file without colors }
  719. src:=DirAndNameOf(src)+'.txt';
  720. if ExistsFile(src) then
  721. begin
  722. Assign(f,src);
  723. Reset(f);
  724. DocPreformatted(true);
  725. while not eof(f) do
  726. begin
  727. Readln(f,SrcLine);
  728. AddText(SrcLine+hscLineBreak);
  729. end;
  730. Close(f);
  731. DocPreformatted(false);
  732. Exit;
  733. end;
  734. end;
  735. end;
  736. if DocGetTagParam('ALT',Alt)=false then
  737. begin
  738. DocGetTagParam('SRC',Alt);
  739. if Alt<>'' then
  740. Alt:='Can''t display '+Alt
  741. else
  742. Alt:='IMG';
  743. end;
  744. if Alt<>'' then
  745. begin
  746. StorePreformatted:=InPreformatted;
  747. InPreformatted:=true;
  748. DocGetTagParam('SRC',src);
  749. AddChar(hscInImage);
  750. AddText('[--'+Src+'--'+hscLineBreak);
  751. AddText(Alt+hscLineBreak+'--]');
  752. AddChar(hscInImage);
  753. AddChar(hscNormText);
  754. InPreformatted:=StorePreformatted;
  755. end;
  756. end;
  757. procedure THTMLTopicRenderer.DocBold(Entered: boolean);
  758. begin
  759. end;
  760. procedure THTMLTopicRenderer.DocCite(Entered: boolean);
  761. begin
  762. end;
  763. procedure THTMLTopicRenderer.DocCode(Entered: boolean);
  764. begin
  765. if AnyCharsInLine then DocBreak;
  766. AddText(hscCode);
  767. DocBreak;
  768. end;
  769. procedure THTMLTopicRenderer.DocEmphasized(Entered: boolean);
  770. begin
  771. end;
  772. procedure THTMLTopicRenderer.DocItalic(Entered: boolean);
  773. begin
  774. end;
  775. procedure THTMLTopicRenderer.DocKbd(Entered: boolean);
  776. begin
  777. end;
  778. procedure THTMLTopicRenderer.DocPreformatted(Entered: boolean);
  779. begin
  780. if AnyCharsInLine then DocBreak;
  781. AddText(hscCode);
  782. DocBreak;
  783. InPreformatted:=Entered;
  784. end;
  785. procedure THTMLTopicRenderer.DocSample(Entered: boolean);
  786. begin
  787. end;
  788. procedure THTMLTopicRenderer.DocStrong(Entered: boolean);
  789. begin
  790. end;
  791. procedure THTMLTopicRenderer.DocTeleType(Entered: boolean);
  792. begin
  793. end;
  794. procedure THTMLTopicRenderer.DocVariable(Entered: boolean);
  795. begin
  796. end;
  797. procedure THTMLTopicRenderer.DocSpan(Entered: boolean);
  798. begin
  799. end;
  800. procedure THTMLTopicRenderer.DocList(Entered: boolean);
  801. begin
  802. if Entered then
  803. begin
  804. Inc(Indent,ListIndent);
  805. DocBreak;
  806. end
  807. else
  808. begin
  809. Dec(Indent,ListIndent);
  810. if AnyCharsInLine then DocBreak;
  811. end;
  812. end;
  813. procedure THTMLTopicRenderer.DocOrderedList(Entered: boolean);
  814. begin
  815. DocList(Entered);
  816. end;
  817. procedure THTMLTopicRenderer.DocListItem;
  818. begin
  819. if AnyCharsInLine then
  820. DocBreak;
  821. AddText('þ'+hscLineStart);
  822. end;
  823. procedure THTMLTopicRenderer.DocDefList(Entered: boolean);
  824. begin
  825. if Entered then
  826. begin
  827. { if LastChar<>hscLineBreak then DocBreak;}
  828. end
  829. else
  830. begin
  831. if AnyCharsInLine then DocBreak;
  832. end;
  833. end;
  834. procedure THTMLTopicRenderer.DocDefTerm;
  835. begin
  836. DocBreak;
  837. end;
  838. procedure THTMLTopicRenderer.DocDefExp;
  839. begin
  840. Inc(Indent,DefIndent);
  841. DocBreak;
  842. Dec(Indent,DefIndent);
  843. end;
  844. procedure THTMLTopicRenderer.DocTable(Entered: boolean);
  845. var
  846. ATable : PTable;
  847. Border : String;
  848. begin
  849. if AnyCharsInLine then
  850. begin
  851. AddChar(hscLineBreak);
  852. AnyCharsInLine:=false;
  853. end;
  854. if Entered then
  855. begin
  856. DocBreak;
  857. New(ATable,Init(CurrentTable));
  858. CurrentTable:=ATable;
  859. CurrentTable^.Renderer:=@Self;
  860. if DocGetTagParam('BORDER',border) then
  861. if Border<>'0' then
  862. CurrentTable^.WithBorder:=true;
  863. end
  864. else
  865. begin
  866. CurrentTable^.FormatTable;
  867. ATable:=CurrentTable;
  868. CurrentTable:=ATable^.PreviousTable;
  869. Dispose(ATable,Done);
  870. end;
  871. end;
  872. procedure THTMLTopicRenderer.DocTableRow(Entered: boolean);
  873. var
  874. ATableLine : PTableLine;
  875. begin
  876. if AnyCharsInLine or
  877. (assigned(CurrentTable) and
  878. assigned(CurrentTable^.FirstLine)) then
  879. begin
  880. AddChar(hscLineBreak);
  881. AnyCharsInLine:=false;
  882. end;
  883. if Entered then
  884. begin
  885. New(ATableLine,Init);
  886. if CurrentTable^.GlobalTextBegin=0 then
  887. CurrentTable^.GlobalTextBegin:=TextPtr;
  888. CurrentTable^.AddLine(ATableLine);
  889. end;
  890. end;
  891. procedure THTMLTopicRenderer.DocTableItem(Entered: boolean);
  892. var
  893. Align : String;
  894. i : sw_word;
  895. NewEl : PTableElement;
  896. PAlignEl : TParagraphAlign;
  897. begin
  898. if Entered then
  899. begin
  900. if assigned(CurrentTable^.LastLine) and Assigned(CurrentTable^.LastLine^.LastEl) and
  901. (CurrentTable^.LastLine^.LastEl^.TextEnd=sw_word(-1)) then
  902. begin
  903. NewEl:=CurrentTable^.LastLine^.LastEl;
  904. NewEl^.TextEnd:=TextPtr;
  905. NewEl^.TextLength:=ComputeTextLength(
  906. NewEl^.TextBegin+CurrentTable^.GlobalOffset,
  907. TextPtr+CurrentTable^.GlobalOffset);
  908. end;
  909. PAlignEl:=paLeft;
  910. if DocGetTagParam('ALIGN',Align) then
  911. DecodeAlign(Align,PAlignEl);
  912. New(NewEl,Init(PAlignEl));
  913. CurrentTable^.AddElement(NewEl);
  914. NewEl^.TextBegin:=TextPtr;
  915. NewEl^.TextEnd:=sw_word(-1);
  916. { AddText(' - ');}
  917. end
  918. else
  919. begin
  920. NewEl:=CurrentTable^.LastLine^.LastEl;
  921. NewEl^.TextEnd:=TextPtr;
  922. NewEl^.TextLength:=ComputeTextLength(
  923. NewEl^.TextBegin+CurrentTable^.GlobalOffset,
  924. TextPtr+CurrentTable^.GlobalOffset);
  925. NewEl^.NumNL:=0;
  926. for i:=NewEl^.TextBegin to TextPtr do
  927. begin
  928. if Topic^.Text^[i]=ord(hscLineBreak) then
  929. inc(NewEl^.NumNL);
  930. end;
  931. end;
  932. end;
  933. procedure THTMLTopicRenderer.DocHorizontalRuler;
  934. var OAlign: TParagraphAlign;
  935. begin
  936. OAlign:=PAlign;
  937. if AnyCharsInLine then DocBreak;
  938. PAlign:=paCenter;
  939. DocAddText(' '+CharStr('Ä',60)+' ');
  940. DocBreak;
  941. PAlign:=OAlign;
  942. end;
  943. procedure THTMLTopicRenderer.AddChar(C: char);
  944. begin
  945. if (Topic=nil) or (TextPtr=MaxBytes) then Exit;
  946. Topic^.Text^[TextPtr]:=ord(C);
  947. Inc(TextPtr);
  948. if (C>#15) and ((C<>' ') or (InPreFormatted=true)) then
  949. AnyCharsInLine:=true;
  950. end;
  951. procedure THTMLTopicRenderer.AddCharAt(C: char;AtPtr : sw_word);
  952. begin
  953. if (Topic=nil) or (TextPtr=MaxBytes) then Exit;
  954. if AtPtr>TextPtr then
  955. AtPtr:=TextPtr
  956. else
  957. begin
  958. Move(Topic^.Text^[AtPtr],Topic^.Text^[AtPtr+1],TextPtr-AtPtr);
  959. end;
  960. Topic^.Text^[AtPtr]:=ord(C);
  961. Inc(TextPtr);
  962. end;
  963. procedure THTMLTopicRenderer.AddText(const S: string);
  964. var I: sw_integer;
  965. begin
  966. for I:=1 to length(S) do
  967. AddChar(S[I]);
  968. end;
  969. function THTMLTopicRenderer.ComputeTextLength(TStart,TEnd : sw_word) : sw_word;
  970. var I,tot: sw_integer;
  971. begin
  972. tot:=0;
  973. i:=TStart;
  974. while i<= TEnd-1 do
  975. begin
  976. inc(tot);
  977. case chr(Topic^.Text^[i]) of
  978. hscLink,hscCode,
  979. hscCenter,hscRight,
  980. hscNamedMark,hscNormText :
  981. Dec(tot);{ Do not increase tot }
  982. hscDirect:
  983. begin
  984. Inc(i); { Skip next }
  985. //Inc(tot);
  986. end;
  987. hscTextAttr,
  988. hscTextColor:
  989. begin
  990. Inc(i);
  991. Dec(tot);
  992. end;
  993. end;
  994. inc(i);
  995. end;
  996. ComputeTextLength:=tot;
  997. end;
  998. function THTMLTopicRenderer.AddTextAt(const S: String;AtPtr : sw_word) : sw_word;
  999. var
  1000. i,slen,len : sw_word;
  1001. begin
  1002. if (Topic=nil) or (TextPtr>=MaxBytes) then Exit;
  1003. slen:=length(s);
  1004. if TextPtr+slen>=MaxBytes then
  1005. slen:=MaxBytes-TextPtr;
  1006. if AtPtr>TextPtr then
  1007. AtPtr:=TextPtr
  1008. else
  1009. begin
  1010. len:=TextPtr-AtPtr;
  1011. Move(Topic^.Text^[AtPtr],Topic^.Text^[AtPtr+slen],len);
  1012. end;
  1013. for i:=1 to slen do
  1014. begin
  1015. Topic^.Text^[AtPtr]:=ord(S[i]);
  1016. Inc(TextPtr);
  1017. inc(AtPtr);
  1018. if (TextPtr=MaxBytes) then Exit;
  1019. end;
  1020. AddTextAt:=slen;
  1021. end;
  1022. function THTMLTopicRenderer.GetSectionColor(Section: THTMLSection; var Color: byte): boolean;
  1023. begin
  1024. GetSectionColor:=HTMLGetSectionColor(Section,Color);
  1025. end;
  1026. function THTMLTopicRenderer.BuildTopic(P: PTopic; AURL: string; HTMLFile: PTextFile;
  1027. ATopicLinks: PTopicLinkCollection): boolean;
  1028. var OK: boolean;
  1029. TP: pointer;
  1030. I: sw_integer;
  1031. begin
  1032. URL:=AURL;
  1033. Topic:=P; TopicLinks:=ATopicLinks;
  1034. OK:=Assigned(Topic) and Assigned(HTMLFile) and Assigned(TopicLinks);
  1035. if OK then
  1036. begin
  1037. if (Topic^.TextSize<>0) and Assigned(Topic^.Text) then
  1038. begin
  1039. FreeMem(Topic^.Text,Topic^.TextSize);
  1040. Topic^.TextSize:=0; Topic^.Text:=nil;
  1041. end;
  1042. Topic^.TextSize:=MaxHelpTopicSize;
  1043. GetMem(Topic^.Text,Topic^.TextSize);
  1044. TopicTitle:='';
  1045. InTitle:=false; InBody:={false}true; InAnchor:=false;
  1046. InParagraph:=false; InPreformatted:=false;
  1047. Indent:=0; CurHeadLevel:=0;
  1048. PAlign:=paLeft;
  1049. TextPtr:=0; LinkPtr:=0;
  1050. AnyCharsInLine:=false;
  1051. LastTextChar:=#0;
  1052. OK:=Process(HTMLFile);
  1053. if OK then
  1054. begin
  1055. { --- topic links --- }
  1056. if (Topic^.Links<>nil) and (Topic^.LinkSize>0) then
  1057. begin
  1058. FreeMem(Topic^.Links,Topic^.LinkSize);
  1059. Topic^.Links:=nil; Topic^.LinkCount:=0;
  1060. end;
  1061. Topic^.LinkCount:=LinkPtr{TopicLinks^.Count}; { <- eeeeeek! }
  1062. GetMem(Topic^.Links,Topic^.LinkSize);
  1063. if Topic^.LinkCount>0 then { FP causes numeric RTE 215 without this }
  1064. for I:=0 to Min(Topic^.LinkCount-1,High(LinkIndexes)-1) do
  1065. begin
  1066. Topic^.Links^[I].FileID:=Topic^.FileID;
  1067. Topic^.Links^[I].Context:=EncodeHTMLCtx(Topic^.FileID,LinkIndexes[I]+1);
  1068. end;
  1069. { --- topic text --- }
  1070. GetMem(TP,TextPtr);
  1071. Move(Topic^.Text^,TP^,TextPtr);
  1072. FreeMem(Topic^.Text,Topic^.TextSize);
  1073. Topic^.Text:=TP; Topic^.TextSize:=TextPtr;
  1074. end
  1075. else
  1076. begin
  1077. DisposeTopic(Topic);
  1078. Topic:=nil;
  1079. end;
  1080. end;
  1081. BuildTopic:=OK;
  1082. end;
  1083. constructor TCustomHTMLHelpFile.Init(AID: word);
  1084. begin
  1085. inherited Init(AID);
  1086. New(Renderer, Init);
  1087. New(TopicLinks, Init(50,500));
  1088. end;
  1089. function TCustomHTMLHelpFile.SearchTopic(HelpCtx: THelpCtx): PTopic;
  1090. function MatchCtx(P: PTopic): boolean; {$ifndef FPC}far;{$endif}
  1091. begin
  1092. MatchCtx:=P^.HelpCtx=HelpCtx;
  1093. end;
  1094. var FileID,LinkNo: word;
  1095. P: PTopic;
  1096. FName: string;
  1097. begin
  1098. DecodeHTMLCtx(HelpCtx,FileID,LinkNo);
  1099. if (HelpCtx<>0) and (FileID<>ID) then P:=nil else
  1100. if (FileID=ID) and (LinkNo>TopicLinks^.Count) then P:=nil else
  1101. begin
  1102. P:=Topics^.FirstThat(@MatchCtx);
  1103. if P=nil then
  1104. begin
  1105. if LinkNo=0 then
  1106. FName:=DefaultFileName
  1107. else
  1108. FName:=TopicLinks^.At(LinkNo-1)^;
  1109. P:=NewTopic(ID,HelpCtx,0,FName,nil,0);
  1110. Topics^.Insert(P);
  1111. end;
  1112. end;
  1113. SearchTopic:=P;
  1114. end;
  1115. function TCustomHTMLHelpFile.GetTopicInfo(T: PTopic) : string;
  1116. var OK: boolean;
  1117. Name: string;
  1118. Link,Bookmark: string;
  1119. P: sw_integer;
  1120. begin
  1121. Bookmark:='';
  1122. OK:=T<>nil;
  1123. if OK then
  1124. begin
  1125. if T^.HelpCtx=0 then
  1126. begin
  1127. Name:=DefaultFileName;
  1128. P:=0;
  1129. end
  1130. else
  1131. begin
  1132. Link:=TopicLinks^.At((T^.HelpCtx and $ffff)-1)^;
  1133. Link:=FormatPath(Link);
  1134. {$ifdef DEBUG_WHTMLHLP}
  1135. DebugMessage(Link,' looking for',1,1);
  1136. {$endif DEBUG_WHTMLHLP}
  1137. P:=Pos('#',Link);
  1138. if P>0 then
  1139. begin
  1140. Bookmark:=copy(Link,P+1,length(Link));
  1141. Link:=copy(Link,1,P-1);
  1142. end;
  1143. { if CurFileName='' then Name:=Link else
  1144. Name:=CompletePath(CurFileName,Link);}
  1145. Name:=Link;
  1146. end;
  1147. end;
  1148. GetTopicInfo:=Name+'#'+BookMark;
  1149. end;
  1150. function TCustomHTMLHelpFile.ReadTopic(T: PTopic): boolean;
  1151. var OK: boolean;
  1152. HTMLFile: PMemoryTextFile;
  1153. Name: string;
  1154. Link,Bookmark: string;
  1155. P: sw_integer;
  1156. begin
  1157. Bookmark:='';
  1158. OK:=T<>nil;
  1159. if OK then
  1160. begin
  1161. if T^.HelpCtx=0 then
  1162. begin
  1163. Name:=DefaultFileName;
  1164. P:=0;
  1165. end
  1166. else
  1167. begin
  1168. Link:=TopicLinks^.At((T^.HelpCtx and $ffff)-1)^;
  1169. Link:=FormatPath(Link);
  1170. {$ifdef DEBUG}
  1171. DebugMessage(Link,' looking for',1,1);
  1172. {$endif DEBUG}
  1173. P:=Pos('#',Link);
  1174. if P>0 then
  1175. begin
  1176. Bookmark:=copy(Link,P+1,length(Link));
  1177. Link:=copy(Link,1,P-1);
  1178. end;
  1179. { if CurFileName='' then Name:=Link else
  1180. Name:=CompletePath(CurFileName,Link);}
  1181. Name:=Link;
  1182. end;
  1183. HTMLFile:=nil;
  1184. if Name<>'' then
  1185. HTMLFile:=New(PDOSTextFile, Init(Name));
  1186. if (HTMLFile=nil)and (CurFileName<>'') then
  1187. begin
  1188. Name:=CurFileName;
  1189. HTMLFile:=New(PDOSTextFile, Init(Name));
  1190. end;
  1191. if (HTMLFile=nil) then
  1192. begin
  1193. {$ifdef DEBUG}
  1194. DebugMessage(Link,' filename not known :(',1,1);
  1195. {$endif DEBUG}
  1196. end;
  1197. if (p>1) and (HTMLFile=nil) then
  1198. begin
  1199. {$ifdef DEBUG}
  1200. if p>0 then
  1201. DebugMessage(Name,Link+'#'+Bookmark+' not found',1,1)
  1202. else
  1203. DebugMessage(Name,Link+' not found',1,1);
  1204. {$endif DEBUG}
  1205. New(HTMLFile, Init);
  1206. HTMLFile^.AddLine('<HEAD><TITLE>'+msg_pagenotavailable+'</TITLE></HEAD>');
  1207. HTMLFile^.AddLine(
  1208. '<BODY>'+
  1209. FormatStrStr(msg_cantaccessurl,Name)+'<br><br>'+
  1210. '</BODY>');
  1211. end;
  1212. OK:=Renderer^.BuildTopic(T,Name,HTMLFile,TopicLinks);
  1213. if OK then
  1214. CurFileName:=Name
  1215. else
  1216. begin
  1217. {$ifdef DEBUG}
  1218. if p>0 then
  1219. DebugMessage(Name,Link+'#'+Bookmark+' not found',1,1)
  1220. else
  1221. DebugMessage(Name,Link+' not found',1,1);
  1222. {$endif DEBUG}
  1223. end;
  1224. if HTMLFile<>nil then
  1225. Dispose(HTMLFile, Done);
  1226. if BookMark='' then
  1227. T^.StartNamedMark:=0
  1228. else
  1229. begin
  1230. P:=T^.GetNamedMarkIndex(BookMark);
  1231. {$ifdef DEBUG}
  1232. if p=-1 then
  1233. DebugMessage(Name,Link+'#'+Bookmark+' bookmark not found',1,1);
  1234. {$endif DEBUG}
  1235. T^.StartNamedMark:=P+1;
  1236. end;
  1237. end;
  1238. ReadTopic:=OK;
  1239. end;
  1240. destructor TCustomHTMLHelpFile.Done;
  1241. begin
  1242. inherited Done;
  1243. if Renderer<>nil then Dispose(Renderer, Done);
  1244. if TopicLinks<>nil then Dispose(TopicLinks, Done);
  1245. end;
  1246. constructor THTMLHelpFile.Init(AFileName: string; AID: word; ATOCEntry: string);
  1247. begin
  1248. if inherited Init(AID)=false then Fail;
  1249. DefaultFileName:=AFileName; TOCEntry:=ATOCEntry;
  1250. if DefaultFileName='' then
  1251. begin
  1252. Done;
  1253. Fail;
  1254. end;
  1255. end;
  1256. function THTMLHelpFile.LoadIndex: boolean;
  1257. begin
  1258. IndexEntries^.Insert(NewIndexEntry(TOCEntry,ID,0));
  1259. LoadIndex:=true;
  1260. end;
  1261. constructor THTMLIndexHelpFile.Init(AFileName: string; AID: word);
  1262. begin
  1263. inherited Init(AID);
  1264. IndexFileName:=AFileName;
  1265. end;
  1266. function THTMLIndexHelpFile.LoadIndex: boolean;
  1267. function FormatAlias(Alias: string): string;
  1268. begin
  1269. if Assigned(HelpFacility) then
  1270. if length(Alias)>HelpFacility^.IndexTabSize-4 then
  1271. Alias:=Trim(copy(Alias,1,HelpFacility^.IndexTabSize-4-2))+'..';
  1272. FormatAlias:=Alias;
  1273. end;
  1274. (*procedure AddDoc(P: PHTMLLinkScanDocument); {$ifndef FPC}far;{$endif}
  1275. var I: sw_integer;
  1276. TLI: THelpCtx;
  1277. begin
  1278. for I:=1 to P^.GetAliasCount do
  1279. begin
  1280. TLI:=TopicLinks^.AddItem(P^.GetName);
  1281. TLI:=EncodeHTMLCtx(ID,TLI+1);
  1282. IndexEntries^.Insert(NewIndexEntry(FormatAlias(P^.GetAlias(I-1)),ID,TLI));
  1283. end;
  1284. end;*)
  1285. var S: PBufStream;
  1286. LS: PHTMLLinkScanner;
  1287. OK: boolean;
  1288. TLI: THelpCtx;
  1289. I,J: sw_integer;
  1290. begin
  1291. New(S, Init(IndexFileName,stOpenRead,4096));
  1292. OK:=Assigned(S);
  1293. if OK then
  1294. begin
  1295. New(LS, LoadDocuments(S^));
  1296. OK:=Assigned(LS);
  1297. if OK then
  1298. begin
  1299. LS^.SetBaseDir(DirOf(IndexFileName));
  1300. for I:=0 to LS^.GetDocumentCount-1 do
  1301. begin
  1302. TLI:=TopicLinks^.AddItem(LS^.GetDocumentURL(I));
  1303. TLI:=EncodeHTMLCtx(ID,TLI+1);
  1304. for J:=0 to LS^.GetDocumentAliasCount(I)-1 do
  1305. IndexEntries^.Insert(NewIndexEntry(
  1306. FormatAlias(LS^.GetDocumentAlias(I,J)),ID,TLI));
  1307. end;
  1308. Dispose(LS, Done);
  1309. end;
  1310. Dispose(S, Done);
  1311. end;
  1312. LoadIndex:=OK;
  1313. end;
  1314. function CreateProcHTML(const FileName,Param: string;Index : longint): PHelpFile; {$ifndef FPC}far;{$endif}
  1315. var H: PHelpFile;
  1316. begin
  1317. H:=nil;
  1318. if CompareText(copy(ExtOf(FileName),1,length(extHTML)),extHTML)=0 then
  1319. H:=New(PHTMLHelpFile, Init(FileName,Index,Param));
  1320. CreateProcHTML:=H;
  1321. end;
  1322. function CreateProcHTMLIndex(const FileName,Param: string;Index : longint): PHelpFile; {$ifndef FPC}far;{$endif}
  1323. var H: PHelpFile;
  1324. begin
  1325. H:=nil;
  1326. if CompareText(ExtOf(FileName),extHTMLIndex)=0 then
  1327. H:=New(PHTMLIndexHelpFile, Init(FileName,Index));
  1328. CreateProcHTMLIndex:=H;
  1329. end;
  1330. procedure RegisterHelpType;
  1331. begin
  1332. RegisterHelpFileType({$ifdef FPC}@{$endif}CreateProcHTML);
  1333. RegisterHelpFileType({$ifdef FPC}@{$endif}CreateProcHTMLIndex);
  1334. end;
  1335. END.