whtmlhlp.pas 32 KB

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