summaryrefslogtreecommitdiffstats
path: root/khtml/xml/dom_elementimpl.h
blob: ee1be3e4ae23584f01cacf2ac716d65f63b937a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
/*
 * This file is part of the DOM implementation for KDE.
 *
 * Copyright (C) 1999 Lars Knoll ([email protected])
 *           (C) 1999 Antti Koivisto ([email protected])
 *           (C) 2001 Peter Kelly ([email protected])
 *           (C) 2001 Dirk Mueller ([email protected])
 *           (C) 2003 Apple Computer, Inc.
 *
 * 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.
 *
 */
#ifndef _DOM_ELEMENTImpl_h_
#define _DOM_ELEMENTImpl_h_

#include "dom_nodeimpl.h"
#include "dom/dom_exception.h"
#include "dom/dom_element.h"
#include "xml/dom_stringimpl.h"
#include "misc/shared.h"

namespace khtml {
    class CSSStyleSelector;
}

namespace DOM {

class ElementImpl;
class DocumentImpl;
class NamedAttrMapImpl;

// Attr can have Text and EntityReference children
// therefore it has to be a fullblown Node. The plan
// is to dynamically allocate a textchild and store the
// resulting nodevalue in the AttributeImpl upon
// destruction. however, this is not yet implemented.
class AttrImpl : public NodeBaseImpl
{
    friend class ElementImpl;
    friend class NamedAttrMapImpl;

public:
    AttrImpl(ElementImpl* element, DocumentImpl* docPtr, NodeImpl::Id attrId,
	     DOMStringImpl *value, DOMStringImpl *prefix = 0);
    ~AttrImpl();

private:
    AttrImpl(const AttrImpl &other);
    AttrImpl &operator = (const AttrImpl &other);
public:

    // DOM methods & attributes for Attr
    bool specified() const { return m_specified; }
    ElementImpl* ownerElement() const { return m_element; }
    void setOwnerElement( ElementImpl* impl ) { m_element = impl; }
    DOMString name() const;

    //DOMString value() const;
    void setValue( const DOMString &v, int &exceptioncode );

    // DOM methods overridden from  parent classes
    virtual DOMString nodeName() const;
    virtual unsigned short nodeType() const;
    virtual DOMString prefix() const;
    virtual void setPrefix(const DOMString &_prefix, int &exceptioncode );
    virtual DOMString namespaceURI() const;
    virtual DOMString localName() const;

    virtual DOMString nodeValue() const;
    virtual void setNodeValue( const DOMString &, int &exceptioncode );
    virtual NodeImpl *cloneNode ( bool deep );

    virtual DOMStringImpl* textContent() const;
    virtual void           setTextContent( const DOMString &text, int& exceptioncode );


    // Other methods (not part of DOM)
    virtual bool isAttributeNode() const { return true; }
    virtual bool childAllowed( NodeImpl *newChild );
    virtual bool childTypeAllowed( unsigned short type );
    virtual NodeImpl::Id id() const { return m_attrId; }

    virtual DOMString toString() const;

    void setElement(ElementImpl *element);
    DOMStringImpl *val() { return m_value; }

protected:
    ElementImpl *m_element;
    NodeImpl::Id m_attrId;
    DOMStringImpl *m_value;
    DOMStringImpl *m_prefix;
    DOMStringImpl *m_localName;
};

// Mini version of AttrImpl internal to NamedAttrMapImpl.
// Stores either the id and value of an attribute
// (in the case of m_attrId != 0), or a pointer to an AttrImpl (if m_attrId == 0)
// The latter case only happens when the Attr node is requested by some DOM
// code or is an XML attribute.
// In most cases the id and value is all we need to store, which is more
// memory efficient.
struct AttributeImpl
{
    NodeImpl::Id id() const { return m_attrId ? m_attrId : m_data.attr->id(); }
    DOMStringImpl *val() const { return m_attrId ? m_data.value : m_data.attr->val(); }
    DOMString value() const { return val(); }
    AttrImpl *attr() const { return m_attrId ? 0 : m_data.attr; }
    DOMString namespaceURI() { return m_attrId ? DOMString() : m_data.attr->namespaceURI(); }
    DOMString prefix() { return m_attrId ? DOMString() : m_data.attr->prefix(); }
    DOMString localName() { return m_attrId ? DOMString() : m_data.attr->localName(); }
    DOMString name() { return m_attrId ? DOMString() : m_data.attr->name(); }

    void setValue(DOMStringImpl *value, ElementImpl *element);
    AttrImpl *createAttr(ElementImpl *element, DocumentImpl *docPtr);
    void free();

    NodeImpl::Id m_attrId;
    union {
        DOMStringImpl *value;
        AttrImpl *attr;
    } m_data;
};

class ElementImpl : public NodeBaseImpl
{
    friend class DocumentImpl;
    friend class NamedAttrMapImpl;
    friend class AttrImpl;
    friend class NodeImpl;
    friend class khtml::CSSStyleSelector;
public:
    ElementImpl(DocumentImpl *doc);
    ~ElementImpl();

    DOMString getAttribute( NodeImpl::Id id, bool nsAware = 0, const DOMString& qName = DOMString() ) const;
    DOMStringImpl* getAttributeImpl( NodeImpl::Id id, bool nsAware = 0, DOMStringImpl* qName = 0 ) const;
    void setAttribute( NodeImpl::Id id, const DOMString &value, const DOMString &qName,
                       int &exceptioncode );
    void setAttributeNS( const DOMString &namespaceURI, const DOMString &qualifiedName,
                         const DOMString& value, int &exceptioncode );
    virtual DOMString prefix() const;
    void setPrefix(const DOMString &_prefix, int &exceptioncode );
    virtual DOMString namespaceURI() const;

    // DOM methods overridden from  parent classes
    virtual DOMString tagName() const = 0;
    virtual unsigned short nodeType() const;
    virtual NodeImpl *cloneNode ( bool deep );
    virtual DOMString nodeName() const;
    virtual NodeImpl::Id id() const = 0;
    virtual bool isElementNode() const { return true; }
    virtual void insertedIntoDocument();
    virtual void removedFromDocument();

    // convenience methods which ignore exceptions
    void setAttribute (NodeImpl::Id id, const DOMString &value);

    NamedAttrMapImpl* attributes(bool readonly = false) const
    {
        if (!readonly && !namedAttrMap) createAttributeMap();
        return namedAttrMap;
    }

    //This is always called, whenever an attribute changed
    virtual void parseAttribute(AttributeImpl *) {}
    void parseAttribute(NodeImpl::Id attrId, DOMStringImpl *value) {
	AttributeImpl aimpl;
	aimpl.m_attrId = attrId;
	aimpl.m_data.value = value;
	parseAttribute(&aimpl);
    }

    // not part of the DOM
    void setAttributeMap ( NamedAttrMapImpl* list );

    // State of the element.
    virtual TQString state() { return TQString::null; }

    virtual void attach();
    virtual void close();
    virtual void detach();
    virtual void structureChanged();
    virtual void backwardsStructureChanged();
    virtual void attributeChanged(NodeImpl::Id attrId);

    virtual khtml::RenderStyle *styleForRenderer(khtml::RenderObject *parent);
    virtual khtml::RenderObject *createRenderer(khtml::RenderArena *, khtml::RenderStyle *);
    virtual void recalcStyle( StyleChange = NoChange );

    virtual void mouseEventHandler( MouseEvent* /*ev*/, bool /*inside*/ ) {}
    virtual bool isFocusable() const;
    virtual bool childAllowed( NodeImpl *newChild );
    virtual bool childTypeAllowed( unsigned short type );

    DOM::CSSStyleDeclarationImpl *styleRules() {
      if (!m_styleDecls) createDecl();
      return m_styleDecls;
    }

    void dispatchAttrRemovalEvent(NodeImpl::Id id, DOMStringImpl *value);
    void dispatchAttrAdditionEvent(NodeImpl::Id id, DOMStringImpl *value);

    virtual DOMString toString() const;
    virtual DOMString selectionToString(NodeImpl *selectionStart, NodeImpl *selectionEnd, int startOffset, int endOffset, bool &found) const;

    virtual bool contentEditable() const;
    void setContentEditable(bool enabled);

    void scrollIntoView(bool alignToTop);

    /** Returns the opening tag and properties.
     *  Examples:  '<b', '<img alt="hello" src="image.png"
     *
     *  For security reasons, passwords are stripped out of all src= and
     *  href=  tags if expandurls is turned on.
     *
     *  @param expandurls If this is set then in the above example, it would give
     *                    src="http://website.com/image.png".  Note that the password
     *                    is stripped out of the url.
     *
     *  DOM::RangeImpl uses this which is why it is public.
     */
    DOMString openTagStartToString(bool expandurls = false) const;

    void updateId(DOMStringImpl* oldId, DOMStringImpl* newId);
    //Called when mapping from id to this node in document should be removed
    virtual void removeId(const TQString& id);
    //Called when mapping from id to this node in document should be added
    virtual void addId   (const TQString& id);

protected:
    void createAttributeMap() const;
    void createDecl();
    void finishCloneNode( ElementImpl *clone, bool deep );

private:
    // map of default attributes. derived element classes are responsible
    // for setting this according to the corresponding element description
    // in the DTD
    virtual NamedAttrMapImpl* defaultMap() const;

protected: // member variables
    mutable NamedAttrMapImpl *namedAttrMap;

    DOM::CSSStyleDeclarationImpl *m_styleDecls;
    DOMStringImpl *m_prefix;
};


class XMLElementImpl : public ElementImpl
{

public:
    XMLElementImpl(DocumentImpl *doc, NodeImpl::Id id);
    XMLElementImpl(DocumentImpl *doc, NodeImpl::Id id, DOMStringImpl *_qualifiedName);
    ~XMLElementImpl();

    // DOM methods overridden from  parent classes
    virtual DOMString tagName() const;
    virtual DOMString localName() const;
    virtual NodeImpl *cloneNode ( bool deep );

    // Other methods (not part of DOM)
    virtual bool isXMLElementNode() const { return true; }
    virtual Id id() const { return m_id; }

protected:
    Id  m_id;
};

// the map of attributes of an element
class NamedAttrMapImpl : public NamedNodeMapImpl
{
    friend class ElementImpl;
public:
    NamedAttrMapImpl(ElementImpl *element);
    virtual ~NamedAttrMapImpl();

    // DOM methods & attributes for NamedNodeMap
    virtual NodeImpl *getNamedItem ( NodeImpl::Id id, bool nsAware = false, DOMStringImpl* qName = 0 ) const;
    virtual Node removeNamedItem ( NodeImpl::Id id, bool nsAware, DOMStringImpl* qName, int &exceptioncode );
    virtual Node setNamedItem ( NodeImpl* arg, bool nsAware, DOMStringImpl* qName, int &exceptioncode );

    virtual NodeImpl *item ( unsigned long index ) const;
    virtual unsigned long length(  ) const;

    // Other methods (not part of DOM)
    virtual bool isReadOnly() { return false; }

    AttributeImpl *attrAt(unsigned long index) const { return &m_attrs[index]; }
    // ### replace idAt and getValueAt with attrAt
    NodeImpl::Id idAt(unsigned long index) const;
    DOMStringImpl *valueAt(unsigned long index) const;
    DOMStringImpl *getValue(NodeImpl::Id id, bool nsAware = false, DOMStringImpl* qName = 0) const;
    void setValue(NodeImpl::Id id, DOMStringImpl *value, DOMStringImpl* qName = 0,
                  DOMStringImpl *prefix = 0, bool nsAware = false, bool hasNS = false);
    Attr removeAttr(AttrImpl *attr);
    NodeImpl::Id mapId(DOMStringImpl* namespaceURI, DOMStringImpl* localName, bool readonly);
    void copyAttributes(NamedAttrMapImpl *other);
    void setElement(ElementImpl *element);
    void detachFromElement();

protected:
    ElementImpl *m_element;
    AttributeImpl *m_attrs;
    unsigned long m_attrCount;
};

// ------------  inline DOM helper functions ---------------

inline bool checkQualifiedName(const DOMString &qualifiedName, const DOMString &namespaceURI, int *colonPos,
                               bool nameCanBeNull, bool nameCanBeEmpty, int *pExceptioncode)
{

    // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied
    if (!nameCanBeNull && qualifiedName.isNull()) {
        if (pExceptioncode)
            *pExceptioncode = DOMException::NAMESPACE_ERR;
        return false;
    }

    // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
    if (!qualifiedName.isNull() && !Element::khtmlValidQualifiedName(qualifiedName)
        && ( !qualifiedName.isEmpty() || !nameCanBeEmpty ) ) {
        if (pExceptioncode)
            *pExceptioncode = DOMException::INVALID_CHARACTER_ERR;
        return false;
    }

    // NAMESPACE_ERR:
    // - Raised if the qualifiedName is malformed,
    // - if the qualifiedName has a prefix and the namespaceURI is null, or
    // - if the qualifiedName is null and the namespaceURI is different from null
    // - if the qualifiedName has a prefix that is "xml" and the namespaceURI is different
    //   from "http://www.w3.org/XML/1998/namespace" [Namespaces].
    int colonpos = -1;
    uint i;
    DOMStringImpl *qname = qualifiedName.implementation();
    for (i = 0 ; i < qname->l ; i++) {
        if ((*qname)[i] == ':') {
            colonpos = i;
            break;
        }
    }

    if (!qualifiedName.isNull() && Element::khtmlMalformedQualifiedName(qualifiedName) ||
        (colonpos >= 0 && namespaceURI.isNull()) ||
        (qualifiedName.isNull() && !namespaceURI.isNull()) ||
        (colonpos == 3 && qualifiedName[0] == 'x' && qualifiedName[1] == 'm' && qualifiedName[2] == 'l' &&
         namespaceURI != "http://www.w3.org/XML/1998/namespace")) {
        if (pExceptioncode)
            *pExceptioncode = DOMException::NAMESPACE_ERR;
        return false;
    }
    if(colonPos)
        *colonPos = colonpos;
    return true;
}

inline void splitPrefixLocalName(DOMStringImpl *qualifiedName, DOMString &prefix, DOMString &localName, int colonPos = -2)
{
    if (colonPos == -2)
        for (uint i = 0 ; i < qualifiedName->l ; ++i)
            if (qualifiedName->s[i] == ':') {
                colonPos = i;
                break;
            }
    if (colonPos >= 0) {
        prefix = qualifiedName->copy();
        localName = prefix.split(colonPos+1);
        prefix.implementation()->truncate(colonPos);
    } else
        localName = qualifiedName->copy();
}

} //namespace

#endif