3434#include " editing/visible_units.h"
3535#include " html/html_elementimpl.h"
3636#include " xml/dom_position.h"
37+ #include " xml/dom_xmlimpl.h"
3738#include " xml/dom2_rangeimpl.h"
3839#include " rendering/render_text.h"
3940#include " htmlnames.h"
@@ -42,6 +43,7 @@ using namespace DOM::HTMLNames;
4243
4344using DOM::AttributeImpl;
4445using DOM::CommentImpl;
46+ using DOM::ProcessingInstructionImpl;
4547using DOM::CSSComputedStyleDeclarationImpl;
4648using DOM::CSSMutableStyleDeclarationImpl;
4749using DOM::DocumentFragmentImpl;
@@ -71,6 +73,9 @@ using DOM::TextImpl;
7173
7274namespace khtml {
7375
76+ static inline bool doesHTMLForbidEndTag (const NodeImpl *node);
77+ static inline bool shouldSelfClose (const NodeImpl *node);
78+
7479static QString escapeHTML (const QString &in)
7580{
7681 QString s = " " ;
@@ -173,6 +178,7 @@ static QString renderedText(const NodeImpl *node, const RangeImpl *range)
173178
174179static QString startMarkup (const NodeImpl *node, const RangeImpl *range, EAnnotateForInterchange annotate, CSSMutableStyleDeclarationImpl *defaultStyle)
175180{
181+ bool documentIsHTML = node->getDocument ()->isHTMLDocument ();
176182 unsigned short type = node->nodeType ();
177183 switch (type) {
178184 case Node::TEXT_NODE: {
@@ -187,18 +193,14 @@ static QString startMarkup(const NodeImpl *node, const RangeImpl *range, EAnnota
187193 if (defaultStyle) {
188194 NodeImpl *element = node->parentNode ();
189195 if (element) {
190- CSSComputedStyleDeclarationImpl *computedStyle = Position (element, 0 ).computedStyle ();
191- computedStyle->ref ();
192- CSSMutableStyleDeclarationImpl *style = computedStyle->copyInheritableProperties ();
193- computedStyle->deref ();
194- style->ref ();
195- defaultStyle->diff (style);
196+ SharedPtr<CSSComputedStyleDeclarationImpl> computedStyle = Position (element, 0 ).computedStyle ();
197+ SharedPtr<CSSMutableStyleDeclarationImpl> style = computedStyle->copyInheritableProperties ();
198+ defaultStyle->diff (style.get ());
196199 if (style->length () > 0 ) {
197200 // FIXME: Handle case where style->cssText() has illegal characters in it, like "
198201 QString openTag = QString (" <span class=\" " ) + AppleStyleSpanClass + " \" style=\" " + style->cssText ().qstring () + " \" >" ;
199202 markup = openTag + markup + " </span>" ;
200203 }
201- style->deref ();
202204 }
203205 }
204206 return annotate ? convertHTMLTextToInterchangeFormat (markup) : markup;
@@ -207,25 +209,23 @@ static QString startMarkup(const NodeImpl *node, const RangeImpl *range, EAnnota
207209 return static_cast <const CommentImpl *>(node)->toString ().qstring ();
208210 case Node::DOCUMENT_NODE:
209211 return " " ;
212+ case Node::PROCESSING_INSTRUCTION_NODE:
213+ return static_cast <const ProcessingInstructionImpl *>(node)->toString ().qstring ();
210214 default : {
211215 QString markup = QChar (' <' ) + node->nodeName ().qstring ();
212216 if (type == Node::ELEMENT_NODE) {
213217 const ElementImpl *el = static_cast <const ElementImpl *>(node);
214218 DOMString additionalStyle;
215219 if (defaultStyle && el->isHTMLElement ()) {
216- CSSComputedStyleDeclarationImpl *computedStyle = Position (const_cast <ElementImpl *>(el), 0 ).computedStyle ();
217- computedStyle->ref ();
218- CSSMutableStyleDeclarationImpl *style = computedStyle->copyInheritableProperties ();
219- computedStyle->deref ();
220- style->ref ();
221- defaultStyle->diff (style);
220+ SharedPtr<CSSComputedStyleDeclarationImpl> computedStyle = Position (const_cast <ElementImpl *>(el), 0 ).computedStyle ();
221+ SharedPtr<CSSMutableStyleDeclarationImpl> style = computedStyle->copyInheritableProperties ();
222+ defaultStyle->diff (style.get ());
222223 if (style->length () > 0 ) {
223224 CSSMutableStyleDeclarationImpl *inlineStyleDecl = static_cast <const HTMLElementImpl *>(el)->inlineStyleDecl ();
224225 if (inlineStyleDecl)
225- inlineStyleDecl->diff (style);
226+ inlineStyleDecl->diff (style. get () );
226227 additionalStyle = style->cssText ();
227228 }
228- style->deref ();
229229 }
230230 NamedAttrMapImpl *attrs = el->attributes ();
231231 unsigned length = attrs->length ();
@@ -240,25 +240,56 @@ static QString startMarkup(const NodeImpl *node, const RangeImpl *range, EAnnota
240240 if (attr->name () == styleAttr && additionalStyle.length () > 0 )
241241 value += " ; " + additionalStyle;
242242 // FIXME: Handle case where value has illegal characters in it, like "
243- // FIXME: Namespaces! XML! Ack!
244- markup += " " + attr->name ().localName ().qstring () + " =\" " + value.qstring () + " \" " ;
243+ if (documentIsHTML)
244+ markup += " " + attr->name ().localName ().qstring ();
245+ else
246+ markup += " " + attr->name ().toString ().qstring ();
247+ markup += " =\" " + value.qstring () + " \" " ;
245248 }
246249 }
247250 }
248- markup += node->isHTMLElement () ? " >" : " />" ;
251+
252+ if (shouldSelfClose (node)) {
253+ if (node->isHTMLElement ())
254+ markup += " " ; // XHTML 1.0 <-> HTML compatibility.
255+ markup += " />" ;
256+ } else
257+ markup += " >" ;
258+
249259 return markup;
250260 }
251261 }
252262}
253263
254- static QString endMarkup (const NodeImpl *node)
264+ static inline bool doesHTMLForbidEndTag (const NodeImpl *node)
255265{
256- bool hasEndTag = node->isElementNode ();
257266 if (node->isHTMLElement ()) {
258267 const HTMLElementImpl* htmlElt = static_cast <const HTMLElementImpl*>(node);
259- hasEndTag = (htmlElt->endTagRequirement () ! = TagStatusForbidden);
268+ return (htmlElt->endTagRequirement () = = TagStatusForbidden);
260269 }
261- if (hasEndTag)
270+ return false ;
271+ }
272+
273+ // Rules of self-closure
274+ // 1. all html elements in html documents close with >
275+ // 2. all elements w/ children close with >
276+ // 3. all non-html elements w/o children close with />
277+ // 4. all html elements with a FORBIDDEN close tag, self close in XML docs
278+ static inline bool shouldSelfClose (const NodeImpl *node)
279+ {
280+ bool htmlForbidsEndTag = doesHTMLForbidEndTag (node);
281+ bool documentIsHTML = node->getDocument ()->isHTMLDocument ();
282+
283+ if (node->isHTMLElement () && (documentIsHTML || !htmlForbidsEndTag))
284+ return false ;
285+ else if (!node->hasChildNodes () || htmlForbidsEndTag)
286+ return true ;
287+ return false ;
288+ }
289+
290+ static QString endMarkup (const NodeImpl *node)
291+ {
292+ if (node->isElementNode () && !shouldSelfClose (node) && !doesHTMLForbidEndTag (node))
262293 return " </" + node->nodeName ().qstring () + " >" ;
263294 return " " ;
264295}
@@ -270,27 +301,18 @@ static QString markup(const NodeImpl *startNode, bool onlyIncludeChildren, bool
270301 QString me = " " ;
271302 for (const NodeImpl *current = startNode; current != NULL ; current = includeSiblings ? current->nextSibling () : NULL ) {
272303 if (!onlyIncludeChildren) {
273- if (nodes) {
304+ if (nodes)
274305 nodes->append (current);
275- }
276306 me += startMarkup (current, 0 , DoNotAnnotateForInterchange, 0 );
277307 }
278-
279- bool container = true ;
280- if (current->isHTMLElement ()) {
281- const HTMLElementImpl* h = static_cast <const HTMLElementImpl*>(current);
282- container = h->endTagRequirement () != TagStatusForbidden;
283- }
284- if (container) {
285- // print children
286- if (NodeImpl *n = current->firstChild ()) {
308+ // print children
309+ if (NodeImpl *n = current->firstChild ())
310+ if (!(n->getDocument ()->isHTMLDocument () && doesHTMLForbidEndTag (current)))
287311 me += markup (n, false , true , nodes);
288- }
289- // Print my ending tag
290- if (!onlyIncludeChildren) {
291- me += endMarkup (current);
292- }
293- }
312+
313+ // Print my ending tag
314+ if (!onlyIncludeChildren)
315+ me += endMarkup (current);
294316 }
295317 return me;
296318}
@@ -477,6 +499,7 @@ QString createMarkup(const RangeImpl *range, QPtrList<NodeImpl> *nodes, EAnnotat
477499
478500DocumentFragmentImpl *createFragmentFromMarkup (DocumentImpl *document, const QString &markup, const QString &baseURL)
479501{
502+ ASSERT (document->documentElement ()->isHTMLElement ());
480503 // FIXME: What if the document element is not an HTML element?
481504 HTMLElementImpl *element = static_cast <HTMLElementImpl *>(document->documentElement ());
482505
@@ -493,14 +516,7 @@ QString createMarkup(const DOM::NodeImpl *node, EChildrenOnly includeChildren,
493516 QPtrList<DOM::NodeImpl> *nodes, EAnnotateForInterchange annotate)
494517{
495518 ASSERT (annotate == DoNotAnnotateForInterchange); // annotation not yet implemented for this code path
496-
497- // FIXME: We could take out this if statement if we had more time to test.
498- // I'm concerned that making this crash when the document is nil might be too risky a change at the moment.
499- DocumentImpl *doc = node->getDocument ();
500- assert (doc);
501- if (doc)
502- doc->updateLayout ();
503-
519+ node->getDocument ()->updateLayout ();
504520 return markup (node, includeChildren, false , nodes);
505521}
506522
0 commit comments