dw_html.pp 98 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491
  1. {
  2. FPDoc - Free Pascal Documentation Tool
  3. Copyright (C) 2000 - 2005 by
  4. Areca Systems GmbH / Sebastian Guenther, [email protected]
  5. * HTML/XHTML output generator
  6. See the file COPYING, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. }
  12. {$mode objfpc}
  13. {$H+}
  14. unit dw_HTML;
  15. interface
  16. uses Classes, contnrs, DOM, DOM_HTML, dGlobals, PasTree, dWriter, ChmWriter, ChmBase;
  17. const
  18. // Subpage indices for modules
  19. ResstrSubindex = 1;
  20. ConstsSubindex = 2;
  21. TypesSubindex = 3;
  22. ClassesSubindex = 4;
  23. ProcsSubindex = 5;
  24. VarsSubindex = 6;
  25. // Maybe needed later for topic overview ??
  26. TopicsSubIndex = 7;
  27. IndexSubIndex = 8;
  28. // Subpage indices for classes
  29. PropertiesByInheritanceSubindex = 1;
  30. PropertiesByNameSubindex = 2;
  31. MethodsByInheritanceSubindex = 3;
  32. MethodsByNameSubindex = 4;
  33. EventsByInheritanceSubindex = 5;
  34. EventsByNameSubindex = 6;
  35. type
  36. TFileAllocator = class
  37. public
  38. procedure AllocFilename(AElement: TPasElement; ASubindex: Integer); virtual;
  39. function GetFilename(AElement: TPasElement;
  40. ASubindex: Integer): String; virtual; abstract;
  41. function GetRelativePathToTop(AElement: TPasElement): String; virtual;
  42. function GetCSSFilename(ARelativeTo: TPasElement): DOMString; virtual;
  43. end;
  44. TShortNameFileAllocator = class(TFileAllocator)
  45. private
  46. FExtension: String;
  47. public
  48. constructor Create(const AExtension: String);
  49. procedure AllocFilename(AElement: TPasElement; ASubindex: Integer); override;
  50. property Extension: String read FExtension;
  51. end;
  52. TLongNameFileAllocator = class(TFileAllocator)
  53. private
  54. FExtension: String;
  55. public
  56. constructor Create(const AExtension: String);
  57. function GetFilename(AElement: TPasElement;
  58. ASubindex: Integer): String; override;
  59. function GetRelativePathToTop(AElement: TPasElement): String; override;
  60. property Extension: String read FExtension;
  61. end;
  62. TPageInfo = class
  63. Element: TPasElement;
  64. SubpageIndex: Integer;
  65. end;
  66. { THTMLWriter }
  67. THTMLWriter = class(TFPDocWriter)
  68. private
  69. FOnTest: TNotifyEvent;
  70. FPackage: TPasPackage;
  71. FCharSet : String;
  72. function GetPageCount: Integer;
  73. procedure SetOnTest(const AValue: TNotifyEvent);
  74. protected
  75. FCSSFile: String;
  76. FAllocator: TFileAllocator;
  77. CurDirectory: String; // relative to curdir of process
  78. BaseDirectory: String; // relative path to package base directory
  79. PageInfos: TObjectList; // list of TPageInfo objects
  80. Doc: THTMLDocument;
  81. BodyElement, TitleElement: TDOMElement;
  82. Module: TPasModule;
  83. OutputNodeStack: TList;
  84. CurOutputNode: TDOMNode;
  85. InsideHeadRow, DoPasHighlighting: Boolean;
  86. HighlighterFlags: Byte;
  87. FooterFile: string;
  88. FIDF : Boolean;
  89. FDateFormat: String;
  90. FIndexColCount : Integer;
  91. FSearchPage : String;
  92. FBaseImageURL : String;
  93. Procedure CreateAllocator; virtual;
  94. function ResolveLinkID(const Name: String): DOMString;
  95. function ResolveLinkIDInUnit(const Name,AUnitName: String): DOMString;
  96. function ResolveLinkWithinPackage(AElement: TPasElement;
  97. ASubpageIndex: Integer): String;
  98. // Helper functions for creating DOM elements
  99. function CreateEl(Parent: TDOMNode; const AName: DOMString): THTMLElement;
  100. function CreatePara(Parent: TDOMNode): THTMLElement;
  101. function CreateH1(Parent: TDOMNode): THTMLElement;
  102. function CreateH2(Parent: TDOMNode): THTMLElement;
  103. function CreateH3(Parent: TDOMNode): THTMLElement;
  104. function CreateTable(Parent: TDOMNode; const AClass: DOMString = ''): THTMLElement;
  105. function CreateContentTable(Parent: TDOMNode): THTMLElement;
  106. function CreateTR(Parent: TDOMNode): THTMLElement;
  107. function CreateTD(Parent: TDOMNode): THTMLElement;
  108. function CreateTD_vtop(Parent: TDOMNode): THTMLElement;
  109. function CreateLink(Parent: TDOMNode; const AHRef: DOMString): THTMLElement;
  110. function CreateAnchor(Parent: TDOMNode; const AName: DOMString): THTMLElement;
  111. function CreateCode(Parent: TDOMNode): THTMLElement;
  112. function CreateWarning(Parent: TDOMNode): THTMLElement;
  113. // Description node conversion
  114. procedure PushOutputNode(ANode: TDOMNode);
  115. procedure PopOutputNode;
  116. procedure DescrWriteText(const AText: DOMString); override;
  117. procedure DescrBeginBold; override;
  118. procedure DescrEndBold; override;
  119. procedure DescrBeginItalic; override;
  120. procedure DescrEndItalic; override;
  121. procedure DescrBeginEmph; override;
  122. procedure DescrEndEmph; override;
  123. procedure DescrWriteImageEl(const AFileName, ACaption, ALinkName : DOMString); override;
  124. procedure DescrWriteFileEl(const AText: DOMString); override;
  125. procedure DescrWriteKeywordEl(const AText: DOMString); override;
  126. procedure DescrWriteVarEl(const AText: DOMString); override;
  127. procedure DescrBeginLink(const AId: DOMString); override;
  128. procedure DescrEndLink; override;
  129. procedure DescrBeginURL(const AURL: DOMString); override;
  130. procedure DescrEndURL; override;
  131. procedure DescrWriteLinebreak; override;
  132. procedure DescrBeginParagraph; override;
  133. procedure DescrEndParagraph; override;
  134. procedure DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String); override;
  135. procedure DescrWriteCodeLine(const ALine: String); override;
  136. procedure DescrEndCode; override;
  137. procedure DescrBeginOrderedList; override;
  138. procedure DescrEndOrderedList; override;
  139. procedure DescrBeginUnorderedList; override;
  140. procedure DescrEndUnorderedList; override;
  141. procedure DescrBeginDefinitionList; override;
  142. procedure DescrEndDefinitionList; override;
  143. procedure DescrBeginListItem; override;
  144. procedure DescrEndListItem; override;
  145. procedure DescrBeginDefinitionTerm; override;
  146. procedure DescrEndDefinitionTerm; override;
  147. procedure DescrBeginDefinitionEntry; override;
  148. procedure DescrEndDefinitionEntry; override;
  149. procedure DescrBeginSectionTitle; override;
  150. procedure DescrBeginSectionBody; override;
  151. procedure DescrEndSection; override;
  152. procedure DescrBeginRemark; override;
  153. procedure DescrEndRemark; override;
  154. procedure DescrBeginTable(ColCount: Integer; HasBorder: Boolean); override;
  155. procedure DescrEndTable; override;
  156. procedure DescrBeginTableCaption; override;
  157. procedure DescrEndTableCaption; override;
  158. procedure DescrBeginTableHeadRow; override;
  159. procedure DescrEndTableHeadRow; override;
  160. procedure DescrBeginTableRow; override;
  161. procedure DescrEndTableRow; override;
  162. procedure DescrBeginTableCell; override;
  163. procedure DescrEndTableCell; override;
  164. procedure AppendText(Parent: TDOMNode; const AText: DOMString);
  165. procedure AppendNbSp(Parent: TDOMNode; ACount: Integer);
  166. procedure AppendSym(Parent: TDOMNode; const AText: DOMString);
  167. procedure AppendKw(Parent: TDOMNode; const AText: DOMString);
  168. function AppendPasSHFragment(Parent: TDOMNode; const AText: String;
  169. AShFlags: Byte): Byte;
  170. Procedure AppendShortDescr(AContext : TPasElement;Parent: TDOMNode; DocNode : TDocNode);
  171. procedure AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
  172. procedure AppendShortDescrCell(Parent: TDOMNode; Element: TPasElement);
  173. procedure AppendDescr(AContext: TPasElement; Parent: TDOMNode;
  174. DescrNode: TDOMElement; AutoInsertBlock: Boolean);
  175. procedure AppendDescrSection(AContext: TPasElement; Parent: TDOMNode;
  176. DescrNode: TDOMElement; const ATitle: DOMString);
  177. function AppendHyperlink(Parent: TDOMNode; Element: TPasElement): TDOMElement;
  178. function AppendType(CodeEl, TableEl: TDOMElement;
  179. Element: TPasType; Expanded: Boolean;
  180. NestingLevel: Integer = 0): TDOMElement;
  181. function AppendProcType(CodeEl, TableEl: TDOMElement;
  182. Element: TPasProcedureType; Indent: Integer): TDOMElement;
  183. procedure AppendProcExt(CodeEl: TDOMElement; Element: TPasProcedure);
  184. procedure AppendProcDecl(CodeEl, TableEl: TDOMElement;
  185. Element: TPasProcedureBase);
  186. procedure AppendProcArgsSection(Parent: TDOMNode;
  187. Element: TPasProcedureType);
  188. function AppendRecordType(CodeEl, TableEl: TDOMElement;
  189. Element: TPasRecordType; NestingLevel: Integer): TDOMElement;
  190. procedure AppendTitle(const AText: DOMString);
  191. procedure AppendMenuBar(ASubpageIndex: Integer);
  192. procedure AppendTopicMenuBar(Topic : TTopicElement);
  193. procedure AppendSourceRef(AElement: TPasElement);
  194. procedure FinishElementPage(AElement: TPasElement);
  195. Procedure AppendSeeAlsoSection(AElement : TPasElement;DocNode : TDocNode);
  196. Procedure AppendExampleSection(AElement : TPasElement;DocNode : TDocNode);
  197. procedure AppendFooter;
  198. procedure CreateIndexPage(L : TStringList);
  199. procedure CreateModuleIndexPage(AModule: TPasModule);
  200. procedure CreatePageBody(AElement: TPasElement; ASubpageIndex: Integer); virtual;
  201. procedure CreatePackagePageBody;
  202. procedure CreatePackageIndex;
  203. procedure AddModuleIdentifiers(AModule : TPasModule; L : TStrings);
  204. Procedure CreateTopicPageBody(AElement : TTopicElement);
  205. procedure CreateModulePageBody(AModule: TPasModule; ASubpageIndex: Integer);
  206. procedure CreateConstPageBody(AConst: TPasConst);
  207. procedure CreateTypePageBody(AType: TPasType);
  208. procedure CreateClassPageBody(AClass: TPasClassType; ASubpageIndex: Integer);
  209. procedure CreateClassMemberPageBody(AElement: TPasElement);
  210. procedure CreateVarPageBody(AVar: TPasVariable);
  211. procedure CreateProcPageBody(AProc: TPasProcedureBase);
  212. Procedure CreateTopicLinks(Node : TDocNode; PasElement : TPasElement);
  213. public
  214. constructor Create(APackage: TPasPackage; AEngine: TFPDocEngine); override;
  215. destructor Destroy; override;
  216. // Single-page generation
  217. function CreateHTMLPage(AElement: TPasElement;
  218. ASubpageIndex: Integer): TXMLDocument;
  219. function CreateXHTMLPage(AElement: TPasElement;
  220. ASubpageIndex: Integer): TXMLDocument;
  221. // For producing complete package documentation
  222. procedure WriteHTMLPages; virtual;
  223. procedure WriteXHTMLPages;
  224. Function InterPretOption(Const Cmd,Arg : String) : boolean; override;
  225. Procedure WriteDoc; override;
  226. class procedure Usage(List: TStrings); override;
  227. Property SearchPage: String Read FSearchPage Write FSearchPage;
  228. property Allocator: TFileAllocator read FAllocator;
  229. property Package: TPasPackage read FPackage;
  230. property PageCount: Integer read GetPageCount;
  231. Property IncludeDateInFooter : Boolean Read FIDF Write FIDF;
  232. Property DateFormat : String Read FDateFormat Write FDateFormat;
  233. property OnTest: TNotifyEvent read FOnTest write SetOnTest;
  234. Property CharSet : String Read FCharSet Write FCharSet;
  235. Property IndexColCount : Integer Read FIndexColCount write FIndexColCount;
  236. Property BaseImageURL : String Read FBaseImageURL Write FBaseImageURL;
  237. end;
  238. THTMWriter = class(THTMLWriter)
  239. Protected
  240. Procedure CreateAllocator; override;
  241. end;
  242. {$DEFINE chmInterface}
  243. {$I dw_htmlchm.inc}
  244. {$UNDEF chmInterface}
  245. implementation
  246. uses SysUtils, XHTML, XMLRead, XMLWrite, HTMWrite, sh_pas,chmsitemap;
  247. Function FixHTMLpath(S : String) : STring;
  248. begin
  249. Result:=StringReplace(S,'\','/',[rfReplaceAll]);
  250. end;
  251. {$I dw_htmlchm.inc}
  252. procedure TFileAllocator.AllocFilename(AElement: TPasElement;
  253. ASubindex: Integer);
  254. begin
  255. end;
  256. function TFileAllocator.GetRelativePathToTop(AElement: TPasElement): String;
  257. begin
  258. SetLength(Result, 0);
  259. end;
  260. function TFileAllocator.GetCSSFilename(ARelativeTo: TPasElement): DOMString;
  261. begin
  262. Result := GetRelativePathToTop(ARelativeTo) + 'fpdoc.css';
  263. end;
  264. constructor TShortNameFileAllocator.Create(const AExtension: String);
  265. begin
  266. inherited Create;
  267. FExtension := AExtension;
  268. end;
  269. procedure TShortNameFileAllocator.AllocFilename(AElement: TPasElement;
  270. ASubindex: Integer);
  271. begin
  272. // !!!: Add element to file list
  273. end;
  274. constructor TLongNameFileAllocator.Create(const AExtension: String);
  275. begin
  276. inherited Create;
  277. FExtension := AExtension;
  278. end;
  279. function TLongNameFileAllocator.GetFilename(AElement: TPasElement;
  280. ASubindex: Integer): String;
  281. var
  282. s: String;
  283. i: Integer;
  284. begin
  285. if AElement.ClassType = TPasPackage then
  286. Result := 'index'
  287. else if AElement.ClassType = TPasModule then
  288. Result := LowerCase(AElement.Name) + PathDelim + 'index'
  289. else
  290. begin
  291. if AElement is TPasOperator then
  292. begin
  293. Result := LowerCase(AElement.Parent.PathName) + '.op-';
  294. s := Copy(AElement.Name, Pos(' ', AElement.Name) + 1, Length(AElement.Name));
  295. s := Copy(s, 1, Pos('(', s) - 1);
  296. if s = ':=' then
  297. s := 'assign'
  298. else if s = '+' then
  299. s := 'add'
  300. else if s = '-' then
  301. s := 'sub'
  302. else if s = '*' then
  303. s := 'mul'
  304. else if s = '/' then
  305. s := 'div'
  306. else if s = '**' then
  307. s := 'power'
  308. else if s = '=' then
  309. s := 'equal'
  310. else if s = '<>' then
  311. s := 'unequal'
  312. else if s = '<' then
  313. s := 'less'
  314. else if s = '<=' then
  315. s := 'lessequal'
  316. else if s = '>' then
  317. s := 'greater'
  318. else if s = '>=' then
  319. s := 'greaterthan'
  320. else if s = '><' then
  321. s := 'symmetricdifference';
  322. Result := Result + s + '-';
  323. s := '';
  324. i := 1;
  325. while AElement.Name[i] <> '(' do
  326. Inc(i);
  327. Inc(i);
  328. while AElement.Name[i] <> ')' do
  329. begin
  330. if AElement.Name[i] = ',' then
  331. begin
  332. s := s + '-';
  333. Inc(i);
  334. end else
  335. s := s + AElement.Name[i];
  336. Inc(i);
  337. end;
  338. Result := Result + LowerCase(s) + '-' + LowerCase(Copy(AElement.Name,
  339. Pos('):', AElement.Name) + 3, Length(AElement.Name)));
  340. end else
  341. Result := LowerCase(AElement.PathName);
  342. i := 1;
  343. if (Length(Result) > 0) and (Result[1] = '#') then
  344. begin
  345. while Result[i] <> '.' do
  346. Inc(i);
  347. Result := Copy(Result, i + 1, Length(Result));
  348. end;
  349. i := 1;
  350. while (i <= Length(Result)) and (Result[i] <> '.') do
  351. Inc(i);
  352. if (i <= Length(Result)) and (i > 0) then
  353. Result[i] := PathDelim;
  354. end;
  355. if ASubindex > 0 then
  356. Result := Result + '-' + IntToStr(ASubindex);
  357. Result := Result + Extension;
  358. end;
  359. function TLongNameFileAllocator.GetRelativePathToTop(AElement: TPasElement): String;
  360. begin
  361. if (AElement.ClassType=TPasPackage) then
  362. Result := ''
  363. else if (AElement.ClassType=TTopicElement) then
  364. begin
  365. If (AElement.Parent.ClassType=TTopicElement) then
  366. Result:='../'+GetRelativePathToTop(AElement.Parent)
  367. else if (AElement.Parent.ClassType=TPasPackage) then
  368. Result:=''
  369. else if (AElement.Parent.ClassType=TPasModule) then
  370. Result:='../';
  371. end
  372. else
  373. Result := '../';
  374. end;
  375. Type
  376. { TLinkData }
  377. TLinkData = Class(TObject)
  378. FPathName,
  379. FLink,
  380. FModuleName : String;
  381. Constructor Create(Const APathName,ALink,AModuleName : string);
  382. end;
  383. { TLinkData }
  384. constructor TLinkData.Create(Const APathName, ALink, AModuleName: string);
  385. begin
  386. FPathName:=APathName;
  387. FLink:=ALink;
  388. FModuleName:=AModuleName;
  389. end;
  390. constructor THTMLWriter.Create(APackage: TPasPackage; AEngine: TFPDocEngine);
  391. procedure AddPage(AElement: TPasElement; ASubpageIndex: Integer);
  392. var
  393. PageInfo: TPageInfo;
  394. begin
  395. PageInfo := TPageInfo.Create;
  396. PageInfo.Element := AElement;
  397. PageInfo.SubpageIndex := ASubpageIndex;
  398. PageInfos.Add(PageInfo);
  399. Allocator.AllocFilename(AElement, ASubpageIndex);
  400. if ASubpageIndex = 0 then
  401. Engine.AddLink(AElement.PathName,
  402. Allocator.GetFilename(AElement, ASubpageIndex));
  403. end;
  404. procedure AddTopicPages(AElement: TPasElement);
  405. var
  406. PreviousTopic,
  407. TopicElement : TTopicElement;
  408. PageInfo : TPageInfo;
  409. DocNode,
  410. TopicNode : TDocNode;
  411. begin
  412. DocNode:=Engine.FindDocNode(AElement);
  413. If not Assigned(DocNode) then
  414. exit;
  415. TopicNode:=DocNode.FirstChild;
  416. PreviousTopic:=Nil;
  417. While Assigned(TopicNode) do
  418. begin
  419. If TopicNode.TopicNode then
  420. begin
  421. TopicElement:=TTopicElement.Create(TopicNode.Name,AElement);
  422. Topics.Add(TopicElement);
  423. TopicElement.TopicNode:=TopicNode;
  424. TopicElement.Previous:=PreviousTopic;
  425. If Assigned(PreviousTopic) then
  426. PreviousTopic.Next:=TopicElement;
  427. PreviousTopic:=TopicElement;
  428. if AElement is TTopicElement then
  429. TTopicElement(AElement).SubTopics.Add(TopicElement);
  430. PageInfo := TPageInfo.Create;
  431. PageInfo.Element := TopicElement;
  432. PageInfo.SubpageIndex := 0;
  433. PageInfos.Add(PageInfo);
  434. Allocator.AllocFilename(TopicElement,0);
  435. Engine.AddLink(TopicElement.PathName, Allocator.GetFilename(TopicElement,0));
  436. if AElement is TTopicElement then
  437. TTopicElement(AElement).SubTopics.Add(TopicElement)
  438. else // Only one level of recursion.
  439. AddTopicPages(TopicElement);
  440. end;
  441. TopicNode:=TopicNode.NextSibling;
  442. end;
  443. end;
  444. procedure AddPages(AElement: TPasElement; ASubpageIndex: Integer;
  445. AList: TFPList);
  446. var
  447. i: Integer;
  448. begin
  449. if AList.Count > 0 then
  450. begin
  451. AddPage(AElement, ASubpageIndex);
  452. for i := 0 to AList.Count - 1 do
  453. AddPage(TPasElement(AList[i]), 0);
  454. end;
  455. end;
  456. procedure ScanModule(AModule: TPasModule; LinkList : TObjectList);
  457. var
  458. i, j, k: Integer;
  459. s: String;
  460. ClassEl: TPasClassType;
  461. FPEl, AncestorMemberEl: TPasElement;
  462. DocNode: TDocNode;
  463. ALink : DOMString;
  464. DidAutolink: Boolean;
  465. begin
  466. AddPage(AModule, 0);
  467. AddPage(AModule,IndexSubIndex);
  468. AddTopicPages(AModule);
  469. with AModule do
  470. begin
  471. if InterfaceSection.ResStrings.Count > 0 then
  472. begin
  473. AddPage(AModule, ResstrSubindex);
  474. s := Allocator.GetFilename(AModule, ResstrSubindex);
  475. for i := 0 to InterfaceSection.ResStrings.Count - 1 do
  476. with TPasResString(InterfaceSection.ResStrings[i]) do
  477. Engine.AddLink(PathName, s + '#' + LowerCase(Name));
  478. end;
  479. AddPages(AModule, ConstsSubindex, InterfaceSection.Consts);
  480. AddPages(AModule, TypesSubindex, InterfaceSection.Types);
  481. if InterfaceSection.Classes.Count > 0 then
  482. begin
  483. AddPage(AModule, ClassesSubindex);
  484. for i := 0 to InterfaceSection.Classes.Count - 1 do
  485. begin
  486. ClassEl := TPasClassType(InterfaceSection.Classes[i]);
  487. AddPage(ClassEl, 0);
  488. // !!!: Only add when there are items
  489. AddPage(ClassEl, PropertiesByInheritanceSubindex);
  490. AddPage(ClassEl, PropertiesByNameSubindex);
  491. AddPage(ClassEl, MethodsByInheritanceSubindex);
  492. AddPage(ClassEl, MethodsByNameSubindex);
  493. AddPage(ClassEl, EventsByInheritanceSubindex);
  494. AddPage(ClassEl, EventsByNameSubindex);
  495. for j := 0 to ClassEl.Members.Count - 1 do
  496. begin
  497. FPEl := TPasElement(ClassEl.Members[j]);
  498. if ((FPEl.Visibility = visPrivate) and Engine.HidePrivate) or
  499. ((FPEl.Visibility = visProtected) and Engine.HideProtected) then
  500. continue;
  501. DocNode := Engine.FindDocNode(FPEl);
  502. if Assigned(DocNode) then
  503. begin
  504. if Assigned(DocNode.Node) then
  505. ALink:=DocNode.Node['link']
  506. else
  507. ALink:='';
  508. If (ALink<>'') then
  509. LinkList.Add(TLinkData.Create(FPEl.PathName,ALink,AModule.name))
  510. else
  511. AddPage(FPEl, 0);
  512. end
  513. else
  514. begin
  515. DidAutolink := False;
  516. if Assigned(ClassEl.AncestorType) and
  517. (ClassEl.AncestorType.ClassType = TPasClassType) then
  518. begin
  519. for k := 0 to TPasClassType(ClassEl.AncestorType).Members.Count - 1 do
  520. begin
  521. AncestorMemberEl :=
  522. TPasElement(TPasClassType(ClassEl.AncestorType).Members[k]);
  523. if AncestorMemberEl.Name = FPEl.Name then
  524. begin
  525. DocNode := Engine.FindDocNode(AncestorMemberEl);
  526. if Assigned(DocNode) then
  527. begin
  528. DidAutolink := True;
  529. Engine.AddLink(FPEl.PathName,
  530. Engine.FindAbsoluteLink(AncestorMemberEl.PathName));
  531. break;
  532. end;
  533. end;
  534. end;
  535. end;
  536. if not DidAutolink then
  537. AddPage(FPEl, 0);
  538. end;
  539. end;
  540. end;
  541. end;
  542. AddPages(AModule, ProcsSubindex, InterfaceSection.Functions);
  543. AddPages(AModule, VarsSubindex, InterfaceSection.Variables);
  544. end;
  545. end;
  546. var
  547. i: Integer;
  548. L : TObjectList;
  549. begin
  550. inherited ;
  551. IndexColCount:=3;
  552. Charset:='iso-8859-1';
  553. CreateAllocator;
  554. FPackage := APackage;
  555. OutputNodeStack := TList.Create;
  556. PageInfos := TObjectList.Create;
  557. // Allocate page for the package itself, if a name is given (i.e. <> '#')
  558. if Length(Package.Name) > 1 then
  559. begin
  560. AddPage(Package, 0);
  561. AddPage(Package,IndexSubIndex);
  562. AddTopicPages(Package);
  563. end;
  564. L:=TObjectList.Create;
  565. try
  566. for i := 0 to Package.Modules.Count - 1 do
  567. ScanModule(TPasModule(Package.Modules[i]),L);
  568. // Resolve links
  569. For I:=0 to L.Count-1 do
  570. With TLinkData(L[i]) do
  571. Engine.AddLink(FPathName,ResolveLinkIDInUnit(FLink,FModuleName));
  572. finally
  573. L.Free;
  574. end;
  575. end;
  576. destructor THTMLWriter.Destroy;
  577. begin
  578. PageInfos.Free;
  579. OutputNodeStack.Free;
  580. FAllocator.Free;
  581. inherited Destroy;
  582. end;
  583. function THTMLWriter.CreateHTMLPage(AElement: TPasElement;
  584. ASubpageIndex: Integer): TXMLDocument;
  585. var
  586. HTMLEl: THTMLHtmlElement;
  587. HeadEl: THTMLHeadElement;
  588. El: TDOMElement;
  589. begin
  590. Doc := THTMLDocument.Create;
  591. Result := Doc;
  592. Doc.AppendChild(Doc.Impl.CreateDocumentType(
  593. 'HTML', '-//W3C//DTD HTML 4.01 Transitional//EN',
  594. 'http://www.w3.org/TR/html4/loose.dtd'));
  595. HTMLEl := Doc.CreateHtmlElement;
  596. Doc.AppendChild(HTMLEl);
  597. HeadEl := Doc.CreateHeadElement;
  598. HTMLEl.AppendChild(HeadEl);
  599. El := Doc.CreateElement('meta');
  600. HeadEl.AppendChild(El);
  601. El['http-equiv'] := 'Content-Type';
  602. El['content'] := 'text/html; charset=utf-8';
  603. TitleElement := Doc.CreateElement('title');
  604. HeadEl.AppendChild(TitleElement);
  605. El := Doc.CreateElement('link');
  606. BodyElement := Doc.CreateElement('body');
  607. HTMLEl.AppendChild(BodyElement);
  608. CreatePageBody(AElement, ASubpageIndex);
  609. AppendFooter;
  610. HeadEl.AppendChild(El);
  611. El['rel'] := 'stylesheet';
  612. El['type'] := 'text/css';
  613. El['href'] := FixHtmlPath(Allocator.GetCSSFilename(AElement));
  614. end;
  615. function THTMLWriter.CreateXHTMLPage(AElement: TPasElement;
  616. ASubpageIndex: Integer): TXMLDocument;
  617. begin
  618. Result := nil;
  619. end;
  620. procedure CreatePath(const AFilename: String);
  621. var
  622. EndIndex: Integer;
  623. Path: String;
  624. begin
  625. EndIndex := Length(AFilename);
  626. if EndIndex = 0 then
  627. exit;
  628. while not (AFilename[EndIndex] in AllowDirectorySeparators) do
  629. begin
  630. Dec(EndIndex);
  631. if EndIndex = 0 then
  632. exit;
  633. end;
  634. Path := Copy(AFilename, 1, EndIndex - 1);
  635. if not DirectoryExists(Path) then
  636. begin
  637. CreatePath(Path);
  638. MkDir(Path);
  639. end;
  640. end;
  641. procedure THTMLWriter.WriteHTMLPages;
  642. var
  643. i: Integer;
  644. PageDoc: TXMLDocument;
  645. Filename: String;
  646. TempStream: TMemoryStream;
  647. begin
  648. if Engine.Output <> '' then
  649. Engine.Output := IncludeTrailingBackSlash(Engine.Output);
  650. for i := 0 to PageInfos.Count - 1 do
  651. with TPageInfo(PageInfos[i]) do
  652. begin
  653. PageDoc := CreateHTMLPage(Element, SubpageIndex);
  654. try
  655. Filename := Engine.Output + Allocator.GetFilename(Element, SubpageIndex);
  656. try
  657. CreatePath(Filename);
  658. WriteHTMLFile(PageDoc, Filename);
  659. except
  660. on E: Exception do
  661. DoLog(SErrCouldNotCreateFile, [FileName, e.Message]);
  662. end;
  663. finally
  664. PageDoc.Free;
  665. end;
  666. end;
  667. if FCSSFile <> '' then
  668. begin
  669. if not FileExists(FCSSFile) Then
  670. begin
  671. DoLog('Can''t find CSS file "%s"',[FCSSFILE]);
  672. halt(1);
  673. end;
  674. TempStream := TMemoryStream.Create;
  675. TempStream.LoadFromFile(FCSSFile);
  676. TempStream.Position := 0;
  677. TempStream.SaveToFile(Engine.output+ExtractFileName(FCSSFile));
  678. TempStream.Free;
  679. end;
  680. end;
  681. procedure THTMLWriter.WriteXHTMLPages;
  682. begin
  683. end;
  684. {procedure THTMLWriter.CreateDoc(const ATitle: DOMString;
  685. AElement: TPasElement; const AFilename: String);
  686. var
  687. El: TDOMElement;
  688. DocInfo: TDocInfo;
  689. CSSName: String;
  690. begin
  691. Doc := TXHTMLDocument.Create;
  692. with TXHTMLDocument(Doc) do
  693. begin
  694. Encoding := 'ISO8859-1';
  695. CSSName := 'fpdoc.css';
  696. if Assigned(Module) then
  697. CSSName := '../' + CSSName;
  698. $IFNDEF ver1_0
  699. StylesheetType := 'text/css';
  700. StylesheetHRef := CSSName;
  701. $ENDIF
  702. CreateRoot(xhtmlStrict);
  703. with RequestHeadElement do
  704. begin
  705. AppendText(RequestTitleElement, ATitle);
  706. El := CreateElement('link');
  707. AppendChild(El);
  708. El['rel'] := 'stylesheet';
  709. El['type'] := 'text/css';
  710. El['href'] := FixHtmlPath(CSSName);
  711. end;
  712. Self.BodyElement := RequestBodyElement('en');
  713. end;
  714. if Length(AFilename) > 0 then
  715. begin
  716. DocInfo := TDocInfo.Create;
  717. DocInfos.Add(DocInfo);
  718. DocInfo.Element := AElement;
  719. DocInfo.Filename := AFilename;
  720. end;
  721. end;
  722. }
  723. { Used for:
  724. - <link> elements in descriptions
  725. - "see also" entries
  726. - AppendHyperlink (for unresolved parse tree element links)
  727. }
  728. function THTMLWriter.ResolveLinkIDInUnit(const Name,AUnitName: String): DOMString;
  729. begin
  730. Result:=ResolveLinkID(Name);
  731. If (Result='') and (AUnitName<>'') then
  732. Result:=ResolveLinkID(AUnitName+'.'+Name);
  733. end;
  734. function THTMLWriter.ResolveLinkID(const Name: String): DOMString;
  735. var
  736. i: Integer;
  737. ThisPackage: TLinkNode;
  738. begin
  739. if Length(Name) = 0 then
  740. begin
  741. SetLength(Result, 0);
  742. exit;
  743. end;
  744. if Name[1] = '#' then
  745. Result := Engine.FindAbsoluteLink(Name)
  746. else
  747. begin
  748. SetLength(Result, 0);
  749. { Try all packages }
  750. ThisPackage := Engine.RootLinkNode.FirstChild;
  751. while Assigned(ThisPackage) do
  752. begin
  753. Result := Engine.FindAbsoluteLink(ThisPackage.Name + '.' + Name);
  754. if Length(Result) = 0 then
  755. begin
  756. if Assigned(Module) then
  757. begin
  758. Result := Engine.FindAbsoluteLink(Module.PathName + '.' + Name);
  759. // WriteLn('Searching for ', Module.PathName + '.' + Name, ' => ', Result);
  760. end;
  761. if Length(Result) = 0 then
  762. for i := Length(Name) downto 1 do
  763. if Name[i] = '.' then
  764. begin
  765. Result := ResolveLinkID(Copy(Name, 1, i - 1));
  766. exit;
  767. end;
  768. end;
  769. ThisPackage := ThisPackage.NextSibling;
  770. end;
  771. end;
  772. if Length(Result) > 0 then
  773. if Copy(Result, 1, Length(CurDirectory) + 1) = CurDirectory + '/' then
  774. Result := Copy(Result, Length(CurDirectory) + 2, Length(Result))
  775. else if not IsLinkAbsolute(Result) then
  776. Result := BaseDirectory + Result;
  777. end;
  778. function THTMLWriter.ResolveLinkWithinPackage(AElement: TPasElement;
  779. ASubpageIndex: Integer): String;
  780. var
  781. ParentEl: TPasElement;
  782. begin
  783. ParentEl := AElement;
  784. while Assigned(ParentEl) and not (ParentEl.ClassType = TPasPackage) do
  785. ParentEl := ParentEl.Parent;
  786. if Assigned(ParentEl) and (TPasPackage(ParentEl) = Engine.Package) then
  787. begin
  788. Result := Allocator.GetFilename(AElement, ASubpageIndex);
  789. if Copy(Result, 1, Length(CurDirectory) + 1) = CurDirectory + '/' then
  790. Result := Copy(Result, Length(CurDirectory) + 2, Length(Result))
  791. else
  792. Result := BaseDirectory + Result;
  793. end else
  794. SetLength(Result, 0);
  795. end;
  796. function THTMLWriter.CreateEl(Parent: TDOMNode;
  797. const AName: DOMString): THTMLElement;
  798. begin
  799. Result := Doc.CreateElement(AName);
  800. Parent.AppendChild(Result);
  801. end;
  802. function THTMLWriter.CreatePara(Parent: TDOMNode): THTMLElement;
  803. begin
  804. Result := CreateEl(Parent, 'p');
  805. end;
  806. function THTMLWriter.CreateH1(Parent: TDOMNode): THTMLElement;
  807. begin
  808. Result := CreateEl(Parent, 'h1');
  809. end;
  810. function THTMLWriter.CreateH2(Parent: TDOMNode): THTMLElement;
  811. begin
  812. Result := CreateEl(Parent, 'h2');
  813. end;
  814. function THTMLWriter.CreateH3(Parent: TDOMNode): THTMLElement;
  815. begin
  816. Result := CreateEl(Parent, 'h3');
  817. end;
  818. function THTMLWriter.CreateTable(Parent: TDOMNode; const AClass: DOMString = ''): THTMLElement;
  819. begin
  820. Result := CreateEl(Parent, 'table');
  821. Result['cellspacing'] := '0';
  822. Result['cellpadding'] := '0';
  823. if AClass <> '' then
  824. Result['class'] := AClass;
  825. end;
  826. function THTMLWriter.CreateContentTable(Parent: TDOMNode): THTMLElement;
  827. begin
  828. Result := CreateEl(Parent, 'table');
  829. end;
  830. function THTMLWriter.CreateTR(Parent: TDOMNode): THTMLElement;
  831. begin
  832. Result := CreateEl(Parent, 'tr');
  833. end;
  834. function THTMLWriter.CreateTD(Parent: TDOMNode): THTMLElement;
  835. begin
  836. Result := CreateEl(Parent, 'td');
  837. end;
  838. function THTMLWriter.CreateTD_vtop(Parent: TDOMNode): THTMLElement;
  839. begin
  840. Result := CreateEl(Parent, 'td');
  841. Result['valign'] := 'top';
  842. end;
  843. function THTMLWriter.CreateLink(Parent: TDOMNode;
  844. const AHRef: DOMString): THTMLElement;
  845. begin
  846. Result := CreateEl(Parent, 'a');
  847. Result['href'] := FixHtmlPath(AHRef);
  848. end;
  849. function THTMLWriter.CreateAnchor(Parent: TDOMNode;
  850. const AName: DOMString): THTMLElement;
  851. begin
  852. Result := CreateEl(Parent, 'a');
  853. Result['name'] := AName;
  854. end;
  855. function THTMLWriter.CreateCode(Parent: TDOMNode): THTMLElement;
  856. begin
  857. Result := CreateEl(CreateEl(Parent, 'tt'), 'span');
  858. Result['class'] := 'code';
  859. end;
  860. function THTMLWriter.CreateWarning(Parent: TDOMNode): THTMLElement;
  861. begin
  862. Result := CreateEl(Parent, 'span');
  863. Result['class'] := 'warning';
  864. end;
  865. procedure THTMLWriter.PushOutputNode(ANode: TDOMNode);
  866. begin
  867. OutputNodeStack.Add(CurOutputNode);
  868. CurOutputNode := ANode;
  869. end;
  870. procedure THTMLWriter.PopOutputNode;
  871. begin
  872. CurOutputNode := TDOMNode(OutputNodeStack[OutputNodeStack.Count - 1]);
  873. OutputNodeStack.Delete(OutputNodeStack.Count - 1);
  874. end;
  875. procedure THTMLWriter.DescrWriteText(const AText: DOMString);
  876. begin
  877. AppendText(CurOutputNode, AText);
  878. end;
  879. procedure THTMLWriter.DescrBeginBold;
  880. begin
  881. PushOutputNode(CreateEl(CurOutputNode, 'b'));
  882. end;
  883. procedure THTMLWriter.DescrEndBold;
  884. begin
  885. PopOutputNode;
  886. end;
  887. procedure THTMLWriter.DescrBeginItalic;
  888. begin
  889. PushOutputNode(CreateEl(CurOutputNode, 'i'));
  890. end;
  891. procedure THTMLWriter.DescrEndItalic;
  892. begin
  893. PopOutputNode;
  894. end;
  895. procedure THTMLWriter.DescrBeginEmph;
  896. begin
  897. PushOutputNode(CreateEl(CurOutputNode, 'em'));
  898. end;
  899. procedure THTMLWriter.DescrEndEmph;
  900. begin
  901. PopOutputNode;
  902. end;
  903. procedure THTMLWriter.DescrWriteImageEl(const AFileName, ACaption, ALinkName : DOMString);
  904. Var
  905. Pel,Cel,Lel : TDOMNode;
  906. El :TDomElement;
  907. D : String;
  908. L : Integer;
  909. begin
  910. // Determine parent node.
  911. If (ACaption='') then
  912. Pel:=CurOutputNode
  913. else
  914. begin
  915. Cel:=CreateTable(CurOutputNode, 'imagetable');
  916. Pel:=CreateTD(CreateTR(Cel));
  917. Cel:=CreateTD(CreateTR(Cel));
  918. El := CreateEl(Cel, 'span');
  919. El['class'] := 'imagecaption';
  920. Cel := El;
  921. If (ALinkName<>'') then
  922. Cel:=CreateAnchor(Cel,ALinkName);
  923. AppendText(Cel,ACaption);
  924. end;
  925. // Determine URL for image.
  926. D:=BaseImageURL;
  927. If (D='') then
  928. begin
  929. If (Module=Nil) then
  930. D:=Allocator.GetRelativePathToTop(Package)
  931. else
  932. D:=Allocator.GetRelativePathToTop(Module);
  933. L:=Length(D);
  934. If (L>0) and (D[L]<>'/') then
  935. D:=D+'/';
  936. D:=D+'images/';
  937. end
  938. else
  939. L:=Length(D);
  940. If (L>0) and (D[L]<>'/') then
  941. D:=D+'/';
  942. // Create image node.
  943. El:=CreateEl(Pel,'img');
  944. EL['src']:=D+AFileName;
  945. El['alt']:=ACaption;
  946. end;
  947. procedure THTMLWriter.DescrWriteFileEl(const AText: DOMString);
  948. var
  949. NewEl: TDOMElement;
  950. begin
  951. NewEl := CreateEl(CurOutputNode, 'span');
  952. NewEl['class'] := 'file';
  953. AppendText(NewEl, AText);
  954. end;
  955. procedure THTMLWriter.DescrWriteKeywordEl(const AText: DOMString);
  956. var
  957. NewEl: TDOMElement;
  958. begin
  959. NewEl := CreateEl(CurOutputNode, 'span');
  960. NewEl['class'] := 'kw';
  961. AppendText(NewEl, AText);
  962. end;
  963. procedure THTMLWriter.DescrWriteVarEl(const AText: DOMString);
  964. begin
  965. AppendText(CreateEl(CurOutputNode, 'var'), AText);
  966. end;
  967. procedure THTMLWriter.DescrBeginLink(const AId: DOMString);
  968. var
  969. a,s: String;
  970. begin
  971. a:=AId;
  972. s := ResolveLinkID(a);
  973. if Length(s) = 0 then
  974. begin
  975. if assigned(module) then
  976. s:=module.name
  977. else
  978. s:='?';
  979. if a='' then a:='<empty>';
  980. DoLog(SErrUnknownLinkID, [s,a]);
  981. PushOutputNode(CreateEl(CurOutputNode, 'b'));
  982. end else
  983. PushOutputNode(CreateLink(CurOutputNode, s));
  984. end;
  985. procedure THTMLWriter.DescrEndLink;
  986. begin
  987. PopOutputNode;
  988. end;
  989. procedure THTMLWriter.DescrBeginURL(const AURL: DOMString);
  990. begin
  991. PushOutputNode(CreateLink(CurOutputNode, AURL));
  992. end;
  993. procedure THTMLWriter.DescrEndURL;
  994. begin
  995. PopOutputNode;
  996. end;
  997. procedure THTMLWriter.DescrWriteLinebreak;
  998. begin
  999. CreateEl(CurOutputNode, 'br');
  1000. end;
  1001. procedure THTMLWriter.DescrBeginParagraph;
  1002. begin
  1003. PushOutputNode(CreatePara(CurOutputNode));
  1004. end;
  1005. procedure THTMLWriter.DescrEndParagraph;
  1006. begin
  1007. PopOutputNode;
  1008. end;
  1009. procedure THTMLWriter.DescrBeginCode(HasBorder: Boolean; const AHighlighterName: String);
  1010. begin
  1011. DoPasHighlighting := (AHighlighterName = '') or (AHighlighterName = 'Pascal');
  1012. HighlighterFlags := 0;
  1013. PushOutputNode(CreateEl(CurOutputNode, 'pre'));
  1014. end;
  1015. procedure THTMLWriter.DescrWriteCodeLine(const ALine: String);
  1016. begin
  1017. if DoPasHighlighting then
  1018. begin
  1019. HighlighterFlags := AppendPasSHFragment(CurOutputNode, ALine,
  1020. HighlighterFlags);
  1021. AppendText(CurOutputNode, #10);
  1022. end else
  1023. AppendText(CurOutputNode, ALine + #10);
  1024. end;
  1025. procedure THTMLWriter.DescrEndCode;
  1026. begin
  1027. PopOutputNode;
  1028. end;
  1029. procedure THTMLWriter.DescrBeginOrderedList;
  1030. begin
  1031. PushOutputNode(CreateEl(CurOutputNode, 'ol'));
  1032. end;
  1033. procedure THTMLWriter.DescrEndOrderedList;
  1034. begin
  1035. PopOutputNode;
  1036. end;
  1037. procedure THTMLWriter.DescrBeginUnorderedList;
  1038. begin
  1039. PushOutputNode(CreateEl(CurOutputNode, 'ul'));
  1040. end;
  1041. procedure THTMLWriter.DescrEndUnorderedList;
  1042. begin
  1043. PopOutputNode;
  1044. end;
  1045. procedure THTMLWriter.DescrBeginDefinitionList;
  1046. begin
  1047. PushOutputNode(CreateEl(CurOutputNode, 'dl'));
  1048. end;
  1049. procedure THTMLWriter.DescrEndDefinitionList;
  1050. begin
  1051. PopOutputNode;
  1052. end;
  1053. procedure THTMLWriter.DescrBeginListItem;
  1054. begin
  1055. PushOutputNode(CreateEl(CurOutputNode, 'li'));
  1056. end;
  1057. procedure THTMLWriter.DescrEndListItem;
  1058. begin
  1059. PopOutputNode;
  1060. end;
  1061. procedure THTMLWriter.DescrBeginDefinitionTerm;
  1062. begin
  1063. PushOutputNode(CreateEl(CurOutputNode, 'dt'));
  1064. end;
  1065. procedure THTMLWriter.DescrEndDefinitionTerm;
  1066. begin
  1067. PopOutputNode;
  1068. end;
  1069. procedure THTMLWriter.DescrBeginDefinitionEntry;
  1070. begin
  1071. PushOutputNode(CreateEl(CurOutputNode, 'dd'));
  1072. end;
  1073. procedure THTMLWriter.DescrEndDefinitionEntry;
  1074. begin
  1075. PopOutputNode;
  1076. end;
  1077. procedure THTMLWriter.DescrBeginSectionTitle;
  1078. begin
  1079. PushOutputNode(CreateEl(CurOutputNode, 'h3'));
  1080. end;
  1081. procedure THTMLWriter.DescrBeginSectionBody;
  1082. begin
  1083. PopOutputNode;
  1084. end;
  1085. procedure THTMLWriter.DescrEndSection;
  1086. begin
  1087. end;
  1088. procedure THTMLWriter.DescrBeginRemark;
  1089. var
  1090. NewEl, TDEl: TDOMElement;
  1091. begin
  1092. NewEl := CreateEl(CurOutputNode, 'table');
  1093. NewEl['width'] := '100%';
  1094. NewEl['border'] := '0';
  1095. NewEl['CellSpacing'] := '0';
  1096. NewEl['class'] := 'remark';
  1097. NewEl := CreateTR(NewEl);
  1098. TDEl := CreateTD(NewEl);
  1099. TDEl['valign'] := 'top';
  1100. TDEl['class'] := 'pre';
  1101. AppendText(CreateEl(TDEl, 'b'), SDocRemark);
  1102. PushOutputNode(CreateTD(NewEl));
  1103. end;
  1104. procedure THTMLWriter.DescrEndRemark;
  1105. begin
  1106. PopOutputNode;
  1107. end;
  1108. procedure THTMLWriter.DescrBeginTable(ColCount: Integer; HasBorder: Boolean);
  1109. var
  1110. Table: TDOMElement;
  1111. begin
  1112. Table := CreateEl(CurOutputNode, 'table');
  1113. Table['border'] := IntToStr(Ord(HasBorder));
  1114. PushOutputNode(Table);
  1115. end;
  1116. procedure THTMLWriter.DescrEndTable;
  1117. begin
  1118. PopOutputNode;
  1119. end;
  1120. procedure THTMLWriter.DescrBeginTableCaption;
  1121. begin
  1122. PushOutputNode(CreateEl(CurOutputNode, 'caption'));
  1123. end;
  1124. procedure THTMLWriter.DescrEndTableCaption;
  1125. begin
  1126. PopOutputNode;
  1127. end;
  1128. procedure THTMLWriter.DescrBeginTableHeadRow;
  1129. begin
  1130. PushOutputNode(CreateTr(CurOutputNode));
  1131. InsideHeadRow := True;
  1132. end;
  1133. procedure THTMLWriter.DescrEndTableHeadRow;
  1134. begin
  1135. InsideHeadRow := False;
  1136. PopOutputNode;
  1137. end;
  1138. procedure THTMLWriter.DescrBeginTableRow;
  1139. begin
  1140. PushOutputNode(CreateTR(CurOutputNode));
  1141. end;
  1142. procedure THTMLWriter.DescrEndTableRow;
  1143. begin
  1144. PopOutputNode;
  1145. end;
  1146. procedure THTMLWriter.DescrBeginTableCell;
  1147. begin
  1148. if InsideHeadRow then
  1149. PushOutputNode(CreateEl(CurOutputNode, 'th'))
  1150. else
  1151. PushOutputNode(CreateTD(CurOutputNode));
  1152. end;
  1153. procedure THTMLWriter.DescrEndTableCell;
  1154. begin
  1155. PopOutputNode;
  1156. end;
  1157. procedure THTMLWriter.AppendText(Parent: TDOMNode; const AText: DOMString);
  1158. begin
  1159. Parent.AppendChild(Doc.CreateTextNode(AText));
  1160. end;
  1161. procedure THTMLWriter.AppendNbSp(Parent: TDOMNode; ACount: Integer);
  1162. begin
  1163. while ACount > 0 do
  1164. begin
  1165. Parent.AppendChild(Doc.CreateEntityReference('nbsp'));
  1166. Dec(ACount);
  1167. end;
  1168. end;
  1169. procedure THTMLWriter.AppendSym(Parent: TDOMNode; const AText: DOMString);
  1170. var
  1171. El: TDOMElement;
  1172. begin
  1173. El := CreateEl(Parent, 'span');
  1174. El['class'] := 'sym';
  1175. AppendText(El, AText);
  1176. end;
  1177. procedure THTMLWriter.AppendKw(Parent: TDOMNode; const AText: DOMString);
  1178. var
  1179. El: TDOMElement;
  1180. begin
  1181. El := CreateEl(Parent, 'span');
  1182. El['class'] := 'kw';
  1183. AppendText(El, AText);
  1184. end;
  1185. function THTMLWriter.AppendPasSHFragment(Parent: TDOMNode;
  1186. const AText: String; AShFlags: Byte): Byte;
  1187. var
  1188. Line, Last, p: PChar;
  1189. IsInSpecial: Boolean;
  1190. lastwasasm : boolean;
  1191. El: TDOMElement;
  1192. Procedure MaybeOutput;
  1193. Var
  1194. CurParent: TDomNode;
  1195. begin
  1196. If (Last<>Nil) then
  1197. begin
  1198. If (el<>Nil) then
  1199. CurParent:=El
  1200. else
  1201. CurParent:=Parent;
  1202. AppendText(CurParent,Last);
  1203. El:=Nil;
  1204. Last:=Nil;
  1205. end;
  1206. end;
  1207. Function NewEl(Const ElType,Attr,AttrVal : String) : TDomElement;
  1208. begin
  1209. Result:=CreateEl(Parent,ElType);
  1210. Result[Attr]:=AttrVal;
  1211. end;
  1212. Function NewSpan(Const AttrVal : String) : TDomElement;
  1213. begin
  1214. Result:=CreateEl(Parent,'span');
  1215. Result['class']:=AttrVal;
  1216. end;
  1217. begin
  1218. GetMem(Line, Length(AText) * 3 + 4);
  1219. Try
  1220. DoPascalHighlighting(AShFlags, PChar(AText), Line);
  1221. Result := AShFlags;
  1222. IsInSpecial := False;
  1223. Last := Nil;
  1224. p := Line;
  1225. el:=nil;
  1226. while p[0] <> #0 do
  1227. begin
  1228. if p[0] = LF_ESCAPE then
  1229. begin
  1230. p[0] := #0;
  1231. MaybeOutput;
  1232. case Ord(p[1]) of
  1233. shDefault: El:=Nil;
  1234. shInvalid: El:=newel('font','color','red');
  1235. shSymbol : El:=newspan('sym');
  1236. shKeyword: El:=newspan('kw');
  1237. shComment: El:=newspan('cmt');
  1238. shDirective: El:=newspan('dir');
  1239. shNumbers: El:=newspan('num');
  1240. shCharacters: El:=newspan('chr');
  1241. shStrings: El:=newspan('str');
  1242. shAssembler: El:=newspan('asm');
  1243. end;
  1244. Inc(P);
  1245. end
  1246. else If (Last=Nil) then
  1247. Last:=P;
  1248. Inc(p);
  1249. end;
  1250. MaybeOutput;
  1251. Finally
  1252. FreeMem(Line);
  1253. end;
  1254. end;
  1255. Procedure THTMLWriter.AppendShortDescr(AContext: TPasElement; Parent: TDOMNode; DocNode : TDocNode);
  1256. Var
  1257. N : TDocNode;
  1258. begin
  1259. if Assigned(DocNode) then
  1260. begin
  1261. If (DocNode.Link<>'') then
  1262. begin
  1263. N:=Engine.FindLinkedNode(DocNode);
  1264. If (N<>Nil) then
  1265. DocNode:=N;
  1266. end;
  1267. If Assigned(DocNode.ShortDescr) then
  1268. begin
  1269. PushOutputNode(Parent);
  1270. try
  1271. if not ConvertShort(AContext,TDomElement(DocNode.ShortDescr)) then
  1272. Warning(AContext, SErrInvalidShortDescr)
  1273. finally
  1274. PopOutputNode;
  1275. end;
  1276. end;
  1277. end;
  1278. end;
  1279. procedure THTMLWriter.AppendShortDescr(Parent: TDOMNode; Element: TPasElement);
  1280. begin
  1281. AppendShortDescr(Element,Parent,Engine.FindDocNode(Element));
  1282. end;
  1283. procedure THTMLWriter.AppendShortDescrCell(Parent: TDOMNode;
  1284. Element: TPasElement);
  1285. var
  1286. ParaEl: TDOMElement;
  1287. begin
  1288. if Assigned(Engine.FindShortDescr(Element)) then
  1289. begin
  1290. AppendNbSp(CreatePara(CreateTD(Parent)), 2);
  1291. ParaEl := CreatePara(CreateTD(Parent));
  1292. ParaEl['class'] := 'cmt';
  1293. AppendShortDescr(ParaEl, Element);
  1294. end;
  1295. end;
  1296. procedure THTMLWriter.AppendDescr(AContext: TPasElement; Parent: TDOMNode;
  1297. DescrNode: TDOMElement; AutoInsertBlock: Boolean);
  1298. begin
  1299. if Assigned(DescrNode) then
  1300. begin
  1301. PushOutputNode(Parent);
  1302. try
  1303. ConvertDescr(AContext, DescrNode, AutoInsertBlock);
  1304. finally
  1305. PopOutputNode;
  1306. end;
  1307. end;
  1308. end;
  1309. procedure THTMLWriter.AppendDescrSection(AContext: TPasElement;
  1310. Parent: TDOMNode; DescrNode: TDOMElement; const ATitle: DOMString);
  1311. begin
  1312. if not IsDescrNodeEmpty(DescrNode) then
  1313. begin
  1314. If (ATitle<>'') then // Can be empty for topic.
  1315. AppendText(CreateH2(Parent), ATitle);
  1316. AppendDescr(AContext, Parent, DescrNode, True);
  1317. end;
  1318. end;
  1319. function THTMLWriter.AppendHyperlink(Parent: TDOMNode;
  1320. Element: TPasElement): TDOMElement;
  1321. var
  1322. s: String;
  1323. UnitList: TFPList;
  1324. i: Integer;
  1325. ThisPackage: TLinkNode;
  1326. begin
  1327. if Assigned(Element) then
  1328. begin
  1329. if Element.InheritsFrom(TPasUnresolvedTypeRef) then
  1330. begin
  1331. s := ResolveLinkID(Element.Name);
  1332. if Length(s) = 0 then
  1333. begin
  1334. { Try all packages }
  1335. ThisPackage := Engine.RootLinkNode.FirstChild;
  1336. while Assigned(ThisPackage) do
  1337. begin
  1338. s := ResolveLinkID(ThisPackage.Name + '.' + Element.Name);
  1339. if Length(s) > 0 then
  1340. break;
  1341. ThisPackage := ThisPackage.NextSibling;
  1342. end;
  1343. if Length(s) = 0 then
  1344. begin
  1345. { Okay, then we have to try all imported units of the current module }
  1346. UnitList := Module.InterfaceSection.UsesList;
  1347. for i := UnitList.Count - 1 downto 0 do
  1348. begin
  1349. { Try all packages }
  1350. ThisPackage := Engine.RootLinkNode.FirstChild;
  1351. while Assigned(ThisPackage) do
  1352. begin
  1353. s := ResolveLinkID(ThisPackage.Name + '.' +
  1354. TPasType(UnitList[i]).Name + '.' + Element.Name);
  1355. if Length(s) > 0 then
  1356. break;
  1357. ThisPackage := ThisPackage.NextSibling;
  1358. end;
  1359. if length(s)=0 then
  1360. s := ResolveLinkID('#rtl.System.' + Element.Name);
  1361. if Length(s) > 0 then
  1362. break;
  1363. end;
  1364. end;
  1365. end;
  1366. end else if Element is TPasEnumValue then
  1367. s := ResolveLinkID(Element.Parent.PathName)
  1368. else
  1369. s := ResolveLinkID(Element.PathName);
  1370. if Length(s) > 0 then
  1371. begin
  1372. Result := CreateLink(Parent, s);
  1373. AppendText(Result, Element.Name);
  1374. end else
  1375. begin
  1376. Result := nil;
  1377. AppendText(Parent, Element.Name);
  1378. end;
  1379. end else
  1380. begin
  1381. Result := nil;
  1382. AppendText(CreateWarning(Parent), '<NIL>');
  1383. end;
  1384. end;
  1385. { Returns the new CodeEl, which will be the old CodeEl in most cases }
  1386. function THTMLWriter.AppendType(CodeEl, TableEl: TDOMElement;
  1387. Element: TPasType; Expanded: Boolean; NestingLevel: Integer): TDOMElement;
  1388. Var
  1389. S : String;
  1390. begin
  1391. Result := CodeEl;
  1392. if not Assigned(Element) then
  1393. AppendText(CreateWarning(CodeEl), '<NIL>')
  1394. else if (not Expanded) and (Length(Element.Name) > 0) then
  1395. AppendHyperlink(CodeEl, Element)
  1396. else
  1397. // Array
  1398. if Element.ClassType = TPasArrayType then
  1399. begin
  1400. S:='array ';
  1401. If (TPasArrayType(Element).IndexRange<>'') then
  1402. S:=S+'[' + TPasArrayType(Element).IndexRange + '] ';
  1403. S:=S+'of ';
  1404. If (TPasArrayType(Element).ElType=Nil) then
  1405. S:=S+'Const';
  1406. AppendPasSHFragment(CodeEl,S,0);
  1407. If (TPasArrayType(Element).ElType<>Nil) then
  1408. Result := AppendType(CodeEl, TableEl, TPasArrayType(Element).ElType, False);
  1409. end else
  1410. // Procedure or funtion type
  1411. if Element.InheritsFrom(TPasProcedureType) then
  1412. begin
  1413. AppendKw(CodeEl, TPasProcedureType(Element).TypeName);
  1414. Result := AppendProcType(CodeEl, TableEl, TPasProcedureType(Element), 0)
  1415. end else
  1416. // Range type
  1417. if Element.InheritsFrom(TPasRangeType) then
  1418. AppendPasSHFragment(CodeEl, TPasRangeType(Element).RangeStart + '..' +
  1419. TPasRangeType(Element).RangeEnd, 0)
  1420. // Record type
  1421. else if Element.ClassType = TPasRecordType then
  1422. Result := AppendRecordType(CodeEl, TableEl, TPasRecordType(Element), NestingLevel)
  1423. else if (Element.ClassType = TPasFileType) and (TPasFileType(Element).elType=Nil) then
  1424. AppendPasSHFragment(CodeEl,'file',0)
  1425. else
  1426. // Other types
  1427. AppendHyperlink(CodeEl, Element);
  1428. end;
  1429. function THTMLWriter.AppendProcType(CodeEl, TableEl: TDOMElement;
  1430. Element: TPasProcedureType; Indent: Integer): TDOMElement;
  1431. function CreateIndentedCodeEl(Indent: Integer): TDOMElement;
  1432. begin
  1433. Result := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
  1434. AppendNbSp(Result, Indent);
  1435. end;
  1436. var
  1437. i: Integer;
  1438. Arg: TPasArgument;
  1439. begin
  1440. if Element.Args.Count > 0 then
  1441. begin
  1442. AppendSym(CodeEl, '(');
  1443. for i := 0 to Element.Args.Count - 1 do
  1444. begin
  1445. Arg := TPasArgument(Element.Args[i]);
  1446. CodeEl := CreateIndentedCodeEl(Indent + 2);
  1447. case Arg.Access of
  1448. argConst: AppendKw(CodeEl, 'const ');
  1449. argVar: AppendKw(CodeEl, 'var ');
  1450. argOut: AppendKw(CodeEl, 'out ');
  1451. end;
  1452. AppendText(CodeEl, Arg.Name);
  1453. if Assigned(Arg.ArgType) then
  1454. begin
  1455. AppendSym(CodeEl, ': ');
  1456. CodeEl := AppendType(CodeEl, TableEl, Arg.ArgType, False);
  1457. end;
  1458. if Length(Arg.Value) > 0 then
  1459. AppendPasSHFragment(CodeEl, ' = ' + Arg.Value, 0);
  1460. if i < Element.Args.Count - 1 then
  1461. AppendSym(CodeEl, ';');
  1462. end;
  1463. if Element.InheritsFrom(TPasFunctionType) or Element.IsOfObject then
  1464. begin
  1465. CodeEl := CreateIndentedCodeEl(Indent);
  1466. if Element.InheritsFrom(TPasFunctionType) then
  1467. begin
  1468. AppendSym(CodeEl, '):');
  1469. AppendHyperlink(CodeEl, TPasFunctionType(Element).ResultEl.ResultType);
  1470. end else
  1471. AppendSym(CodeEl, ')');
  1472. if Element.IsOfObject then
  1473. begin
  1474. AppendText(CodeEl, ' '); // Don't remove
  1475. AppendKw(CodeEl, 'of object');
  1476. end;
  1477. end else
  1478. if Indent > 0 then
  1479. AppendSym(CodeEl, ')')
  1480. else
  1481. begin
  1482. CodeEl := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
  1483. AppendSym(CodeEl, ')');
  1484. end;
  1485. end else
  1486. begin
  1487. { Procedure or function without arguments }
  1488. if Element.InheritsFrom(TPasFunctionType) then
  1489. begin
  1490. AppendSym(CodeEl, ': ');
  1491. AppendHyperlink(CodeEl, TPasFunctionType(Element).ResultEl.ResultType);
  1492. end;
  1493. if Element.IsOfObject then
  1494. AppendKw(CodeEl, ' of object');
  1495. end;
  1496. Result := CodeEl;
  1497. end;
  1498. procedure THTMLWriter.AppendProcExt(CodeEl: TDOMElement;
  1499. Element: TPasProcedure);
  1500. procedure AppendExt(const Ext: String);
  1501. begin
  1502. AppendKw(CodeEl, ' ' + Ext);
  1503. AppendSym(CodeEl, ';');
  1504. end;
  1505. begin
  1506. if Element.IsVirtual then
  1507. AppendExt('virtual');
  1508. if Element.IsDynamic then
  1509. AppendExt('dynamic');
  1510. if Element.IsAbstract then
  1511. AppendExt('abstract');
  1512. if Element.IsOverride then
  1513. AppendExt('override');
  1514. if Element.IsOverload then
  1515. AppendExt('overload');
  1516. if Element.IsMessage then
  1517. AppendExt('message');
  1518. end;
  1519. { Used in two places:
  1520. - Page for the method of a class
  1521. - Page for a tandalone procedure or function. }
  1522. procedure THTMLWriter.AppendProcDecl(CodeEl, TableEl: TDOMElement;
  1523. Element: TPasProcedureBase);
  1524. procedure WriteVariant(AProc: TPasProcedure);
  1525. begin
  1526. AppendProcArgsSection(TableEl.ParentNode, AProc.ProcType);
  1527. AppendKw(CodeEl, AProc.TypeName);
  1528. if Element.Parent.ClassType = TPasClassType then
  1529. begin
  1530. AppendText(CodeEl, ' ');
  1531. AppendHyperlink(CodeEl, Element.Parent);
  1532. AppendSym(CodeEl, '.');
  1533. AppendText(CodeEl, AProc.Name);
  1534. end else
  1535. AppendText(CodeEl, ' ' + AProc.FullName);
  1536. CodeEl := AppendProcType(CodeEl, TableEl, AProc.ProcType, 0);
  1537. AppendSym(CodeEl, ';');
  1538. AppendProcExt(CodeEl, AProc);
  1539. end;
  1540. var
  1541. i: Integer;
  1542. begin
  1543. if Element.ClassType = TPasOverloadedProc then
  1544. for i := 0 to TPasOverloadedProc(Element).Overloads.Count - 1 do
  1545. begin
  1546. if i > 0 then
  1547. begin
  1548. CreateEl(CodeEl, 'br');
  1549. CreateEl(CodeEl, 'br');
  1550. end;
  1551. WriteVariant(TPasProcedure(TPasOverloadedProc(Element).Overloads[i]));
  1552. end
  1553. else
  1554. WriteVariant(TPasProcedure(Element));
  1555. end;
  1556. procedure THTMLWriter.AppendProcArgsSection(Parent: TDOMNode;
  1557. Element: TPasProcedureType);
  1558. var
  1559. HasFullDescr, IsFirst: Boolean;
  1560. ResultEl: TPasResultElement;
  1561. ArgTableEl, TREl: TDOMElement;
  1562. DocNode: TDocNode;
  1563. i: Integer;
  1564. Arg: TPasArgument;
  1565. begin
  1566. IsFirst := True;
  1567. for i := 0 to Element.Args.Count - 1 do
  1568. begin
  1569. Arg := TPasArgument(Element.Args[i]);
  1570. if IsDescrNodeEmpty(Engine.FindShortDescr(Arg)) then
  1571. continue;
  1572. if IsFirst then
  1573. begin
  1574. IsFirst := False;
  1575. AppendText(CreateH2(Parent), SDocArguments);
  1576. ArgTableEl := CreateTable(Parent);
  1577. end;
  1578. TREl := CreateTR(ArgTableEl);
  1579. AppendText(CreateCode(CreatePara(CreateTD_vtop(TREl))), Arg.Name);
  1580. AppendShortDescrCell(TREl, Arg);
  1581. end;
  1582. if Element.ClassType = TPasFunctionType then
  1583. begin
  1584. ResultEl := TPasFunctionType(Element).ResultEl;
  1585. DocNode := Engine.FindDocNode(ResultEl);
  1586. HasFullDescr := Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.Descr);
  1587. if HasFullDescr or
  1588. (Assigned(DocNode) and not IsDescrNodeEmpty(DocNode.ShortDescr)) then
  1589. begin
  1590. AppendText(CreateH2(Parent), SDocFunctionResult);
  1591. if HasFullDescr then
  1592. AppendDescr(ResultEl, Parent, DocNode.Descr, True)
  1593. else
  1594. AppendDescr(ResultEl, CreatePara(Parent), DocNode.ShortDescr, False);
  1595. end;
  1596. end;
  1597. end;
  1598. function THTMLWriter.AppendRecordType(CodeEl, TableEl: TDOMElement;
  1599. Element: TPasRecordType; NestingLevel: Integer): TDOMElement;
  1600. var
  1601. i, j: Integer;
  1602. Variable: TPasVariable;
  1603. TREl, TDEl: TDOMElement;
  1604. CurVariant: TPasVariant;
  1605. begin
  1606. if not (Element.Parent is TPasVariant) then
  1607. if Element.IsPacked then
  1608. If Element.IsBitPacked then
  1609. AppendKw(CodeEl, 'bitpacked record')
  1610. else
  1611. AppendKW(CodeEl, 'packed record')
  1612. else
  1613. AppendKw(CodeEl, 'record');
  1614. for i := 0 to Element.Members.Count - 1 do
  1615. begin
  1616. Variable := TPasVariable(Element.Members[i]);
  1617. TREl := CreateTR(TableEl);
  1618. CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
  1619. AppendShortDescrCell(TREl, Variable);
  1620. AppendNbSp(CodeEl, NestingLevel * 2 + 2);
  1621. AppendText(CodeEl, Variable.Name);
  1622. AppendSym(CodeEl, ': ');
  1623. CodeEl := AppendType(CodeEl, TableEl, Variable.VarType, False, NestingLevel + 1);
  1624. AppendSym(CodeEl, ';');
  1625. end;
  1626. if Assigned(Element.VariantType) then
  1627. begin
  1628. TREl := CreateTR(TableEl);
  1629. CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
  1630. AppendNbSp(CodeEl, NestingLevel * 2 + 2);
  1631. AppendKw(CodeEl, 'case ');
  1632. if TPasRecordType(Element).VariantName <> '' then
  1633. begin
  1634. AppendText(CodeEl, TPasRecordType(Element).VariantName);
  1635. AppendSym(CodeEl, ': ');
  1636. end;
  1637. CodeEl := AppendType(CodeEl, TableEl, TPasRecordType(Element).VariantType, True);
  1638. AppendKw(CodeEl, ' of');
  1639. for i := 0 to TPasRecordType(Element).Variants.Count - 1 do
  1640. begin
  1641. CurVariant := TPasVariant(Element.Variants[i]);
  1642. TREl := CreateTR(TableEl);
  1643. CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
  1644. AppendNbSp(CodeEl, NestingLevel * 2 + 4);
  1645. for j := 0 to CurVariant.Values.Count - 1 do
  1646. begin
  1647. if j > 0 then
  1648. AppendSym(CodeEl, ', ');
  1649. AppendPasSHFragment(CodeEl, CurVariant.Values[j], 0);
  1650. end;
  1651. AppendSym(CodeEl, ': (');
  1652. AppendType(CodeEl, TableEl, CurVariant.Members, True, NestingLevel + 3);
  1653. CodeEl := CreateCode(CreatePara(CreateTD_vtop(CreateTR(TableEl))));
  1654. AppendNbSp(CodeEl, NestingLevel * 2 + 6);
  1655. AppendSym(CodeEl, ');');
  1656. end;
  1657. end;
  1658. if not (Element.Parent is TPasVariant) then
  1659. begin
  1660. CodeEl := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
  1661. AppendText(CodeEl, ' '); // !!!: Dirty trick, necessary for current XML writer
  1662. AppendNbSp(CodeEl, NestingLevel * 2);
  1663. AppendKw(CodeEl, 'end');
  1664. end;
  1665. Result := CodeEl;
  1666. end;
  1667. procedure THTMLWriter.AppendTitle(const AText: DOMString);
  1668. begin
  1669. AppendText(TitleElement, AText);
  1670. AppendText(CreateH1(BodyElement), AText);
  1671. end;
  1672. procedure THTMLWriter.AppendTopicMenuBar(Topic : TTopicElement);
  1673. var
  1674. TableEl, TREl, ParaEl, TitleEl: TDOMElement;
  1675. procedure AddLink(El : TPasElement; const AName: String);
  1676. begin
  1677. AppendText(ParaEl, '[');
  1678. AppendText(CreateLink(ParaEl, ResolveLinkWithinPackage(El,0)),AName);
  1679. AppendText(ParaEl, ']');
  1680. end;
  1681. begin
  1682. TableEl := CreateEl(BodyElement, 'table');
  1683. TableEl['cellpadding'] := '4';
  1684. TableEl['cellspacing'] := '0';
  1685. TableEl['border'] := '0';
  1686. TableEl['width'] := '100%';
  1687. TableEl['class'] := 'bar';
  1688. TREl := CreateTR(TableEl);
  1689. ParaEl := CreateEl(CreateTD(TREl), 'b');
  1690. If Assigned(Topic.Previous) then
  1691. AddLink(Topic.Previous,SDocPrevious);
  1692. If Assigned(Topic.Parent) then
  1693. AddLink(Topic.Parent,SDocUp);
  1694. if Assigned(Topic.Next) then
  1695. AddLink(Topic.Next,SDocNext);
  1696. if Length(SearchPage) > 0 then
  1697. begin
  1698. AppendText(ParaEl, '[');
  1699. AppendText(CreateLink(ParaEl, SearchPage), SDocSearch);
  1700. AppendText(ParaEl, ']');
  1701. end;
  1702. ParaEl := CreateTD(TREl);
  1703. ParaEl['align'] := 'right';
  1704. TitleEl := CreateEl(ParaEl, 'span');
  1705. TitleEl['class'] := 'bartitle';
  1706. if Assigned(Module) then
  1707. AppendText(TitleEl, Format(SDocUnitTitle, [Module.Name]));
  1708. if Assigned(Package) then
  1709. begin
  1710. AppendText(TitleEl, ' (');
  1711. AppendHyperlink(TitleEl, Package);
  1712. AppendText(TitleEl, ')');
  1713. end;
  1714. end;
  1715. procedure THTMLWriter.AppendMenuBar(ASubpageIndex: Integer);
  1716. var
  1717. TableEl, TREl, ParaEl, TitleEl: TDOMElement;
  1718. procedure AddLink(ALinkSubpageIndex: Integer; const AName: String);
  1719. begin
  1720. AppendText(ParaEl, '[');
  1721. if ALinkSubpageIndex = ASubpageIndex then
  1722. AppendText(ParaEl, AName)
  1723. else
  1724. AppendText(
  1725. CreateLink(ParaEl, ResolveLinkWithinPackage(Module, ALinkSubpageIndex)),
  1726. AName);
  1727. AppendText(ParaEl, ']');
  1728. end;
  1729. begin
  1730. TableEl := CreateEl(BodyElement, 'table');
  1731. TableEl['cellpadding'] := '4';
  1732. TableEl['cellspacing'] := '0';
  1733. TableEl['border'] := '0';
  1734. TableEl['width'] := '100%';
  1735. TableEl['class'] := 'bar';
  1736. TREl := CreateTR(TableEl);
  1737. ParaEl := CreateEl(CreateTD(TREl), 'b');
  1738. if Assigned(Module) then
  1739. begin
  1740. AddLink(0, SDocOverview);
  1741. if Module.InterfaceSection.ResStrings.Count > 0 then
  1742. AddLink(ResstrSubindex, SDocResStrings);
  1743. if Module.InterfaceSection.Consts.Count > 0 then
  1744. AddLink(ConstsSubindex, SDocConstants);
  1745. if Module.InterfaceSection.Types.Count > 0 then
  1746. AddLink(TypesSubindex, SDocTypes);
  1747. if Module.InterfaceSection.Classes.Count > 0 then
  1748. AddLink(ClassesSubindex, SDocClasses);
  1749. if Module.InterfaceSection.Functions.Count > 0 then
  1750. AddLink(ProcsSubindex, SDocProceduresAndFunctions);
  1751. if Module.InterfaceSection.Variables.Count > 0 then
  1752. AddLink(VarsSubindex, SDocVariables);
  1753. AddLink(IndexSubIndex,SDocIdentifierIndex);
  1754. end
  1755. else
  1756. begin
  1757. // Manually add link for package page
  1758. AppendText(ParaEl, '[');
  1759. if (IndexSubIndex = ASubpageIndex) then
  1760. AppendText(ParaEl, SDocIdentifierIndex)
  1761. else
  1762. AppendText(
  1763. CreateLink(ParaEl, ResolveLinkWithinPackage(Package, IndexSubIndex)),
  1764. SDocIdentifierIndex);
  1765. AppendText(ParaEl, ']');
  1766. end;
  1767. if Length(SearchPage) > 0 then
  1768. begin
  1769. AppendText(ParaEl, '[');
  1770. AppendText(CreateLink(ParaEl, SearchPage), SDocSearch);
  1771. AppendText(ParaEl, ']');
  1772. end;
  1773. ParaEl := CreateTD(TREl);
  1774. ParaEl['align'] := 'right';
  1775. TitleEl := CreateEl(ParaEl, 'span');
  1776. TitleEl['class'] := 'bartitle';
  1777. if Assigned(Module) then
  1778. AppendText(TitleEl, Format(SDocUnitTitle, [Module.Name]));
  1779. if Assigned(Package) then
  1780. begin
  1781. AppendText(TitleEl, ' (');
  1782. AppendHyperlink(TitleEl, Package);
  1783. AppendText(TitleEl, ')');
  1784. end;
  1785. end;
  1786. procedure THTMLWriter.AppendSourceRef(AElement: TPasElement);
  1787. begin
  1788. AppendText(CreatePara(BodyElement), Format(SDocSourcePosition,
  1789. [ExtractFileName(AElement.SourceFilename), AElement.SourceLinenumber]));
  1790. end;
  1791. Procedure THTMLWriter.AppendSeeAlsoSection(AElement : TPasElement;DocNode : TDocNode);
  1792. var
  1793. Node: TDOMNode;
  1794. TableEl, El, TREl, TDEl, ParaEl, NewEl, DescrEl: TDOMElement;
  1795. l,s: String;
  1796. f: Text;
  1797. IsFirstSeeAlso : Boolean;
  1798. begin
  1799. if Not (Assigned(DocNode) and Assigned(DocNode.SeeAlso)) then
  1800. Exit;
  1801. IsFirstSeeAlso := True;
  1802. Node:=DocNode.SeeAlso.FirstChild;
  1803. While Assigned(Node) do
  1804. begin
  1805. if (Node.NodeType=ELEMENT_NODE) and (Node.NodeName='link') then
  1806. begin
  1807. if IsFirstSeeAlso then
  1808. begin
  1809. IsFirstSeeAlso := False;
  1810. AppendText(CreateH2(BodyElement), SDocSeeAlso);
  1811. TableEl := CreateTable(BodyElement);
  1812. end;
  1813. El:=TDOMElement(Node);
  1814. TREl:=CreateTR(TableEl);
  1815. ParaEl:=CreatePara(CreateTD_vtop(TREl));
  1816. l:=El['id'];
  1817. s:= ResolveLinkID(l);
  1818. if Length(s)=0 then
  1819. begin
  1820. if assigned(module) then
  1821. s:=module.name
  1822. else
  1823. s:='?';
  1824. if l='' then l:='<empty>';
  1825. DoLog(SErrUnknownLinkID, [s,l]);
  1826. NewEl := CreateEl(ParaEl,'b')
  1827. end
  1828. else
  1829. NewEl := CreateLink(ParaEl,s);
  1830. if Not IsDescrNodeEmpty(El) then
  1831. begin
  1832. PushOutputNode(NewEl);
  1833. Try
  1834. ConvertBaseShortList(AElement, El, True)
  1835. Finally
  1836. PopOutputNode;
  1837. end;
  1838. end
  1839. else
  1840. AppendText(NewEl,El['id']);
  1841. l:=El['id'];
  1842. DescrEl := Engine.FindShortDescr(AElement.GetModule,L);
  1843. if Assigned(DescrEl) then
  1844. begin
  1845. AppendNbSp(CreatePara(CreateTD(TREl)), 2);
  1846. ParaEl := CreatePara(CreateTD(TREl));
  1847. ParaEl['class'] := 'cmt';
  1848. PushOutputNode(ParaEl);
  1849. try
  1850. ConvertShort(AElement, DescrEl);
  1851. finally
  1852. PopOutputNode;
  1853. end;
  1854. end;
  1855. end; // Link node
  1856. Node := Node.NextSibling;
  1857. end; // While
  1858. end;
  1859. Procedure THTMLWriter.AppendExampleSection(AElement : TPasElement;DocNode : TDocNode);
  1860. var
  1861. Node: TDOMNode;
  1862. // TableEl, El, TREl, TDEl, ParaEl, NewEl, DescrEl: TDOMElement;
  1863. fn,s: String;
  1864. f: Text;
  1865. begin
  1866. if not (Assigned(DocNode) and Assigned(DocNode.FirstExample)) then
  1867. Exit;
  1868. Node := DocNode.FirstExample;
  1869. while Assigned(Node) do
  1870. begin
  1871. if (Node.NodeType = ELEMENT_NODE) and (Node.NodeName = 'example') then
  1872. begin
  1873. fn:=Engine.GetExampleFilename(TDOMElement(Node));
  1874. If (fn<>'') then
  1875. begin
  1876. AppendText(CreateH2(BodyElement), SDocExample);
  1877. try
  1878. Assign(f, FN);
  1879. Reset(f);
  1880. try
  1881. PushOutputNode(BodyElement);
  1882. DescrBeginCode(False, TDOMElement(Node)['highlighter']);
  1883. while not EOF(f) do
  1884. begin
  1885. ReadLn(f, s);
  1886. DescrWriteCodeLine(s);
  1887. end;
  1888. DescrEndCode;
  1889. PopOutputNode;
  1890. finally
  1891. Close(f);
  1892. end;
  1893. except
  1894. on e: Exception do
  1895. begin
  1896. e.Message := '[example] ' + e.Message;
  1897. raise;
  1898. end;
  1899. end;
  1900. end;
  1901. end;
  1902. Node := Node.NextSibling;
  1903. end;
  1904. end;
  1905. procedure THTMLWriter.AppendFooter;
  1906. Var
  1907. S : String;
  1908. F : TDomElement;
  1909. begin
  1910. if FooterFile<>'' then
  1911. ReadXMLFragment(BodyElement, FooterFile)
  1912. else if IncludeDateInFooter then
  1913. begin
  1914. CreateEl(BodyElement, 'hr');
  1915. F:=CreateEl(BodyElement,'span');
  1916. F['class']:='footer';
  1917. If (FDateFormat='') then
  1918. S:=DateToStr(Date)
  1919. else
  1920. S:=FormatDateTime(FDateFormat,Date);
  1921. AppendText(F,Format(SDocDateGenerated,[S]));
  1922. end;
  1923. end;
  1924. procedure THTMLWriter.FinishElementPage(AElement: TPasElement);
  1925. var
  1926. DocNode: TDocNode;
  1927. begin
  1928. DocNode := Engine.FindDocNode(AElement);
  1929. If Assigned(DocNode) then
  1930. begin
  1931. // Description
  1932. if Assigned(DocNode.Descr) then
  1933. AppendDescrSection(AElement, BodyElement, DocNode.Descr, SDocDescription);
  1934. // Append "Errors" section
  1935. if Assigned(DocNode.ErrorsDoc) then
  1936. AppendDescrSection(AElement, BodyElement, DocNode.ErrorsDoc, SDocErrors);
  1937. // Append Version info
  1938. if Assigned(DocNode.Version) then
  1939. AppendDescrSection(AElement, BodyElement, DocNode.Version, SDocVersion);
  1940. // Append "See also" section
  1941. AppendSeeAlsoSection(AElement,DocNode);
  1942. // Append examples, if present
  1943. AppendExampleSection(AElement,DocNode);
  1944. end;
  1945. end;
  1946. Procedure THTMLWriter.CreateTopicPageBody(AElement : TTopicElement);
  1947. var
  1948. DocNode: TDocNode;
  1949. TableEl, TREl: TDOMElement;
  1950. I : Integer;
  1951. S : String;
  1952. begin
  1953. AppendTopicMenuBar(AElement);
  1954. DocNode:=AElement.TopicNode;
  1955. if Assigned(DocNode) then // should always be true, but we're being careful.
  1956. begin
  1957. AppendShortDescr(AElement,TitleElement, DocNode);
  1958. AppendShortDescr(AElement,CreateH2(BodyElement), DocNode);
  1959. if Assigned(DocNode.Descr) then
  1960. AppendDescrSection(AElement, BodyElement, DocNode.Descr, '');
  1961. AppendSeeAlsoSection(AElement,DocNode);
  1962. CreateTopicLinks(DocNode,AElement);
  1963. AppendExampleSection(AElement,DocNode);
  1964. end;
  1965. end;
  1966. procedure THTMLWriter.CreatePageBody(AElement: TPasElement;
  1967. ASubpageIndex: Integer);
  1968. var
  1969. i: Integer;
  1970. Element: TPasElement;
  1971. begin
  1972. CurDirectory := Allocator.GetFilename(AElement, ASubpageIndex);
  1973. i := Length(CurDirectory);
  1974. while (i > 0) and not (CurDirectory[i] in AllowDirectorySeparators) do
  1975. Dec(i);
  1976. CurDirectory := Copy(CurDirectory, 1, i);
  1977. BaseDirectory := Allocator.GetRelativePathToTop(AElement);
  1978. if AElement.ClassType = TPasPackage then
  1979. begin
  1980. Module:=Nil;
  1981. If (ASubPageIndex=0) then
  1982. CreatePackagePageBody
  1983. else if ASubPageIndex=IndexSubIndex then
  1984. CreatePackageIndex
  1985. end
  1986. else
  1987. begin
  1988. Element := AElement;
  1989. while (Element<>Nil) and (Element.ClassType<>TPasModule) do
  1990. Element := Element.Parent;
  1991. Module := TPasModule(Element);
  1992. if AElement.ClassType = TPasModule then
  1993. CreateModulePageBody(TPasModule(AElement), ASubpageIndex)
  1994. else if AElement.Parent.InheritsFrom(TPasClassType) then
  1995. CreateClassMemberPageBody(AElement)
  1996. else if AElement.ClassType = TPasConst then
  1997. CreateConstPageBody(TPasConst(AElement))
  1998. else if AElement.InheritsFrom(TPasClassType) then
  1999. CreateClassPageBody(TPasClassType(AElement), ASubpageIndex)
  2000. else if AElement.InheritsFrom(TPasType) then
  2001. CreateTypePageBody(TPasType(AElement))
  2002. else if AElement.ClassType = TPasVariable then
  2003. CreateVarPageBody(TPasVariable(AElement))
  2004. else if AElement.InheritsFrom(TPasProcedureBase) then
  2005. CreateProcPageBody(TPasProcedure(AElement))
  2006. else if AElement.ClassType = TTopicELement then
  2007. CreateTopicPageBody(TTopicElement(AElement))
  2008. end;
  2009. end;
  2010. procedure THTMLWriter.CreateIndexPage(L : TStringList);
  2011. Var
  2012. Lists : Array['A'..'Z'] of TStringList;
  2013. LOther : TStringList;
  2014. CL : TStringList;
  2015. TableEl, TREl, EL: TDOMElement;
  2016. E : TPasElement;
  2017. I,Rows,J,Index : Integer;
  2018. S : String;
  2019. C : Char;
  2020. begin
  2021. For C:='A' to 'Z' do
  2022. Lists[C]:=Nil;
  2023. L.Sort;
  2024. Cl:=Nil;
  2025. // Divide over alphabet
  2026. For I:=0 to L.Count-1 do
  2027. begin
  2028. S:=L[i];
  2029. E:=TPasElement(L.Objects[i]);
  2030. If not (E is TPasUnresolvedTypeRef) then
  2031. begin
  2032. If (S<>'') then
  2033. begin
  2034. C:=Upcase(S[1]);
  2035. If C='_' then
  2036. C:='A';
  2037. If (C in ['A'..'Z']) and (Lists[C]=Nil) then
  2038. begin
  2039. CL:=TStringList.Create;
  2040. Lists[C]:=CL;
  2041. end;
  2042. end;
  2043. if assigned(cl) then
  2044. CL.AddObject(S,E);
  2045. end;
  2046. end;
  2047. Try
  2048. // Create a quick jump table to all available letters.
  2049. TableEl := CreateTable(BodyElement);
  2050. TableEl['border']:='1';
  2051. TableEl['width']:='50%';
  2052. TREl := CreateTR(TableEl);
  2053. for C:='A' to 'Z' do
  2054. If (Lists[C]<>Nil) then
  2055. begin
  2056. El:=CreateTD_vtop(TREl);
  2057. AppendText(CreateLink(El,'#SECTION'+C),C);
  2058. If C<>'Z' then
  2059. AppendNBsp(El,1);
  2060. end;
  2061. // Now emit all identifiers.
  2062. TableEl:=Nil;
  2063. For C:='A' to 'Z' do
  2064. begin
  2065. CL:=Lists[C];
  2066. If CL<>Nil then
  2067. begin
  2068. El:=CreateH2(BodyElement);
  2069. AppendText(El,C);
  2070. CreateAnchor(El,'SECTION'+C);
  2071. TableEl := CreateTable(BodyElement);
  2072. TableEl['Width']:='80%';
  2073. // Determine number of rows needed
  2074. Rows:=(CL.Count div IndexColCount);
  2075. If ((CL.Count Mod IndexColCount)<>0) then
  2076. Inc(Rows);
  2077. // Fill rows
  2078. For I:=0 to Rows-1 do
  2079. begin
  2080. TREl := CreateTR(TableEl);
  2081. For J:=0 to IndexColCount-1 do
  2082. begin
  2083. El:=CreateTD_vtop(TREl);
  2084. Index:=(J*Rows)+I;
  2085. If (Index<CL.Count) then
  2086. begin
  2087. S:=CL[Index];
  2088. E:=TPasElement(CL.Objects[Index]);
  2089. AppendHyperlink(El,E);
  2090. end;
  2091. end;
  2092. end;
  2093. end; // have List
  2094. end; // For C:=
  2095. Finally
  2096. for C:='A' to 'Z' do
  2097. FreeAndNil(Lists[C]);
  2098. end;
  2099. end;
  2100. procedure THTMLWriter.AddModuleIdentifiers(AModule : TPasModule; L : TStrings);
  2101. Procedure AddElementsFromList(L : TStrings; List : TFPList);
  2102. Var
  2103. I : Integer;
  2104. El : TPasElement;
  2105. begin
  2106. For I:=0 to List.Count-1 do
  2107. begin
  2108. El:=TPasElement(List[I]);
  2109. L.AddObject(El.Name,El);
  2110. If el is TPasEnumType then
  2111. AddElementsFromList(L,TPasEnumType(el).Values);
  2112. end;
  2113. end;
  2114. begin
  2115. AddElementsFromList(L,AModule.InterfaceSection.Consts);
  2116. AddElementsFromList(L,AModule.InterfaceSection.Types);
  2117. AddElementsFromList(L,AModule.InterfaceSection.Functions);
  2118. AddElementsFromList(L,AModule.InterfaceSection.Classes);
  2119. AddElementsFromList(L,AModule.InterfaceSection.Variables);
  2120. AddElementsFromList(L,AModule.InterfaceSection.ResStrings);
  2121. end;
  2122. procedure THTMLWriter.CreatePackageIndex;
  2123. Var
  2124. L : TStringList;
  2125. I : Integer;
  2126. M : TPasModule;
  2127. E : TPasElement;
  2128. S : String;
  2129. begin
  2130. L:=TStringList.Create;
  2131. try
  2132. L.Capacity:=PageInfos.Count; // Too much, but that doesn't hurt.
  2133. For I:=0 to Package.Modules.Count-1 do
  2134. begin
  2135. M:=TPasModule(Package.Modules[i]);
  2136. L.AddObject(M.Name,M);
  2137. AddModuleIdentifiers(M,L);
  2138. end;
  2139. AppendMenuBar(IndexSubIndex);
  2140. S:=Package.Name;
  2141. If Length(S)>0 then
  2142. Delete(S,1,1);
  2143. AppendTitle(Format(SDocPackageIndex, [S]));
  2144. CreateIndexPage(L);
  2145. Finally
  2146. L.Free;
  2147. end;
  2148. end;
  2149. procedure THTMLWriter.CreatePackagePageBody;
  2150. var
  2151. DocNode: TDocNode;
  2152. TableEl, TREl: TDOMElement;
  2153. i: Integer;
  2154. ThisModule: TPasModule;
  2155. L : TStringList;
  2156. begin
  2157. AppendMenuBar(0);
  2158. AppendTitle(Format(SDocPackageTitle, [Copy(Package.Name, 2, 256)]));
  2159. AppendShortDescr(CreatePara(BodyElement), Package);
  2160. AppendText(CreateH2(BodyElement), SDocUnits);
  2161. TableEl := CreateTable(BodyElement);
  2162. L:=TStringList.Create;
  2163. Try
  2164. L.Sorted:=True;
  2165. // Sort modules.
  2166. For I:=0 to Package.Modules.Count-1 do
  2167. L.AddObject(TPasModule(Package.Modules[i]).Name,TPasModule(Package.Modules[i]));
  2168. // Now create table.
  2169. for i:=0 to L.Count - 1 do
  2170. begin
  2171. ThisModule := TPasModule(L.Objects[i]);
  2172. TREl := CreateTR(TableEl);
  2173. AppendHyperlink(CreateCode(CreatePara(CreateTD_vtop(TREl))), ThisModule);
  2174. AppendShortDescrCell(TREl, ThisModule);
  2175. end;
  2176. Finally
  2177. L.Free;
  2178. end;
  2179. DocNode := Engine.FindDocNode(Package);
  2180. if Assigned(DocNode) then
  2181. begin
  2182. if Assigned(DocNode.Descr) then
  2183. AppendDescrSection(nil, BodyElement, DocNode.Descr, SDocDescription);
  2184. CreateTopicLinks(DocNode,Package);
  2185. end;
  2186. end;
  2187. Procedure THTMLWriter.CreateTopicLinks(Node : TDocNode; PasElement : TPasElement);
  2188. var
  2189. DocNode: TDocNode;
  2190. TableEl, TREl: TDOMElement;
  2191. First : Boolean;
  2192. ThisTopic: TPasElement;
  2193. begin
  2194. DocNode:=Node.FirstChild;
  2195. First:=True;
  2196. While Assigned(DocNode) do
  2197. begin
  2198. If DocNode.TopicNode then
  2199. begin
  2200. if first then
  2201. begin
  2202. First:=False;
  2203. AppendText(CreateH2(BodyElement), SDocRelatedTopics);
  2204. TableEl := CreateTable(BodyElement);
  2205. end;
  2206. TREl := CreateTR(TableEl);
  2207. ThisTopic:=FindTopicElement(DocNode);
  2208. if Assigned(ThisTopic) then
  2209. AppendHyperlink(CreateCode(CreatePara(CreateTD_vtop(TREl))), ThisTopic);
  2210. AppendShortDescrCell(TREl, ThisTopic);
  2211. end;
  2212. DocNode:=DocNode.NextSibling;
  2213. end;
  2214. end;
  2215. procedure THTMLWriter.CreateModuleIndexPage(AModule: TPasModule);
  2216. Var
  2217. L : TStringList;
  2218. begin
  2219. L:=TStringList.Create;
  2220. try
  2221. AddModuleIdentifiers(AModule,L);
  2222. AppendMenuBar(IndexSubIndex);
  2223. AppendTitle(Format(SDocModuleIndex, [AModule.Name]));
  2224. CreateIndexPage(L);
  2225. Finally
  2226. L.Free;
  2227. end;
  2228. end;
  2229. procedure THTMLWriter.CreateModulePageBody(AModule: TPasModule;
  2230. ASubpageIndex: Integer);
  2231. procedure CreateMainPage;
  2232. var
  2233. TableEl, TREl, TDEl, CodeEl: TDOMElement;
  2234. i: Integer;
  2235. UnitRef: TPasType;
  2236. DocNode: TDocNode;
  2237. begin
  2238. AppendMenuBar(0);
  2239. AppendTitle(Format(SDocUnitTitle, [AModule.Name]));
  2240. AppendShortDescr(CreatePara(BodyElement), AModule);
  2241. if AModule.InterfaceSection.UsesList.Count > 0 then
  2242. begin
  2243. TableEl := CreateTable(BodyElement);
  2244. AppendKw(CreateCode(CreatePara(CreateTD(CreateTR(TableEl)))), 'uses');
  2245. for i := 0 to AModule.InterfaceSection.UsesList.Count - 1 do
  2246. begin
  2247. UnitRef := TPasType(AModule.InterfaceSection.UsesList[i]);
  2248. DocNode := Engine.FindDocNode(UnitRef);
  2249. if Assigned(DocNode) and DocNode.IsSkipped then
  2250. continue;
  2251. TREl := CreateTR(TableEl);
  2252. TDEl := CreateTD_vtop(TREl);
  2253. CodeEl := CreateCode(CreatePara(TDEl));
  2254. AppendNbSp(CodeEl, 2);
  2255. AppendHyperlink(CodeEl, UnitRef);
  2256. if i < AModule.InterfaceSection.UsesList.Count - 1 then
  2257. AppendSym(CodeEl, ',')
  2258. else
  2259. AppendSym(CodeEl, ';');
  2260. AppendText(CodeEl, ' '); // Space for descriptions
  2261. AppendShortDescrCell(TREl, UnitRef);
  2262. end;
  2263. end;
  2264. DocNode := Engine.FindDocNode(AModule);
  2265. if Assigned(DocNode) then
  2266. begin
  2267. if Assigned(DocNode.Descr) then
  2268. AppendDescrSection(AModule, BodyElement, DocNode.Descr, SDocOverview);
  2269. CreateTopicLinks(DocNode,AModule);
  2270. end;
  2271. end;
  2272. procedure CreateSimpleSubpage(const ATitle: DOMString; AList: TFPList);
  2273. var
  2274. TableEl, TREl, TDEl, CodeEl: TDOMElement;
  2275. i, j: Integer;
  2276. Decl: TPasElement;
  2277. SortedList: TFPList;
  2278. DocNode: TDocNode;
  2279. S : String;
  2280. begin
  2281. AppendMenuBar(ASubpageIndex);
  2282. S:=ATitle;
  2283. AppendTitle(Format(SDocUnitTitle + ': %s', [AModule.Name, S]));
  2284. SortedList := TFPList.Create;
  2285. try
  2286. for i := 0 to AList.Count - 1 do
  2287. begin
  2288. Decl := TPasElement(AList[i]);
  2289. DocNode := Engine.FindDocNode(Decl);
  2290. if (not Assigned(DocNode)) or (not DocNode.IsSkipped) then
  2291. begin
  2292. j := 0;
  2293. while (j < SortedList.Count) and (CompareText(
  2294. TPasElement(SortedList[j]).PathName, Decl.PathName) < 0) do
  2295. Inc(j);
  2296. SortedList.Insert(j, Decl);
  2297. end;
  2298. end;
  2299. TableEl := CreateTable(BodyElement);
  2300. for i := 0 to SortedList.Count - 1 do
  2301. begin
  2302. Decl := TPasElement(SortedList[i]);
  2303. TREl := CreateTR(TableEl);
  2304. CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
  2305. AppendHyperlink(CodeEl, Decl);
  2306. AppendShortDescrCell(TREl, Decl);
  2307. end;
  2308. finally
  2309. SortedList.Free;
  2310. end;
  2311. end;
  2312. procedure CreateResStringsPage;
  2313. var
  2314. ParaEl: TDOMElement;
  2315. i, j: Integer;
  2316. Decl: TPasResString;
  2317. DocNode: TDocNode;
  2318. begin
  2319. AppendMenuBar(ResstrSubindex);
  2320. AppendTitle(Format(SDocUnitTitle + ': %s', [AModule.Name, SDocResStrings]));
  2321. for i := 0 to AModule.InterfaceSection.ResStrings.Count - 1 do
  2322. begin
  2323. Decl := TPasResString(AModule.InterfaceSection.ResStrings[i]);
  2324. CreateEl(BodyElement, 'a')['name'] := LowerCase(Decl.Name);
  2325. ParaEl := CreatePara(BodyElement);
  2326. AppendText(CreateCode(ParaEl), Decl.Name);
  2327. CreateEl(ParaEl, 'br');
  2328. AppendText(ParaEl, Decl.Expr.getDeclaration(true));
  2329. end;
  2330. end;
  2331. begin
  2332. case ASubpageIndex of
  2333. 0:
  2334. CreateMainPage;
  2335. ResstrSubindex:
  2336. CreateResStringsPage;
  2337. ConstsSubindex:
  2338. CreateSimpleSubpage(SDocConstants, AModule.InterfaceSection.Consts);
  2339. TypesSubindex:
  2340. CreateSimpleSubpage(SDocTypes, AModule.InterfaceSection.Types);
  2341. ClassesSubindex:
  2342. CreateSimpleSubpage(SDocClasses, AModule.InterfaceSection.Classes);
  2343. ProcsSubindex:
  2344. CreateSimpleSubpage(SDocProceduresAndFunctions, AModule.InterfaceSection.Functions);
  2345. VarsSubindex:
  2346. CreateSimpleSubpage(SDocVariables, AModule.InterfaceSection.Variables);
  2347. IndexSubIndex:
  2348. CreateModuleIndexPage(AModule);
  2349. end;
  2350. end;
  2351. procedure THTMLWriter.CreateConstPageBody(AConst: TPasConst);
  2352. var
  2353. TableEl, CodeEl: TDOMElement;
  2354. begin
  2355. AppendMenuBar(-1);
  2356. AppendTitle(AConst.Name);
  2357. AppendShortDescr(CreatePara(BodyElement), AConst);
  2358. AppendText(CreateH2(BodyElement), SDocDeclaration);
  2359. AppendSourceRef(AConst);
  2360. TableEl := CreateTable(BodyElement);
  2361. CodeEl := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
  2362. AppendKw(CodeEl, 'const');
  2363. AppendText(CodeEl, ' ' + AConst.Name);
  2364. if Assigned(AConst.VarType) then
  2365. begin
  2366. AppendSym(CodeEl, ': ');
  2367. AppendType(CodeEl, TableEl, AConst.VarType, False);
  2368. end;
  2369. AppendPasSHFragment(CodeEl, ' = ' + AConst.Expr.GetDeclaration(True) + ';', 0);
  2370. FinishElementPage(AConst);
  2371. end;
  2372. procedure THTMLWriter.CreateTypePageBody(AType: TPasType);
  2373. var
  2374. TableEl, TREl, TDEl, CodeEl: TDOMElement;
  2375. DocNode: TDocNode;
  2376. i: Integer;
  2377. s: String;
  2378. EnumType: TPasEnumType;
  2379. EnumValue: TPasEnumValue;
  2380. Variable: TPasVariable;
  2381. begin
  2382. AppendMenuBar(-1);
  2383. AppendTitle(AType.Name);
  2384. AppendShortDescr(CreatePara(BodyElement), AType);
  2385. AppendText(CreateH2(BodyElement), SDocDeclaration);
  2386. AppendSourceRef(AType);
  2387. TableEl := CreateTable(BodyElement);
  2388. TREl := CreateTR(TableEl);
  2389. TDEl := CreateTD(TREl);
  2390. CodeEl := CreateCode(CreatePara(TDEl));
  2391. DocNode := Engine.FindDocNode(AType);
  2392. AppendKw(CodeEl, 'type ');
  2393. AppendText(CodeEl, AType.Name);
  2394. AppendSym(CodeEl, ' = ');
  2395. If Assigned(DocNode) and
  2396. Assigned(DocNode.Node) and
  2397. (Docnode.Node['opaque']='1') then
  2398. AppendText(CodeEl,SDocOpaque)
  2399. else
  2400. begin
  2401. // Alias
  2402. if AType.ClassType = TPasAliasType then
  2403. begin
  2404. if Assigned(TPasAliasType(AType).DestType) then
  2405. AppendHyperlink(CodeEl, TPasAliasType(AType).DestType)
  2406. else
  2407. AppendText(CreateWarning(CodeEl), '<Destination type is NIL>');
  2408. AppendSym(CodeEl, ';');
  2409. end else
  2410. // Class of
  2411. if AType.ClassType = TPasClassOfType then
  2412. begin
  2413. AppendKw(CodeEl, 'class of ');
  2414. AppendHyperlink(CodeEl, TPasClassOfType(AType).DestType);
  2415. AppendSym(CodeEl, ';');
  2416. end else
  2417. // Enumeration
  2418. if AType.ClassType = TPasEnumType then
  2419. begin
  2420. AppendSym(CodeEl, '(');
  2421. for i := 0 to TPasEnumType(AType).Values.Count - 1 do
  2422. begin
  2423. EnumValue := TPasEnumValue(TPasEnumType(AType).Values[i]);
  2424. TREl := CreateTR(TableEl);
  2425. CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
  2426. AppendShortDescrCell(TREl, EnumValue);
  2427. AppendNbSp(CodeEl, 2);
  2428. s := EnumValue.Name;
  2429. if EnumValue.AssignedValue<>'' then
  2430. s := s + ' = ' + EnumValue.AssignedValue;
  2431. if i < TPasEnumType(AType).Values.Count - 1 then
  2432. s := s + ',';
  2433. AppendPasSHFragment(CodeEl, s, 0);
  2434. end;
  2435. AppendSym(CreateCode(CreatePara(CreateTD(CreateTR(TableEl)))), ');');
  2436. end else
  2437. // Pointer type
  2438. if AType.ClassType = TPasPointerType then
  2439. begin
  2440. AppendSym(CodeEl, '^');
  2441. if Assigned(TPasPointerType(AType).DestType) then
  2442. AppendHyperlink(CodeEl, TPasPointerType(AType).DestType)
  2443. else
  2444. AppendText(CreateWarning(CodeEl), '<Destination type is NIL>');
  2445. AppendSym(CodeEl, ';');
  2446. end else
  2447. if AType.InheritsFrom(TPasProcedureType) then
  2448. begin
  2449. AppendSym(AppendType(CodeEl, TableEl, TPasType(AType), True), ';');
  2450. AppendProcArgsSection(BodyElement, TPasProcedureType(AType));
  2451. end else
  2452. // Record
  2453. if AType.ClassType = TPasRecordType then
  2454. begin
  2455. CodeEl := AppendRecordType(CodeEl, TableEl, TPasRecordType(AType), 0);
  2456. AppendSym(CodeEl, ';');
  2457. end else
  2458. // Set
  2459. if AType.ClassType = TPasSetType then
  2460. begin
  2461. AppendKw(CodeEl, 'set of ');
  2462. if TPasSetType(AType).EnumType.ClassType = TPasEnumType then
  2463. begin
  2464. AppendSym(CodeEl, '(');
  2465. EnumType := TPasEnumType(TPasSetType(AType).EnumType);
  2466. for i := 0 to EnumType.Values.Count - 1 do
  2467. begin
  2468. EnumValue := TPasEnumValue(EnumType.Values[i]);
  2469. TREl := CreateTR(TableEl);
  2470. CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
  2471. AppendShortDescrCell(TREl, EnumValue);
  2472. AppendNbSp(CodeEl, 2);
  2473. s := EnumValue.Name;
  2474. if (EnumValue.AssignedValue<>'') then
  2475. s := s + ' = ' + EnumValue.AssignedValue;
  2476. if i < EnumType.Values.Count - 1 then
  2477. s := s + ',';
  2478. AppendPasSHFragment(CodeEl, s, 0);
  2479. end;
  2480. AppendSym(CreateCode(CreatePara(CreateTD(CreateTR(TableEl)))), ');');
  2481. end else
  2482. begin
  2483. AppendHyperlink(CodeEl, TPasSetType(AType).EnumType);
  2484. AppendSym(CodeEl, ';');
  2485. end;
  2486. end else
  2487. // Type alias
  2488. if AType.ClassType = TPasTypeAliasType then
  2489. begin
  2490. AppendKw(CodeEl, 'type ');
  2491. AppendHyperlink(CodeEl, TPasTypeAliasType(AType).DestType);
  2492. AppendSym(CodeEl, ';');
  2493. end else
  2494. // Probably one of the simple types, which allowed in other places as wel...
  2495. AppendSym(AppendType(CodeEl, TableEl, TPasType(AType), True), ';');
  2496. end;
  2497. FinishElementPage(AType);
  2498. end;
  2499. function PropertyFilter(AMember: TPasElement): Boolean;
  2500. begin
  2501. Result := (AMember.ClassType = TPasProperty) and
  2502. (Copy(AMember.Name, 1, 2) <> 'On');
  2503. end;
  2504. function MethodFilter(AMember: TPasElement): Boolean;
  2505. begin
  2506. Result := AMember.InheritsFrom(TPasProcedureBase);
  2507. end;
  2508. function EventFilter(AMember: TPasElement): Boolean;
  2509. begin
  2510. Result := (AMember.ClassType = TPasProperty) and
  2511. (Copy(AMember.Name, 1, 2) = 'On');
  2512. end;
  2513. procedure THTMLWriter.CreateClassPageBody(AClass: TPasClassType;
  2514. ASubpageIndex: Integer);
  2515. type
  2516. TMemberFilter = function(AMember: TPasElement): Boolean;
  2517. var
  2518. ParaEl: TDOMElement;
  2519. procedure AppendMemberListLink(AListSubpageIndex: Integer;
  2520. const AText: DOMString);
  2521. var
  2522. LinkEl: TDOMElement;
  2523. begin
  2524. AppendText(ParaEl, '[');
  2525. LinkEl := CreateEl(ParaEl, 'a');
  2526. LinkEl['href'] :=
  2527. FixHtmlPath(ResolveLinkWithinPackage(AClass, AListSubpageIndex));
  2528. LinkEl['onClick'] := 'window.open(''' + LinkEl['href'] + ''', ''list'', ' +
  2529. '''dependent=yes,resizable=yes,scrollbars=yes,height=400,width=300''); return false;';
  2530. AppendText(LinkEl, AText);
  2531. AppendText(ParaEl, ' (');
  2532. LinkEl := CreateEl(ParaEl, 'a');
  2533. LinkEl['href'] :=
  2534. FixHtmlPath(ResolveLinkWithinPackage(AClass, AListSubpageIndex + 1));
  2535. LinkEl['onClick'] := 'window.open(''' + LinkEl['href'] + ''', ''list'', ' +
  2536. '''dependent=yes,resizable=yes,scrollbars=yes,height=400,width=300''); return false;';
  2537. AppendText(LinkEl, SDocByName);
  2538. AppendText(ParaEl, ')');
  2539. AppendText(ParaEl, '] ');
  2540. end;
  2541. procedure AppendGenericTypes(CodeEl : TDomElement; AList : TFPList; isSpecialize : Boolean);
  2542. Var
  2543. I : integer;
  2544. begin
  2545. for I:=0 to AList.Count-1 do
  2546. begin
  2547. if I=0 then
  2548. AppendSym(CodeEl, '<')
  2549. else
  2550. AppendSym(CodeEl, ',');
  2551. AppendText(CodeEl,TPasGenericTemplateType(AList[i]).Name);
  2552. end;
  2553. AppendSym(CodeEl, '>');
  2554. end;
  2555. procedure CreateMainPage;
  2556. var
  2557. TableEl, TREl, TDEl, CodeEl: TDOMElement;
  2558. DocNode: TDocNode;
  2559. Member: TPasElement;
  2560. CurVisibility: TPasMemberVisibility;
  2561. i: Integer;
  2562. s: String;
  2563. ThisInterface,
  2564. ThisClass: TPasClassType;
  2565. HaveSeenTObject: Boolean;
  2566. begin
  2567. AppendMenuBar(-1);
  2568. AppendTitle(AClass.Name);
  2569. ParaEl := CreatePara(BodyElement);
  2570. AppendMemberListLink(PropertiesByInheritanceSubindex, SDocProperties);
  2571. AppendMemberListLink(MethodsByInheritanceSubindex, SDocMethods);
  2572. AppendMemberListLink(EventsByInheritanceSubindex, SDocEvents);
  2573. AppendShortDescr(CreatePara(BodyElement), AClass);
  2574. AppendText(CreateH2(BodyElement), SDocDeclaration);
  2575. AppendSourceRef(AClass);
  2576. TableEl := CreateTable(BodyElement);
  2577. TREl := CreateTR(TableEl);
  2578. TDEl := CreateTD(TREl);
  2579. CodeEl := CreateCode(CreatePara(TDEl));
  2580. AppendKw(CodeEl, 'type');
  2581. if AClass.ObjKind=okGeneric then
  2582. AppendKw(CodeEl, ' generic ');
  2583. AppendText(CodeEl, ' ' + AClass.Name + ' ');
  2584. if AClass.ObjKind=okGeneric then
  2585. AppendGenericTypes(CodeEl,AClass.GenericTemplateTypes,false);
  2586. AppendSym(CodeEl, '=');
  2587. AppendText(CodeEl, ' ');
  2588. if AClass.ObjKind<>okSpecialize then
  2589. AppendKw(CodeEl, ObjKindNames[AClass.ObjKind])
  2590. else
  2591. AppendKw(CodeEl, ' specialize ');
  2592. if Assigned(AClass.AncestorType) then
  2593. begin
  2594. if AClass.ObjKind=okSpecialize then
  2595. begin
  2596. AppendHyperlink(CodeEl, AClass.AncestorType);
  2597. AppendGenericTypes(CodeEl,AClass.GenericTemplateTypes,true)
  2598. end
  2599. else
  2600. begin
  2601. AppendSym(CodeEl, '(');
  2602. AppendHyperlink(CodeEl, AClass.AncestorType);
  2603. if AClass.Interfaces.count>0 Then
  2604. begin
  2605. for i:=0 to AClass.interfaces.count-1 do
  2606. begin
  2607. AppendSym(CodeEl, ', ');
  2608. AppendHyperlink(CodeEl,TPasClassType(AClass.Interfaces[i]));
  2609. end;
  2610. end;
  2611. AppendSym(CodeEl, ')');
  2612. end;
  2613. end;
  2614. if AClass.Members.Count > 0 then
  2615. begin
  2616. CurVisibility := visDefault;
  2617. for i := 0 to AClass.Members.Count - 1 do
  2618. begin
  2619. Member := TPasElement(AClass.Members[i]);
  2620. if CurVisibility <> Member.Visibility then
  2621. begin
  2622. CurVisibility := Member.Visibility;
  2623. if ((CurVisibility = visPrivate) and Engine.HidePrivate) or
  2624. ((CurVisibility = visProtected) and Engine.HideProtected) then
  2625. continue;
  2626. case CurVisibility of
  2627. visPrivate: s := 'private';
  2628. visProtected: s := 'protected';
  2629. visPublic: s := 'public';
  2630. visPublished: s := 'published';
  2631. visAutomated: s := 'automated';
  2632. end;
  2633. AppendKw(CreateCode(CreatePara(CreateTD(CreateTR(TableEl)))), s);
  2634. end else
  2635. if ((CurVisibility = visPrivate) and Engine.HidePrivate) or
  2636. ((CurVisibility = visProtected) and Engine.HideProtected) then
  2637. continue;
  2638. TREl := CreateTR(TableEl);
  2639. CodeEl := CreateCode(CreatePara(CreateTD_vtop(TREl)));
  2640. AppendNbSp(CodeEl, 2);
  2641. AppendShortDescrCell(TREl, Member);
  2642. if Member.InheritsFrom(TPasProcedureBase) then
  2643. begin
  2644. AppendKw(CodeEl, TPasProcedureBase(Member).TypeName + ' ');
  2645. AppendHyperlink(CodeEl, Member);
  2646. if (Member.ClassType = TPasOverloadedProc) or
  2647. (TPasProcedure(Member).ProcType.Args.Count > 0) then
  2648. AppendSym(CodeEl, '();')
  2649. else
  2650. AppendSym(CodeEl, ';');
  2651. if Member.ClassType <> TPasOverloadedProc then
  2652. AppendProcExt(CodeEl, TPasProcedure(Member));
  2653. end else
  2654. if Member.ClassType = TPasVariable then
  2655. begin
  2656. AppendHyperlink(CodeEl, Member);
  2657. AppendSym(CodeEl, ': ');
  2658. AppendHyperlink(CodeEl, TPasVariable(Member).VarType);
  2659. AppendSym(CodeEl, ';');
  2660. end else
  2661. if Member.ClassType = TPasProperty then
  2662. begin
  2663. AppendKw(CodeEl, 'property ');
  2664. AppendHyperlink(CodeEl, Member);
  2665. if Assigned(TPasProperty(Member).VarType) then
  2666. begin
  2667. AppendSym(CodeEl, ': ');
  2668. AppendHyperlink(CodeEl, TPasProperty(Member).VarType);
  2669. end;
  2670. AppendSym(CodeEl, ';');
  2671. if TPasProperty(Member).IsDefault then
  2672. begin
  2673. AppendKw(CodeEl, ' default');
  2674. AppendSym(CodeEl, ';');
  2675. end;
  2676. if (TPasProperty(Member).ImplementsName<>'') then
  2677. begin
  2678. AppendKw(CodeEl, ' implements');
  2679. AppendText(CodeEl, ' '+TPasProperty(Member).ImplementsName);
  2680. AppendSym(CodeEl, ';');
  2681. end;
  2682. SetLength(s, 0);
  2683. if Length(TPasProperty(Member).ReadAccessorName) > 0 then
  2684. s := s + 'r';
  2685. if Length(TPasProperty(Member).WriteAccessorName) > 0 then
  2686. s := s + 'w';
  2687. if Length(TPasProperty(Member).StoredAccessorName) > 0 then
  2688. s := s + 's';
  2689. if Length(s) > 0 then
  2690. AppendText(CodeEl, ' [' + s + ']');
  2691. end else
  2692. AppendText(CreateWarning(CodeEl), '<' + Member.ClassName + '>');
  2693. end;
  2694. CodeEl := CreateCode(CreatePara(CreateTD(CreateTR(TableEl))));
  2695. end;
  2696. AppendText(CodeEl, ' '); // !!!: Dirty trick, necessary for current XML writer
  2697. if not AClass.IsShortDefinition then
  2698. AppendKw(CodeEl, 'end');
  2699. AppendSym(CodeEl, ';');
  2700. AppendText(CreateH2(BodyElement), SDocInheritance);
  2701. TableEl := CreateTable(BodyElement);
  2702. HaveSeenTObject := AClass.ObjKind <> okClass;
  2703. ThisClass := AClass;
  2704. while True do
  2705. begin
  2706. TREl := CreateTR(TableEl);
  2707. TDEl := CreateTD_vtop(TREl);
  2708. TDEl['align'] := 'center';
  2709. CodeEl := CreateCode(CreatePara(TDEl));
  2710. AppendHyperlink(CodeEl, ThisClass);
  2711. if ThisClass.Interfaces.count>0 then
  2712. begin
  2713. for i:=0 to ThisClass.interfaces.count-1 do
  2714. begin
  2715. ThisInterface:=TPasClassType(ThisClass.Interfaces[i]);
  2716. AppendText(CodeEl,',');
  2717. AppendHyperlink(CodeEl, ThisInterface);
  2718. end;
  2719. end;
  2720. AppendShortDescrCell(TREl, ThisClass);
  2721. if HaveSeenTObject or (CompareText(ThisClass.Name, 'TObject') = 0) then
  2722. HaveSeenTObject := True
  2723. else
  2724. begin
  2725. TDEl := CreateTD(CreateTR(TableEl));
  2726. TDEl['align'] := 'center';
  2727. AppendText(TDEl, '|');
  2728. end;
  2729. if Assigned(ThisClass.AncestorType) then
  2730. begin
  2731. if ThisClass.AncestorType.InheritsFrom(TPasClassType) then
  2732. ThisClass := TPasClassType(ThisClass.AncestorType)
  2733. else
  2734. begin
  2735. TDEl := CreateTD(CreateTR(TableEl));
  2736. TDEl['align'] := 'center';
  2737. AppendText(CreateCode(CreatePara(TDEl)), ThisClass.AncestorType.Name);
  2738. if CompareText(ThisClass.AncestorType.Name, 'TObject') = 0 then
  2739. HaveSeenTObject := True
  2740. else
  2741. begin
  2742. TDEl := CreateTD(CreateTR(TableEl));
  2743. TDEl['align'] := 'center';
  2744. AppendText(TDEl, '?');
  2745. end;
  2746. break;
  2747. end
  2748. end else
  2749. break;
  2750. end;
  2751. if not HaveSeenTObject then
  2752. begin
  2753. TDEl := CreateTD(CreateTR(TableEl));
  2754. TDEl['align'] := 'center';
  2755. AppendText(CreateCode(CreatePara(TDEl)), 'TObject');
  2756. end;
  2757. FinishElementPage(AClass);
  2758. end;
  2759. procedure CreateInheritanceSubpage(AFilter: TMemberFilter);
  2760. var
  2761. ThisClass: TPasClassType;
  2762. i: Integer;
  2763. Member: TPasElement;
  2764. TableEl, TREl, TDEl, ParaEl, LinkEl: TDOMElement;
  2765. begin
  2766. TableEl := CreateTable(BodyElement);
  2767. ThisClass := AClass;
  2768. while True do
  2769. begin
  2770. TREl := CreateTR(TableEl);
  2771. TDEl := CreateTD(TREl);
  2772. TDEl['colspan'] := '3';
  2773. CreateTD(TREl);
  2774. LinkEl := AppendHyperlink(CreateEl(CreateCode(CreatePara(TDEl)), 'b'), ThisClass);
  2775. if Assigned(LinkEl) then
  2776. LinkEl['onClick'] := 'opener.location.href = ''' + LinkEl['href'] +
  2777. '''; return false;';
  2778. for i := 0 to ThisClass.Members.Count - 1 do
  2779. begin
  2780. Member := TPasElement(ThisClass.Members[i]);
  2781. if ((Member.Visibility = visPrivate) and Engine.HidePrivate) or
  2782. ((Member.Visibility = visProtected) and Engine.HideProtected) or
  2783. not AFilter(Member) then
  2784. continue;
  2785. TREl := CreateTR(TableEl);
  2786. ParaEl := CreatePara(CreateTD(TREl));
  2787. case Member.Visibility of
  2788. visPrivate:
  2789. AppendText(ParaEl, 'pv');
  2790. visProtected:
  2791. AppendText(ParaEl, 'pt');
  2792. visPublished:
  2793. AppendText(ParaEl, 'pl');
  2794. end;
  2795. AppendNbSp(ParaEl, 1);
  2796. ParaEl := CreateTD(TREl);
  2797. if (Member.ClassType = TPasProperty) and
  2798. (Length(TPasProperty(Member).WriteAccessorName) = 0) then
  2799. begin
  2800. AppendText(ParaEl, 'ro');
  2801. AppendNbSp(ParaEl, 1);
  2802. end;
  2803. LinkEl := AppendHyperlink(CreatePara(CreateTD(TREl)), Member);
  2804. if Assigned(LinkEl) then
  2805. LinkEl['onClick'] := 'opener.location.href = ''' + LinkEl['href'] +
  2806. '''; return false;';
  2807. end;
  2808. if (not Assigned(ThisClass.AncestorType)) or
  2809. (not (ThisClass.AncestorType.ClassType = TPasClassType)) then
  2810. break;
  2811. ThisClass := TPasClassType(ThisClass.AncestorType);
  2812. AppendNbSp(CreatePara(CreateTD(CreateTR(TableEl))), 1);
  2813. end;
  2814. end;
  2815. procedure CreateSortedSubpage(AFilter: TMemberFilter);
  2816. var
  2817. List: TFPList;
  2818. ThisClass: TPasClassType;
  2819. i, j: Integer;
  2820. Member: TPasElement;
  2821. TableEl, TREl, TDEl, ParaEl, LinkEl: TDOMElement;
  2822. begin
  2823. List := TFPList.Create;
  2824. try
  2825. ThisClass := AClass;
  2826. while True do
  2827. begin
  2828. for i := 0 to ThisClass.Members.Count - 1 do
  2829. begin
  2830. Member := TPasElement(ThisClass.Members[i]);
  2831. if (not (((Member.Visibility = visPrivate) and Engine.HidePrivate) or
  2832. ((Member.Visibility = visProtected) and Engine.HideProtected))) and
  2833. AFilter(Member) then
  2834. begin
  2835. j := 0;
  2836. while (j < List.Count) and
  2837. (CompareText(TPasElement(List[j]).Name, Member.Name) < 0) do
  2838. Inc(j);
  2839. List.Insert(j, Member);
  2840. end;
  2841. end;
  2842. if (not Assigned(ThisClass.AncestorType)) or
  2843. (not (ThisClass.AncestorType.ClassType = TPasClassType)) then
  2844. break;
  2845. ThisClass := TPasClassType(ThisClass.AncestorType);
  2846. end;
  2847. TableEl := CreateTable(BodyElement);
  2848. for i := 0 to List.Count - 1 do
  2849. begin
  2850. Member := TPasElement(List[i]);
  2851. TREl := CreateTR(TableEl);
  2852. ParaEl := CreatePara(CreateTD(TREl));
  2853. case Member.Visibility of
  2854. visPrivate:
  2855. AppendText(ParaEl, 'pv');
  2856. visProtected:
  2857. AppendText(ParaEl, 'pt');
  2858. visPublished:
  2859. AppendText(ParaEl, 'pl');
  2860. end;
  2861. AppendNbSp(ParaEl, 1);
  2862. ParaEl := CreatePara(CreateTD(TREl));
  2863. if (Member.ClassType = TPasProperty) and
  2864. (Length(TPasProperty(Member).WriteAccessorName) = 0) then
  2865. begin
  2866. AppendText(ParaEl, 'ro');
  2867. AppendNbSp(ParaEl, 1);
  2868. end;
  2869. TDEl := CreateTD(TREl);
  2870. TDEl['nowrap'] := 'nowrap';
  2871. ParaEl := CreatePara(TDEl);
  2872. LinkEl := AppendHyperlink(ParaEl, Member);
  2873. if Assigned(LinkEl) then
  2874. LinkEl['onClick'] := 'opener.location.href = ''' + LinkEl['href'] +
  2875. '''; return false;';
  2876. AppendText(ParaEl, ' (');
  2877. LinkEl := AppendHyperlink(ParaEl, Member.Parent);
  2878. if Assigned(LinkEl) then
  2879. LinkEl['onClick'] := 'opener.location.href = ''' + LinkEl['href'] +
  2880. '''; return false;';
  2881. AppendText(ParaEl, ')');
  2882. end;
  2883. finally
  2884. List.Free;
  2885. end;
  2886. end;
  2887. begin
  2888. case ASubpageIndex of
  2889. 0:
  2890. CreateMainPage;
  2891. PropertiesByInheritanceSubindex:
  2892. CreateInheritanceSubpage(@PropertyFilter);
  2893. PropertiesByNameSubindex:
  2894. CreateSortedSubpage(@PropertyFilter);
  2895. MethodsByInheritanceSubindex:
  2896. CreateInheritanceSubpage(@MethodFilter);
  2897. MethodsByNameSubindex:
  2898. CreateSortedSubpage(@MethodFilter);
  2899. EventsByInheritanceSubindex:
  2900. CreateInheritanceSubpage(@EventFilter);
  2901. EventsByNameSubindex:
  2902. CreateSortedSubpage(@EventFilter);
  2903. end;
  2904. end;
  2905. procedure THTMLWriter.CreateClassMemberPageBody(AElement: TPasElement);
  2906. var
  2907. TableEl, TREl, CodeEl: TDOMElement;
  2908. procedure CreateVarPage(Element: TPasVariable);
  2909. begin
  2910. AppendHyperlink(CodeEl, Element.Parent);
  2911. AppendSym(CodeEl, '.');
  2912. AppendText(CodeEl, Element.Name);
  2913. if Assigned(Element.VarType) then
  2914. begin
  2915. AppendSym(CodeEl, ': ');
  2916. AppendSym(AppendType(CodeEl, TableEl, Element.VarType, False), ';');
  2917. end;
  2918. end;
  2919. procedure CreatePropertyPage(Element: TPasProperty);
  2920. var
  2921. NeedBreak: Boolean;
  2922. begin
  2923. AppendKw(CodeEl, 'property ');
  2924. AppendHyperlink(CodeEl, Element.Parent);
  2925. AppendSym(CodeEl, '.');
  2926. AppendText(CodeEl, Element.Name);
  2927. if Assigned(Element.VarType) then
  2928. begin
  2929. AppendSym(CodeEl, ': ');
  2930. AppendType(CodeEl, TableEl, Element.VarType, False);
  2931. end;
  2932. NeedBreak := False;
  2933. if Length(TPasProperty(Element).IndexValue) <> 0 then
  2934. begin
  2935. CreateEl(CodeEl, 'br');
  2936. AppendNbsp(CodeEl, 2);
  2937. AppendKw(CodeEl, 'index ');
  2938. AppendPasSHFragment(CodeEl, TPasProperty(Element).IndexValue, 0);
  2939. NeedBreak := True;
  2940. end;
  2941. if Length(TPasProperty(Element).ReadAccessorName) <> 0 then
  2942. begin
  2943. CreateEl(CodeEl, 'br');
  2944. AppendNbsp(CodeEl, 2);
  2945. AppendKw(CodeEl, 'read ');
  2946. AppendText(CodeEl, TPasProperty(Element).ReadAccessorName);
  2947. NeedBreak := True;
  2948. end;
  2949. if Length(TPasProperty(Element).WriteAccessorName) <> 0 then
  2950. begin
  2951. CreateEl(CodeEl, 'br');
  2952. AppendNbsp(CodeEl, 2);
  2953. AppendKw(CodeEl, 'write ');
  2954. AppendText(CodeEl, TPasProperty(Element).WriteAccessorName);
  2955. NeedBreak := True;
  2956. end;
  2957. if Length(TPasProperty(Element).StoredAccessorName) <> 0 then
  2958. begin
  2959. CreateEl(CodeEl, 'br');
  2960. AppendNbsp(CodeEl, 2);
  2961. AppendKw(CodeEl, 'stored ');
  2962. AppendText(CodeEl, TPasProperty(Element).StoredAccessorName);
  2963. NeedBreak := True;
  2964. end;
  2965. if Length(TPasProperty(Element).DefaultValue) <> 0 then
  2966. begin
  2967. CreateEl(CodeEl, 'br');
  2968. AppendNbsp(CodeEl, 2);
  2969. AppendKw(CodeEl, 'default ');
  2970. AppendPasSHFragment(CodeEl, TPasProperty(Element).DefaultValue, 0);
  2971. NeedBreak := True;
  2972. end;
  2973. AppendSym(CodeEl, ';');
  2974. if TPasProperty(Element).IsDefault or TPasProperty(Element).IsNodefault then
  2975. begin
  2976. if NeedBreak then
  2977. begin
  2978. CreateEl(CodeEl, 'br');
  2979. AppendNbsp(CodeEl, 2);
  2980. end;
  2981. if TPasProperty(Element).IsDefault then
  2982. AppendKw(CodeEl, 'default')
  2983. else
  2984. AppendKw(CodeEl, 'nodefault');
  2985. AppendSym(CodeEl, ';');
  2986. end;
  2987. end;
  2988. var
  2989. s: String;
  2990. DocNode: TDocNode;
  2991. begin
  2992. AppendMenuBar(-1);
  2993. AppendTitle(AElement.FullName);
  2994. AppendShortDescr(CreatePara(BodyElement), AElement);
  2995. AppendText(CreateH2(BodyElement), SDocDeclaration);
  2996. AppendSourceRef(AElement);
  2997. TableEl := CreateTable(BodyElement);
  2998. TREl := CreateTR(TableEl);
  2999. CodeEl := CreateCode(CreatePara(CreateTD(TREl)));
  3000. AppendText(CodeEl, ' '); // !!!: Workaround for current HTML writer
  3001. case AElement.Visibility of
  3002. visPrivate: s := 'private';
  3003. visProtected: s := 'protected';
  3004. visPublic: s := 'public';
  3005. visPublished: s := 'published';
  3006. visAutomated: s := 'automated';
  3007. else s := '';
  3008. end;
  3009. if Length(s) > 0 then
  3010. AppendKw(CodeEl, s);
  3011. AppendText(CodeEl, ' ');
  3012. if AElement.ClassType = TPasVariable then
  3013. CreateVarPage(TPasVariable(AElement))
  3014. else if AElement.InheritsFrom(TPasProcedureBase) then
  3015. AppendProcDecl(CodeEl, TableEl, TPasProcedureBase(AElement))
  3016. else if AElement.ClassType = TPasProperty then
  3017. CreatePropertyPage(TPasProperty(AElement))
  3018. else
  3019. AppendText(CreateWarning(BodyElement), '<' + AElement.ClassName + '>');
  3020. FinishElementPage(AElement);
  3021. end;
  3022. procedure THTMLWriter.CreateVarPageBody(AVar: TPasVariable);
  3023. var
  3024. TableEl, TREl, TDEl, CodeEl, El: TDOMElement;
  3025. DocNode: TDocNode;
  3026. begin
  3027. AppendMenuBar(-1);
  3028. AppendTitle(AVar.FullName);
  3029. AppendShortDescr(CreatePara(BodyElement), AVar);
  3030. AppendText(CreateH2(BodyElement), SDocDeclaration);
  3031. AppendSourceRef(AVar);
  3032. TableEl := CreateTable(BodyElement);
  3033. TREl := CreateTR(TableEl);
  3034. TDEl := CreateTD(TREl);
  3035. CodeEl := CreateCode(CreatePara(TDEl));
  3036. AppendKw(CodeEl, 'var');
  3037. AppendText(CodeEl, ' ' + AVar.Name);
  3038. if Assigned(AVar.VarType) then
  3039. begin
  3040. AppendSym(CodeEl, ': ');
  3041. El := AppendType(CodeEl, TableEl, AVar.VarType, False);
  3042. end else
  3043. El := CodeEl;
  3044. if Length(AVar.Value) > 0 then
  3045. AppendPasSHFragment(El, ' = ' + AVar.Value + ';', 0)
  3046. else
  3047. AppendSym(El, ';');
  3048. FinishElementPage(AVar);
  3049. end;
  3050. procedure THTMLWriter.CreateProcPageBody(AProc: TPasProcedureBase);
  3051. var
  3052. TableEl, TREl, TDEl, CodeEl: TDOMElement;
  3053. begin
  3054. AppendMenuBar(-1);
  3055. AppendTitle(AProc.Name);
  3056. AppendShortDescr(CreatePara(BodyElement), AProc);
  3057. AppendText(CreateH2(BodyElement), SDocDeclaration);
  3058. AppendSourceRef(AProc);
  3059. TableEl := CreateTable(BodyElement);
  3060. TREl := CreateTR(TableEl);
  3061. TDEl := CreateTD(TREl);
  3062. CodeEl := CreateCode(CreatePara(TDEl));
  3063. AppendProcDecl(CodeEl, TableEl, AProc);
  3064. FinishElementPage(AProc);
  3065. end;
  3066. Function THTMLWriter.InterPretOption(Const Cmd,Arg : String) : boolean;
  3067. begin
  3068. Result:=True;
  3069. if Cmd = '--html-search' then
  3070. SearchPage := Arg
  3071. else if Cmd = '--footer' then
  3072. FooterFile := Arg
  3073. else if Cmd = '--charset' then
  3074. CharSet := Arg
  3075. else if Cmd = '--index-colcount' then
  3076. IndexColCount := StrToIntDef(Arg,IndexColCount)
  3077. else if Cmd = '--image-url' then
  3078. FBaseImageURL := Arg
  3079. else if Cmd = '--css-file' then
  3080. FCSSFile := arg
  3081. else if Cmd = '--footer-date' then
  3082. begin
  3083. FIDF:=True;
  3084. FDateFormat:=Arg;
  3085. end
  3086. else
  3087. Result:=False;
  3088. end;
  3089. procedure THTMLWriter.WriteDoc;
  3090. begin
  3091. DoLog(SWritingPages, [PageCount]);
  3092. WriteHTMLPages;
  3093. end;
  3094. class procedure THTMLWriter.Usage(List: TStrings);
  3095. begin
  3096. List.add('--footer');
  3097. List.Add(SHTMLUsageFooter);
  3098. List.Add('--footer-date[=Fmt]');
  3099. List.Add(SHTMLUsageFooterDate);
  3100. List.Add('--charset=set');
  3101. List.Add(SHTMLUsageCharset);
  3102. List.Add('--html-search=pagename');
  3103. List.Add(SHTMLHtmlSearch);
  3104. List.Add('--index-colcount=N');
  3105. List.Add(SHTMLIndexColcount);
  3106. List.Add('--image-url=url');
  3107. List.Add(SHTMLImageUrl);
  3108. end;
  3109. // private methods
  3110. function THTMLWriter.GetPageCount: Integer;
  3111. begin
  3112. Result := PageInfos.Count;
  3113. end;
  3114. procedure THTMLWriter.SetOnTest(const AValue: TNotifyEvent);
  3115. begin
  3116. if FOnTest=AValue then exit;
  3117. FOnTest:=AValue;
  3118. end;
  3119. procedure THTMLWriter.CreateAllocator;
  3120. begin
  3121. FAllocator:=TLongNameFileAllocator.Create('.html');
  3122. end;
  3123. procedure THTMWriter.CreateAllocator;
  3124. begin
  3125. FAllocator:=TShortNameFileAllocator.Create('.htm');
  3126. end;
  3127. initialization
  3128. // Do not localize.
  3129. RegisterWriter(THTMLWriter,'html','HTML output using fpdoc.css stylesheet.');
  3130. RegisterWriter(THTMWriter,'htm','HTM (8.3 filenames) output using fpdoc.css stylesheet.');
  3131. RegisterWriter(TCHMHTMLWriter,'chm','Compressed HTML file output using fpdoc.css stylesheet.');
  3132. finalization
  3133. UnRegisterWriter('html');
  3134. UnRegisterWriter('htm');
  3135. UnRegisterWriter('chm');
  3136. end.