whtmlhlp.pas 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1999-2000 by Berczi Gabor
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit WHTMLHlp;
  12. interface
  13. uses Objects,WHTML,WAnsi,WHelp;
  14. const
  15. extHTML = '.htm';
  16. extHTMLIndex = '.htx';
  17. ListIndent = 2;
  18. DefIndent = 4;
  19. MaxTopicLinks = 4000; { maximum number of links on a single HTML page }
  20. type
  21. THTMLSection = (hsNone,hsHeading1,hsHeading2,hsHeading3,hsHeading4,hsHeading5,hsHeading6);
  22. PTopicLinkCollection = ^TTopicLinkCollection;
  23. TTopicLinkCollection = object(TStringCollection)
  24. procedure Insert(Item: Pointer); virtual;
  25. function At(Index: sw_Integer): PString;
  26. function AddItem(Item: string): integer;
  27. end;
  28. TParagraphAlign = (paLeft,paCenter,paRight);
  29. PTableElement = ^TTableElement;
  30. TTableElement = object(Tobject)
  31. TextBegin,TextEnd : sw_word;
  32. Alignment : TParagraphAlign;
  33. NextEl : PTableElement;
  34. constructor init(AAlignment : TParagraphAlign);
  35. end;
  36. PTableLine = ^TTableLine;
  37. TTableLine = object(Tobject)
  38. NumElements : sw_word;
  39. Nextline : PTableLine;
  40. FirstEl,LastEl : PTableElement;
  41. constructor Init;
  42. procedure AddElement(PTE : PTableElement);
  43. destructor Done; virtual;
  44. end;
  45. PHTMLTopicRenderer = ^THTMLTopicRenderer;
  46. PTable = ^TTable;
  47. TTable = object(Tobject)
  48. NumLines,NumCols : sw_word;
  49. GlobalOffset,
  50. GlobalTextBegin : sw_word;
  51. WithBorder : boolean;
  52. FirstLine : PTableLine;
  53. LastLine : PTableLine;
  54. PreviousTable : PTable;
  55. Renderer : PHTMLTopicRenderer;
  56. constructor Init(Previous : PTable);
  57. procedure AddLine(PL : PTableLine);
  58. procedure AddElement(PTE : PTableElement);
  59. procedure TextInsert(Pos : sw_word;const S : string);
  60. procedure FormatTable;
  61. destructor Done; virtual;
  62. end;
  63. THTMLTopicRenderer = object(THTMLParser)
  64. function BuildTopic(P: PTopic; AURL: string; HTMLFile: PTextFile; ATopicLinks: PTopicLinkCollection): boolean;
  65. public
  66. function DocAddTextChar(C: char): boolean; virtual;
  67. procedure DocSoftBreak; virtual;
  68. procedure DocTYPE; virtual;
  69. procedure DocHTML(Entered: boolean); virtual;
  70. procedure DocHEAD(Entered: boolean); virtual;
  71. procedure DocMETA; virtual;
  72. procedure DocTITLE(Entered: boolean); virtual;
  73. procedure DocBODY(Entered: boolean); virtual;
  74. procedure DocAnchor(Entered: boolean); 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 DocList(Entered: boolean); virtual;
  91. procedure DocOrderedList(Entered: boolean); virtual;
  92. procedure DocListItem; virtual;
  93. procedure DocDefList(Entered: boolean); virtual;
  94. procedure DocDefTerm; virtual;
  95. procedure DocDefExp; virtual;
  96. procedure DocTable(Entered: boolean); virtual;
  97. procedure DocTableRow(Entered: boolean); virtual;
  98. procedure DocTableItem(Entered: boolean); virtual;
  99. procedure DocHorizontalRuler; virtual;
  100. public
  101. function GetSectionColor(Section: THTMLSection; var Color: byte): boolean; virtual;
  102. private
  103. URL: string;
  104. Topic: PTopic;
  105. TopicLinks: PTopicLinkCollection;
  106. TextPtr: sw_word;
  107. InTitle: boolean;
  108. InBody: boolean;
  109. InAnchor: boolean;
  110. InParagraph: boolean;
  111. InPreformatted: boolean;
  112. TopicTitle: string;
  113. Indent: integer;
  114. AnyCharsInLine: boolean;
  115. CurHeadLevel: integer;
  116. PAlign: TParagraphAlign;
  117. LinkIndexes: array[0..MaxTopicLinks] of sw_integer;
  118. LinkPtr: sw_integer;
  119. LastTextChar: char;
  120. { Anchor: TAnchor;}
  121. { Table stuff }
  122. CurrentTable : PTable;
  123. procedure AddText(S: string);
  124. procedure AddChar(C: char);
  125. procedure AddCharAt(C: char;AtPtr : 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 : longint;
  243. begin
  244. for i:=1 to Length(S) do
  245. begin
  246. Renderer^.AddCharAt(S[i],Pos+i-1+GlobalOffset);
  247. end;
  248. GlobalOffset:=GlobalOffset+length(S);
  249. end;
  250. procedure TTable.FormatTable;
  251. const
  252. MaxCols = 200;
  253. type
  254. TLengthArray = Array [ 1 .. MaxCols] of sw_word;
  255. PLengthArray = ^TLengthArray;
  256. var
  257. ColLengthArray : PLengthArray;
  258. CurLine : PTableLine;
  259. CurEl : PTableElement;
  260. Align : TParagraphAlign;
  261. TextBegin,TextEnd : sw_word;
  262. i,j,Length : sw_word;
  263. begin
  264. GetMem(ColLengthArray,Sizeof(sw_word)*NumCols);
  265. FillChar(ColLengthArray^,Sizeof(sw_word)*NumCols,#0);
  266. { Compute the largest cell }
  267. CurLine:=FirstLine;
  268. For i:=1 to NumLines do
  269. begin
  270. CurEl:=CurLine^.FirstEl;
  271. For j:=1 to NumCols do
  272. begin
  273. if not assigned(CurEl) then
  274. break;
  275. Length:=CurEl^.TextEnd-CurEl^.TextBegin;
  276. if Length>ColLengthArray^[j] then
  277. ColLengthArray^[j]:=Length;
  278. CurEl:=CurEl^.NextEl;
  279. end;
  280. CurLine:=CurLine^.NextLine;
  281. end;
  282. { Adjust to largest cell }
  283. CurLine:=FirstLine;
  284. TextBegin:=GlobalTextBegin;
  285. If (NumLines>0) and WithBorder then
  286. Begin
  287. TextInsert(TextBegin,#218);
  288. For j:=1 to NumCols do
  289. begin
  290. TextInsert(TextBegin,CharStr(#196,ColLengthArray^[j]));
  291. if j<NumCols then
  292. TextInsert(TextBegin,#194);
  293. end;
  294. TextInsert(TextBegin,#191);
  295. TextInsert(TextBegin,hscLineBreak);
  296. End;
  297. For i:=1 to NumLines do
  298. begin
  299. CurEl:=CurLine^.FirstEl;
  300. For j:=1 to NumCols do
  301. begin
  302. if not assigned(CurEl) then
  303. begin
  304. Length:=0;
  305. Align:=paLeft;
  306. end
  307. else
  308. begin
  309. TextBegin:=CurEl^.TextBegin;
  310. TextEnd:=CurEl^.TextEnd;
  311. Length:=CurEl^.TextEnd-CurEl^.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. begin
  642. if DocGetTagParam('SRC',src) then
  643. begin
  644. if src<>'' then
  645. begin
  646. src:=CompleteURL(URL,src);
  647. { this should be a image file ending by .gif or .jpg...
  648. Try to see if a file with same name and extension .git
  649. exists PM }
  650. src:=DirAndNameOf(src)+'.ans';
  651. if ExistsFile(src) then
  652. begin
  653. PA:=New(PHTMLAnsiView,init(@self));
  654. PA^.LoadFile(src);
  655. if AnyCharsInLine then DocBreak;
  656. InPreformatted:=true;
  657. {AddText('Image from '+src+hscLineBreak); }
  658. AddChar(hscInImage);
  659. PA^.CopyToHTML;
  660. InPreformatted:=false;
  661. AddChar(hscInImage);
  662. AddChar(hscNormText);
  663. if AnyCharsInLine then DocBreak;
  664. Dispose(PA,Done);
  665. Exit;
  666. end;
  667. { also look for a raw text file without colors }
  668. src:=DirAndNameOf(src)+'.txt';
  669. if ExistsFile(src) then
  670. begin
  671. Assign(f,src);
  672. Reset(f);
  673. DocPreformatted(true);
  674. while not eof(f) do
  675. begin
  676. Readln(f,SrcLine);
  677. AddText(SrcLine+hscLineBreak);
  678. end;
  679. Close(f);
  680. DocPreformatted(false);
  681. Exit;
  682. end;
  683. end;
  684. end;
  685. if DocGetTagParam('ALT',Alt)=false then
  686. begin
  687. DocGetTagParam('SRC',Alt);
  688. if Alt<>'' then
  689. Alt:='Can''t display '+Alt
  690. else
  691. Alt:='IMG';
  692. end;
  693. if Alt<>'' then
  694. begin
  695. AddText('['+Alt+']');
  696. end;
  697. end;
  698. procedure THTMLTopicRenderer.DocBold(Entered: boolean);
  699. begin
  700. end;
  701. procedure THTMLTopicRenderer.DocCite(Entered: boolean);
  702. begin
  703. end;
  704. procedure THTMLTopicRenderer.DocCode(Entered: boolean);
  705. begin
  706. if AnyCharsInLine then DocBreak;
  707. AddText(hscCode);
  708. DocBreak;
  709. end;
  710. procedure THTMLTopicRenderer.DocEmphasized(Entered: boolean);
  711. begin
  712. end;
  713. procedure THTMLTopicRenderer.DocItalic(Entered: boolean);
  714. begin
  715. end;
  716. procedure THTMLTopicRenderer.DocKbd(Entered: boolean);
  717. begin
  718. end;
  719. procedure THTMLTopicRenderer.DocPreformatted(Entered: boolean);
  720. begin
  721. if AnyCharsInLine then DocBreak;
  722. AddText(hscCode);
  723. DocBreak;
  724. InPreformatted:=Entered;
  725. end;
  726. procedure THTMLTopicRenderer.DocSample(Entered: boolean);
  727. begin
  728. end;
  729. procedure THTMLTopicRenderer.DocStrong(Entered: boolean);
  730. begin
  731. end;
  732. procedure THTMLTopicRenderer.DocTeleType(Entered: boolean);
  733. begin
  734. end;
  735. procedure THTMLTopicRenderer.DocVariable(Entered: boolean);
  736. begin
  737. end;
  738. procedure THTMLTopicRenderer.DocList(Entered: boolean);
  739. begin
  740. if Entered then
  741. begin
  742. Inc(Indent,ListIndent);
  743. DocBreak;
  744. end
  745. else
  746. begin
  747. Dec(Indent,ListIndent);
  748. if AnyCharsInLine then DocBreak;
  749. end;
  750. end;
  751. procedure THTMLTopicRenderer.DocOrderedList(Entered: boolean);
  752. begin
  753. DocList(Entered);
  754. end;
  755. procedure THTMLTopicRenderer.DocListItem;
  756. begin
  757. if AnyCharsInLine then
  758. DocBreak;
  759. AddText('þ'+hscLineStart);
  760. end;
  761. procedure THTMLTopicRenderer.DocDefList(Entered: boolean);
  762. begin
  763. if Entered then
  764. begin
  765. { if LastChar<>hscLineBreak then DocBreak;}
  766. end
  767. else
  768. begin
  769. if AnyCharsInLine then DocBreak;
  770. end;
  771. end;
  772. procedure THTMLTopicRenderer.DocDefTerm;
  773. begin
  774. DocBreak;
  775. end;
  776. procedure THTMLTopicRenderer.DocDefExp;
  777. begin
  778. Inc(Indent,DefIndent);
  779. DocBreak;
  780. Dec(Indent,DefIndent);
  781. end;
  782. procedure THTMLTopicRenderer.DocTable(Entered: boolean);
  783. var
  784. ATable : PTable;
  785. Border : String;
  786. begin
  787. if AnyCharsInLine then
  788. begin
  789. AddChar(hscLineBreak);
  790. AnyCharsInLine:=false;
  791. end;
  792. if Entered then
  793. begin
  794. DocBreak;
  795. New(ATable,Init(CurrentTable));
  796. CurrentTable:=ATable;
  797. CurrentTable^.Renderer:=@Self;
  798. if DocGetTagParam('BORDER',border) then
  799. CurrentTable^.WithBorder:=true;
  800. end
  801. else
  802. begin
  803. CurrentTable^.FormatTable;
  804. ATable:=CurrentTable;
  805. CurrentTable:=ATable^.PreviousTable;
  806. Dispose(ATable,Done);
  807. end;
  808. end;
  809. procedure THTMLTopicRenderer.DocTableRow(Entered: boolean);
  810. var
  811. ATableLine : PTableLine;
  812. begin
  813. if AnyCharsInLine then
  814. begin
  815. AddChar(hscLineBreak);
  816. AnyCharsInLine:=false;
  817. end;
  818. if Entered then
  819. begin
  820. New(ATableLine,Init);
  821. if CurrentTable^.GlobalTextBegin=0 then
  822. CurrentTable^.GlobalTextBegin:=TextPtr;
  823. CurrentTable^.AddLine(ATableLine);
  824. end;
  825. end;
  826. procedure THTMLTopicRenderer.DocTableItem(Entered: boolean);
  827. var
  828. Align : String;
  829. NewEl : PTableElement;
  830. PAlignEl : TParagraphAlign;
  831. begin
  832. if Entered then
  833. begin
  834. if assigned(CurrentTable^.LastLine) and Assigned(CurrentTable^.LastLine^.LastEl) then
  835. begin
  836. NewEl:=CurrentTable^.LastLine^.LastEl;
  837. NewEl^.TextEnd:=TextPtr;
  838. end;
  839. PAlignEl:=paLeft;
  840. if DocGetTagParam('ALIGN',Align) then
  841. DecodeAlign(Align,PAlignEl);
  842. New(NewEl,Init(PAlignEl));
  843. CurrentTable^.AddElement(NewEl);
  844. NewEl^.TextBegin:=TextPtr;
  845. { AddText(' - ');}
  846. end
  847. else
  848. begin
  849. NewEl:=CurrentTable^.LastLine^.LastEl;
  850. NewEl^.TextEnd:=TextPtr;
  851. end;
  852. end;
  853. procedure THTMLTopicRenderer.DocHorizontalRuler;
  854. var OAlign: TParagraphAlign;
  855. begin
  856. OAlign:=PAlign;
  857. if AnyCharsInLine then DocBreak;
  858. PAlign:=paCenter;
  859. DocAddText(' '+CharStr('Ä',60)+' ');
  860. DocBreak;
  861. PAlign:=OAlign;
  862. end;
  863. procedure THTMLTopicRenderer.AddChar(C: char);
  864. begin
  865. if (Topic=nil) or (TextPtr=MaxBytes) then Exit;
  866. Topic^.Text^[TextPtr]:=ord(C);
  867. Inc(TextPtr);
  868. if (C>#15) and ((C<>' ') or (InPreFormatted=true)) then
  869. AnyCharsInLine:=true;
  870. end;
  871. procedure THTMLTopicRenderer.AddCharAt(C: char;AtPtr : sw_word);
  872. begin
  873. if (Topic=nil) or (TextPtr=MaxBytes) then Exit;
  874. if AtPtr>TextPtr then
  875. AtPtr:=TextPtr
  876. else
  877. begin
  878. Move(Topic^.Text^[AtPtr],Topic^.Text^[AtPtr+1],TextPtr-AtPtr);
  879. end;
  880. Topic^.Text^[AtPtr]:=ord(C);
  881. Inc(TextPtr);
  882. end;
  883. procedure THTMLTopicRenderer.AddText(S: string);
  884. var I: sw_integer;
  885. begin
  886. for I:=1 to length(S) do
  887. AddChar(S[I]);
  888. end;
  889. function THTMLTopicRenderer.GetSectionColor(Section: THTMLSection; var Color: byte): boolean;
  890. begin
  891. GetSectionColor:=HTMLGetSectionColor(Section,Color);
  892. end;
  893. function THTMLTopicRenderer.BuildTopic(P: PTopic; AURL: string; HTMLFile: PTextFile;
  894. ATopicLinks: PTopicLinkCollection): boolean;
  895. var OK: boolean;
  896. TP: pointer;
  897. I: sw_integer;
  898. begin
  899. URL:=AURL;
  900. Topic:=P; TopicLinks:=ATopicLinks;
  901. OK:=Assigned(Topic) and Assigned(HTMLFile) and Assigned(TopicLinks);
  902. if OK then
  903. begin
  904. if (Topic^.TextSize<>0) and Assigned(Topic^.Text) then
  905. begin
  906. FreeMem(Topic^.Text,Topic^.TextSize);
  907. Topic^.TextSize:=0; Topic^.Text:=nil;
  908. end;
  909. Topic^.TextSize:=MaxHelpTopicSize;
  910. GetMem(Topic^.Text,Topic^.TextSize);
  911. TopicTitle:='';
  912. InTitle:=false; InBody:={false}true; InAnchor:=false;
  913. InParagraph:=false; InPreformatted:=false;
  914. Indent:=0; CurHeadLevel:=0;
  915. PAlign:=paLeft;
  916. TextPtr:=0; LinkPtr:=0;
  917. AnyCharsInLine:=false;
  918. LastTextChar:=#0;
  919. OK:=Process(HTMLFile);
  920. if OK then
  921. begin
  922. { --- topic links --- }
  923. if (Topic^.Links<>nil) and (Topic^.LinkSize>0) then
  924. begin
  925. FreeMem(Topic^.Links,Topic^.LinkSize);
  926. Topic^.Links:=nil; Topic^.LinkCount:=0;
  927. end;
  928. Topic^.LinkCount:=LinkPtr{TopicLinks^.Count}; { <- eeeeeek! }
  929. GetMem(Topic^.Links,Topic^.LinkSize);
  930. if Topic^.LinkCount>0 then { FP causes numeric RTE 215 without this }
  931. for I:=0 to Min(Topic^.LinkCount-1,High(LinkIndexes)-1) do
  932. begin
  933. Topic^.Links^[I].FileID:=Topic^.FileID;
  934. Topic^.Links^[I].Context:=EncodeHTMLCtx(Topic^.FileID,LinkIndexes[I]+1);
  935. end;
  936. { --- topic text --- }
  937. GetMem(TP,TextPtr);
  938. Move(Topic^.Text^,TP^,TextPtr);
  939. FreeMem(Topic^.Text,Topic^.TextSize);
  940. Topic^.Text:=TP; Topic^.TextSize:=TextPtr;
  941. end
  942. else
  943. begin
  944. DisposeTopic(Topic);
  945. Topic:=nil;
  946. end;
  947. end;
  948. BuildTopic:=OK;
  949. end;
  950. constructor TCustomHTMLHelpFile.Init(AID: word);
  951. begin
  952. inherited Init(AID);
  953. New(Renderer, Init);
  954. New(TopicLinks, Init(50,500));
  955. end;
  956. function TCustomHTMLHelpFile.SearchTopic(HelpCtx: THelpCtx): PTopic;
  957. function MatchCtx(P: PTopic): boolean; {$ifndef FPC}far;{$endif}
  958. begin
  959. MatchCtx:=P^.HelpCtx=HelpCtx;
  960. end;
  961. var FileID,LinkNo: word;
  962. P: PTopic;
  963. FName: string;
  964. begin
  965. DecodeHTMLCtx(HelpCtx,FileID,LinkNo);
  966. if (HelpCtx<>0) and (FileID<>ID) then P:=nil else
  967. if (FileID=ID) and (LinkNo>TopicLinks^.Count) then P:=nil else
  968. begin
  969. P:=Topics^.FirstThat(@MatchCtx);
  970. if P=nil then
  971. begin
  972. if LinkNo=0 then
  973. FName:=DefaultFileName
  974. else
  975. FName:=TopicLinks^.At(LinkNo-1)^;
  976. P:=NewTopic(ID,HelpCtx,0,FName,nil,0);
  977. Topics^.Insert(P);
  978. end;
  979. end;
  980. SearchTopic:=P;
  981. end;
  982. function TCustomHTMLHelpFile.ReadTopic(T: PTopic): boolean;
  983. var OK: boolean;
  984. HTMLFile: PMemoryTextFile;
  985. Name: string;
  986. Link,Bookmark: string;
  987. P: sw_integer;
  988. begin
  989. Bookmark:='';
  990. OK:=T<>nil;
  991. if OK then
  992. begin
  993. if T^.HelpCtx=0 then Name:=DefaultFileName else
  994. begin
  995. Link:=TopicLinks^.At((T^.HelpCtx and $ffff)-1)^;
  996. Link:=FormatPath(Link);
  997. P:=Pos('#',Link);
  998. if P>0 then
  999. begin
  1000. Bookmark:=copy(Link,P+1,length(Link));
  1001. Link:=copy(Link,1,P-1);
  1002. end;
  1003. { if CurFileName='' then Name:=Link else
  1004. Name:=CompletePath(CurFileName,Link);}
  1005. Name:=Link;
  1006. end;
  1007. HTMLFile:=New(PDOSTextFile, Init(Name));
  1008. if HTMLFile=nil then
  1009. begin
  1010. New(HTMLFile, Init);
  1011. HTMLFile^.AddLine('<HEAD><TITLE>'+msg_pagenotavailable+'</TITLE></HEAD>');
  1012. HTMLFile^.AddLine(
  1013. '<BODY>'+
  1014. FormatStrStr(msg_cantaccessurl,Name)+'<br><br>'+
  1015. '</BODY>');
  1016. end;
  1017. OK:=Renderer^.BuildTopic(T,Name,HTMLFile,TopicLinks);
  1018. if OK then CurFileName:=Name;
  1019. if HTMLFile<>nil then Dispose(HTMLFile, Done);
  1020. if BookMark='' then
  1021. T^.StartNamedMark:=0
  1022. else
  1023. T^.StartNamedMark:=T^.GetNamedMarkIndex(BookMark)+1;
  1024. end;
  1025. ReadTopic:=OK;
  1026. end;
  1027. destructor TCustomHTMLHelpFile.Done;
  1028. begin
  1029. inherited Done;
  1030. if Renderer<>nil then Dispose(Renderer, Done);
  1031. if TopicLinks<>nil then Dispose(TopicLinks, Done);
  1032. end;
  1033. constructor THTMLHelpFile.Init(AFileName: string; AID: word; ATOCEntry: string);
  1034. begin
  1035. if inherited Init(AID)=false then Fail;
  1036. DefaultFileName:=AFileName; TOCEntry:=ATOCEntry;
  1037. if DefaultFileName='' then
  1038. begin
  1039. Done;
  1040. Fail;
  1041. end;
  1042. end;
  1043. function THTMLHelpFile.LoadIndex: boolean;
  1044. begin
  1045. IndexEntries^.Insert(NewIndexEntry(TOCEntry,ID,0));
  1046. LoadIndex:=true;
  1047. end;
  1048. constructor THTMLIndexHelpFile.Init(AFileName: string; AID: word);
  1049. begin
  1050. inherited Init(AID);
  1051. IndexFileName:=AFileName;
  1052. end;
  1053. function THTMLIndexHelpFile.LoadIndex: boolean;
  1054. function FormatAlias(Alias: string): string;
  1055. begin
  1056. if Assigned(HelpFacility) then
  1057. if length(Alias)>HelpFacility^.IndexTabSize-4 then
  1058. Alias:=Trim(copy(Alias,1,HelpFacility^.IndexTabSize-4-2))+'..';
  1059. FormatAlias:=Alias;
  1060. end;
  1061. (*procedure AddDoc(P: PHTMLLinkScanDocument); {$ifndef FPC}far;{$endif}
  1062. var I: sw_integer;
  1063. TLI: THelpCtx;
  1064. begin
  1065. for I:=1 to P^.GetAliasCount do
  1066. begin
  1067. TLI:=TopicLinks^.AddItem(P^.GetName);
  1068. TLI:=EncodeHTMLCtx(ID,TLI+1);
  1069. IndexEntries^.Insert(NewIndexEntry(FormatAlias(P^.GetAlias(I-1)),ID,TLI));
  1070. end;
  1071. end;*)
  1072. var S: PBufStream;
  1073. LS: PHTMLLinkScanner;
  1074. OK: boolean;
  1075. TLI: THelpCtx;
  1076. I,J: sw_integer;
  1077. begin
  1078. New(S, Init(IndexFileName,stOpenRead,4096));
  1079. OK:=Assigned(S);
  1080. if OK then
  1081. begin
  1082. New(LS, LoadDocuments(S^));
  1083. OK:=Assigned(LS);
  1084. if OK then
  1085. begin
  1086. LS^.SetBaseDir(DirOf(IndexFileName));
  1087. for I:=0 to LS^.GetDocumentCount-1 do
  1088. begin
  1089. TLI:=TopicLinks^.AddItem(LS^.GetDocumentURL(I));
  1090. TLI:=EncodeHTMLCtx(ID,TLI+1);
  1091. for J:=0 to LS^.GetDocumentAliasCount(I)-1 do
  1092. IndexEntries^.Insert(NewIndexEntry(FormatAlias(LS^.GetDocumentAlias(I,J)),ID,TLI));
  1093. end;
  1094. Dispose(LS, Done);
  1095. end;
  1096. Dispose(S, Done);
  1097. end;
  1098. LoadIndex:=OK;
  1099. end;
  1100. function CreateProcHTML(const FileName,Param: string;Index : longint): PHelpFile; {$ifndef FPC}far;{$endif}
  1101. var H: PHelpFile;
  1102. begin
  1103. H:=nil;
  1104. if CompareText(copy(ExtOf(FileName),1,length(extHTML)),extHTML)=0 then
  1105. H:=New(PHTMLHelpFile, Init(FileName,Index,Param));
  1106. CreateProcHTML:=H;
  1107. end;
  1108. function CreateProcHTMLIndex(const FileName,Param: string;Index : longint): PHelpFile; {$ifndef FPC}far;{$endif}
  1109. var H: PHelpFile;
  1110. begin
  1111. H:=nil;
  1112. if CompareText(ExtOf(FileName),extHTMLIndex)=0 then
  1113. H:=New(PHTMLIndexHelpFile, Init(FileName,Index));
  1114. CreateProcHTMLIndex:=H;
  1115. end;
  1116. procedure RegisterHelpType;
  1117. begin
  1118. RegisterHelpFileType({$ifdef FPC}@{$endif}CreateProcHTML);
  1119. RegisterHelpFileType({$ifdef FPC}@{$endif}CreateProcHTMLIndex);
  1120. end;
  1121. END.
  1122. {
  1123. $Log$
  1124. Revision 1.6 2002-09-07 15:40:49 peter
  1125. * old logs removed and tabs fixed
  1126. Revision 1.5 2002/04/23 09:55:22 pierre
  1127. + added lastsynonym and InNameAnchor fields to TCustomHTMLLinkScanner
  1128. these allow to eliminate double index entries pointing to the same
  1129. html file location (which had two different names).
  1130. Revision 1.4 2002/04/11 07:04:23 pierre
  1131. + handle tables
  1132. Revision 1.3 2002/03/20 17:16:11 pierre
  1133. * correct some ansii file conversion problems
  1134. }