/parser/htmlparser/src/CNavDTD.h

http://github.com/zpao/v8monkey · C Header · 406 lines · 115 code · 41 blank · 250 comment · 0 complexity · 1792c351b18ed59efad1cff4adb51459 MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* vim: set sw=2 ts=2 et tw=78: */
  3. /* ***** BEGIN LICENSE BLOCK *****
  4. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5. *
  6. * The contents of this file are subject to the Mozilla Public License Version
  7. * 1.1 (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. * http://www.mozilla.org/MPL/
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is mozilla.org code.
  17. *
  18. * The Initial Developer of the Original Code is
  19. * Netscape Communications Corporation.
  20. * Portions created by the Initial Developer are Copyright (C) 1998
  21. * the Initial Developer. All Rights Reserved.
  22. *
  23. * Contributor(s):
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either of the GNU General Public License Version 2 or later (the "GPL"),
  27. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. /**
  39. * MODULE NOTES:
  40. *
  41. * NavDTD is an implementation of the nsIDTD interface.
  42. * In particular, this class captures the behaviors of the original
  43. * Navigator parser productions.
  44. *
  45. * This DTD, like any other in NGLayout, provides a few basic services:
  46. * - First, the DTD collaborates with the Parser class to convert plain
  47. * text into a sequence of HTMLTokens.
  48. * - Second, the DTD describes containment rules for known elements.
  49. * - Third the DTD controls and coordinates the interaction between the
  50. * parsing system and content sink. (The content sink is the interface
  51. * that serves as a proxy for content model).
  52. * - Fourth the DTD maintains an internal style-stack to handle residual (leaky)
  53. * style tags.
  54. *
  55. * You're most likely working in this class file because
  56. * you want to add or change a behavior inherent in this DTD. The remainder
  57. * of this section will describe what you need to do to affect the kind of
  58. * change you want in this DTD.
  59. *
  60. * RESIDUAL-STYLE HANDLNG:
  61. * There are a number of ways to represent style in an HTML document.
  62. * 1) explicit style tags (<B>, <I> etc)
  63. * 2) implicit styles (like those implicit in <Hn>)
  64. * 3) CSS based styles
  65. *
  66. * Residual style handling results from explicit style tags that are
  67. * not closed. Consider this example: <p>text <b>bold </p>
  68. * When the <p> tag closes, the <b> tag is NOT automatically closed.
  69. * Unclosed style tags are handled by the process we call residual-style
  70. * tag handling.
  71. *
  72. * There are two aspects to residual style tag handling. The first is the
  73. * construction and managing of a stack of residual style tags. The
  74. * second is the automatic emission of residual style tags onto leaf content
  75. * in subsequent portions of the document.This step is necessary to propagate
  76. * the expected style behavior to subsequent portions of the document.
  77. *
  78. * Construction and managing the residual style stack is an inline process that
  79. * occurs during the model building phase of the parse process. During the model-
  80. * building phase of the parse process, a content stack is maintained which tracks
  81. * the open container hierarchy. If a style tag(s) fails to be closed when a normal
  82. * container is closed, that style tag is placed onto the residual style stack. If
  83. * that style tag is subsequently closed (in most contexts), it is popped off the
  84. * residual style stack -- and are of no further concern.
  85. *
  86. * Residual style tag emission occurs when the style stack is not empty, and leaf
  87. * content occurs. In our earlier example, the <b> tag "leaked" out of the <p>
  88. * container. Just before the next leaf is emitted (in this or another container) the
  89. * style tags that are on the stack are emitted in succession. These same residual
  90. * style tags get closed automatically when the leaf's container closes, or if a
  91. * child container is opened.
  92. *
  93. *
  94. */
  95. #ifndef NS_NAVHTMLDTD__
  96. #define NS_NAVHTMLDTD__
  97. #include "nsIDTD.h"
  98. #include "nsISupports.h"
  99. #include "nsIParser.h"
  100. #include "nsHTMLTags.h"
  101. #include "nsDeque.h"
  102. #include "nsParserCIID.h"
  103. #include "nsDTDUtils.h"
  104. #include "nsParser.h"
  105. #include "nsCycleCollectionParticipant.h"
  106. class nsIHTMLContentSink;
  107. class nsIParserNode;
  108. class nsDTDContext;
  109. class nsEntryStack;
  110. class nsITokenizer;
  111. class nsCParserNode;
  112. class nsTokenAllocator;
  113. /***************************************************************
  114. Now the main event: CNavDTD.
  115. This not so simple class performs all the duties of token
  116. construction and model building. It works in conjunction with
  117. an nsParser.
  118. ***************************************************************/
  119. #ifdef _MSC_VER
  120. #pragma warning( disable : 4275 )
  121. #endif
  122. class CNavDTD : public nsIDTD
  123. {
  124. #ifdef _MSC_VER
  125. #pragma warning( default : 4275 )
  126. #endif
  127. public:
  128. /**
  129. * Common constructor for navdtd. You probably want to call
  130. * NS_NewNavHTMLDTD().
  131. */
  132. CNavDTD();
  133. virtual ~CNavDTD();
  134. /**
  135. * This method is offered publically for the sole use from
  136. * nsParser::ParseFragment. In general, you should prefer to use methods
  137. * that are directly on nsIDTD, since those will be guaranteed to do the
  138. * right thing.
  139. *
  140. * @param aNode The parser node that contains the token information for
  141. * this tag.
  142. * @param aTag The actual tag that is being opened (should correspond to
  143. * aNode.
  144. * @param aStyleStack The style stack that aNode might be a member of
  145. * (usually null).
  146. */
  147. nsresult OpenContainer(const nsCParserNode *aNode,
  148. eHTMLTags aTag,
  149. nsEntryStack* aStyleStack = nsnull);
  150. NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  151. NS_DECL_NSIDTD
  152. NS_DECL_CYCLE_COLLECTION_CLASS(CNavDTD)
  153. private:
  154. /**
  155. * This method is called to determine whether or not a tag
  156. * of one type can contain a tag of another type.
  157. *
  158. * @param aParent Tag of parent container
  159. * @param aChild Tag of child container
  160. * @return true if parent can contain child
  161. */
  162. bool CanPropagate(eHTMLTags aParent,
  163. eHTMLTags aChild,
  164. PRInt32 aParentContains);
  165. /**
  166. * This method gets called to determine whether a given
  167. * child tag can be omitted by the given parent.
  168. *
  169. * @param aParent Parent tag being asked about omitting given child
  170. * @param aChild Child tag being tested for omittability by parent
  171. * @param aParentContains Can be 0,1,-1 (false,true, unknown)
  172. * XXX should be PRInt32, not bool
  173. * @return true if given tag can be omitted
  174. */
  175. bool CanOmit(eHTMLTags aParent,
  176. eHTMLTags aChild,
  177. PRInt32& aParentContains);
  178. /**
  179. * Looking at aParent, try to see if we can propagate from aChild to
  180. * aParent. If aParent is a TR tag, then see if we can start at TD instead
  181. * of at aChild.
  182. *
  183. * @param aParent Tag type of parent
  184. * @param aChild Tag type of child
  185. * @return true if closure was achieved -- otherwise false
  186. */
  187. bool ForwardPropagate(nsString& aSequence,
  188. eHTMLTags aParent,
  189. eHTMLTags aChild);
  190. /**
  191. * Given aParent that does not contain aChild, starting with aChild's
  192. * first root tag, try to find aParent. If we can reach aParent simply by
  193. * going up each first root tag, then return true. Otherwise, we could not
  194. * propagate from aChild up to aParent, so return false.
  195. *
  196. * @param aParent Tag type of parent
  197. * @param aChild Tag type of child
  198. * @return true if closure was achieved -- other false
  199. */
  200. bool BackwardPropagate(nsString& aSequence,
  201. eHTMLTags aParent,
  202. eHTMLTags aChild) const;
  203. /**
  204. * Attempt forward and/or backward propagation for the given child within
  205. * the current context vector stack. And actually open the required tags.
  206. *
  207. * @param aParent The tag we're trying to open this element inside of.
  208. * @param aChild Type of child to be propagated.
  209. */
  210. void CreateContextStackFor(eHTMLTags aParent, eHTMLTags aChild);
  211. /**
  212. * Ask if a given container is open anywhere on its stack
  213. *
  214. * @param id of container you want to test for
  215. * @return TRUE if the given container type is open -- otherwise FALSE
  216. */
  217. bool HasOpenContainer(eHTMLTags aContainer) const;
  218. /**
  219. * This method allows the caller to determine if a any member
  220. * in a set of tags is currently open.
  221. *
  222. * @param aTagSet A set of tags you care about.
  223. * @return true if any of the members of aTagSet are currently open.
  224. */
  225. bool HasOpenContainer(const eHTMLTags aTagSet[], PRInt32 aCount) const;
  226. /**
  227. * Accessor that retrieves the tag type of the topmost item on the DTD's
  228. * tag stack.
  229. *
  230. * @return The tag type (may be unknown)
  231. */
  232. eHTMLTags GetTopNode() const;
  233. /**
  234. * Finds the topmost occurrence of given tag within context vector stack.
  235. *
  236. * @param tag to be found
  237. * @return index of topmost tag occurrence -- may be -1 (kNotFound).
  238. */
  239. PRInt32 LastOf(eHTMLTags aTagSet[], PRInt32 aCount) const;
  240. nsresult HandleToken(CToken* aToken);
  241. /**
  242. * This method gets called when a start token has been
  243. * encountered in the parse process. If the current container
  244. * can contain this tag, then add it. Otherwise, you have
  245. * two choices: 1) create an implicit container for this tag
  246. * to be stored in
  247. * 2) close the top container, and add this to
  248. * whatever container ends up on top.
  249. *
  250. * @param aToken -- next (start) token to be handled
  251. * @return Whether or not we should block the parser.
  252. */
  253. nsresult HandleStartToken(CToken* aToken);
  254. /**
  255. * This method gets called when a start token has been
  256. * encountered in the parse process. If the current container
  257. * can contain this tag, then add it. Otherwise, you have
  258. * two choices: 1) create an implicit container for this tag
  259. * to be stored in
  260. * 2) close the top container, and add this to
  261. * whatever container ends up on top.
  262. *
  263. * @param aToken Next (start) token to be handled.
  264. * @param aChildTag The tag corresponding to aToken.
  265. * @param aNode CParserNode representing this start token
  266. * @return A potential request to block the parser.
  267. */
  268. nsresult HandleDefaultStartToken(CToken* aToken, eHTMLTags aChildTag,
  269. nsCParserNode *aNode);
  270. nsresult HandleEndToken(CToken* aToken);
  271. nsresult HandleEntityToken(CToken* aToken);
  272. nsresult HandleCommentToken(CToken* aToken);
  273. nsresult HandleAttributeToken(CToken* aToken);
  274. nsresult HandleProcessingInstructionToken(CToken* aToken);
  275. nsresult HandleDocTypeDeclToken(CToken* aToken);
  276. nsresult BuildNeglectedTarget(eHTMLTags aTarget, eHTMLTokenTypes aType);
  277. nsresult OpenHTML(const nsCParserNode *aNode);
  278. nsresult OpenBody(const nsCParserNode *aNode);
  279. /**
  280. * The special purpose methods automatically close
  281. * one or more open containers.
  282. * @return error code - 0 if all went well.
  283. */
  284. nsresult CloseContainer(const eHTMLTags aTag, bool aMalformed);
  285. nsresult CloseContainersTo(eHTMLTags aTag, bool aClosedByStartTag);
  286. nsresult CloseContainersTo(PRInt32 anIndex, eHTMLTags aTag,
  287. bool aClosedByStartTag);
  288. nsresult CloseResidualStyleTags(const eHTMLTags aTag,
  289. bool aClosedByStartTag);
  290. /**
  291. * Causes leaf to be added to sink at current vector pos.
  292. * @param aNode is leaf node to be added.
  293. * @return error code - 0 if all went well.
  294. */
  295. nsresult AddLeaf(const nsIParserNode *aNode);
  296. nsresult AddHeadContent(nsIParserNode *aNode);
  297. /**
  298. * This set of methods is used to create and manage the set of
  299. * transient styles that occur as a result of poorly formed HTML
  300. * or bugs in the original navigator.
  301. *
  302. * @param aTag -- represents the transient style tag to be handled.
  303. * @return error code -- usually 0
  304. */
  305. nsresult OpenTransientStyles(eHTMLTags aChildTag,
  306. bool aCloseInvalid = true);
  307. void PopStyle(eHTMLTags aTag);
  308. nsresult PushIntoMisplacedStack(CToken* aToken)
  309. {
  310. NS_ENSURE_ARG_POINTER(aToken);
  311. aToken->SetNewlineCount(0); // Note: We have already counted the newlines for these tokens
  312. mMisplacedContent.Push(aToken);
  313. return NS_OK;
  314. }
  315. protected:
  316. nsresult CollectAttributes(nsIParserNode* aNode,eHTMLTags aTag,PRInt32 aCount);
  317. /**
  318. * This gets called before we've handled a given start tag.
  319. * It's a generic hook to let us do pre processing.
  320. *
  321. * @param aToken contains the tag in question
  322. * @param aTag is the tag itself.
  323. * @param aNode is the node (tag) with associated attributes.
  324. * @return NS_OK if we should continue, a failure code otherwise.
  325. */
  326. nsresult WillHandleStartTag(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode);
  327. nsresult DidHandleStartTag(nsIParserNode& aNode,eHTMLTags aChildTag);
  328. /**
  329. * This method gets called when a start token has been encountered that
  330. * the parent wants to omit. It stashes it in the current element if that
  331. * element accepts such misplaced tokens.
  332. *
  333. * @param aToken Next (start) token to be handled
  334. * @param aChildTag id of the child in question
  335. * @param aParent id of the parent in question
  336. * @param aNode CParserNode representing this start token
  337. */
  338. void HandleOmittedTag(CToken* aToken, eHTMLTags aChildTag,
  339. eHTMLTags aParent, nsIParserNode *aNode);
  340. nsresult HandleSavedTokens(PRInt32 anIndex);
  341. nsresult HandleKeyGen(nsIParserNode *aNode);
  342. bool IsAlternateTag(eHTMLTags aTag);
  343. bool IsBlockElement(PRInt32 aTagID, PRInt32 aParentID) const;
  344. bool IsInlineElement(PRInt32 aTagID, PRInt32 aParentID) const;
  345. nsDeque mMisplacedContent;
  346. nsCOMPtr<nsIHTMLContentSink> mSink;
  347. nsTokenAllocator* mTokenAllocator;
  348. nsDTDContext* mBodyContext;
  349. nsDTDContext* mTempContext;
  350. bool mCountLines;
  351. nsITokenizer* mTokenizer; // weak
  352. nsString mFilename;
  353. nsString mScratch; //used for various purposes; non-persistent
  354. nsCString mMimeType;
  355. nsNodeAllocator mNodeAllocator;
  356. nsDTDMode mDTDMode;
  357. eParserDocType mDocType;
  358. eParserCommands mParserCommand; //tells us to viewcontent/viewsource/viewerrors...
  359. PRInt32 mLineNumber;
  360. PRInt32 mOpenMapCount;
  361. PRInt32 mHeadContainerPosition;
  362. PRUint16 mFlags;
  363. };
  364. #endif