dw_latex.pp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316
  1. {
  2. $Id$
  3. FPDoc - Free Pascal Documentation Tool
  4. Copyright (C) 2000 - 2003 by
  5. Areca Systems GmbH / Sebastian Guenther, [email protected]
  6. * LaTeX output generator
  7. See the file COPYING, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. }
  13. unit dw_LaTeX;
  14. {$MODE objfpc}
  15. {$H+}
  16. interface
  17. uses DOM, dGlobals, PasTree;
  18. const
  19. LateXHighLight: Boolean = False;
  20. procedure CreateLaTeXDocForPackage(APackage: TPasPackage; AEngine: TFPDocEngine);
  21. implementation
  22. uses SysUtils, Classes, dWriter;
  23. type
  24. TLabelType = (ltConst,ltVar,ltType,ltFunction,ltProcedure,ltClass,
  25. ltChapter,ltSection,ltSubsection,
  26. ltTable,ltFigure);
  27. TLaTeXWriter = class(TFPDocWriter)
  28. protected
  29. f: Text;
  30. FLink: String;
  31. Package: TPasPackage;
  32. PackageName: String;
  33. Module: TPasModule;
  34. ModuleName: String;
  35. FTableCount : Integer;
  36. TableRowStartFlag, TableCaptionWritten: Boolean;
  37. function GetLabel(AElement: TPasElement): String;
  38. procedure Write(const s: String);
  39. procedure WriteF(const s: String; const Args: array of const);
  40. procedure WriteLn(const s: String);
  41. procedure WriteLnF(const s: String; const Args: array of const);
  42. // Tex functions
  43. procedure WriteLabel(El: TPasElement);
  44. procedure WriteLabel(const s: String);
  45. procedure WriteIndex(El: TPasElement);
  46. procedure WriteIndex(const s: String);
  47. procedure StartListing(Frames: Boolean; const name: String);
  48. procedure StartListing(Frames: Boolean);
  49. procedure EndListing;
  50. procedure WriteCommentLine;
  51. procedure WriteComment(Comment : String);
  52. procedure StartSection(SectionName : String; SectionLabel : String);
  53. procedure StartSection(SectionName : String);
  54. procedure StartSubSection(SubSectionName : String; SubSectionLabel : String);
  55. procedure StartSubSection(SubSectionName : String);
  56. procedure StartChapter(ChapterName : String; ChapterLabel : String);
  57. procedure StartChapter(ChapterName : String);
  58. // Description node conversion
  59. procedure DescrWriteText(const AText: DOMString); override;
  60. procedure DescrBeginBold; override;
  61. procedure DescrEndBold; override;
  62. procedure DescrBeginItalic; override;
  63. procedure DescrEndItalic; override;
  64. procedure DescrBeginEmph; override;
  65. procedure DescrEndEmph; override;
  66. procedure DescrWriteFileEl(const AText: DOMString); override;
  67. procedure DescrWriteKeywordEl(const AText: DOMString); override;
  68. procedure DescrWriteVarEl(const AText: DOMString); override;
  69. procedure DescrBeginLink(const AId: DOMString); override;
  70. procedure DescrEndLink; override;
  71. procedure DescrWriteLinebreak; override;
  72. procedure DescrBeginParagraph; override;
  73. procedure DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String); override;
  74. procedure DescrWriteCodeLine(const ALine: String); override;
  75. procedure DescrEndCode; override;
  76. procedure DescrEndParagraph; override;
  77. procedure DescrBeginOrderedList; override;
  78. procedure DescrEndOrderedList; override;
  79. procedure DescrBeginUnorderedList; override;
  80. procedure DescrEndUnorderedList; override;
  81. procedure DescrBeginDefinitionList; override;
  82. procedure DescrEndDefinitionList; override;
  83. procedure DescrBeginListItem; override;
  84. procedure DescrEndListItem; override;
  85. procedure DescrBeginDefinitionTerm; override;
  86. procedure DescrEndDefinitionTerm; override;
  87. procedure DescrBeginDefinitionEntry; override;
  88. procedure DescrEndDefinitionEntry; override;
  89. procedure DescrBeginSectionTitle; override;
  90. procedure DescrBeginSectionBody; override;
  91. procedure DescrEndSection; override;
  92. procedure DescrBeginRemark; override;
  93. procedure DescrEndRemark; override;
  94. procedure DescrBeginTable(ColCount: Integer; HasBorder: Boolean); override;
  95. procedure DescrEndTable; override;
  96. procedure DescrBeginTableCaption; override;
  97. procedure DescrEndTableCaption; override;
  98. procedure DescrBeginTableHeadRow; override;
  99. procedure DescrEndTableHeadRow; override;
  100. procedure DescrBeginTableRow; override;
  101. procedure DescrEndTableRow; override;
  102. procedure DescrBeginTableCell; override;
  103. procedure DescrEndTableCell; override;
  104. procedure WriteDescr(Element: TPasElement);
  105. procedure WriteDescr(AContext: TPasElement; DescrNode: TDOMElement);
  106. function ConstValue(ConstDecl: TPasConst): String;
  107. procedure ProcessSection(ASection: TPasSection);
  108. // Documentation writing methods.
  109. procedure WriteResourceStrings(ASection: TPasSection);
  110. procedure WriteUnitOverview(ASection: TPasSection);
  111. procedure WriteVarsConstsTypes(ASection: TPasSection);
  112. procedure WriteConsts(ASection: TPasSection);
  113. procedure WriteTypes(ASection: TPasSection);
  114. procedure WriteEnumElements(TypeDecl : TPasEnumType);
  115. procedure WriteVars(ASection: TPasSection);
  116. procedure WriteFunctionsAndProcedures(ASection: TPasSection);
  117. procedure WriteProcedure(ProcDecl: TPasProcedureBase);
  118. procedure WriteClasses(ASection: TPasSection);
  119. procedure WriteClassDecl(ClassDecl: TPasClassType);
  120. procedure WriteClassMethodOverview(ClassDecl: TPasClassType);
  121. procedure WriteClassPropertyOverview(ClassDecl: TPasClassType);
  122. procedure WriteProperty(PropDecl: TPasProperty);
  123. procedure WriteExample(ADocNode: TDocNode);
  124. procedure WriteSeeAlso(ADocNode: TDocNode);
  125. procedure SortElementList(List : TList);
  126. Function ShowMember(M : TPasElement) : boolean;
  127. public
  128. constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine);
  129. procedure WriteDoc;
  130. end;
  131. constructor TLaTeXWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
  132. procedure AddLabel(AElement: TPasElement);
  133. begin
  134. Engine.AddLink(AElement.PathName, GetLabel(AElement));
  135. end;
  136. procedure AddList(AElement: TPasElement; AList: TList);
  137. var
  138. i: Integer;
  139. begin
  140. for i := 0 to AList.Count - 1 do
  141. AddLabel(TPasElement(AList[i]));
  142. end;
  143. procedure ScanModule(AModule: TPasModule);
  144. var
  145. i, j, k: Integer;
  146. s: String;
  147. ClassEl: TPasClassType;
  148. FPEl, AncestorMemberEl: TPasElement;
  149. DocNode: TDocNode;
  150. DidAutolink: Boolean;
  151. begin
  152. AddLabel(AModule);
  153. with AModule do
  154. begin
  155. AddList(AModule, InterfaceSection.ResStrings);
  156. AddList(AModule, InterfaceSection.Consts);
  157. AddList(AModule, InterfaceSection.Types);
  158. if InterfaceSection.Classes.Count > 0 then
  159. begin
  160. for i := 0 to InterfaceSection.Classes.Count - 1 do
  161. begin
  162. ClassEl := TPasClassType(InterfaceSection.Classes[i]);
  163. AddLabel(ClassEl);
  164. for j := 0 to ClassEl.Members.Count - 1 do
  165. begin
  166. FPEl := TPasElement(ClassEl.Members[j]);
  167. if ((FPEl.Visibility = visPrivate) and Engine.HidePrivate) or
  168. ((FPEl.Visibility = visProtected) and Engine.HideProtected) then
  169. continue;
  170. DocNode := Engine.FindDocNode(FPEl);
  171. if not Assigned(DocNode) then
  172. begin
  173. DidAutolink := False;
  174. if Assigned(ClassEl.AncestorType) and
  175. (ClassEl.AncestorType.ClassType = TPasClassType) then
  176. begin
  177. for k := 0 to TPasClassType(ClassEl.AncestorType).Members.Count - 1 do
  178. begin
  179. AncestorMemberEl :=
  180. TPasElement(TPasClassType(ClassEl.AncestorType).Members[k]);
  181. if AncestorMemberEl.Name = FPEl.Name then
  182. begin
  183. DocNode := Engine.FindDocNode(AncestorMemberEl);
  184. if Assigned(DocNode) then
  185. begin
  186. DidAutolink := True;
  187. Engine.AddLink(FPEl.PathName,
  188. Engine.FindAbsoluteLink(AncestorMemberEl.PathName));
  189. break;
  190. end;
  191. end;
  192. end;
  193. end;
  194. if not DidAutolink then
  195. AddLabel(FPEl);
  196. end else
  197. AddLabel(FPEl);
  198. end;
  199. end;
  200. end;
  201. AddList(AModule, InterfaceSection.Functions);
  202. AddList(AModule, InterfaceSection.Variables);
  203. end;
  204. end;
  205. var
  206. i: Integer;
  207. begin
  208. inherited Create(AEngine);
  209. Package := APackage;
  210. { Allocate labels for all elements for which we are going to create
  211. documentation. This is needed for links to work correctly. }
  212. // Allocate label for the package itself, if a name is given (i.e. <> '#')
  213. if Length(Package.Name) > 1 then
  214. AddLabel(Package);
  215. for i := 0 to Package.Modules.Count - 1 do
  216. ScanModule(TPasModule(Package.Modules[i]));
  217. end;
  218. procedure TLaTeXWriter.WriteDoc;
  219. var
  220. i: Integer;
  221. begin
  222. PackageName := LowerCase(Copy(Package.Name, 2, 255));
  223. Assign(f, Engine.Output + PathDelim + PackageName + '.tex');
  224. Rewrite(f);
  225. try
  226. WriteLn('% This file has been created automatically by FPDoc,');
  227. WriteLn('% (c) 2000-2003 by Areca Systems GmbH / Sebastian Guenther ([email protected])');
  228. for i := 0 to Package.Modules.Count - 1 do
  229. begin
  230. Module := TPasModule(Package.Modules[i]);
  231. ModuleName := LowerCase(Module.Name);
  232. WriteLn('');
  233. WriteLnF('\chapter{%s}', [Format(SDocUnitTitle, [Module.Name])]);
  234. WriteLabel(Module);
  235. ProcessSection(Module.InterfaceSection);
  236. end;
  237. finally
  238. Close(f);
  239. end;
  240. end;
  241. function TLaTeXWriter.GetLabel(AElement: TPasElement): String;
  242. var
  243. i: Integer;
  244. begin
  245. if AElement.ClassType = TPasUnresolvedTypeRef then
  246. Result := Engine.ResolveLink(Module, AElement.Name)
  247. else
  248. begin
  249. Result := AElement.PathName;
  250. Result := LowerCase(Copy(Result, 2, Length(Result) - 1));
  251. end;
  252. for i := 1 to Length(Result) do
  253. if Result[i] = '.' then
  254. Result[i] := ':';
  255. end;
  256. procedure TLaTeXWriter.Write(const s: String);
  257. begin
  258. System.Write(f, s);
  259. end;
  260. procedure TLaTeXWriter.WriteF(const s: String; const Args: array of const);
  261. begin
  262. System.Write(f, Format(s, Args));
  263. end;
  264. procedure TLaTeXWriter.WriteLn(const s: String);
  265. begin
  266. System.WriteLn(f, s);
  267. end;
  268. procedure TLaTeXWriter.WriteLnF(const s: String; const Args: array of const);
  269. begin
  270. System.WriteLn(f, Format(s, Args));
  271. end;
  272. procedure TLaTeXWriter.DescrWriteText(const AText: DOMString);
  273. var
  274. i: Integer;
  275. s: DOMString;
  276. begin
  277. SetLength(s, 0);
  278. for i := 1 to Length(AText) do
  279. case AText[i] of
  280. '&','{','}','#','_','$','%': // Escape these characters
  281. s := s + '\' + AText[i];
  282. '~','^':
  283. S := S + '\'+AText[i]+' ';
  284. '\':
  285. S:=S+'$\backslash$'
  286. else
  287. s := s + AText[i];
  288. end;
  289. Write(s);
  290. end;
  291. procedure TLaTeXWriter.DescrBeginBold;
  292. begin
  293. Write('\textbf{');
  294. end;
  295. procedure TLaTeXWriter.DescrEndBold;
  296. begin
  297. Write('}');
  298. end;
  299. procedure TLaTeXWriter.DescrBeginItalic;
  300. begin
  301. Write('\textit{');
  302. end;
  303. procedure TLaTeXWriter.DescrEndItalic;
  304. begin
  305. Write('}');
  306. end;
  307. procedure TLaTeXWriter.DescrBeginEmph;
  308. begin
  309. Write('\emph{');
  310. end;
  311. procedure TLaTeXWriter.DescrEndEmph;
  312. begin
  313. Write('}');
  314. end;
  315. procedure TLaTeXWriter.DescrWriteFileEl(const AText: DOMString);
  316. begin
  317. Write('\file{');
  318. DescrWriteText(AText);
  319. Write('}');
  320. end;
  321. procedure TLaTeXWriter.DescrWriteKeywordEl(const AText: DOMString);
  322. begin
  323. Write('\textbf{\\ttfamily ');
  324. DescrWriteText(AText);
  325. Write('}');
  326. end;
  327. procedure TLaTeXWriter.DescrWriteVarEl(const AText: DOMString);
  328. begin
  329. Write('\var{');
  330. DescrWriteText(AText);
  331. Write('}');
  332. end;
  333. procedure TLaTeXWriter.DescrBeginLink(const AId: DOMString);
  334. var
  335. i: Integer;
  336. begin
  337. FLink := Engine.ResolveLink(Module, AId);
  338. // System.WriteLn('Link "', AId, '" => ', FLink);
  339. end;
  340. procedure TLaTeXWriter.DescrEndLink;
  341. begin
  342. WriteF(' (\pageref{%s})',[Flink]);
  343. end;
  344. procedure TLaTeXWriter.DescrWriteLinebreak;
  345. begin
  346. WriteLn('\\');
  347. end;
  348. procedure TLaTeXWriter.DescrBeginParagraph;
  349. begin
  350. // Do nothing
  351. end;
  352. procedure TLaTeXWriter.DescrEndParagraph;
  353. begin
  354. WriteLn('');
  355. WriteLn('');
  356. end;
  357. procedure TLaTeXWriter.DescrBeginCode(HasBorder: Boolean;
  358. const AHighlighterName: String);
  359. begin
  360. StartListing(HasBorder);
  361. end;
  362. procedure TLaTeXWriter.DescrWriteCodeLine(const ALine: String);
  363. begin
  364. WriteLn(ALine);
  365. end;
  366. procedure TLaTeXWriter.DescrEndCode;
  367. begin
  368. EndListing
  369. end;
  370. procedure TLaTeXWriter.DescrBeginOrderedList;
  371. begin
  372. WriteLn('\begin{enumerate}');
  373. end;
  374. procedure TLaTeXWriter.DescrEndOrderedList;
  375. begin
  376. WriteLn('\end{enumerate}');
  377. end;
  378. procedure TLaTeXWriter.DescrBeginUnorderedList;
  379. begin
  380. WriteLn('\begin{itemize}');
  381. end;
  382. procedure TLaTeXWriter.DescrEndUnorderedList;
  383. begin
  384. WriteLn('\end{itemize}');
  385. end;
  386. procedure TLaTeXWriter.DescrBeginDefinitionList;
  387. begin
  388. WriteLn('\begin{description');
  389. end;
  390. procedure TLaTeXWriter.DescrEndDefinitionList;
  391. begin
  392. WriteLn('\end{description}');
  393. end;
  394. procedure TLaTeXWriter.DescrBeginListItem;
  395. begin
  396. Write('\item ');
  397. end;
  398. procedure TLaTeXWriter.DescrEndListItem;
  399. begin
  400. WriteLn('');
  401. end;
  402. procedure TLaTeXWriter.DescrBeginDefinitionTerm;
  403. begin
  404. Write('\item[');
  405. end;
  406. procedure TLaTeXWriter.DescrEndDefinitionTerm;
  407. begin
  408. WriteLn(']');
  409. end;
  410. procedure TLaTeXWriter.DescrBeginDefinitionEntry;
  411. begin
  412. // Do nothing
  413. end;
  414. procedure TLaTeXWriter.DescrEndDefinitionEntry;
  415. begin
  416. WriteLn('');
  417. end;
  418. procedure TLaTeXWriter.DescrBeginSectionTitle;
  419. begin
  420. Write('\subsection{');
  421. end;
  422. procedure TLaTeXWriter.DescrBeginSectionBody;
  423. begin
  424. WriteLn('}');
  425. end;
  426. procedure TLaTeXWriter.DescrEndSection;
  427. begin
  428. // Do noting
  429. end;
  430. procedure TLaTeXWriter.DescrBeginRemark;
  431. begin
  432. WriteLn('\begin{remark}');
  433. end;
  434. procedure TLaTeXWriter.DescrEndRemark;
  435. begin
  436. WriteLn('\end{remark}');
  437. end;
  438. procedure TLaTeXWriter.DescrBeginTable(ColCount: Integer; HasBorder: Boolean);
  439. var
  440. i: Integer;
  441. begin
  442. // !!!: How do we set the border?
  443. Write('\begin{FPCltable}{');
  444. for i := 1 to ColCount do
  445. Write('l');
  446. write('}{');
  447. TableCaptionWritten:=False;
  448. end;
  449. procedure TLaTeXWriter.DescrEndTable;
  450. begin
  451. WriteLn('\end{FPCltable}');
  452. end;
  453. procedure TLaTeXWriter.DescrBeginTableCaption;
  454. begin
  455. // Do nothing.
  456. end;
  457. procedure TLaTeXWriter.DescrEndTableCaption;
  458. begin
  459. Write('}{table');
  460. Inc(FTableCount);
  461. Write(IntToStr(FTableCount));
  462. Writeln('}');
  463. TableCaptionWritten := True;
  464. end;
  465. procedure TLaTeXWriter.DescrBeginTableHeadRow;
  466. begin
  467. if not TableCaptionWritten then
  468. DescrEndTableCaption;
  469. TableRowStartFlag := True;
  470. end;
  471. procedure TLaTeXWriter.DescrEndTableHeadRow;
  472. begin
  473. WriteLn('\\ \hline');
  474. end;
  475. procedure TLaTeXWriter.DescrBeginTableRow;
  476. begin
  477. if not TableCaptionWritten then
  478. DescrEndTableCaption;
  479. TableRowStartFlag := True;
  480. end;
  481. procedure TLaTeXWriter.DescrEndTableRow;
  482. begin
  483. WriteLn('\\');
  484. end;
  485. procedure TLaTeXWriter.DescrBeginTableCell;
  486. begin
  487. if TableRowStartFlag then
  488. TableRowStartFlag := False
  489. else
  490. Write(' & ');
  491. end;
  492. procedure TLaTeXWriter.DescrEndTableCell;
  493. begin
  494. // Do nothing
  495. end;
  496. procedure TLaTeXWriter.WriteDescr(Element: TPasElement);
  497. var
  498. DocNode: TDocNode;
  499. begin
  500. DocNode := Engine.FindDocNode(Element);
  501. if Assigned(DocNode) then
  502. begin
  503. if not IsDescrNodeEmpty(DocNode.Descr) then
  504. WriteDescr(Element, DocNode.Descr)
  505. else if not IsDescrNodeEmpty(DocNode.ShortDescr) then
  506. WriteDescr(Element, DocNode.ShortDescr);
  507. end;
  508. end;
  509. procedure TLaTeXWriter.WriteDescr(AContext: TPasElement; DescrNode: TDOMElement);
  510. begin
  511. if Assigned(DescrNode) then
  512. ConvertDescr(AContext, DescrNode, False);
  513. end;
  514. function TLaTeXWriter.ConstValue(ConstDecl: TPasConst): String;
  515. begin
  516. if Assigned(ConstDecl) then
  517. Result := ConstDecl.ClassName
  518. else
  519. Result := '<nil>';
  520. end;
  521. procedure TLaTexWriter.WriteUnitOverview(ASection: TPasSection);
  522. var
  523. i: Integer;
  524. UnitRef: TPasType;
  525. DocNode: TDocNode;
  526. begin
  527. if ASection.UsesList.Count > 0 then
  528. begin
  529. WriteLnF('\section{%s}', [SDocUsedUnits]);
  530. WriteLnF('\begin{FPCltable}{lr}{%s}{%s:0units}',
  531. [Format(SDocUsedUnitsByUnitXY, [Module.Name]), ModuleName]);
  532. WriteLn('Name & Page \\ \hline');
  533. for i := 0 to ASection.UsesList.Count - 1 do
  534. begin
  535. UnitRef := TPasType(ASection.UsesList[i]);
  536. WriteLnF('%s\index{unit!%s} & \pageref{%s} \\',
  537. [UnitRef.Name, UnitRef.Name, GetLabel(UnitRef)]);
  538. end;
  539. WriteLn('\end{FPCltable}');
  540. end;
  541. DocNode := Engine.FindDocNode(ASection.Parent);
  542. if Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.Descr) then
  543. begin
  544. WriteLnF('\section{%s}', [SDocOverview]);
  545. WriteDescr(ASection.Parent, DocNode.Descr);
  546. Writeln('');
  547. end;
  548. end;
  549. procedure TLaTeXWriter.WriteResourceStrings(ASection: TPasSection);
  550. var
  551. ResStrDecl: TPasResString;
  552. i: Integer;
  553. begin
  554. if ASection.ResStrings.Count > 0 then
  555. begin
  556. StartSubSection(SDocResStrings,ModuleName+'ResStrings');
  557. for i := 0 to ASection.ResStrings.Count - 1 do
  558. begin
  559. ResStrDecl := TPasResString(ASection.ResStrings[i]);
  560. StartListing(false, '');
  561. Writeln(ResStrDecl.GetDeclaration(True));
  562. EndListing;
  563. WriteLabel(ResStrDecl);
  564. WriteIndex(ResStrDecl);
  565. WriteDescr(ResStrDecl);
  566. Writeln('');
  567. end;
  568. end;
  569. end;
  570. procedure TLaTeXWriter.WriteConsts(ASection: TPasSection);
  571. var
  572. i: Integer;
  573. ConstDecl: TPasConst;
  574. begin
  575. if ASection.Consts.Count > 0 then
  576. begin
  577. WriteLnF('\subsection{%s}\label{suse:%sConstants}',
  578. [SDocConstants, ModuleName]);
  579. for i := 0 to ASection.Consts.Count - 1 do
  580. begin
  581. ConstDecl := TPasConst(ASection.Consts[i]);
  582. StartListing(False);
  583. WriteLn(ConstDecl.GetDeclaration(True));
  584. EndListing;
  585. WriteLabel(ConstDecl);
  586. WriteIndex(ConstDecl);
  587. WriteDescr(ConstDecl);
  588. end;
  589. end;
  590. end;
  591. procedure TLaTeXWriter.WriteEnumElements(TypeDecl : TPasEnumType);
  592. Var
  593. EV : TPasEnumValue;
  594. I : Integer;
  595. DocNode : TDocNode;
  596. begin
  597. With TypeDecl do
  598. begin
  599. SortElementList(Values);
  600. DescrBeginTable(2,True);
  601. DescrBeginTableCaption;
  602. Writeln(Format(SDocValuesForEnum,[TypeDecl.Name]));
  603. DescrEndTableCaption;
  604. DescrBeginTableHeadRow;
  605. DescrBeginTableCell;
  606. Writeln(SDocValue);
  607. DescrEndTableCell;
  608. DescrBeginTableCell;
  609. Writeln(SDocExplanation);
  610. DescrEndTableCell;
  611. DescrEndTableHeadRow;
  612. For I:=0 to Values.Count-1 do
  613. begin
  614. EV:=TPasEnumValue(Values[i]);
  615. DescrBeginTableRow;
  616. DescrBeginTableCell;
  617. Writeln(EV.Name);
  618. DescrEndTableCell;
  619. DescrBeginTableCell;
  620. DocNode := Engine.FindDocNode(EV);
  621. if Assigned(DocNode) and (not IsDescrNodeEmpty(DocNode.ShortDescr)) then
  622. WriteDescr(EV,DocNode.ShortDescr);
  623. DescrEndTableCell;
  624. DescrEndTableRow;
  625. end;
  626. DescrEndTable;
  627. end;
  628. end;
  629. procedure TLaTeXWriter.WriteTypes(ASection: TPasSection);
  630. var
  631. i: Integer;
  632. TypeDecl: TPasType;
  633. begin
  634. if ASection.Types.Count > 0 then
  635. begin
  636. StartSubSection(SDocTypes,ModuleName+'Types');
  637. for i := 0 to ASection.Types.Count - 1 do
  638. begin
  639. TypeDecl := TPasType(ASection.Types[i]);
  640. StartListing(False);
  641. Writeln(TypeDecl.GetDeclaration(True));
  642. EndListing;
  643. WriteLabel(TypeDecl);
  644. WriteIndex(TypeDecl);
  645. If TypeDecl is TPasEnumType then
  646. begin
  647. WriteENumElements(TypeDecl as TPasEnumType);
  648. end;
  649. WriteDescr(TypeDecl);
  650. end;
  651. end;
  652. end;
  653. procedure TLaTeXWriter.WriteVars(ASection: TPasSection);
  654. var
  655. VarDecl: TPasVariable;
  656. i: Integer;
  657. begin
  658. if ASection.Variables.Count > 0 then
  659. begin
  660. StartSubsection(SDocVariables,ModuleName+'Variables');
  661. for i := 0 to ASection.Variables.Count - 1 do
  662. begin
  663. VarDecl := TPasVariable(ASection.Variables[i]);
  664. StartListing(False);
  665. WriteLn(VarDecl.GetDeclaration(True));
  666. EndListing;
  667. WriteLabel(VarDecl);
  668. WriteIndex(VarDecl);
  669. WriteDescr(VarDecl);
  670. end;
  671. end;
  672. end;
  673. procedure TLaTeXWriter.WriteVarsConstsTypes(ASection: TPasSection);
  674. begin
  675. With Asection do
  676. if (Consts.Count > 0) or
  677. (Types.Count > 0) or
  678. (Variables.Count > 0) or
  679. (ResStrings.Count>0) then
  680. begin
  681. StartSection(SDocConstsTypesVars, ModuleName+'ConstsTypesVars');
  682. WriteResourceStrings(ASection);
  683. WriteConsts(ASection);
  684. WriteTypes(ASection);
  685. WriteVars(ASection);
  686. end;
  687. end;
  688. const
  689. SVisibility: array[TPasMemberVisibility] of string =
  690. ('Default', 'Private', 'Protected', 'Public',
  691. 'Published', 'Automated');
  692. procedure TLatexWriter.WriteProcedure(ProcDecl : TPasProcedureBase);
  693. var
  694. DocNode: TDocNode;
  695. OP : TPasOverloadedProc;
  696. i : integer;
  697. begin
  698. With ProcDecl do
  699. begin
  700. if Not (Assigned(Parent) and Parent.InheritsFrom(TPasClassType)) then
  701. begin
  702. StartSubSection(Name);
  703. WriteLabel(ProcDecl);
  704. WriteIndex(ProcDecl);
  705. end
  706. else
  707. begin // Parent assigned and hence method.
  708. StartSubSection(Parent.Name+'.'+Name);
  709. WriteLabel(ProcDecl);
  710. WriteIndex(Parent.Name+'.'+Name);
  711. end;
  712. Writeln('\begin{FPCList}');
  713. DocNode := Engine.FindDocNode(ProcDecl);
  714. if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
  715. begin
  716. Writeln('\Synopsis');
  717. WriteDescr(ProcDecl, DocNode.ShortDescr);
  718. end;
  719. Writeln('\Declaration ');
  720. StartListing(False);
  721. if ClassType = TPasOverloadedProc then
  722. begin
  723. OP:=TPasOverloadedProc(ProcDecl);
  724. for i := 0 to OP.Overloads.Count - 1 do
  725. begin
  726. WriteLn(TPasProcedure(OP.Overloads[i]).GetDeclaration(True));
  727. end;
  728. end
  729. else
  730. WriteLn(GetDeclaration(True));
  731. EndListing;
  732. If Assigned(Parent) then
  733. begin
  734. Writeln('\Visibility');
  735. Writeln(VisibilityNames[Visibility])
  736. end;
  737. if Assigned(DocNode) and Assigned(DocNode.Descr) then
  738. begin
  739. Writeln('\Description');
  740. WriteDescr(ProcDecl);
  741. end;
  742. if Assigned(DocNode) and Assigned(DocNode.ErrorsDoc) then
  743. begin
  744. Writeln('\Errors');
  745. WriteDescr(ProcDecl, DocNode.ErrorsDoc);
  746. end;
  747. WriteSeeAlso(DocNode);
  748. Writeln('\end{FPCList}');
  749. WriteExample(DocNode);
  750. end;
  751. end;
  752. procedure TLaTeXWriter.WriteFunctionsAndProcedures(ASection: TPasSection);
  753. var
  754. i: Integer;
  755. begin
  756. if ASection.Functions.Count > 0 then
  757. begin
  758. StartSection(SDocProceduresAndFunctions,ModuleName+'Functions');
  759. for i := 0 to ASection.Functions.Count - 1 do
  760. WriteProcedure(TPasProcedureBase(ASection.Functions[i]));
  761. end;
  762. end;
  763. procedure TlatexWriter.WriteExample(ADocNode: TDocNode);
  764. var
  765. Example: TDOMElement;
  766. begin
  767. if Assigned(ADocNode) then
  768. begin
  769. Example := ADocNode.FirstExample;
  770. while Assigned(Example) do
  771. begin
  772. WritelnF('\FPCexample{%s}', [Engine.GetExampleFileName(Example)]);
  773. if Assigned(Example.NextSibling) then
  774. WriteLn('');
  775. Example := TDomElement(Example.NextSibling);
  776. end;
  777. end;
  778. end;
  779. procedure TLateXWriter.WriteSeeAlso(ADocNode: TDocNode);
  780. var
  781. Node: TDOMNode;
  782. s: String;
  783. begin
  784. if Assigned(ADocNode) and Assigned(ADocNode.SeeAlso) and
  785. Assigned(ADocNode.SeeAlso.FirstChild) then
  786. begin
  787. Writeln('\SeeAlso');
  788. Node := ADocNode.SeeAlso.FirstChild;
  789. while Assigned(Node) do
  790. begin
  791. if (Node.NodeType = ELEMENT_NODE) and
  792. (Node.NodeName = 'link') then
  793. begin
  794. S:=TDomElement(Node)['id'];
  795. DescrBeginLink(S);
  796. Writeln(S);
  797. DescrEndLink();
  798. if Assigned(Node.NextSibling) Then
  799. Writeln(',');
  800. end;
  801. Node:=Node.NextSibling;
  802. end;
  803. end;
  804. end;
  805. procedure TLaTeXWriter.WriteClasses(ASection: TPasSection);
  806. var
  807. i: Integer;
  808. begin
  809. if (ASection.Classes.Count > 0) then
  810. begin
  811. for i := 0 to ASection.Classes.Count - 1 do
  812. WriteClassDecl(TPasClassType(ASection.Classes[i]));
  813. end;
  814. end;
  815. procedure TLaTeXWriter.ProcessSection(ASection: TPasSection);
  816. begin
  817. With ASection do
  818. begin
  819. SortElementList(UsesList);
  820. SortElementList(Declarations);
  821. SortElementList(ResStrings);
  822. SortElementList(Types);
  823. SortElementList(Consts);
  824. SortElementList(Classes);
  825. SortElementList(Functions);
  826. SortElementList(Variables);
  827. end;
  828. WriteUnitOverView(ASection);
  829. WriteVarsConstsTypes(ASection);
  830. WriteFunctionsAndProcedures(ASection);
  831. WriteClasses(ASection);
  832. end;
  833. Function TLatexWriter.ShowMember(M : TPasElement) : boolean;
  834. begin
  835. Result:=not ((M.Visibility=visPrivate) and Engine.HidePrivate);
  836. If Result then
  837. Result:=Not ((M.Visibility=visProtected) and Engine.HideProtected)
  838. end;
  839. procedure TLatexWriter.WriteClassMethodOverview(ClassDecl : TPasClassType);
  840. var
  841. Member: TPasElement;
  842. i, j: Integer;
  843. s: String;
  844. Arg: TPasArgument;
  845. DocNode: TDocNode;
  846. Ref : String;
  847. List : TStringList;
  848. begin
  849. List:=TStringList.Create;
  850. Try
  851. List.Sorted:=True;
  852. for i := 0 to ClassDecl.Members.Count - 1 do
  853. begin
  854. Member := TPasElement(ClassDecl.Members[i]);
  855. With Member do
  856. if InheritsFrom(TPasProcedureBase) and ShowMember(Member) then
  857. List.AddObject(Member.Name,Member);
  858. end;
  859. If List.Count>0 then
  860. begin
  861. StartSubSection(SDocMethodOverview);
  862. WriteLabel(GetLabel(ClassDecl) + ':Methods');
  863. WriteLn('\begin{tabularx}{\textwidth}{llX}');
  864. WriteLnF('%s & %s & %s \\ \hline', [SDocPage, SDocMethod, SDocDescription]);
  865. For I:=0 to List.Count-1 do
  866. begin
  867. Member:=TPasElement(List.Objects[i]);
  868. DocNode := Engine.FindDocNode(Member);
  869. if Assigned(DocNode) and (Length(DocNode.Link) > 0) then
  870. ref:=Format('%s:%s',[Modulename,DocNode.link])
  871. else
  872. ref:=Format('%s:%s.%s',[ModuleName, LowerCase(ClassDecl.Name),LowerCase(Member.Name)]);
  873. WriteF('\pageref{%s} & %s & ',[GetLabel(Member), Member.Name]);
  874. if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
  875. WriteDescr(Member, DocNode.ShortDescr);
  876. WriteLn('\\');
  877. end;
  878. WriteLn('\hline');
  879. WriteLn('\end{tabularx}');
  880. end;
  881. Finally
  882. List.Free;
  883. end;
  884. end;
  885. procedure TLatexWriter.WriteClassPropertyOverview(ClassDecl : TPasClassType);
  886. var
  887. Member: TPasElement;
  888. i, j: Integer;
  889. s: String;
  890. Arg: TPasArgument;
  891. DocNode: TDocNode;
  892. List : TStringList;
  893. begin
  894. // Write property overview
  895. List:=TStringList.Create;
  896. Try
  897. List.Sorted:=True;
  898. for i := 0 to ClassDecl.Members.Count - 1 do
  899. begin
  900. Member := TPasElement(ClassDecl.Members[i]);
  901. With Member do
  902. if InheritsFrom(TPasProperty) and SHowMember(Member) then
  903. List.AddObject(Member.Name,Member)
  904. end;
  905. If (List.Count>0) then
  906. begin
  907. StartSubSection(SDocPropertyOverview);
  908. WriteLabel(GetLabel(ClassDecl) + ':Properties');
  909. WriteLn('\begin{tabularx}{\textwidth}{lllX}');
  910. WriteLnF('%s & %s & %s & %s \\ \hline',
  911. [SDocPage, SDocProperty, SDocAccess, SDocDescription]);
  912. For I:=0 to List.Count-1 do
  913. begin
  914. Member:=TPasElement(List.objects[i]);
  915. WriteF('\pageref{%s} & %s & ', [GetLabel(Member), Member.Name]);
  916. setlength(S,0);
  917. if Length(TPasProperty(Member).ReadAccessorName) > 0 then
  918. s := s + 'r';
  919. if Length(TPasProperty(Member).WriteAccessorName) > 0 then
  920. s := s + 'w';
  921. if Length(TPasProperty(Member).StoredAccessorName) > 0 then
  922. s := s + 's';
  923. Write(s + ' & ');
  924. DocNode := Engine.FindDocNode(Member);
  925. if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
  926. WriteDescr(Member, DocNode.ShortDescr);
  927. WriteLn('\\');
  928. end;
  929. WriteLn('\hline');
  930. WriteLn('\end{tabularx}');
  931. end;
  932. Finally
  933. List.Free;
  934. end;
  935. end;
  936. procedure TLaTeXWriter.WriteClassDecl(ClassDecl: TPasClassType);
  937. var
  938. DocNode: TDocNode;
  939. Vis: TPasMemberVisibilities;
  940. Member: TPasElement;
  941. i: Integer;
  942. begin
  943. StartSection(ClassDecl.Name);
  944. WriteLabel(ClassDecl);
  945. WriteIndex(ClassDecl);
  946. DocNode := Engine.FindDocNode(ClassDecl);
  947. if Assigned(DocNode) and ((not IsDescrNodeEmpty(DocNode.Descr)) or
  948. (not IsDescrNodeEmpty(DocNode.ShortDescr))) then
  949. begin
  950. StartSubSection(SDocDescription);
  951. WriteDescr(ClassDecl);
  952. end;
  953. // Write method overview
  954. WriteClassMethodOverView(ClassDecl);
  955. // Write Property Overview;
  956. WriteClassPropertyOverView(ClassDecl);
  957. // Write method & property descriptions
  958. // Determine visibilities
  959. Vis := AllVisibilities;
  960. if Engine.HidePrivate then
  961. Exclude(Vis,visPrivate);
  962. if Engine.HideProtected then
  963. Exclude(Vis,visProtected);
  964. for i := 0 to ClassDecl.Members.Count - 1 do
  965. begin
  966. Member := TPasElement(ClassDecl.Members[i]);
  967. if ((Member.InheritsFrom(TPasProcedureBase)) and
  968. (Member.Visibility in Vis)) then
  969. WriteProcedure(TPasProcedureBase(Member));
  970. end;
  971. // properties.
  972. for i := 0 to ClassDecl.Members.Count - 1 do
  973. begin
  974. Member := TPasElement(ClassDecl.Members[i]);
  975. if ((Member.InheritsFrom(TPasProperty)) and
  976. (Member.Visibility in Vis)) then
  977. WriteProperty(TPasProperty(Member));
  978. end;
  979. end;
  980. procedure TLaTexWriter.WriteProperty(PropDecl : TPasProperty);
  981. var
  982. DocNode: TDocNode;
  983. S: String;
  984. begin
  985. With PropDecl do
  986. begin
  987. StartSubSection(Parent.Name+'.'+Name);
  988. WriteLabel(PropDecl);
  989. WriteIndex(Parent.Name+'.'+Name);
  990. Writeln('\begin{FPCList}');
  991. DocNode := Engine.FindDocNode(PropDecl);
  992. if Assigned(DocNode) and Assigned(DocNode.ShortDescr) then
  993. begin
  994. Writeln('\Synopsis');
  995. WriteDescr(PropDecl, DocNode.ShortDescr);
  996. end;
  997. Writeln('\Declaration ');
  998. StartListing(False);
  999. WriteLn('Property '+GetDeclaration(True));
  1000. EndListing;
  1001. If Assigned(Parent) then
  1002. begin
  1003. Writeln('\Visibility');
  1004. Writeln(VisibilityNames[Visibility])
  1005. end;
  1006. Writeln('\Access');
  1007. Setlength(S,0);
  1008. If Length(ReadAccessorName) > 0 then
  1009. S:='Read';
  1010. if Length(WriteAccessorName) > 0 then
  1011. begin
  1012. If S<>'' then
  1013. S:=S+',';
  1014. S:=S+'Write';
  1015. end;
  1016. Writeln(S);
  1017. if Assigned(DocNode) and Assigned(DocNode.Descr) then
  1018. begin
  1019. Writeln('\Description');
  1020. WriteDescr(PropDecl);
  1021. end;
  1022. if Assigned(DocNode) and Assigned(DocNode.ErrorsDoc) then
  1023. begin
  1024. Writeln('\Errors');
  1025. WriteDescr(PropDecl, DocNode.ErrorsDoc);
  1026. end;
  1027. WriteSeeAlso(DocNode);
  1028. Writeln('\end{FPCList}');
  1029. WriteExample(DocNode);
  1030. end;
  1031. end;
  1032. Function CompareElements(P1,P2 : Pointer) : Integer;
  1033. begin
  1034. Result:=CompareText(TPasElement(P1).Name,TPasElement(P2).Name);
  1035. end;
  1036. procedure TLaTeXWriter.SortElementList(List : TList);
  1037. begin
  1038. List.Sort(@CompareElements)
  1039. end;
  1040. procedure TLaTeXWriter.WriteLabel(El: TPasElement);
  1041. begin
  1042. WriteLabel(GetLabel(El));
  1043. end;
  1044. procedure TLaTeXWriter.WriteLabel(const s: String);
  1045. begin
  1046. WriteLnF('\label{%s}', [LowerCase(s)]);
  1047. end;
  1048. procedure TLaTeXWriter.WriteIndex(El : TPasElement);
  1049. begin
  1050. WriteIndex(El.Name);
  1051. end;
  1052. procedure TLaTeXWriter.WriteIndex(const s : String);
  1053. begin
  1054. Write('\index{');
  1055. Write(s);
  1056. Writeln('}');
  1057. end;
  1058. procedure TLaTeXWriter.StartListing(Frames: Boolean; const name: String);
  1059. begin
  1060. if Not LaTexHighLight then
  1061. Writeln('\begin{verbatim}')
  1062. else
  1063. if Frames then
  1064. Writelnf('\begin{lstlisting}{%s}',[Name])
  1065. else
  1066. Writelnf('\begin{lstlisting}[frame=]{%s}',[Name]);
  1067. end;
  1068. procedure TLaTeXWriter.StartListing(Frames : Boolean);
  1069. begin
  1070. StartListing(Frames,'');
  1071. end;
  1072. procedure TLaTeXWriter.EndListing;
  1073. begin
  1074. If LaTexHighLight then
  1075. Writeln('\end{lstlisting}')
  1076. else
  1077. Writeln('\end{verbatim}')
  1078. end;
  1079. procedure TLatexWriter.WriteCommentLine;
  1080. const
  1081. CommentLine =
  1082. '%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%';
  1083. begin
  1084. Writeln(CommentLine);
  1085. end;
  1086. procedure TLatexWriter.WriteComment(Comment : String);
  1087. begin
  1088. Write('% ');
  1089. Writeln(Comment);
  1090. end;
  1091. procedure TLatexWriter.StartSection(SectionName : String; SectionLabel : String);
  1092. begin
  1093. StartSection(SectionName);
  1094. WriteLabel(SectionLabel);
  1095. end;
  1096. procedure TLatexWriter.StartSection(SectionName : String);
  1097. begin
  1098. Writeln('');
  1099. WriteCommentLine;
  1100. WriteComment(SectionName);
  1101. Writeln('\section{'+SectionName+'}');
  1102. end;
  1103. procedure TLatexWriter.StartSubSection(SubSectionName : String; SubSectionLabel : String);
  1104. begin
  1105. StartSubSection(SubSectionName);
  1106. WriteLabel(SubsectionLabel);
  1107. end;
  1108. procedure TLatexWriter.StartSubSection(SubSectionName : String);
  1109. begin
  1110. Writeln('');
  1111. WriteComment(SubsectionName);
  1112. Writeln('\subsection{'+SubSectionName+'}');
  1113. end;
  1114. procedure TLatexWriter.StartChapter(ChapterName : String; ChapterLabel : String);
  1115. begin
  1116. StartChapter(ChapterName);
  1117. WriteLabel(ChapterLabel);
  1118. end;
  1119. procedure TLatexWriter.StartChapter(ChapterName : String);
  1120. begin
  1121. Writeln('');
  1122. WriteCommentLine;
  1123. WriteComment(ChapterName);
  1124. WriteCommentLine;
  1125. Writeln('\chapter{'+ChapterName+'}');
  1126. end;
  1127. procedure CreateLaTeXDocForPackage(APackage: TPasPackage; AEngine: TFPDocEngine);
  1128. var
  1129. Writer: TLaTeXWriter;
  1130. begin
  1131. Writer := TLaTeXWriter.Create(APackage, AEngine);
  1132. try
  1133. Writer.WriteDoc;
  1134. finally
  1135. Writer.Free;
  1136. end;
  1137. end;
  1138. end.
  1139. {
  1140. $Log$
  1141. Revision 1.1 2003-03-17 23:03:20 michael
  1142. + Initial import in CVS
  1143. Revision 1.13 2003/03/13 22:02:13 sg
  1144. * New version with many bugfixes and our own parser (now independent of the
  1145. compiler source)
  1146. Revision 1.12 2002/10/20 22:49:31 michael
  1147. + Sorted all overviews. Added table with enumeration values for enumerated types.
  1148. Revision 1.11 2002/05/24 00:13:22 sg
  1149. * much improved new version, including many linking and output fixes
  1150. Revision 1.10 2002/03/12 10:58:36 sg
  1151. * reworked linking engine and internal structure
  1152. Revision 1.9 2002/01/20 11:19:55 michael
  1153. + Added link attribute and property to TFPElement
  1154. Revision 1.8 2002/01/08 13:00:06 michael
  1155. + Added correct array handling and syntax highlighting is now optional
  1156. Revision 1.7 2002/01/08 08:22:40 michael
  1157. + Implemented latex writer
  1158. Revision 1.6 2001/12/17 14:41:42 michael
  1159. + Split out of latex writer
  1160. Revision 1.5 2001/12/17 13:41:18 jonas
  1161. * OsPathSeparator -> PathDelim
  1162. }