dom_docimpl.cpp 93.3 KB
Newer Older
George Staikos's avatar
George Staikos committed
1 2 3 4 5 6
/**
 * This file is part of the DOM implementation for KDE.
 *
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
7 8
 *           (C) 2002-2006 Apple Computer, Inc.
 *           (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com)
9 10
 *           (C) 2005 Frerich Raabe <raabe@kde.org>
 *           (C) 2010 Maksim Orlovich <maksim@kde.org>
George Staikos's avatar
George Staikos committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

Alex Merry's avatar
Alex Merry committed
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include "dom_docimpl.h"

#include <dom/dom_exception.h>

#include "dom_textimpl.h"
#include "dom_xmlimpl.h"
#include "dom2_rangeimpl.h"
#include "dom2_eventsimpl.h"
#include "xml_tokenizer.h"
#include <html/htmltokenizer.h>
#include "dom_restyler.h"

#include <css/cssstyleselector.h>
#include <css/css_stylesheetimpl.h>
#include <misc/seed.h>
#include <misc/loader.h>
#include <ecma/kjs_proxy.h>
#include <ecma/kjs_binding.h>
George Staikos's avatar
George Staikos committed
46

Tobias Koenig's avatar
Tobias Koenig committed
47
#include <QtCore/QStack>
George Staikos's avatar
George Staikos committed
48 49
//Added by qt3to4:
#include <QTimerEvent>
Christian Ehrlicher's avatar
Christian Ehrlicher committed
50
#include <QtCore/QList>
George Staikos's avatar
George Staikos committed
51 52 53
#include <kdebug.h>
#include <klocale.h>

Alex Merry's avatar
Alex Merry committed
54 55 56 57 58 59 60
#include <rendering/counter_tree.h>
#include <rendering/render_canvas.h>
#include <rendering/render_replaced.h>
#include <rendering/render_arena.h>
#include <rendering/render_layer.h>
#include <rendering/render_frames.h>
#include <rendering/render_image.h>
George Staikos's avatar
George Staikos committed
61

Alex Merry's avatar
Alex Merry committed
62 63
#include <khtmlview.h>
#include <khtml_part.h>
George Staikos's avatar
George Staikos committed
64 65 66
#include <kauthorized.h>
#include <kglobalsettings.h>
#include <kstringhandler.h>
Aaron J. Seigo's avatar
Aaron J. Seigo committed
67
#include <kdatetime.h>
Alex Merry's avatar
Alex Merry committed
68 69 70
#include <khtml_settings.h>
#include <khtmlpart_p.h>

71
#include <xml/dom3_xpathimpl.h>
Alex Merry's avatar
Alex Merry committed
72 73 74 75 76 77 78 79 80 81 82
#include <html/html_baseimpl.h>
#include <html/html_blockimpl.h>
#include <html/html_canvasimpl.h>
#include <html/html_documentimpl.h>
#include <html/html_formimpl.h>
#include <html/html_headimpl.h>
#include <html/html_imageimpl.h>
#include <html/html_listimpl.h>
#include <html/html_miscimpl.h>
#include <html/html_tableimpl.h>
#include <html/html_objectimpl.h>
83 84 85
#include <html/HTMLAudioElement.h>
#include <html/HTMLVideoElement.h>
#include <html/HTMLSourceElement.h>
86
#include <editing/jsediting.h>
George Staikos's avatar
George Staikos committed
87

88 89
#include <ecma/kjs_window.h>

90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
// SVG (WebCore)
#include <svg/SVGElement.h>
#include <svg/SVGSVGElement.h>
#include <svg/SVGNames.h>
#include <svg/SVGDocumentExtensions.h>
#include <svg/SVGRectElement.h>
#include <svg/SVGDocument.h>
#include <svg/SVGCircleElement.h>
#include <svg/SVGStyleElement.h>
#include <svg/SVGEllipseElement.h>
#include <svg/SVGPolygonElement.h>
#include <svg/SVGPolylineElement.h>
#include <svg/SVGPathElement.h>
#include <svg/SVGDefsElement.h>
#include <svg/SVGLinearGradientElement.h>
#include <svg/SVGRadialGradientElement.h>
#include <svg/SVGStopElement.h>
#include <svg/SVGClipPathElement.h>
#include <svg/SVGGElement.h>
#include <svg/SVGUseElement.h>
#include <svg/SVGLineElement.h>
#include <svg/SVGTextElement.h>
#include <svg/SVGAElement.h>
#include <svg/SVGScriptElement.h>
#include <svg/SVGDescElement.h>
#include <svg/SVGTitleElement.h>
116 117 118 119 120
#include <svg/SVGTextPathElement.h>
#include <svg/SVGTSpanElement.h>
#include <svg/SVGHKernElement.h>
#include <svg/SVGAltGlyphElement.h>
#include <svg/SVGFontElement.h>
121

George Staikos's avatar
George Staikos committed
122 123 124
#include <kio/job.h>

#include <stdlib.h>
Harri Porten's avatar
Harri Porten committed
125
#include <limits.h>
George Staikos's avatar
George Staikos committed
126

127 128
template class QStack<DOM::NodeImpl*>;

George Staikos's avatar
George Staikos committed
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
using namespace DOM;
using namespace khtml;

// ------------------------------------------------------------------------

DOMImplementationImpl::DOMImplementationImpl()
{
}

DOMImplementationImpl::~DOMImplementationImpl()
{
}

bool DOMImplementationImpl::hasFeature ( const DOMString &feature, const DOMString &version )
{
    // ### update when we (fully) support the relevant features
145
    QString lower = feature.string().toLower();
George Staikos's avatar
George Staikos committed
146
    if ((lower == "html" || lower == "xml") &&
147
        (version.isEmpty() || version == "1.0" || version == "2.0"))
George Staikos's avatar
George Staikos committed
148 149 150 151
        return true;

    // ## Do we support Core Level 3 ?
    if ((lower == "core" ) &&
152 153 154 155 156
        (version.isEmpty() || version == "2.0"))
        return true;

    if ((lower == "traversal") &&
        (version.isEmpty() || version == "2.0"))
George Staikos's avatar
George Staikos committed
157 158
        return true;

Maks Orlovich's avatar
Maks Orlovich committed
159 160 161 162
    if ((lower == "css") &&
        (version.isEmpty() || version == "2.0"))
        return true;

George Staikos's avatar
George Staikos committed
163 164 165
    if ((lower == "events" || lower == "uievents" ||
         lower == "mouseevents" || lower == "mutationevents" ||
         lower == "htmlevents" || lower == "textevents" ) &&
166
        (version.isEmpty() || version == "2.0" || version == "3.0"))
George Staikos's avatar
George Staikos committed
167
        return true;
168 169 170 171

    if (lower == "selectors-api" && version == "1.0")
        return true;
        
George Staikos's avatar
George Staikos committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    return false;
}

DocumentTypeImpl *DOMImplementationImpl::createDocumentType( const DOMString &qualifiedName, const DOMString &publicId,
                                                             const DOMString &systemId, int &exceptioncode )
{
    // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied
    if (qualifiedName.isNull()) {
        exceptioncode = DOMException::NAMESPACE_ERR;
        return 0;
    }

    // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
    if (!Element::khtmlValidQualifiedName(qualifiedName)) {
        exceptioncode = DOMException::INVALID_CHARACTER_ERR;
        return 0;
    }

    // NAMESPACE_ERR: Raised if the qualifiedName is malformed.
    // Added special case for the empty string, which seems to be a common pre-DOM2 misuse
    if (!qualifiedName.isEmpty() && Element::khtmlMalformedQualifiedName(qualifiedName)) {
        exceptioncode = DOMException::NAMESPACE_ERR;
        return 0;
    }

197
    return new DocumentTypeImpl(this, 0, qualifiedName, publicId, systemId);
George Staikos's avatar
George Staikos committed
198 199 200
}

DocumentImpl *DOMImplementationImpl::createDocument( const DOMString &namespaceURI, const DOMString &qualifiedName,
201 202 203
                                                     DocumentTypeImpl* dtype,
                                                     KHTMLView* v,
                                                     int &exceptioncode )
George Staikos's avatar
George Staikos committed
204 205 206 207 208 209 210 211 212
{
    exceptioncode = 0;

    if (!checkQualifiedName(qualifiedName, namespaceURI, 0, true/*nameCanBeNull*/,
                            true /*nameCanBeEmpty, see #61650*/, &exceptioncode) )
        return 0;

    // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was
    // created from a different implementation.
213 214 215 216
    // We elide the "different implementation" case here, since we're not doing interop
    // of different implementations, and different impl objects exist only for
    // isolation  reasons
    if (dtype && dtype->document()) {
George Staikos's avatar
George Staikos committed
217 218 219 220
        exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
        return 0;
    }

221 222 223
    // ### view can be 0 which can cause problems
    DocumentImpl* doc;
    if (namespaceURI == XHTML_NAMESPACE)
224
        doc = new HTMLDocumentImpl(v);
225
    else
226
        doc = new DocumentImpl(v);
227

Harri Porten's avatar
Harri Porten committed
228
    if (dtype) {
229 230
        dtype->setDocument(doc);
        doc->appendChild(dtype,exceptioncode);
Harri Porten's avatar
Harri Porten committed
231
    }
George Staikos's avatar
George Staikos committed
232

David Faure's avatar
David Faure committed
233
    // the document must be created empty if all parameters are null
George Staikos's avatar
George Staikos committed
234 235 236 237 238 239 240 241 242 243 244 245 246
    // (or empty for qName/nsURI as a tolerance) - see DOM 3 Core.
    if (dtype || !qualifiedName.isEmpty() || !namespaceURI.isEmpty()) {
        ElementImpl *element = doc->createElementNS(namespaceURI,qualifiedName);
        doc->appendChild(element,exceptioncode);
        if (exceptioncode) {
            delete element;
            delete doc;
            return 0;
        }
    }
    return doc;
}

247
CSSStyleSheetImpl *DOMImplementationImpl::createCSSStyleSheet(DOMStringImpl* title, DOMStringImpl *media,
George Staikos's avatar
George Staikos committed
248 249
                                                              int &/*exceptioncode*/)
{
250
    // ### TODO : media could have wrong syntax, in which case we should
George Staikos's avatar
George Staikos committed
251 252 253
	// generate an exception.
	CSSStyleSheetImpl *parent = 0L;
	CSSStyleSheetImpl *sheet = new CSSStyleSheetImpl(parent, DOMString());
Germain Garand's avatar
Germain Garand committed
254
	sheet->setMedia(new MediaListImpl(sheet, media, true /*fallbackToDescriptor*/));
255
	sheet->setTitle(DOMString(title));
George Staikos's avatar
George Staikos committed
256 257 258 259 260
	return sheet;
}

DocumentImpl *DOMImplementationImpl::createDocument( KHTMLView *v )
{
261
    DocumentImpl* doc = new DocumentImpl(v);
262

Harri Porten's avatar
Harri Porten committed
263
    return doc;
George Staikos's avatar
George Staikos committed
264 265
}

266 267
XMLDocumentImpl *DOMImplementationImpl::createXMLDocument( KHTMLView *v )
{
268
    XMLDocumentImpl* doc = new XMLDocumentImpl(v);
269 270 271 272

    return doc;
}

George Staikos's avatar
George Staikos committed
273 274
HTMLDocumentImpl *DOMImplementationImpl::createHTMLDocument( KHTMLView *v )
{
275
    HTMLDocumentImpl* doc = new HTMLDocumentImpl(v);
276

Harri Porten's avatar
Harri Porten committed
277
    return doc;
George Staikos's avatar
George Staikos committed
278 279
}

280 281 282
// create SVG document
WebCore::SVGDocument *DOMImplementationImpl::createSVGDocument( KHTMLView *v )
{
283
    WebCore::SVGDocument* doc = new WebCore::SVGDocument(v);
284 285 286 287

    return doc;
}

George Staikos's avatar
George Staikos committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301
HTMLDocumentImpl* DOMImplementationImpl::createHTMLDocument( const DOMString& title )
{
    HTMLDocumentImpl* r = createHTMLDocument( 0 /* ### create a view otherwise it doesn't work */);

    r->open();

    r->write(QLatin1String("<HTML><HEAD><TITLE>") + title.string() +
             QLatin1String("</TITLE></HEAD>"));

    return r;
}

// ------------------------------------------------------------------------

302
ElementMappingCache::ElementMappingCache():m_dict()
303
{
304 305 306 307 308
}

ElementMappingCache::~ElementMappingCache()
{
    qDeleteAll( m_dict );
309
}
George Staikos's avatar
George Staikos committed
310

311
void ElementMappingCache::add(const DOMString& id, ElementImpl* nd)
George Staikos's avatar
George Staikos committed
312 313 314
{
    if (id.isEmpty()) return;

315
    ItemInfo* info = m_dict.value(id);
George Staikos's avatar
George Staikos committed
316 317 318 319 320 321 322 323 324 325 326 327 328 329
    if (info)
    {
        info->ref++;
        info->nd = 0; //Now ambigous
    }
    else
    {
        ItemInfo* info = new ItemInfo();
        info->ref = 1;
        info->nd  = nd;
        m_dict.insert(id, info);
    }
}

330
void ElementMappingCache::set(const DOMString& id, ElementImpl* nd)
George Staikos's avatar
George Staikos committed
331 332 333
{
    if (id.isEmpty()) return;

334 335
    assert(m_dict.contains(id));
    ItemInfo* info = m_dict.value(id);
George Staikos's avatar
George Staikos committed
336 337 338
    info->nd = nd;
}

339
void ElementMappingCache::remove(const DOMString& id, ElementImpl* nd)
George Staikos's avatar
George Staikos committed
340 341 342
{
    if (id.isEmpty()) return;

343 344
    assert(m_dict.contains(id));
    ItemInfo* info = m_dict.value(id);
George Staikos's avatar
George Staikos committed
345 346 347 348 349 350 351 352 353 354 355 356 357
    info->ref--;
    if (info->ref == 0)
    {
        m_dict.take(id);
        delete info;
    }
    else
    {
        if (info->nd == nd)
            info->nd = 0;
    }
}

358
bool ElementMappingCache::contains(const DOMString& id)
George Staikos's avatar
George Staikos committed
359 360
{
    if (id.isEmpty()) return false;
361
    return m_dict.contains(id);
George Staikos's avatar
George Staikos committed
362 363
}

364
ElementMappingCache::ItemInfo* ElementMappingCache::get(const DOMString& id)
George Staikos's avatar
George Staikos committed
365 366
{
    if (id.isEmpty()) return 0;
367
    return m_dict.value(id);
George Staikos's avatar
George Staikos committed
368 369
}

Christian Ehrlicher's avatar
Christian Ehrlicher committed
370 371
typedef QList<DocumentImpl*> ChangedDocuments ;
K_GLOBAL_STATIC(ChangedDocuments, s_changedDocuments)
George Staikos's avatar
George Staikos committed
372 373

// KHTMLView might be 0
374
DocumentImpl::DocumentImpl(KHTMLView *v)
375
    : NodeBaseImpl( 0 ), m_svgExtensions(0), m_counterDict(),
George Staikos's avatar
George Staikos committed
376 377
      m_imageLoadEventTimer(0)
{
378
    m_document.resetSkippingRef(this); //Make document return us..
Germain Garand's avatar
Germain Garand committed
379 380
    m_selfOnlyRefCount = 0;

George Staikos's avatar
George Staikos committed
381
    m_paintDevice = 0;
David Faure's avatar
David Faure committed
382
    //m_decoderMibEnum = 0;
George Staikos's avatar
George Staikos committed
383 384 385
    m_textColor = Qt::black;

    m_view = v;
Maks Orlovich's avatar
Maks Orlovich committed
386
    m_renderArena.reset();
George Staikos's avatar
George Staikos committed
387

388
    KHTMLGlobal::registerDocumentImpl(this);
George Staikos's avatar
George Staikos committed
389 390 391 392 393 394 395 396 397 398 399 400 401

    if ( v ) {
        m_docLoader = new DocLoader(v->part(), this );
        setPaintDevice( m_view );
    }
    else
        m_docLoader = new DocLoader( 0, this );

    visuallyOrdered = false;
    m_bParsing = false;
    m_docChanged = false;
    m_elemSheet = 0;
    m_tokenizer = 0;
402
    m_decoder = 0;
Harri Porten's avatar
Harri Porten committed
403
    m_doctype = 0;
404
    m_implementation = 0;
George Staikos's avatar
George Staikos committed
405 406
    pMode = Strict;
    hMode = XHtml;
407
    m_htmlCompat = false;
George Staikos's avatar
George Staikos committed
408 409 410
    m_textColor = "#000000";
    m_focusNode = 0;
    m_hoverNode = 0;
411
    m_activeNode = 0;
George Staikos's avatar
George Staikos committed
412 413 414
    m_defaultView = new AbstractViewImpl(this);
    m_defaultView->ref();
    m_listenerTypes = 0;
415
    m_styleSheets = new StyleSheetListImpl(this);
George Staikos's avatar
George Staikos committed
416 417 418 419 420
    m_styleSheets->ref();
    m_addedStyleSheets = 0;
    m_inDocument = true;
    m_styleSelectorDirty = false;
    m_styleSelector = 0;
421
    m_styleSheetListDirty = true;
George Staikos's avatar
George Staikos committed
422 423 424 425 426 427 428

    m_inStyleRecalc = false;
    m_pendingStylesheets = 0;
    m_ignorePendingStylesheets = false;
    m_async = true;
    m_hadLoadError = false;
    m_docLoading = false;
429
    m_bVariableLength = false;
Germain Garand's avatar
Germain Garand committed
430
    m_inSyncLoad = 0;
George Staikos's avatar
George Staikos committed
431
    m_loadingXMLDoc = 0;
432
    m_documentElement = 0;
George Staikos's avatar
George Staikos committed
433
    m_cssTarget = 0;
434
    m_jsEditor = 0;
435
    m_dynamicDomRestyler = new khtml::DynamicDomRestyler();
436
    m_stateRestorePos = 0;
437 438
    m_windowEventTarget = new WindowEventTargetImpl(this);
    m_windowEventTarget->ref();
439 440 441
    
    for (int c = 0; c < NumTreeVersions; ++c)
        m_domTreeVersions[c] = 0;
George Staikos's avatar
George Staikos committed
442 443
}

Germain Garand's avatar
Germain Garand committed
444 445 446 447 448
void DocumentImpl::removedLastRef()
{
    if (m_selfOnlyRefCount) {
        /* In this case, the only references to us are from children,
           so we have a cycle. We'll try to break it by disconnecting the
449 450
           children from us; this sucks/is wrong, but it's pretty much
           the best we can do without tracing.
Germain Garand's avatar
Germain Garand committed
451

452
           Of course, if dumping the children causes the refcount from them to
Germain Garand's avatar
Germain Garand committed
453 454 455 456 457 458 459 460
           drop to 0 we can get killed right here, so better hold
           a temporary reference, too
        */
        DocPtr<DocumentImpl> guard(this);

        // we must make sure not to be retaining any of our children through
        // these extra pointers or we will create a reference cycle
        if (m_doctype) {
461
            m_doctype->deref();
Germain Garand's avatar
Germain Garand committed
462 463
            m_doctype = 0;
        }
464

Germain Garand's avatar
Germain Garand committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478
        if (m_cssTarget) {
            m_cssTarget->deref();
            m_cssTarget = 0;
        }

        if (m_focusNode) {
            m_focusNode->deref();
            m_focusNode = 0;
        }

        if (m_hoverNode) {
            m_hoverNode->deref();
            m_hoverNode = 0;
        }
479

Germain Garand's avatar
Germain Garand committed
480 481 482 483
        if (m_activeNode) {
            m_activeNode->deref();
            m_activeNode = 0;
        }
484

485 486 487 488
        if (m_documentElement) {
            m_documentElement->deref();
            m_documentElement = 0;
        }
Germain Garand's avatar
Germain Garand committed
489 490 491 492 493 494 495 496 497 498

        removeChildren();

        delete m_tokenizer;
        m_tokenizer = 0;
    } else {
        delete this;
    }
}

George Staikos's avatar
George Staikos committed
499 500
DocumentImpl::~DocumentImpl()
{
Germain Garand's avatar
Germain Garand committed
501 502
    //Important: if you need to remove stuff here,
    //you may also have to fix removedLastRef() above - M.O.
George Staikos's avatar
George Staikos committed
503 504
    assert( !m_render );

Maks Orlovich's avatar
Maks Orlovich committed
505
    QHashIterator<long,DynamicNodeListImpl::Cache*> it(m_nodeListCache);
506 507
    while (it.hasNext())
        it.next().value()->deref();
George Staikos's avatar
George Staikos committed
508 509 510

    if (m_loadingXMLDoc)
	m_loadingXMLDoc->deref(this);
Christian Ehrlicher's avatar
Christian Ehrlicher committed
511 512
    if (s_changedDocuments && m_docChanged)
        s_changedDocuments->removeAll(this);
George Staikos's avatar
George Staikos committed
513
    delete m_tokenizer;
Germain Garand's avatar
Germain Garand committed
514
    m_document.resetSkippingRef(0);
George Staikos's avatar
George Staikos committed
515 516 517 518 519
    delete m_styleSelector;
    delete m_docLoader;
    if (m_elemSheet )  m_elemSheet->deref();
    if (m_doctype)
        m_doctype->deref();
520 521
    if (m_implementation)
        m_implementation->deref();
522
    delete m_dynamicDomRestyler;
523
    delete m_jsEditor;
George Staikos's avatar
George Staikos committed
524 525 526 527
    m_defaultView->deref();
    m_styleSheets->deref();
    if (m_addedStyleSheets)
        m_addedStyleSheets->deref();
528 529
    if (m_cssTarget)
        m_cssTarget->deref();
George Staikos's avatar
George Staikos committed
530 531 532 533
    if (m_focusNode)
        m_focusNode->deref();
    if ( m_hoverNode )
        m_hoverNode->deref();
Germain Garand's avatar
Germain Garand committed
534 535
    if (m_activeNode)
        m_activeNode->deref();
536 537
    if (m_documentElement)
        m_documentElement->deref();
538
    m_windowEventTarget->deref();
539
    qDeleteAll(m_counterDict);
George Staikos's avatar
George Staikos committed
540

Maks Orlovich's avatar
Maks Orlovich committed
541
    m_renderArena.reset();
George Staikos's avatar
George Staikos committed
542

543
    KHTMLGlobal::deregisterDocumentImpl(this);
George Staikos's avatar
George Staikos committed
544 545 546 547 548
}


DOMImplementationImpl *DocumentImpl::implementation() const
{
549 550 551 552
    if (!m_implementation) {
        m_implementation = new DOMImplementationImpl();
        m_implementation->ref();
    }
George Staikos's avatar
George Staikos committed
553 554 555
    return m_implementation;
}

556 557 558 559 560 561
void DocumentImpl::childrenChanged()
{
    // invalidate the document element we have cached in case it was replaced
    if (m_documentElement)
        m_documentElement->deref();
    m_documentElement = 0;
562 563 564 565 566

    // same for m_docType
    if (m_doctype)
        m_doctype->deref();
    m_doctype = 0;
567 568
}

George Staikos's avatar
George Staikos committed
569 570
ElementImpl *DocumentImpl::documentElement() const
{
571 572 573 574 575 576 577 578 579
    if (!m_documentElement) {
        NodeImpl* n = firstChild();
        while (n && n->nodeType() != Node::ELEMENT_NODE)
            n = n->nextSibling();
        m_documentElement = static_cast<ElementImpl*>(n);
        if (m_documentElement)
            m_documentElement->ref();
    }
    return m_documentElement;
George Staikos's avatar
George Staikos committed
580 581
}

582 583 584 585 586 587 588 589 590 591 592 593 594 595
DocumentTypeImpl *DocumentImpl::doctype() const
{
    if (!m_doctype) {
        NodeImpl* n = firstChild();
        while (n && n->nodeType() != Node::DOCUMENT_TYPE_NODE)
            n = n->nextSibling();
        m_doctype = static_cast<DocumentTypeImpl*>(n);
        if (m_doctype)
            m_doctype->ref();
    }
    return m_doctype;
}


George Staikos's avatar
George Staikos committed
596 597
ElementImpl *DocumentImpl::createElement( const DOMString &name, int* pExceptioncode )
{
598 599
    if (pExceptioncode && !Element::khtmlValidQualifiedName(name)) {
        *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
George Staikos's avatar
George Staikos committed
600
        return 0;
601
    }
602 603 604 605 606 607

    PrefixName prefix;
    LocalName  localName;
    bool htmlCompat = htmlMode() != XHtml;
    splitPrefixLocalName(name, prefix, localName, htmlCompat);
    XMLElementImpl* e = new XMLElementImpl(document(), emptyNamespaceName, localName, prefix);
608
    e->setHTMLCompat(htmlCompat); // Not a real HTML element, but inside an html-compat doc all tags are uppercase.
George Staikos's avatar
George Staikos committed
609 610 611 612 613
    return e;
}

AttrImpl *DocumentImpl::createAttribute( const DOMString &tagName, int* pExceptioncode )
{
614 615
    if (pExceptioncode && !Element::khtmlValidAttrName(tagName)) {
        *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
George Staikos's avatar
George Staikos committed
616
        return 0;
617
    }
618 619 620

    PrefixName prefix;
    LocalName  localName;
621
    bool htmlCompat = (htmlMode() != XHtml);
622 623 624 625
    splitPrefixLocalName(tagName, prefix, localName, htmlCompat);

    AttrImpl* attr = new AttrImpl(0, document(), NamespaceName::fromId(emptyNamespace),
            localName, prefix, DOMString("").implementation());
626
    attr->setHTMLCompat(htmlCompat);
George Staikos's avatar
George Staikos committed
627 628 629 630 631 632 633 634 635 636 637 638 639
    return attr;
}

DocumentFragmentImpl *DocumentImpl::createDocumentFragment(  )
{
    return new DocumentFragmentImpl( docPtr() );
}

CommentImpl *DocumentImpl::createComment ( DOMStringImpl* data )
{
    return new CommentImpl( docPtr(), data );
}

640
CDATASectionImpl *DocumentImpl::createCDATASection ( DOMStringImpl* data, int &exceptioncode )
George Staikos's avatar
George Staikos committed
641
{
642 643 644 645
    if (isHTMLDocument()) {
        exceptioncode = DOMException::NOT_SUPPORTED_ERR;
        return 0;
    }
George Staikos's avatar
George Staikos committed
646 647 648 649 650 651 652 653
    return new CDATASectionImpl( docPtr(), data );
}

ProcessingInstructionImpl *DocumentImpl::createProcessingInstruction ( const DOMString &target, DOMStringImpl* data )
{
    return new ProcessingInstructionImpl( docPtr(),target,data);
}

654
EntityReferenceImpl *DocumentImpl::createEntityReference ( const DOMString &name, int &exceptioncode )
George Staikos's avatar
George Staikos committed
655
{
656 657 658 659
    if (isHTMLDocument()) {
        exceptioncode = DOMException::NOT_SUPPORTED_ERR;
        return 0;
    }
George Staikos's avatar
George Staikos committed
660 661 662
    return new EntityReferenceImpl(docPtr(), name.implementation());
}

663 664 665 666 667
EditingTextImpl *DocumentImpl::createEditingTextNode(const DOMString &text)
{
    return new EditingTextImpl(docPtr(), text);
}

George Staikos's avatar
George Staikos committed
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
NodeImpl *DocumentImpl::importNode(NodeImpl *importedNode, bool deep, int &exceptioncode)
{
    NodeImpl *result = 0;

    // Not mentioned in spec: throw NOT_FOUND_ERR if evt is null
    if (!importedNode) {
        exceptioncode = DOMException::NOT_FOUND_ERR;
        return 0;
    }

    if(importedNode->nodeType() == Node::ELEMENT_NODE)
    {
        // Why not use cloneNode?
	ElementImpl *otherElem = static_cast<ElementImpl*>(importedNode);
	NamedAttrMapImpl *otherMap = static_cast<ElementImpl *>(importedNode)->attributes(true);

	ElementImpl *tempElementImpl;
685
	tempElementImpl = createElementNS(otherElem->namespaceURI(),otherElem->nonCaseFoldedTagName());
686
	tempElementImpl->setHTMLCompat(htmlMode() != XHtml && otherElem->htmlCompat());
George Staikos's avatar
George Staikos committed
687 688 689
	result = tempElementImpl;

	if(otherMap) {
690
	    for(unsigned i = 0; i < otherMap->length(); i++)
George Staikos's avatar
George Staikos committed
691
	    {
692
		AttrImpl *otherAttr = otherMap->attributeAt(i).createAttr(otherElem,otherElem->docPtr());
George Staikos's avatar
George Staikos committed
693

694
		tempElementImpl->setAttributeNS(otherAttr->namespaceURI(),
George Staikos's avatar
George Staikos committed
695 696
						    otherAttr->name(),
						    otherAttr->nodeValue(),
697
						    exceptioncode);
George Staikos's avatar
George Staikos committed
698 699 700 701 702 703 704 705 706 707 708 709 710

		if(exceptioncode != 0)
		    break; // ### properly cleanup here
	    }
	}
    }
    else if(importedNode->nodeType() == Node::TEXT_NODE)
    {
	result = createTextNode(static_cast<TextImpl*>(importedNode)->string());
	deep = false;
    }
    else if(importedNode->nodeType() == Node::CDATA_SECTION_NODE)
    {
711
	result = createCDATASection(static_cast<CDATASectionImpl*>(importedNode)->string(), exceptioncode);
George Staikos's avatar
George Staikos committed
712 713 714
	deep = false;
    }
    else if(importedNode->nodeType() == Node::ENTITY_REFERENCE_NODE)
715
	result = createEntityReference(importedNode->nodeName(), exceptioncode);
George Staikos's avatar
George Staikos committed
716 717 718 719 720 721 722 723 724 725
    else if(importedNode->nodeType() == Node::PROCESSING_INSTRUCTION_NODE)
    {
	result = createProcessingInstruction(importedNode->nodeName(), importedNode->nodeValue().implementation());
	deep = false;
    }
    else if(importedNode->nodeType() == Node::COMMENT_NODE)
    {
	result = createComment(static_cast<CommentImpl*>(importedNode)->string());
	deep = false;
    }
Germain Garand's avatar
Germain Garand committed
726 727
    else if (importedNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE)
	result = createDocumentFragment();
George Staikos's avatar
George Staikos committed
728 729
    else
	exceptioncode = DOMException::NOT_SUPPORTED_ERR;
730

Germain Garand's avatar
Germain Garand committed
731
    //### FIXME: This should handle Attributes, and a few other things
George Staikos's avatar
George Staikos committed
732

733
    if(deep && result)
George Staikos's avatar
George Staikos committed
734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
    {
	for(Node n = importedNode->firstChild(); !n.isNull(); n = n.nextSibling())
	    result->appendChild(importNode(n.handle(), true, exceptioncode), exceptioncode);
    }

    return result;
}

ElementImpl *DocumentImpl::createElementNS( const DOMString &_namespaceURI, const DOMString &_qualifiedName, int* pExceptioncode )
{
    ElementImpl *e = 0;
    int colonPos = -2;
    // check NAMESPACE_ERR/INVALID_CHARACTER_ERR
    if (pExceptioncode && !checkQualifiedName(_qualifiedName, _namespaceURI, &colonPos,
                                              false/*nameCanBeNull*/, false/*nameCanBeEmpty*/,
                                              pExceptioncode))
        return 0;
    DOMString prefix, localName;
    splitPrefixLocalName(_qualifiedName.implementation(), prefix, localName, colonPos);

754
    if (_namespaceURI == SVG_NAMESPACE) {
755
        e = createSVGElement(QualifiedName(prefix, localName, _namespaceURI));
756
        if (e) return e;
757
        if (!e) {
758
            kWarning() << "svg element" << localName << "either is not supported by khtml or it's not a proper svg element";
759
        }
760 761
    }

762 763 764 765 766 767
    // Regardless of document type (even for HTML), this method will only create HTML
    // elements if given the namespace explicitly. Further, this method is always
    // case sensitive, again, even in HTML; however .tagName will case-normalize
    // in HTML regardless
    if (_namespaceURI == XHTML_NAMESPACE) {
        e = createHTMLElement(localName, false /* case sensitive */);
768 769 770 771 772 773 774
        int _exceptioncode = 0;
        if (!prefix.isNull())
            e->setPrefix(prefix, _exceptioncode);
        if ( _exceptioncode ) {
                if ( pExceptioncode ) *pExceptioncode = _exceptioncode;
                delete e;
                return 0;
George Staikos's avatar
George Staikos committed
775 776 777
        }
    }
    if (!e) {
778 779
        e = new XMLElementImpl(document(), NamespaceName::fromString(_namespaceURI),
                LocalName::fromString(localName), PrefixName::fromString(prefix));
George Staikos's avatar
George Staikos committed
780 781 782 783 784 785 786 787 788 789 790 791 792 793
    }

    return e;
}

AttrImpl *DocumentImpl::createAttributeNS( const DOMString &_namespaceURI,
                                           const DOMString &_qualifiedName, int* pExceptioncode)
{
    int colonPos = -2;
    // check NAMESPACE_ERR/INVALID_CHARACTER_ERR
    if (pExceptioncode && !checkQualifiedName(_qualifiedName, _namespaceURI, &colonPos,
                                              false/*nameCanBeNull*/, false/*nameCanBeEmpty*/,
                                              pExceptioncode))
        return 0;
794 795 796 797 798 799 800
    PrefixName prefix;
    LocalName  localName;
    bool htmlCompat =  _namespaceURI.isNull() && htmlMode() != XHtml;
    splitPrefixLocalName(_qualifiedName, prefix, localName, false, colonPos);
    AttrImpl* attr = new AttrImpl(0, document(), NamespaceName::fromString(_namespaceURI),
            localName, prefix, DOMString("").implementation());
    attr->setHTMLCompat( htmlCompat );
George Staikos's avatar
George Staikos committed
801 802 803 804 805
    return attr;
}

ElementImpl *DocumentImpl::getElementById( const DOMString &elementId ) const
{
806
    ElementMappingCache::ItemInfo* info = m_getElementByIdCache.get(elementId);
George Staikos's avatar
George Staikos committed
807

David Faure's avatar
David Faure committed
808
    if (!info)
George Staikos's avatar
George Staikos committed
809 810 811 812 813 814 815
        return 0;

    //See if cache has an unambiguous answer.
    if (info->nd)
        return info->nd;

    //Now we actually have to walk.
Tobias Koenig's avatar
Tobias Koenig committed
816
    QStack<NodeImpl*> nodeStack;
George Staikos's avatar
George Staikos committed
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
    NodeImpl *current = _first;

    while(1)
    {
        if(!current)
        {
            if(nodeStack.isEmpty()) break;
            current = nodeStack.pop();
            current = current->nextSibling();
        }
        else
        {
            if(current->isElementNode())
            {
                ElementImpl *e = static_cast<ElementImpl *>(current);
                if(e->getAttribute(ATTR_ID) == elementId) {
                    info->nd = e;
                    return e;
                }
            }

            NodeImpl *child = current->firstChild();
            if(child)
            {
                nodeStack.push(current);
                current = child;
            }
            else
            {
                current = current->nextSibling();
            }
        }
    }

    assert(0); //If there is no item with such an ID, we should never get here

Laurent Montel's avatar
Laurent Montel committed
853
    //kDebug() << "WARNING: *DocumentImpl::getElementById not found " << elementId.string();
George Staikos's avatar
George Staikos committed
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869

    return 0;
}

void DocumentImpl::setTitle(const DOMString& _title)
{
    if (_title == m_title && !m_title.isNull()) return;

    m_title = _title;

    QString titleStr = m_title.string();
    for (int i = 0; i < titleStr.length(); ++i)
        if (titleStr[i] < ' ')
            titleStr[i] = ' ';
    titleStr = titleStr.simplified();
    if ( view() && !view()->part()->parentPart() ) {
870
	if (titleStr.isEmpty()) {
George Staikos's avatar
George Staikos committed
871
	    // empty title... set window caption as the URL
872
	    KUrl url = m_url;
George Staikos's avatar
George Staikos committed
873 874
	    url.setRef(QString());
	    url.setQuery(QString());
875
	    titleStr = url.prettyUrl();
George Staikos's avatar
George Staikos committed
876 877
	}

878
	emit view()->part()->setWindowCaption( titleStr );
George Staikos's avatar
George Staikos committed
879 880 881 882 883 884 885 886 887 888 889 890 891
    }
}

DOMString DocumentImpl::nodeName() const
{
    return "#document";
}

unsigned short DocumentImpl::nodeType() const
{
    return Node::DOCUMENT_NODE;
}

892
ElementImpl *DocumentImpl::createHTMLElement( const DOMString &name, bool caseInsensitive )
George Staikos's avatar
George Staikos committed
893
{
894
    LocalName localname = LocalName::fromString(name,
895
                                  caseInsensitive ? IDS_NormalizeLower : IDS_CaseSensitive);
896
    uint id = localname.id();
George Staikos's avatar
George Staikos committed
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017

    ElementImpl *n = 0;
    switch(id)
    {
    case ID_HTML:
        n = new HTMLHtmlElementImpl(docPtr());
        break;
    case ID_HEAD:
        n = new HTMLHeadElementImpl(docPtr());
        break;
    case ID_BODY:
        n = new HTMLBodyElementImpl(docPtr());
        break;

// head elements
    case ID_BASE:
        n = new HTMLBaseElementImpl(docPtr());
        break;
    case ID_LINK:
        n = new HTMLLinkElementImpl(docPtr());
        break;
    case ID_META:
        n = new HTMLMetaElementImpl(docPtr());
        break;
    case ID_STYLE:
        n = new HTMLStyleElementImpl(docPtr());
        break;
    case ID_TITLE:
        n = new HTMLTitleElementImpl(docPtr());
        break;

// frames
    case ID_FRAME:
        n = new HTMLFrameElementImpl(docPtr());
        break;
    case ID_FRAMESET:
        n = new HTMLFrameSetElementImpl(docPtr());
        break;
    case ID_IFRAME:
        n = new HTMLIFrameElementImpl(docPtr());
        break;

// form elements
// ### FIXME: we need a way to set form dependency after we have made the form elements
    case ID_FORM:
            n = new HTMLFormElementImpl(docPtr(), false);
        break;
    case ID_BUTTON:
            n = new HTMLButtonElementImpl(docPtr());
        break;
    case ID_FIELDSET:
            n = new HTMLFieldSetElementImpl(docPtr());
        break;
    case ID_INPUT:
            n = new HTMLInputElementImpl(docPtr());
        break;
    case ID_ISINDEX:
            n = new HTMLIsIndexElementImpl(docPtr());
        break;
    case ID_LABEL:
            n = new HTMLLabelElementImpl(docPtr());
        break;
    case ID_LEGEND:
            n = new HTMLLegendElementImpl(docPtr());
        break;
    case ID_OPTGROUP:
            n = new HTMLOptGroupElementImpl(docPtr());
        break;
    case ID_OPTION:
            n = new HTMLOptionElementImpl(docPtr());
        break;
    case ID_SELECT:
            n = new HTMLSelectElementImpl(docPtr());
        break;
    case ID_TEXTAREA:
            n = new HTMLTextAreaElementImpl(docPtr());
        break;

// lists
    case ID_DL:
        n = new HTMLDListElementImpl(docPtr());
        break;
    case ID_DD:
        n = new HTMLGenericElementImpl(docPtr(), id);
        break;
    case ID_DT:
        n = new HTMLGenericElementImpl(docPtr(), id);
        break;
    case ID_UL:
        n = new HTMLUListElementImpl(docPtr());
        break;
    case ID_OL:
        n = new HTMLOListElementImpl(docPtr());
        break;
    case ID_DIR:
        n = new HTMLDirectoryElementImpl(docPtr());
        break;
    case ID_MENU:
        n = new HTMLMenuElementImpl(docPtr());
        break;
    case ID_LI:
        n = new HTMLLIElementImpl(docPtr());
        break;

// formatting elements (block)
    case ID_DIV:
    case ID_P:
        n = new HTMLDivElementImpl( docPtr(), id );
        break;
    case ID_BLOCKQUOTE:
    case ID_H1:
    case ID_H2:
    case ID_H3:
    case ID_H4:
    case ID_H5:
    case ID_H6:
        n = new HTMLGenericElementImpl(docPtr(), id);
        break;
    case ID_HR:
        n = new HTMLHRElementImpl(docPtr());
        break;
1018 1019
    case ID_PLAINTEXT:
    case ID_XMP:
George Staikos's avatar
George Staikos committed
1020
    case ID_PRE:
1021
    case ID_LISTING:
George Staikos's avatar
George Staikos committed
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
        n = new HTMLPreElementImpl(docPtr(), id);
        break;

// font stuff
    case ID_BASEFONT:
        n = new HTMLBaseFontElementImpl(docPtr());
        break;
    case ID_FONT:
        n = new HTMLFontElementImpl(docPtr());
        break;

// ins/del
    case ID_DEL:
    case ID_INS:
        n = new HTMLGenericElementImpl(docPtr(), id);
        break;

// anchor
    case ID_A:
        n = new HTMLAnchorElementImpl(docPtr());
        break;

// images
    case ID_IMG:
1046
    case ID_IMAGE: // legacy name
George Staikos's avatar
George Staikos committed
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
        n = new HTMLImageElementImpl(docPtr());
        break;
    case ID_CANVAS:
        n = new HTMLCanvasElementImpl(docPtr());
        break;
    case ID_MAP:
        n = new HTMLMapElementImpl(docPtr());
        /*n = map;*/
        break;
    case ID_AREA:
        n = new HTMLAreaElementImpl(docPtr());
        break;

// objects, applets and scripts
    case ID_APPLET:
        n = new HTMLAppletElementImpl(docPtr());
        break;
    case ID_OBJECT:
        n = new HTMLObjectElementImpl(docPtr());
        break;
    case ID_EMBED:
        n = new HTMLEmbedElementImpl(docPtr());
        break;
    case ID_PARAM:
        n = new HTMLParamElementImpl(docPtr());
        break;
    case ID_SCRIPT:
        n = new HTMLScriptElementImpl(docPtr());
        break;

1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
// media
    case ID_AUDIO:
        n = new HTMLAudioElement(docPtr());
        break;
    case ID_VIDEO:
        n = new HTMLVideoElement(docPtr());
        break;
    case ID_SOURCE:
        n = new HTMLSourceElement(docPtr());
        break;

George Staikos's avatar
George Staikos committed
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
// tables
    case ID_TABLE:
        n = new HTMLTableElementImpl(docPtr());
        break;
    case ID_CAPTION:
        n = new HTMLTableCaptionElementImpl(docPtr());
        break;
    case ID_COLGROUP:
    case ID_COL:
        n = new HTMLTableColElementImpl(docPtr(), id);
        break;
    case ID_TR:
        n = new HTMLTableRowElementImpl(docPtr());
        break;
    case ID_TD:
    case ID_TH:
        n = new HTMLTableCellElementImpl(docPtr(), id);
        break;
    case ID_THEAD:
    case ID_TBODY:
    case ID_TFOOT:
        n = new HTMLTableSectionElementImpl(docPtr(), id, false);
        break;

// inline elements
    case ID_BR:
        n = new HTMLBRElementImpl(docPtr());
        break;
1116 1117 1118
    case ID_WBR:
        n = new HTMLWBRElementImpl(docPtr());
        break;
George Staikos's avatar
George Staikos committed
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
    case ID_Q:
        n = new HTMLGenericElementImpl(docPtr(), id);
        break;

// elements with no special representation in the DOM

// block:
    case ID_ADDRESS:
    case ID_CENTER:
        n = new HTMLGenericElementImpl(docPtr(), id);
        break;
// inline
        // %fontstyle
    case ID_TT:
    case ID_U:
    case ID_B:
    case ID_I:
    case ID_S:
    case ID_STRIKE:
    case ID_BIG:
    case ID_SMALL:

        // %phrase
    case ID_EM:
    case ID_STRONG:
    case ID_DFN:
    case ID_CODE:
    case ID_SAMP:
    case ID_KBD:
    case ID_VAR:
    case ID_CITE:
    case ID_ABBR:
    case ID_ACRONYM:

        // %special
    case ID_SUB:
    case ID_SUP:
    case ID_SPAN:
    case ID_NOBR:
1158 1159
    case ID_BDO:
    case ID_NOFRAMES:
1160 1161 1162
    case ID_NOSCRIPT:
    case ID_NOEMBED:
    case ID_NOLAYER:
George Staikos's avatar
George Staikos committed
1163 1164 1165 1166 1167 1168 1169 1170
        n = new HTMLGenericElementImpl(docPtr(), id);
        break;

    case ID_MARQUEE:
        n = new HTMLMarqueeElementImpl(docPtr());
        break;
// text
    case ID_TEXT:
Laurent Montel's avatar
Laurent Montel committed
1171
        kDebug( 6020 ) << "Use document->createTextNode()";
George Staikos's avatar
George Staikos committed
1172 1173 1174
        break;

    default:
1175
        n = new HTMLGenericElementImpl(docPtr(), localname);
George Staikos's avatar
George Staikos committed
1176 1177
        break;
    }
1178
    assert(n);
George Staikos's avatar
George Staikos committed
1179 1180 1181
    return n;
}

1182 1183 1184 1185
// SVG
ElementImpl *DocumentImpl::createSVGElement(const QualifiedName& name)
{
    uint id = name.localNameId().id();
1186 1187
    kDebug() << getPrintableName(name.id()) << endl;
    kDebug() << "svg text:   " << getPrintableName(WebCore::SVGNames::textTag.id()) << endl;
1188 1189

    ElementImpl *n = 0;
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
    switch (id)
    {
    case ID_TEXTPATH:
        n = new WebCore::SVGTextPathElement(name, docPtr());
        break;
    case ID_TSPAN:
        n = new WebCore::SVGTSpanElement(name, docPtr());
        break;
    case ID_HKERN:
        n = new WebCore::SVGHKernElement(name, docPtr());
        break;
    case ID_ALTGLYPH:
        n = new WebCore::SVGAltGlyphElement(name, docPtr());
        break;
    case ID_FONT:
        n = new WebCore::SVGFontElement(name, docPtr());
        break;
    }

1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
    if (id == WebCore::SVGNames::svgTag.localNameId().id()) {
        n = new WebCore::SVGSVGElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::rectTag.localNameId().id()) {
        n = new WebCore::SVGRectElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::circleTag.localNameId().id()) {
        n = new WebCore::SVGCircleElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::ellipseTag.localNameId().id()) {
        n = new WebCore::SVGEllipseElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::polylineTag.localNameId().id()) {
        n = new WebCore::SVGPolylineElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::polygonTag.localNameId().id()) {
        n = new WebCore::SVGPolygonElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::pathTag.localNameId().id()) {
        n = new WebCore::SVGPathElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::defsTag.localNameId().id()) {
        n = new WebCore::SVGDefsElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::linearGradientTag.localNameId().id()) {
        n = new WebCore::SVGLinearGradientElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::radialGradientTag.localNameId().id()) {
        n = new WebCore::SVGRadialGradientElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::stopTag.localNameId().id()) {
        n = new WebCore::SVGStopElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::clipPathTag.localNameId().id()) {
        n = new WebCore::SVGClipPathElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::gTag.localNameId().id()) {
        n = new WebCore::SVGGElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::useTag.localNameId().id()) {
        n = new WebCore::SVGUseElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::lineTag.localNameId().id()) {
        n = new WebCore::SVGLineElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::textTag.localNameId().id()) {
        n = new WebCore::SVGTextElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::aTag.localNameId().id()) {
        n = new WebCore::SVGAElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::scriptTag.localNameId().id()) {
        n = new WebCore::SVGScriptElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::descTag.localNameId().id()) {
        n = new WebCore::SVGDescElement(name, docPtr());
    }

    if (id == WebCore::SVGNames::titleTag.localNameId().id()) {
        n = new WebCore::SVGTitleElement(name, docPtr());
    }

    if (id == makeId(svgNamespace, ID_STYLE)) {
        n = new WebCore::SVGStyleElement(name, docPtr());
    }

    return n;
}

1296
void DocumentImpl::attemptRestoreState(NodeImpl* n)
George Staikos's avatar
George Staikos committed
1297
{
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
    if (!n->isElementNode())
        return;

    ElementImpl* el = static_cast<ElementImpl*>(n);

    if (m_stateRestorePos >= m_state.size())
        return;

    // Grab the state and element info..
    QString idStr = m_state[m_stateRestorePos];
    QString nmStr = m_state[m_stateRestorePos + 1];
    QString tpStr = m_state[m_stateRestorePos + 2];
    QString stStr = m_state[m_stateRestorePos + 3];

    // Make sure it matches!
    if (idStr.toUInt() != el->id())
        return;
    if (nmStr != el->getAttribute(ATTR_NAME).string())
        return;
    if (tpStr != el->getAttribute(ATTR_TYPE).string())
        return;

    m_stateRestorePos += 4;
    if (!stStr.isNull())
        el->restoreState(stStr);
George Staikos's avatar
George Staikos committed
1323 1324 1325 1326 1327
}

QStringList DocumentImpl::docState()
{
    QStringList s;
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339
    for (QListIterator<NodeImpl*> it(m_maintainsState); it.hasNext();) {
        NodeImpl* n = it.next();
        if (!n->isElementNode())
            continue;

        ElementImpl* el = static_cast<ElementImpl*>(n);
        // Encode the element ID, as well as the name and type attributes
        s.append(QString::number(el->id()));
        s.append(el->getAttribute(ATTR_NAME).string());
        s.append(el->getAttribute(ATTR_TYPE).string());
        s.append(el->state());
    }
George Staikos's avatar
George Staikos committed
1340 1341 1342 1343 1344 1345

    return s;
}

bool DocumentImpl::unsubmittedFormChanges()
{
Harri Porten's avatar
Harri Porten committed
1346 1347 1348
    for (QListIterator<NodeImpl*> it(m_maintainsState); it.hasNext();) {
        NodeImpl* node = it.next();
        if (node->isGenericFormElement() && static_cast<HTMLGenericFormElementImpl*>(