whtmlhlp.pas 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800
  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,WChmHWrap;
  13. const
  14. extHTML = '.htm';
  15. extHTMLIndex = '.htx';
  16. extCHM = '.chm';
  17. ListIndent = 2;
  18. DefIndent = 4;
  19. MaxTopicLinks = 24000; { maximum number of links on a single HTML page }
  20. type
  21. THTMLSection = (hsNone,hsHeading1,hsHeading2,hsHeading3,hsHeading4,hsHeading5,hsHeading6);
  22. TParagraphAlign = (paLeft,paCenter,paRight);
  23. PTableElement = ^TTableElement;
  24. TTableElement = object(Tobject)
  25. TextBegin,TextEnd, TextLength, NumNL : sw_word;
  26. Alignment : TParagraphAlign;
  27. NextEl : PTableElement;
  28. constructor init(AAlignment : TParagraphAlign);
  29. end;
  30. PTableLine = ^TTableLine;
  31. TTableLine = object(Tobject)
  32. NumElements : sw_word;
  33. Nextline : PTableLine;
  34. FirstEl,LastEl : PTableElement;
  35. constructor Init;
  36. procedure AddElement(PTE : PTableElement);
  37. destructor Done; virtual;
  38. end;
  39. PHTMLTopicRenderer = ^THTMLTopicRenderer;
  40. PTable = ^TTable;
  41. TTable = object(Tobject)
  42. NumLines,NumCols : sw_word;
  43. GlobalOffset,
  44. GlobalTextBegin : sw_word;
  45. WithBorder : boolean;
  46. IsBar : boolean;
  47. FirstLine : PTableLine;
  48. LastLine : PTableLine;
  49. PreviousTable : PTable;
  50. Renderer : PHTMLTopicRenderer;
  51. constructor Init(Previous : PTable);
  52. procedure AddLine(PL : PTableLine);
  53. procedure AddElement(PTE : PTableElement);
  54. procedure TextInsert(Pos : sw_word;const S : string);
  55. procedure FormatTable;
  56. destructor Done; virtual;
  57. end;
  58. THTMLTopicRenderer = object(THTMLParser)
  59. function BuildTopic(P: PTopic; AURL: string; HTMLFile: PTextFile; ATopicLinks: PTopicLinkCollection): boolean;
  60. public
  61. function DocAddTextChar(C: char): boolean; virtual;
  62. procedure DocSoftBreak; virtual;
  63. procedure DocTYPE; virtual;
  64. procedure DocHTML(Entered: boolean); virtual;
  65. procedure DocHEAD(Entered: boolean); virtual;
  66. procedure DocMETA; virtual;
  67. procedure DocTITLE(Entered: boolean); virtual;
  68. procedure DocBODY(Entered: boolean); virtual;
  69. procedure DocAnchor(Entered: boolean); virtual;
  70. procedure DocUnknownTag; virtual;
  71. procedure DocHeading(Level: integer; Entered: boolean); virtual;
  72. procedure DocParagraph(Entered: boolean); virtual;
  73. procedure DocBreak; virtual;
  74. procedure DocImage; virtual;
  75. procedure DocProcessComment(Comment: string); virtual;
  76. procedure DocBold(Entered: boolean); virtual;
  77. procedure DocCite(Entered: boolean); virtual;
  78. procedure DocCode(Entered: boolean); virtual;
  79. procedure DocEmphasized(Entered: boolean); virtual;
  80. procedure DocItalic(Entered: boolean); virtual;
  81. procedure DocKbd(Entered: boolean); virtual;
  82. procedure DocPreformatted(Entered: boolean); virtual;
  83. procedure DocSample(Entered: boolean); virtual;
  84. procedure DocStrong(Entered: boolean); virtual;
  85. procedure DocTeleType(Entered: boolean); virtual;
  86. procedure DocVariable(Entered: boolean); virtual;
  87. procedure DocSpan(Entered: boolean); virtual;
  88. procedure DocList(Entered: boolean); virtual;
  89. procedure DocOrderedList(Entered: boolean); virtual;
  90. procedure DocListItem(Entered: boolean); virtual;
  91. procedure DocDefList(Entered: boolean); virtual;
  92. procedure DocDefTerm(Entered: boolean); virtual;
  93. procedure DocDefExp(Entered: boolean); virtual;
  94. procedure DocTable(Entered: boolean); virtual;
  95. procedure DocTableRow(Entered: boolean); virtual;
  96. procedure DocTableHeaderItem(Entered: boolean); virtual;
  97. procedure DocTableItem(Entered: boolean); virtual;
  98. procedure DocHorizontalRuler; virtual;
  99. function CanonicalizeURL(const Base,Relative:String):string; 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. SuppressOutput: boolean;
  113. SuppressUntil : string;
  114. InDefExp: boolean;
  115. TopicTitle: string;
  116. Indent: integer;
  117. AnyCharsInLine,
  118. LastAnsiLoadFailed: 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. PCHMTopicRenderer = ^TCHMTopicRenderer;
  134. TCHMTopicRenderer = object(THTMLTopicRenderer)
  135. function CanonicalizeURL(const Base,Relative:String):string; virtual;
  136. end;
  137. PCustomHTMLHelpFile = ^TCustomHTMLHelpFile;
  138. TCustomHTMLHelpFile = object(THelpFile)
  139. constructor Init(AID: word);
  140. destructor Done; virtual;
  141. public
  142. Renderer: PHTMLTopicRenderer;
  143. function GetTopicInfo(T: PTopic) : string; virtual;
  144. function SearchTopic(HelpCtx: THelpCtx): PTopic; virtual;
  145. function ReadTopic(T: PTopic): boolean; virtual;
  146. private
  147. DefaultFileName: string;
  148. CurFileName: string;
  149. TopicLinks: PTopicLinkCollection;
  150. end;
  151. PHTMLHelpFile = ^THTMLHelpFile;
  152. THTMLHelpFile = object(TCustomHTMLHelpFile)
  153. constructor Init(AFileName: string; AID: word; ATOCEntry: string);
  154. public
  155. function LoadIndex: boolean; virtual;
  156. private
  157. TOCEntry: string;
  158. end;
  159. PCHMHelpFile = ^TCHMHelpFile;
  160. TCHMHelpFile = object(TCustomHTMLHelpFile)
  161. constructor Init(AFileName: string; AID: word);
  162. destructor Done; virtual;
  163. public
  164. function LoadIndex: boolean; virtual;
  165. function ReadTopic(T: PTopic): boolean; virtual;
  166. function GetTopicInfo(T: PTopic) : string; virtual;
  167. function SearchTopic(HelpCtx: THelpCtx): PTopic; virtual;
  168. private
  169. Chmw: TCHMWrapper;
  170. end;
  171. PHTMLIndexHelpFile = ^THTMLIndexHelpFile;
  172. THTMLIndexHelpFile = object(TCustomHTMLHelpFile)
  173. constructor Init(AFileName: string; AID: word);
  174. function LoadIndex: boolean; virtual;
  175. private
  176. IndexFileName: string;
  177. end;
  178. PHTMLAnsiView = ^THTMLAnsiView;
  179. PHTMLAnsiConsole = ^THTMLAnsiConsole;
  180. THTMLAnsiConsole = Object(TAnsiViewConsole)
  181. MaxX,MaxY : integer;
  182. procedure GotoXY(X,Y: integer); virtual;
  183. end;
  184. THTMLAnsiView = Object(TAnsiView)
  185. private
  186. HTMLOwner : PHTMLTopicRenderer;
  187. HTMLConsole : PHTMLAnsiConsole;
  188. public
  189. constructor Init(AOwner: PHTMLTopicRenderer);
  190. procedure CopyToHTML;
  191. end;
  192. THTMLGetSectionColorProc = function(Section: THTMLSection; var Color: byte): boolean;
  193. function DefHTMLGetSectionColor(Section: THTMLSection; var Color: byte): boolean;
  194. const HTMLGetSectionColor : THTMLGetSectionColorProc = {$ifdef fpc}@{$endif}DefHTMLGetSectionColor;
  195. procedure RegisterHelpType;
  196. implementation
  197. uses
  198. Views,WConsts,WUtils,WViews,WHTMLScn;
  199. constructor TTableElement.init(AAlignment : TParagraphAlign);
  200. begin
  201. Alignment:=AAlignment;
  202. NextEl:=nil;
  203. TextBegin:=0;
  204. TextEnd:=0;
  205. end;
  206. { TTableLine methods }
  207. constructor TTableLine.Init;
  208. begin
  209. NumElements:=0;
  210. NextLine:=nil;
  211. Firstel:=nil;
  212. LastEl:=nil;
  213. end;
  214. procedure TTableLine.AddElement(PTE : PTableElement);
  215. begin
  216. if not assigned(FirstEl) then
  217. FirstEl:=PTE;
  218. if assigned(LastEl) then
  219. LastEl^.NextEl:=PTE;
  220. LastEl:=PTE;
  221. Inc(NumElements);
  222. end;
  223. destructor TTableLine.Done;
  224. begin
  225. LastEl:=FirstEl;
  226. while assigned(LastEl) do
  227. begin
  228. LastEl:=FirstEl^.NextEl;
  229. Dispose(FirstEl,Done);
  230. FirstEl:=LastEl;
  231. end;
  232. inherited Done;
  233. end;
  234. { TTable methods }
  235. constructor TTable.Init(Previous : PTable);
  236. begin
  237. PreviousTable:=Previous;
  238. NumLines:=0;
  239. NumCols:=0;
  240. GlobalOffset:=0;
  241. GlobalTextBegin:=0;
  242. FirstLine:=nil;
  243. LastLine:=nil;
  244. WithBorder:=false;
  245. IsBar:=false;
  246. end;
  247. procedure TTable.AddLine(PL : PTableLine);
  248. begin
  249. If not assigned(FirstLine) then
  250. FirstLine:=PL;
  251. if Assigned(LastLine) then
  252. LastLine^.NextLine:=PL;
  253. LastLine:=PL;
  254. Inc(NumLines);
  255. end;
  256. procedure TTable.AddElement(PTE : PTableElement);
  257. begin
  258. if assigned(LastLine) then
  259. begin
  260. LastLine^.AddElement(PTE);
  261. If LastLine^.NumElements>NumCols then
  262. NumCols:=LastLine^.NumElements;
  263. end;
  264. end;
  265. procedure TTable.TextInsert(Pos : sw_word;const S : string);
  266. var
  267. i : sw_word;
  268. begin
  269. if S='' then
  270. exit;
  271. i:=Renderer^.AddTextAt(S,Pos+GlobalOffset);
  272. GlobalOffset:=GlobalOffset+i;
  273. end;
  274. procedure TTable.FormatTable;
  275. const
  276. MaxCols = 200;
  277. type
  278. TLengthArray = Array [ 1 .. MaxCols] of sw_word;
  279. PLengthArray = ^TLengthArray;
  280. var
  281. ColLengthArray : PLengthArray;
  282. RowSizeArray : PLengthArray;
  283. CurLine : PTableLine;
  284. CurEl : PTableElement;
  285. Align : TParagraphAlign;
  286. TextBegin,TextEnd : sw_word;
  287. i,j,k,Length : sw_word;
  288. begin
  289. { do nothing for single cell tables }
  290. if (NumCols=1) and (NumLines=1) then
  291. exit;
  292. GetMem(ColLengthArray,Sizeof(sw_word)*NumCols);
  293. FillChar(ColLengthArray^,Sizeof(sw_word)*NumCols,#0);
  294. GetMem(RowSizeArray,Sizeof(sw_word)*NumLines);
  295. FillChar(RowSizeArray^,Sizeof(sw_word)*NumLines,#0);
  296. { Compute the largest cell }
  297. CurLine:=FirstLine;
  298. For i:=1 to NumLines do
  299. begin
  300. CurEl:=CurLine^.FirstEl;
  301. RowSizeArray^[i]:=1;
  302. For j:=1 to NumCols do
  303. begin
  304. if not assigned(CurEl) then
  305. break;
  306. Length:=CurEl^.TextLength;
  307. if assigned(CurEl^.NextEl) and
  308. (CurEl^.NextEl^.TextBegin>CurEl^.TextEnd) then
  309. Inc(Length,Renderer^.ComputeTextLength(
  310. CurEl^.NextEl^.TextBegin+GlobalOffset,
  311. CurEl^.TextBegin+GlobalOffset));
  312. if Length>ColLengthArray^[j] then
  313. ColLengthArray^[j]:=Length;
  314. { We need to handle multiline cells... }
  315. if CurEl^.NumNL>=RowSizeArray^[i] then
  316. RowSizeArray^[i]:=CurEl^.NumNL;
  317. { We don't handle multiline cells yet... }
  318. if CurEl^.NumNL>=1 then
  319. begin
  320. for k:=CurEl^.TextBegin+GlobalOffset to
  321. CurEl^.TextEnd+GlobalOffset do
  322. if Renderer^.Topic^.Text^[k]=ord(hscLineBreak) then
  323. Renderer^.Topic^.Text^[k]:=ord(' ');
  324. end;
  325. CurEl:=CurEl^.NextEl;
  326. end;
  327. CurLine:=CurLine^.NextLine;
  328. end;
  329. { Adjust to largest cell }
  330. CurLine:=FirstLine;
  331. TextBegin:=GlobalTextBegin;
  332. If (NumLines>0) and WithBorder then
  333. Begin
  334. TextInsert(TextBegin,#218);
  335. For j:=1 to NumCols do
  336. begin
  337. TextInsert(TextBegin,CharStr(#196,ColLengthArray^[j]));
  338. if j<NumCols then
  339. TextInsert(TextBegin,#194);
  340. end;
  341. TextInsert(TextBegin,#191);
  342. TextInsert(TextBegin,hscLineBreak);
  343. End;
  344. For i:=1 to NumLines do
  345. begin
  346. CurEl:=CurLine^.FirstEl;
  347. For j:=1 to NumCols do
  348. begin
  349. if not assigned(CurEl) then
  350. begin
  351. Length:=0;
  352. Align:=paLeft;
  353. end
  354. else
  355. begin
  356. TextBegin:=CurEl^.TextBegin;
  357. TextEnd:=CurEl^.TextEnd;
  358. {While (TextEnd>TextBegin) and
  359. (Renderer^.Topic^.Text^[TextEnd+GlobalOffset]=ord(hscLineBreak)) do
  360. dec(TextEnd); }
  361. Length:=CurEl^.TextLength;
  362. Align:=CurEl^.Alignment;
  363. end;
  364. if WithBorder then
  365. TextInsert(TextBegin,#179)
  366. else
  367. TextInsert(TextBegin,' ');
  368. if Length<ColLengthArray^[j] then
  369. begin
  370. case Align of
  371. paLeft:
  372. TextInsert(TextEnd,CharStr(' ',ColLengthArray^[j]-Length));
  373. paRight:
  374. TextInsert(TextBegin,CharStr(' ',ColLengthArray^[j]-Length));
  375. paCenter:
  376. begin
  377. TextInsert(TextBegin,CharStr(' ',(ColLengthArray^[j]-Length) div 2));
  378. TextInsert(TextEnd,CharStr(' ',(ColLengthArray^[j]-Length)- ((ColLengthArray^[j]-Length) div 2)));
  379. end;
  380. end;
  381. end;
  382. if Assigned(CurEl) then
  383. CurEl:=CurEl^.NextEl;
  384. end;
  385. if WithBorder then
  386. TextInsert(TextEnd,#179);
  387. //TextInsert(TextEnd,hscLineBreak);
  388. CurLine:=CurLine^.NextLine;
  389. end;
  390. If (NumLines>0) and WithBorder then
  391. Begin
  392. TextInsert(TextEnd,hscLineBreak);
  393. TextInsert(TextEnd,#192);
  394. For j:=1 to NumCols do
  395. begin
  396. TextInsert(TextEnd,CharStr(#196,ColLengthArray^[j]));
  397. if j<NumCols then
  398. TextInsert(TextEnd,#193);
  399. end;
  400. TextInsert(TextEnd,#217);
  401. TextInsert(TextEnd,hscLineBreak);
  402. End;
  403. FreeMem(ColLengthArray,Sizeof(sw_word)*NumCols);
  404. FreeMem(RowSizeArray,Sizeof(sw_word)*NumLines);
  405. end;
  406. destructor TTable.Done;
  407. begin
  408. LastLine:=FirstLine;
  409. while assigned(LastLine) do
  410. begin
  411. LastLine:=FirstLine^.NextLine;
  412. Dispose(FirstLine,Done);
  413. FirstLine:=LastLine;
  414. end;
  415. if Assigned(PreviousTable) then
  416. Inc(PreviousTable^.GlobalOffset,GlobalOffset);
  417. inherited Done;
  418. end;
  419. { THTMLAnsiConsole methods }
  420. procedure THTMLAnsiConsole.GotoXY(X,Y : integer);
  421. begin
  422. if X>MaxX then MaxX:=X-1;
  423. if Y>MaxY then MaxY:=Y-1;
  424. inherited GotoXY(X,Y);
  425. end;
  426. { THTMLAnsiView methods }
  427. constructor THTMLAnsiView.Init(AOwner : PHTMLTopicRenderer);
  428. var
  429. R : TRect;
  430. begin
  431. if not assigned(AOwner) then
  432. fail;
  433. R.Assign(0,0,80,25);
  434. inherited init(R,nil,nil);
  435. HTMLOwner:=AOwner;
  436. HTMLConsole:=New(PHTMLAnsiConsole,Init(@Self));
  437. HTMLConsole^.HighVideo;
  438. Dispose(Console,Done);
  439. Console:=HTMLConsole;
  440. HTMLConsole^.Size.X:=80;
  441. HTMLConsole^.Size.Y:=25;
  442. HTMLConsole^.ClrScr;
  443. HTMLConsole^.MaxX:=-1;
  444. HTMLConsole^.MaxY:=-1;
  445. HTMLConsole^.BoundChecks:=0;
  446. end;
  447. procedure THTMLAnsiView.CopyToHTML;
  448. var
  449. Attr,NewAttr : byte;
  450. c : char;
  451. X,Y,Pos : longint;
  452. begin
  453. Attr:=(Buffer^[1] shr 8);
  454. HTMLOwner^.AddChar(hscLineBreak);
  455. HTMLOwner^.AddText(hscTextAttr+chr(Attr));
  456. for Y:=0 to HTMLConsole^.MaxY-1 do
  457. begin
  458. for X:=0 to HTMLConsole^.MaxX-1 do
  459. begin
  460. Pos:=(Delta.Y*MaxViewWidth)+X+Y*MaxViewWidth;
  461. NewAttr:=(Buffer^[Pos] shr 8);
  462. if NewAttr <> Attr then
  463. begin
  464. Attr:=NewAttr;
  465. HTMLOwner^.AddText(hscTextAttr+chr(Attr));
  466. end;
  467. c:= chr(Buffer^[Pos] and $ff);
  468. if ord(c)>16 then
  469. HTMLOwner^.AddChar(c)
  470. else
  471. begin
  472. HTMLOwner^.AddChar(hscDirect);
  473. HTMLOwner^.AddChar(c);
  474. end;
  475. end;
  476. { Write start of next line in normal color, for correct alignment }
  477. HTMLOwner^.AddChar(hscNormText);
  478. { Force to set attr again at start of next line }
  479. Attr:=0;
  480. HTMLOwner^.AddChar(hscLineBreak);
  481. end;
  482. end;
  483. function DefHTMLGetSectionColor(Section: THTMLSection; var Color: byte): boolean;
  484. begin
  485. Color:=0;
  486. DefHTMLGetSectionColor:=false;
  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. function THTMLTopicRenderer.DocAddTextChar(C: char): boolean;
  496. var Added: boolean;
  497. begin
  498. Added:=false;
  499. if InTitle then
  500. begin
  501. TopicTitle:=TopicTitle+C;
  502. Added:=true;
  503. end
  504. else
  505. if InBody then
  506. begin
  507. if (InPreFormatted) or (C<>#32) or (LastTextChar<>C) then
  508. if (C<>#32) or (AnyCharsInLine=true) or (InPreFormatted=true) then
  509. begin
  510. AddChar(C);
  511. LastTextChar:=C;
  512. Added:=true;
  513. end;
  514. end;
  515. DocAddTextChar:=Added;
  516. end;
  517. procedure THTMLTopicRenderer.DocSoftBreak;
  518. begin
  519. if InPreformatted then DocBreak else
  520. if AnyCharsInLine and not assigned(CurrentTable) then
  521. begin
  522. AddChar(' ');
  523. LastTextChar:=' ';
  524. end;
  525. end;
  526. procedure THTMLTopicRenderer.DocTYPE;
  527. begin
  528. end;
  529. procedure THTMLTopicRenderer.DocHTML(Entered: boolean);
  530. begin
  531. end;
  532. procedure THTMLTopicRenderer.DocHEAD(Entered: boolean);
  533. begin
  534. end;
  535. procedure THTMLTopicRenderer.DocMETA;
  536. begin
  537. end;
  538. procedure THTMLTopicRenderer.DocTITLE(Entered: boolean);
  539. begin
  540. if Entered then
  541. begin
  542. TopicTitle:='';
  543. end
  544. else
  545. begin
  546. { render topic title here }
  547. if TopicTitle<>'' then
  548. begin
  549. AddText(' '+TopicTitle+' Ü'); DocBreak;
  550. AddText(' '+CharStr('ß',length(TopicTitle)+3)); DocBreak;
  551. end;
  552. end;
  553. InTitle:=Entered;
  554. end;
  555. procedure THTMLTopicRenderer.DocBODY(Entered: boolean);
  556. begin
  557. InBody:=Entered;
  558. end;
  559. procedure THTMLTopicRenderer.DocAnchor(Entered: boolean);
  560. var HRef,Name: string;
  561. begin
  562. if Entered and InAnchor then DocAnchor(false);
  563. if Entered then
  564. begin
  565. if DocGetTagParam('HREF',HRef)=false then HRef:='';
  566. if DocGetTagParam('NAME',Name)=false then Name:='';
  567. if {(HRef='') and} (Name='') then
  568. if DocGetTagParam('ID',Name)=false then
  569. Name:='';
  570. if Name<>'' then
  571. begin
  572. Topic^.NamedMarks^.InsertStr(Name);
  573. {$IFDEF WDEBUG}
  574. DebugMessageS({$i %file%},' Adding Name "'+Name+'"',{$i %line%},'1');
  575. {$endif WDEBUG}
  576. AddChar(hscNamedMark);
  577. end;
  578. if (HRef<>'')then
  579. begin
  580. if (LinkPtr<MaxTopicLinks){ and
  581. not DisableCrossIndexing} then
  582. begin
  583. InAnchor:=true;
  584. AddChar(hscLink);
  585. {$IFDEF WDEBUG}
  586. DebugMessageS({$i %file%},' Adding Link1 "'+HRef+'"'+' "'+url+'"',{$i %line%},'1');
  587. {$ENDIF WDEBUG}
  588. if pos('#',HRef)=1 then
  589. Href:=NameAndExtOf(GetFilename)+Href;
  590. HRef:=canonicalizeURL(URL,HRef);
  591. LinkIndexes[LinkPtr]:=TopicLinks^.AddItem(HRef);
  592. {$IFDEF WDEBUG}
  593. DebugMessageS({$i %file%},' Adding Link2 "'+HRef+'"',{$i %line%},'1');
  594. {$ENDIF WDEBUG}
  595. Inc(LinkPtr);
  596. end;
  597. end;
  598. end
  599. else
  600. begin
  601. if InAnchor=true then AddChar(hscLink);
  602. InAnchor:=false;
  603. end;
  604. end;
  605. procedure THTMLTopicRenderer.DocUnknownTag;
  606. begin
  607. {$IFDEF WDEBUG}
  608. DebugMessageS({$i %file%},' Unknown tag "'+TagName+'" params "'+TagParams+'"' ,{$i %line%},'1');
  609. {$endif WDEBUG}
  610. end;
  611. procedure DecodeAlign(Align: string; var PAlign: TParagraphAlign);
  612. begin
  613. Align:=UpcaseStr(Align);
  614. if Align='LEFT' then PAlign:=paLeft else
  615. if Align='CENTER' then PAlign:=paCenter else
  616. if Align='RIGHT' then PAlign:=paRight;
  617. end;
  618. procedure THTMLTopicRenderer.DocHeading(Level: integer; Entered: boolean);
  619. var Align: string;
  620. C: byte;
  621. SC: THTMLSection;
  622. begin
  623. if Entered then
  624. begin
  625. DocBreak;
  626. CurHeadLevel:=Level;
  627. PAlign:=paLeft;
  628. if DocGetTagParam('ALIGN',Align) then
  629. DecodeAlign(Align,PAlign);
  630. SC:=hsNone;
  631. case Level of
  632. 1: SC:=hsHeading1;
  633. 2: SC:=hsHeading2;
  634. 3: SC:=hsHeading3;
  635. 4: SC:=hsHeading4;
  636. 5: SC:=hsHeading5;
  637. 6: SC:=hsHeading6;
  638. end;
  639. if GetSectionColor(SC,C) then
  640. AddText(hscTextAttr+chr(C));
  641. end
  642. else
  643. begin
  644. AddChar(hscNormText);
  645. CurHeadLevel:=0;
  646. DocBreak;
  647. end;
  648. end;
  649. Function THTMLTopicRenderer.CanonicalizeURL(const Base,Relative:String):string;
  650. // uses info from filesystem (curdir) -> overriden for CHM.
  651. begin
  652. CanonicalizeURL:=CompleteURL(Base,relative);
  653. end;
  654. procedure THTMLTopicRenderer.DocParagraph(Entered: boolean);
  655. var Align: string;
  656. begin
  657. if Entered and InParagraph then DocParagraph(false);
  658. if Entered then
  659. begin
  660. if AnyCharsInLine then DocBreak;
  661. if DocGetTagParam('ALIGN',Align) then
  662. DecodeAlign(Align,PAlign);
  663. end
  664. else
  665. begin
  666. { if AnyCharsInLine then }DocBreak;
  667. PAlign:=paLeft;
  668. end;
  669. InParagraph:=Entered;
  670. end;
  671. procedure THTMLTopicRenderer.DocBreak;
  672. begin
  673. if (CurHeadLevel=1) or (PAlign=paCenter) then
  674. AddChar(hscCenter);
  675. if (PAlign=paRight) then
  676. AddChar(hscRight);
  677. AddChar(hscLineBreak);
  678. if Indent>0 then
  679. AddText(CharStr(#255,Indent)+hscLineStart);
  680. AnyCharsInLine:=false;
  681. end;
  682. procedure THTMLTopicRenderer.DocProcessComment(Comment: string);
  683. var
  684. src,index : string;
  685. begin
  686. if pos('tex4ht:',Comment)=0 then
  687. exit;
  688. {$IFDEF WDEBUG}
  689. DebugMessage(GetFileName,'tex4ht comment "'
  690. +Comment+'"',Line,1);
  691. {$endif WDEBUG}
  692. if SuppressOutput then
  693. begin
  694. if (pos(SuppressUntil,Comment)=0) then
  695. exit
  696. else
  697. begin
  698. {$IFDEF WDEBUG}
  699. DebugMessage(GetFileName,' Found '+SuppressUntil+'comment "'
  700. +Comment+'" SuppressOuput reset to false',Line,1);
  701. {$endif WDEBUG}
  702. SuppressOutput:=false;
  703. SuppressUntil:='';
  704. end;
  705. end;
  706. if (pos('tex4ht:graphics ',Comment)>0) and
  707. LastAnsiLoadFailed then
  708. begin
  709. {$IFDEF WDEBUG}
  710. DebugMessage(GetFileName,' Using tex4ht comment "'
  711. +Comment+'"',Line,1);
  712. {$endif WDEBUG}
  713. { Try again with this info }
  714. TagParams:=Comment;
  715. DocImage;
  716. end;
  717. if (pos('tex4ht:syntaxdiagram ',Comment)>0) then
  718. begin
  719. {$IFDEF WDEBUG}
  720. DebugMessage(GetFileName,' Using tex4ht:syntaxdiagram comment "'
  721. +Comment+'"',Line,1);
  722. {$endif WDEBUG}
  723. { Try again with this info }
  724. TagParams:=Comment;
  725. DocImage;
  726. if not LastAnsiLoadFailed then
  727. begin
  728. SuppressOutput:=true;
  729. SuppressUntil:='tex4ht:endsyntaxdiagram ';
  730. end
  731. end;
  732. if (pos('tex4ht:mysyntdiag ',Comment)>0) then
  733. begin
  734. {$IFDEF WDEBUG}
  735. DebugMessage(GetFileName,' Using tex4ht:mysyntdiag comment "'
  736. +Comment+'"',Line,1);
  737. {$endif WDEBUG}
  738. { Try again with this info }
  739. TagParams:=Comment;
  740. DocGetTagParam('SRC',src);
  741. DocGetTagParam('INDEX',index);
  742. TagParams:='src="../syntax/'+src+'-'+index+'.png"';
  743. DocImage;
  744. if not LastAnsiLoadFailed then
  745. begin
  746. SuppressOutput:=true;
  747. SuppressUntil:='tex4ht:endmysyntdiag ';
  748. end
  749. end;
  750. end;
  751. procedure THTMLTopicRenderer.DocImage;
  752. var Name,Src,Alt,SrcLine: string;
  753. f : text;
  754. attr : byte;
  755. PA : PHTMLAnsiView;
  756. StorePreformatted : boolean;
  757. begin
  758. if SuppressOutput then
  759. exit;
  760. {$IFDEF WDEBUG}
  761. if not DocGetTagParam('NAME',Name) then
  762. Name:='<No name>';
  763. DebugMessage(GetFileName,' Image "'+Name+'"',Line,1);
  764. {$endif WDEBUG}
  765. if DocGetTagParam('SRC',src) then
  766. begin
  767. {$IFDEF WDEBUG}
  768. DebugMessage(GetFileName,' Image source tag "'+Src+'"',Line,1);
  769. {$endif WDEBUG}
  770. if src<>'' then
  771. begin
  772. src:=CompleteURL(URL,src);
  773. { this should be a image file ending by .gif or .jpg...
  774. Try to see if a file with same name and extension .git
  775. exists PM }
  776. src:=DirAndNameOf(src)+'.ans';
  777. {$IFDEF WDEBUG}
  778. DebugMessage(GetFileName,' Trying "'+Src+'"',Line,1);
  779. {$endif WDEBUG}
  780. if not ExistsFile(src) then
  781. begin
  782. DocGetTagParam('SRC',src);
  783. src:=DirAndNameOf(src)+'.ans';
  784. src:=CompleteURL(DirOf(URL)+'../',src);
  785. {$IFDEF WDEBUG}
  786. DebugMessage(GetFileName,' Trying "'+Src+'"',Line,1);
  787. {$endif wDEBUG}
  788. end;
  789. if not ExistsFile(src) then
  790. begin
  791. LastAnsiLoadFailed:=true;
  792. {$IFDEF WDEBUG}
  793. DebugMessage(GetFileName,' "'+Src+'" not found',Line,1);
  794. {$endif WDEBUG}
  795. end
  796. else
  797. begin
  798. PA:=New(PHTMLAnsiView,init(@self));
  799. PA^.LoadFile(src);
  800. LastAnsiLoadFailed:=false;
  801. if AnyCharsInLine then DocBreak;
  802. StorePreformatted:=InPreformatted;
  803. InPreformatted:=true;
  804. {AddText('Image from '+src+hscLineBreak); }
  805. AddChar(hscInImage);
  806. PA^.CopyToHTML;
  807. InPreformatted:=StorePreformatted;
  808. AddChar(hscInImage);
  809. AddChar(hscNormText);
  810. if AnyCharsInLine then DocBreak;
  811. Dispose(PA,Done);
  812. Exit;
  813. end;
  814. { also look for a raw text file without colors }
  815. src:=DirAndNameOf(src)+'.txt';
  816. if not ExistsFile(src) then
  817. begin
  818. LastAnsiLoadFailed:=true;
  819. {$IFDEF WDEBUG}
  820. DebugMessage(GetFileName,' "'+Src+'" not found',Line,1);
  821. {$endif WDEBUG}
  822. end
  823. else
  824. begin
  825. Assign(f,src);
  826. Reset(f);
  827. DocPreformatted(true);
  828. while not eof(f) do
  829. begin
  830. Readln(f,SrcLine);
  831. AddText(SrcLine+hscLineBreak);
  832. end;
  833. Close(f);
  834. LastAnsiLoadFailed:=false;
  835. DocPreformatted(false);
  836. LastAnsiLoadFailed:=false;
  837. Exit;
  838. end;
  839. end;
  840. end;
  841. if DocGetTagParam('ALT',Alt)=false then
  842. begin
  843. DocGetTagParam('SRC',Alt);
  844. if Alt<>'' then
  845. Alt:='Can''t display '+Alt
  846. else
  847. Alt:='IMG';
  848. end;
  849. if Alt<>'' then
  850. begin
  851. StorePreformatted:=InPreformatted;
  852. InPreformatted:=true;
  853. DocGetTagParam('SRC',src);
  854. AddChar(hscInImage);
  855. AddText('[--'+Src+'--'+hscLineBreak);
  856. AddText(Alt+hscLineBreak+'--]');
  857. AddChar(hscInImage);
  858. AddChar(hscNormText);
  859. InPreformatted:=StorePreformatted;
  860. end;
  861. end;
  862. procedure THTMLTopicRenderer.DocBold(Entered: boolean);
  863. begin
  864. end;
  865. procedure THTMLTopicRenderer.DocCite(Entered: boolean);
  866. begin
  867. end;
  868. procedure THTMLTopicRenderer.DocCode(Entered: boolean);
  869. begin
  870. if AnyCharsInLine then DocBreak;
  871. AddText(hscCode);
  872. DocBreak;
  873. end;
  874. procedure THTMLTopicRenderer.DocEmphasized(Entered: boolean);
  875. begin
  876. end;
  877. procedure THTMLTopicRenderer.DocItalic(Entered: boolean);
  878. begin
  879. end;
  880. procedure THTMLTopicRenderer.DocKbd(Entered: boolean);
  881. begin
  882. end;
  883. procedure THTMLTopicRenderer.DocPreformatted(Entered: boolean);
  884. begin
  885. if AnyCharsInLine then DocBreak;
  886. AddText(hscCode);
  887. DocBreak;
  888. InPreformatted:=Entered;
  889. end;
  890. procedure THTMLTopicRenderer.DocSample(Entered: boolean);
  891. begin
  892. end;
  893. procedure THTMLTopicRenderer.DocStrong(Entered: boolean);
  894. begin
  895. end;
  896. procedure THTMLTopicRenderer.DocTeleType(Entered: boolean);
  897. begin
  898. end;
  899. procedure THTMLTopicRenderer.DocVariable(Entered: boolean);
  900. begin
  901. end;
  902. procedure THTMLTopicRenderer.DocSpan(Entered: boolean);
  903. begin
  904. end;
  905. procedure THTMLTopicRenderer.DocList(Entered: boolean);
  906. begin
  907. if Entered then
  908. begin
  909. Inc(Indent,ListIndent);
  910. DocBreak;
  911. end
  912. else
  913. begin
  914. Dec(Indent,ListIndent);
  915. if AnyCharsInLine then DocBreak;
  916. end;
  917. end;
  918. procedure THTMLTopicRenderer.DocOrderedList(Entered: boolean);
  919. begin
  920. DocList(Entered);
  921. end;
  922. procedure THTMLTopicRenderer.DocListItem(Entered: boolean);
  923. begin
  924. if not Entered then
  925. exit;
  926. if AnyCharsInLine then
  927. DocBreak;
  928. AddText('þ'+hscLineStart);
  929. end;
  930. procedure THTMLTopicRenderer.DocDefList(Entered: boolean);
  931. begin
  932. if Entered then
  933. begin
  934. { if LastChar<>hscLineBreak then DocBreak;}
  935. end
  936. else
  937. begin
  938. if AnyCharsInLine then DocBreak;
  939. InDefExp:=false;
  940. end;
  941. end;
  942. procedure THTMLTopicRenderer.DocDefTerm(Entered: boolean);
  943. begin
  944. if not Entered then
  945. exit;
  946. DocBreak;
  947. end;
  948. procedure THTMLTopicRenderer.DocDefExp(Entered: boolean);
  949. begin
  950. if not Entered then
  951. begin
  952. if InDefExp then
  953. Dec(Indent,DefIndent);
  954. InDefExp:=false;
  955. end
  956. else
  957. begin
  958. if not InDefExp then
  959. Inc(Indent,DefIndent);
  960. InDefExp:=true;
  961. DocBreak;
  962. end;
  963. end;
  964. procedure THTMLTopicRenderer.DocTable(Entered: boolean);
  965. var
  966. ATable : PTable;
  967. Param : String;
  968. begin
  969. if AnyCharsInLine then
  970. begin
  971. AddChar(hscLineBreak);
  972. AnyCharsInLine:=false;
  973. end;
  974. if Entered then
  975. begin
  976. DocBreak;
  977. New(ATable,Init(CurrentTable));
  978. CurrentTable:=ATable;
  979. CurrentTable^.Renderer:=@Self;
  980. if DocGetTagParam('BORDER',Param) then
  981. if Param<>'0' then
  982. CurrentTable^.WithBorder:=true;
  983. if DocGetTagParam('CLASS',Param) then
  984. if Param='bar' then
  985. CurrentTable^.IsBar:=true;
  986. end
  987. else
  988. begin
  989. CurrentTable^.FormatTable;
  990. ATable:=CurrentTable;
  991. CurrentTable:=ATable^.PreviousTable;
  992. Dispose(ATable,Done);
  993. end;
  994. end;
  995. procedure THTMLTopicRenderer.DocTableRow(Entered: boolean);
  996. var
  997. ATableLine : PTableLine;
  998. begin
  999. if AnyCharsInLine or
  1000. (assigned(CurrentTable) and
  1001. assigned(CurrentTable^.FirstLine)) then
  1002. begin
  1003. AddChar(hscLineBreak);
  1004. AnyCharsInLine:=false;
  1005. end;
  1006. if Entered then
  1007. begin
  1008. New(ATableLine,Init);
  1009. if CurrentTable^.GlobalTextBegin=0 then
  1010. CurrentTable^.GlobalTextBegin:=TextPtr;
  1011. CurrentTable^.AddLine(ATableLine);
  1012. end;
  1013. end;
  1014. procedure THTMLTopicRenderer.DocTableItem(Entered: boolean);
  1015. var
  1016. Align : String;
  1017. i : sw_word;
  1018. NewEl : PTableElement;
  1019. PAlignEl : TParagraphAlign;
  1020. begin
  1021. if Entered then
  1022. begin
  1023. if assigned(CurrentTable^.LastLine) and Assigned(CurrentTable^.LastLine^.LastEl) and
  1024. (CurrentTable^.LastLine^.LastEl^.TextEnd=sw_word(-1)) then
  1025. begin
  1026. NewEl:=CurrentTable^.LastLine^.LastEl;
  1027. NewEl^.TextEnd:=TextPtr;
  1028. NewEl^.TextLength:=ComputeTextLength(
  1029. NewEl^.TextBegin+CurrentTable^.GlobalOffset,
  1030. TextPtr+CurrentTable^.GlobalOffset);
  1031. end;
  1032. PAlignEl:=paLeft;
  1033. if DocGetTagParam('ALIGN',Align) then
  1034. DecodeAlign(Align,PAlignEl);
  1035. New(NewEl,Init(PAlignEl));
  1036. CurrentTable^.AddElement(NewEl);
  1037. NewEl^.TextBegin:=TextPtr;
  1038. NewEl^.TextEnd:=sw_word(-1);
  1039. { AddText(' - ');}
  1040. end
  1041. else
  1042. begin
  1043. NewEl:=CurrentTable^.LastLine^.LastEl;
  1044. NewEl^.TextEnd:=TextPtr;
  1045. NewEl^.TextLength:=ComputeTextLength(
  1046. NewEl^.TextBegin+CurrentTable^.GlobalOffset,
  1047. TextPtr+CurrentTable^.GlobalOffset);
  1048. NewEl^.NumNL:=0;
  1049. for i:=NewEl^.TextBegin to TextPtr do
  1050. begin
  1051. if Topic^.Text^[i]=ord(hscLineBreak) then
  1052. inc(NewEl^.NumNL);
  1053. end;
  1054. end;
  1055. end;
  1056. procedure THTMLTopicRenderer.DocTableHeaderItem(Entered: boolean);
  1057. begin
  1058. { Treat as a normal item }
  1059. DocTableItem(Entered);
  1060. end;
  1061. procedure THTMLTopicRenderer.DocHorizontalRuler;
  1062. var OAlign: TParagraphAlign;
  1063. begin
  1064. OAlign:=PAlign;
  1065. if AnyCharsInLine then DocBreak;
  1066. PAlign:=paCenter;
  1067. DocAddText(' '+CharStr('Ä',60)+' ');
  1068. DocBreak;
  1069. PAlign:=OAlign;
  1070. end;
  1071. procedure THTMLTopicRenderer.AddChar(C: char);
  1072. begin
  1073. if (Topic=nil) or (TextPtr=MaxBytes) or SuppressOutput then Exit;
  1074. Topic^.Text^[TextPtr]:=ord(C);
  1075. Inc(TextPtr);
  1076. if (C>#15) and ((C<>' ') or (InPreFormatted=true)) then
  1077. AnyCharsInLine:=true;
  1078. end;
  1079. procedure THTMLTopicRenderer.AddCharAt(C: char;AtPtr : sw_word);
  1080. begin
  1081. if (Topic=nil) or (TextPtr=MaxBytes) or SuppressOutput then Exit;
  1082. if AtPtr>TextPtr then
  1083. AtPtr:=TextPtr
  1084. else
  1085. begin
  1086. Move(Topic^.Text^[AtPtr],Topic^.Text^[AtPtr+1],TextPtr-AtPtr);
  1087. end;
  1088. Topic^.Text^[AtPtr]:=ord(C);
  1089. Inc(TextPtr);
  1090. end;
  1091. procedure THTMLTopicRenderer.AddText(const S: string);
  1092. var I: sw_integer;
  1093. begin
  1094. for I:=1 to length(S) do
  1095. AddChar(S[I]);
  1096. end;
  1097. function THTMLTopicRenderer.ComputeTextLength(TStart,TEnd : sw_word) : sw_word;
  1098. var I,tot: sw_integer;
  1099. begin
  1100. tot:=0;
  1101. i:=TStart;
  1102. while i<= TEnd-1 do
  1103. begin
  1104. inc(tot);
  1105. case chr(Topic^.Text^[i]) of
  1106. hscLink,hscCode,
  1107. hscCenter,hscRight,
  1108. hscNamedMark,hscNormText :
  1109. Dec(tot);{ Do not increase tot }
  1110. hscDirect:
  1111. begin
  1112. Inc(i); { Skip next }
  1113. //Inc(tot);
  1114. end;
  1115. hscTextAttr,
  1116. hscTextColor:
  1117. begin
  1118. Inc(i);
  1119. Dec(tot);
  1120. end;
  1121. end;
  1122. inc(i);
  1123. end;
  1124. ComputeTextLength:=tot;
  1125. end;
  1126. function THTMLTopicRenderer.AddTextAt(const S: String;AtPtr : sw_word) : sw_word;
  1127. var
  1128. i,slen,len : sw_word;
  1129. begin
  1130. if (Topic=nil) or (TextPtr>=MaxBytes) or SuppressOutput then Exit;
  1131. slen:=length(s);
  1132. if TextPtr+slen>=MaxBytes then
  1133. slen:=MaxBytes-TextPtr;
  1134. if AtPtr>TextPtr then
  1135. AtPtr:=TextPtr
  1136. else
  1137. begin
  1138. len:=TextPtr-AtPtr;
  1139. Move(Topic^.Text^[AtPtr],Topic^.Text^[AtPtr+slen],len);
  1140. end;
  1141. for i:=1 to slen do
  1142. begin
  1143. Topic^.Text^[AtPtr]:=ord(S[i]);
  1144. Inc(TextPtr);
  1145. inc(AtPtr);
  1146. if (TextPtr=MaxBytes) then Exit;
  1147. end;
  1148. AddTextAt:=slen;
  1149. end;
  1150. function THTMLTopicRenderer.GetSectionColor(Section: THTMLSection; var Color: byte): boolean;
  1151. begin
  1152. GetSectionColor:=HTMLGetSectionColor(Section,Color);
  1153. end;
  1154. function THTMLTopicRenderer.BuildTopic(P: PTopic; AURL: string; HTMLFile: PTextFile;
  1155. ATopicLinks: PTopicLinkCollection): boolean;
  1156. var OK: boolean;
  1157. TP: pointer;
  1158. I: sw_integer;
  1159. begin
  1160. URL:=AURL;
  1161. Topic:=P; TopicLinks:=ATopicLinks;
  1162. OK:=Assigned(Topic) and Assigned(HTMLFile) and Assigned(TopicLinks);
  1163. if OK then
  1164. begin
  1165. if (Topic^.TextSize<>0) and Assigned(Topic^.Text) then
  1166. begin
  1167. FreeMem(Topic^.Text,Topic^.TextSize);
  1168. Topic^.TextSize:=0; Topic^.Text:=nil;
  1169. end;
  1170. Topic^.TextSize:=MaxHelpTopicSize;
  1171. GetMem(Topic^.Text,Topic^.TextSize);
  1172. TopicTitle:='';
  1173. InTitle:=false; InBody:={false}true; InAnchor:=false;
  1174. InParagraph:=false; InPreformatted:=false;
  1175. Indent:=0; CurHeadLevel:=0;
  1176. PAlign:=paLeft;
  1177. TextPtr:=0; LinkPtr:=0;
  1178. AnyCharsInLine:=false;
  1179. LastTextChar:=#0;
  1180. SuppressUntil:='';
  1181. SuppressOutput:=false;
  1182. OK:=Process(HTMLFile);
  1183. if OK then
  1184. begin
  1185. { --- topic links --- }
  1186. if (Topic^.Links<>nil) and (Topic^.LinkSize>0) then
  1187. begin
  1188. FreeMem(Topic^.Links,Topic^.LinkSize);
  1189. Topic^.Links:=nil; Topic^.LinkCount:=0;
  1190. end;
  1191. Topic^.LinkCount:=LinkPtr{TopicLinks^.Count}; { <- eeeeeek! }
  1192. GetMem(Topic^.Links,Topic^.LinkSize);
  1193. if Topic^.LinkCount>0 then { FP causes numeric RTE 215 without this }
  1194. for I:=0 to Min(Topic^.LinkCount-1,High(LinkIndexes)-1) do
  1195. begin
  1196. {$IFDEF WDEBUG}
  1197. DebugMessageS({$i %file%},' Indexing links ('+inttostr(i)+')'+topiclinks^.at(linkindexes[i])^,{$i %line%},'1');
  1198. {$endif WDEBUG}
  1199. Topic^.Links^[I].FileID:=Topic^.FileID;
  1200. Topic^.Links^[I].Context:=EncodeHTMLCtx(Topic^.FileID,LinkIndexes[I]+1);
  1201. end;
  1202. { --- topic text --- }
  1203. GetMem(TP,TextPtr);
  1204. Move(Topic^.Text^,TP^,TextPtr);
  1205. FreeMem(Topic^.Text,Topic^.TextSize);
  1206. Topic^.Text:=TP; Topic^.TextSize:=TextPtr;
  1207. end
  1208. else
  1209. begin
  1210. DisposeTopic(Topic);
  1211. Topic:=nil;
  1212. end;
  1213. end;
  1214. BuildTopic:=OK;
  1215. end;
  1216. Function TCHMTopicRenderer.CanonicalizeURL(const Base,Relative:String):string;
  1217. begin
  1218. if copy(relative,1,7)<>'ms-its:' then
  1219. CanonicalizeUrl:=combinepaths(relative,base)
  1220. else
  1221. CanonicalizeUrl:=relative;
  1222. end;
  1223. constructor TCustomHTMLHelpFile.Init(AID: word);
  1224. begin
  1225. inherited Init(AID);
  1226. New(Renderer, Init);
  1227. New(TopicLinks, Init(50,500));
  1228. end;
  1229. function TCustomHTMLHelpFile.SearchTopic(HelpCtx: THelpCtx): PTopic;
  1230. function MatchCtx(P: PTopic): boolean;
  1231. begin
  1232. MatchCtx:=P^.HelpCtx=HelpCtx;
  1233. end;
  1234. var FileID,LinkNo: word;
  1235. P: PTopic;
  1236. FName: string;
  1237. begin
  1238. DecodeHTMLCtx(HelpCtx,FileID,LinkNo);
  1239. if (HelpCtx<>0) and (FileID<>ID) then P:=nil else
  1240. if (FileID=ID) and (LinkNo>TopicLinks^.Count) then P:=nil else
  1241. begin
  1242. P:=Topics^.FirstThat(@MatchCtx);
  1243. if P=nil then
  1244. begin
  1245. if LinkNo=0 then
  1246. FName:=DefaultFileName
  1247. else
  1248. FName:=TopicLinks^.At(LinkNo-1)^;
  1249. P:=NewTopic(ID,HelpCtx,0,FName,nil,0);
  1250. Topics^.Insert(P);
  1251. end;
  1252. end;
  1253. SearchTopic:=P;
  1254. end;
  1255. function TCustomHTMLHelpFile.GetTopicInfo(T: PTopic) : string;
  1256. var OK: boolean;
  1257. Name: string;
  1258. Link,Bookmark: string;
  1259. P: sw_integer;
  1260. begin
  1261. Bookmark:='';
  1262. OK:=T<>nil;
  1263. if OK then
  1264. begin
  1265. if T^.HelpCtx=0 then
  1266. begin
  1267. Name:=DefaultFileName;
  1268. P:=0;
  1269. end
  1270. else
  1271. begin
  1272. Link:=TopicLinks^.At((T^.HelpCtx and $ffff)-1)^;
  1273. {$IFDEF WDEBUG}
  1274. DebugMessageS({$i %file%},'(Topicinfo) Link before formatpath "'+link+'"',{$i %line%},'1');
  1275. {$ENDIF WDEBUG}
  1276. Link:=FormatPath(Link);
  1277. {$IFDEF WDEBUG}
  1278. DebugMessageS({$i %file%},'(Topicinfo) Link after formatpath "'+link+'"',{$i %line%},'1');
  1279. {$ENDIF WDEBUG}
  1280. P:=Pos('#',Link);
  1281. if P>0 then
  1282. begin
  1283. Bookmark:=copy(Link,P+1,length(Link));
  1284. Link:=copy(Link,1,P-1);
  1285. end;
  1286. { if CurFileName='' then Name:=Link else
  1287. Name:=CompletePath(CurFileName,Link);}
  1288. Name:=Link;
  1289. end;
  1290. end;
  1291. GetTopicInfo:=Name+'#'+BookMark;
  1292. end;
  1293. function TCustomHTMLHelpFile.ReadTopic(T: PTopic): boolean;
  1294. var OK: boolean;
  1295. HTMLFile: PMemoryTextFile;
  1296. Name: string;
  1297. Link,Bookmark: string;
  1298. P: sw_integer;
  1299. begin
  1300. Bookmark:='';
  1301. OK:=T<>nil;
  1302. if OK then
  1303. begin
  1304. if T^.HelpCtx=0 then
  1305. begin
  1306. Name:=DefaultFileName;
  1307. P:=0;
  1308. end
  1309. else
  1310. begin
  1311. Link:=TopicLinks^.At((T^.HelpCtx and $ffff)-1)^;
  1312. {$IFDEF WDEBUG}
  1313. DebugMessageS({$i %file%},'(ReadTopic) Link before formatpath "'+link+'"',{$i %line%},'1');
  1314. {$ENDIF WDEBUG}
  1315. Link:=FormatPath(Link);
  1316. {$IFDEF WDEBUG}
  1317. DebugMessageS({$i %file%},'(ReadTopic) Link before formatpath "'+link+'"',{$i %line%},'1');
  1318. {$ENDIF WDEBUG}
  1319. P:=Pos('#',Link);
  1320. if P>0 then
  1321. begin
  1322. Bookmark:=copy(Link,P+1,length(Link));
  1323. Link:=copy(Link,1,P-1);
  1324. end;
  1325. { if CurFileName='' then Name:=Link else
  1326. Name:=CompletePath(CurFileName,Link);}
  1327. Name:=Link;
  1328. end;
  1329. HTMLFile:=nil;
  1330. if Name<>'' then
  1331. HTMLFile:=New(PDOSTextFile, Init(Name));
  1332. if (HTMLFile=nil) and (CurFileName<>'') then
  1333. begin
  1334. Name:=CurFileName;
  1335. HTMLFile:=New(PDOSTextFile, Init(Name));
  1336. end;
  1337. if (HTMLFile=nil) then
  1338. begin
  1339. {$IFDEF WDEBUG}
  1340. DebugMessageS({$i %file%},'(ReadTopic) Filename not known: "'+link+'"',{$i %line%},'1');
  1341. {$ENDIF WDEBUG}
  1342. end;
  1343. if (p>1) and (HTMLFile=nil) then
  1344. begin
  1345. {$IFDEF WDEBUG}
  1346. if p>0 then
  1347. DebugMessage(Name,Link+'#'+Bookmark+' not found',1,1)
  1348. else
  1349. DebugMessage(Name,Link+' not found',1,1);
  1350. {$endif WDEBUG}
  1351. New(HTMLFile, Init);
  1352. HTMLFile^.AddLine('<HEAD><TITLE>'+msg_pagenotavailable+'</TITLE></HEAD>');
  1353. HTMLFile^.AddLine(
  1354. '<BODY>'+
  1355. FormatStrStr(msg_cantaccessurl,Name)+'<br><br>'+
  1356. '</BODY>');
  1357. end;
  1358. OK:=Renderer^.BuildTopic(T,Name,HTMLFile,TopicLinks);
  1359. if OK then
  1360. CurFileName:=Name
  1361. else
  1362. begin
  1363. {$IFDEF WDEBUG}
  1364. if p>0 then
  1365. DebugMessage(Name,Link+'#'+Bookmark+' not found',1,1)
  1366. else
  1367. DebugMessage(Name,Link+' not found',1,1);
  1368. {$endif WDEBUG}
  1369. end;
  1370. if HTMLFile<>nil then Dispose(HTMLFile, Done);
  1371. if BookMark='' then
  1372. T^.StartNamedMark:=0
  1373. else
  1374. begin
  1375. P:=T^.GetNamedMarkIndex(BookMark);
  1376. {$IFDEF WDEBUG}
  1377. if p=-1 then
  1378. DebugMessage(Name,Link+'#'+Bookmark+' bookmark not found',1,1);
  1379. {$endif WDEBUG}
  1380. T^.StartNamedMark:=P+1;
  1381. end;
  1382. end;
  1383. ReadTopic:=OK;
  1384. end;
  1385. destructor TCustomHTMLHelpFile.Done;
  1386. begin
  1387. inherited Done;
  1388. if Renderer<>nil then Dispose(Renderer, Done);
  1389. if TopicLinks<>nil then Dispose(TopicLinks, Done);
  1390. end;
  1391. constructor THTMLHelpFile.Init(AFileName: string; AID: word; ATOCEntry: string);
  1392. begin
  1393. if inherited Init(AID)=false then Fail;
  1394. DefaultFileName:=AFileName; TOCEntry:=ATOCEntry;
  1395. if DefaultFileName='' then
  1396. begin
  1397. Done;
  1398. Fail;
  1399. end;
  1400. end;
  1401. function THTMLHelpFile.LoadIndex: boolean;
  1402. begin
  1403. IndexEntries^.Insert(NewIndexEntry(TOCEntry,ID,0));
  1404. LoadIndex:=true;
  1405. end;
  1406. constructor THTMLIndexHelpFile.Init(AFileName: string; AID: word);
  1407. begin
  1408. inherited Init(AID);
  1409. IndexFileName:=AFileName;
  1410. end;
  1411. function THTMLIndexHelpFile.LoadIndex: boolean;
  1412. function FormatAlias(Alias: string): string;
  1413. begin
  1414. if Assigned(HelpFacility) then
  1415. if length(Alias)>HelpFacility^.IndexTabSize-4 then
  1416. Alias:=Trim(copy(Alias,1,HelpFacility^.IndexTabSize-4-2))+'..';
  1417. FormatAlias:=Alias;
  1418. end;
  1419. (*procedure AddDoc(P: PHTMLLinkScanDocument);
  1420. var I: sw_integer;
  1421. TLI: THelpCtx;
  1422. begin
  1423. for I:=1 to P^.GetAliasCount do
  1424. begin
  1425. TLI:=TopicLinks^.AddItem(P^.GetName);
  1426. TLI:=EncodeHTMLCtx(ID,TLI+1);
  1427. IndexEntries^.Insert(NewIndexEntry(FormatAlias(P^.GetAlias(I-1)),ID,TLI));
  1428. end;
  1429. end;*)
  1430. var S: PBufStream;
  1431. LS: PHTMLLinkScanner;
  1432. OK: boolean;
  1433. TLI: THelpCtx;
  1434. I,J: sw_integer;
  1435. begin
  1436. New(S, Init(IndexFileName,stOpenRead,4096));
  1437. OK:=Assigned(S);
  1438. if OK then
  1439. begin
  1440. New(LS, LoadDocuments(S^));
  1441. OK:=Assigned(LS);
  1442. if OK then
  1443. begin
  1444. LS^.SetBaseDir(DirOf(IndexFileName));
  1445. for I:=0 to LS^.GetDocumentCount-1 do
  1446. begin
  1447. TLI:=TopicLinks^.AddItem(LS^.GetDocumentURL(I));
  1448. TLI:=EncodeHTMLCtx(ID,TLI+1);
  1449. for J:=0 to LS^.GetDocumentAliasCount(I)-1 do
  1450. IndexEntries^.Insert(NewIndexEntry(
  1451. FormatAlias(LS^.GetDocumentAlias(I,J)),ID,TLI));
  1452. end;
  1453. Dispose(LS, Done);
  1454. end;
  1455. Dispose(S, Done);
  1456. end;
  1457. LoadIndex:=OK;
  1458. end;
  1459. constructor TChmHelpFile.Init(AFileName: string; AID: word);
  1460. begin
  1461. if inherited Init(AID)=false then Fail;
  1462. renderer^.done;
  1463. renderer:=New(PCHMTopicRenderer, Init);
  1464. DefaultFileName:=AFileName;
  1465. if (DefaultFileName='') or not ExistsFile(DefaultFilename) then
  1466. begin
  1467. Done;
  1468. Fail;
  1469. end
  1470. else
  1471. chmw:=TCHMWrapper.Create(DefaultFileName);
  1472. end;
  1473. function TChmHelpFile.LoadIndex: boolean;
  1474. begin
  1475. loadindex:=false;
  1476. if assigned(chmw) then
  1477. loadindex:=chmw.loadindex(id,TopicLinks,IndexEntries,helpfacility);
  1478. end;
  1479. function TChmHelpFile.SearchTopic(HelpCtx: THelpCtx): PTopic;
  1480. function MatchCtx(P: PTopic): boolean;
  1481. begin
  1482. MatchCtx:=P^.HelpCtx=HelpCtx;
  1483. end;
  1484. var FileID,LinkNo: word;
  1485. P: PTopic;
  1486. FName: string;
  1487. begin
  1488. DecodeHTMLCtx(HelpCtx,FileID,LinkNo);
  1489. if (HelpCtx<>0) and (FileID<>ID) then P:=nil else
  1490. if (FileID=ID) and (LinkNo>TopicLinks^.Count) then P:=nil else
  1491. begin
  1492. P:=Topics^.FirstThat(@MatchCtx);
  1493. if P=nil then
  1494. begin
  1495. if LinkNo=0 then
  1496. FName:=DefaultFileName
  1497. else
  1498. FName:=TopicLinks^.At(LinkNo-1)^;
  1499. P:=NewTopic(ID,HelpCtx,0,FName,nil,0);
  1500. Topics^.Insert(P);
  1501. end;
  1502. end;
  1503. SearchTopic:=P;
  1504. end;
  1505. function TChmHelpFile.GetTopicInfo(T: PTopic) : string;
  1506. var OK: boolean;
  1507. Name: string;
  1508. Link,Bookmark: string;
  1509. P: sw_integer;
  1510. begin
  1511. Bookmark:='';
  1512. OK:=T<>nil;
  1513. if OK then
  1514. begin
  1515. if T^.HelpCtx=0 then
  1516. begin
  1517. Name:=DefaultFileName;
  1518. P:=0;
  1519. end
  1520. else
  1521. begin
  1522. Link:=TopicLinks^.At((T^.HelpCtx and $ffff)-1)^;
  1523. Link:=FormatPath(Link);
  1524. {$IFDEF WDEBUG}
  1525. DebugMessageS({$i %file%},' Looking for "'+Link+'"',{$i %line%},'1');
  1526. {$endif WDEBUG}
  1527. P:=Pos('#',Link);
  1528. if P>0 then
  1529. begin
  1530. Bookmark:=copy(Link,P+1,length(Link));
  1531. Link:=copy(Link,1,P-1);
  1532. end;
  1533. { if CurFileName='' then Name:=Link else
  1534. Name:=CompletePath(CurFileName,Link);}
  1535. Name:=Link;
  1536. end;
  1537. end;
  1538. GetTopicInfo:=Name+'#'+BookMark;
  1539. end;
  1540. function TChmHelpFile.ReadTopic(T: PTopic): boolean;
  1541. var OK: boolean;
  1542. HTMLFile: PMemoryTextFile;
  1543. Name: string;
  1544. Link,Bookmark: string;
  1545. P: sw_integer;
  1546. begin
  1547. Bookmark:='';
  1548. OK:=T<>nil;
  1549. if OK then
  1550. begin
  1551. if T^.HelpCtx=0 then
  1552. begin
  1553. Name:=DefaultFileName;
  1554. P:=0;
  1555. end
  1556. else
  1557. begin
  1558. Link:=TopicLinks^.At((T^.HelpCtx and $ffff)-1)^;
  1559. {$IFDEF WDEBUG}
  1560. DebugMessageS({$i %file%},' Looking for "'+Link+'"',{$i %line%},'1');
  1561. {$endif WDEBUG}
  1562. Link:=FormatPath(Link);
  1563. {$IFDEF WDEBUG}
  1564. DebugMessageS({$i %file%},' Looking for (after formatpath) "'+Link+'"',{$i %line%},'1');
  1565. {$endif WDEBUG}
  1566. P:=Pos('#',Link);
  1567. if P>0 then
  1568. begin
  1569. Bookmark:=copy(Link,P+1,length(Link));
  1570. Link:=copy(Link,1,P-1);
  1571. end;
  1572. { if CurFileName='' then Name:=Link else
  1573. Name:=CompletePath(CurFileName,Link);}
  1574. Name:=Link;
  1575. end;
  1576. HTMLFile:=nil;
  1577. if Name<>'' then
  1578. HTMLFile:=chmw.gettopic(name);
  1579. if (HTMLFile=nil) and (CurFileName<>'') then
  1580. begin
  1581. Name:=CurFileName;
  1582. HTMLFile:=chmw.gettopic(name);
  1583. end;
  1584. if (HTMLFile=nil) then
  1585. begin
  1586. {$IFDEF WDEBUG}
  1587. DebugMessage(Link,' filename not known :(',1,1);
  1588. {$endif WDEBUG}
  1589. end;
  1590. if (p>1) and (HTMLFile=nil) then
  1591. begin
  1592. {$IFDEF WDEBUG}
  1593. if p>0 then
  1594. DebugMessage(Name,Link+'#'+Bookmark+' not found',1,1)
  1595. else
  1596. DebugMessage(Name,Link+' not found',1,1);
  1597. {$endif WDEBUG}
  1598. New(HTMLFile, Init);
  1599. HTMLFile^.AddLine('<HEAD><TITLE>'+msg_pagenotavailable+'</TITLE></HEAD>');
  1600. HTMLFile^.AddLine(
  1601. '<BODY>'+
  1602. FormatStrStr(msg_cantaccessurl,Name)+'<br><br>'+
  1603. '</BODY>');
  1604. end;
  1605. OK:=Renderer^.BuildTopic(T,Name,HTMLFile,TopicLinks);
  1606. if OK then
  1607. CurFileName:=Name
  1608. else
  1609. begin
  1610. {$IFDEF WDEBUG}
  1611. if p>0 then
  1612. DebugMessage(Name,Link+'#'+Bookmark+' not found',1,1)
  1613. else
  1614. DebugMessage(Name,Link+' not found',1,1);
  1615. {$endif WDEBUG}
  1616. end;
  1617. if HTMLFile<>nil then Dispose(HTMLFile, Done);
  1618. if BookMark='' then
  1619. T^.StartNamedMark:=0
  1620. else
  1621. begin
  1622. P:=T^.GetNamedMarkIndex(BookMark);
  1623. {$IFDEF WDEBUG}
  1624. if p=-1 then
  1625. DebugMessage(Name,Link+'#'+Bookmark+' bookmark not found',1,1);
  1626. {$endif WDEBUG}
  1627. T^.StartNamedMark:=P+1;
  1628. end;
  1629. end;
  1630. ReadTopic:=OK;
  1631. end;
  1632. destructor TChmHelpFile.done;
  1633. begin
  1634. if assigned(chmw) then
  1635. chmw.free;
  1636. inherited Done;
  1637. end;
  1638. function CreateProcHTML(const FileName,Param: string;Index : longint): PHelpFile;
  1639. var H: PHelpFile;
  1640. begin
  1641. H:=nil;
  1642. if CompareText(copy(ExtOf(FileName),1,length(extHTML)),extHTML)=0 then
  1643. H:=New(PHTMLHelpFile, Init(FileName,Index,Param));
  1644. CreateProcHTML:=H;
  1645. end;
  1646. function CreateProcCHM(const FileName,Param: string;Index : longint): PHelpFile;
  1647. var H: PHelpFile;
  1648. begin
  1649. H:=nil;
  1650. if CompareText(copy(ExtOf(FileName),1,length(extCHM)),extCHM)=0 then
  1651. H:=New(PCHMHelpFile, Init(FileName,Index));
  1652. CreateProcCHM:=H;
  1653. end;
  1654. function CreateProcHTMLIndex(const FileName,Param: string;Index : longint): PHelpFile;
  1655. var H: PHelpFile;
  1656. begin
  1657. H:=nil;
  1658. if CompareText(ExtOf(FileName),extHTMLIndex)=0 then
  1659. H:=New(PHTMLIndexHelpFile, Init(FileName,Index));
  1660. CreateProcHTMLIndex:=H;
  1661. end;
  1662. procedure RegisterHelpType;
  1663. begin
  1664. RegisterHelpFileType({$ifdef FPC}@{$endif}CreateProcHTML);
  1665. RegisterHelpFileType({$ifdef FPC}@{$endif}CreateProcHTMLIndex);
  1666. RegisterHelpFileType({$ifdef FPC}@{$endif}CreateProcCHM);
  1667. end;
  1668. END.