whtmlhlp.pas 38 KB

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