Initial revision
[WebKit-https.git] / WebCore / khtml / html / html_miscimpl.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * $Id$
23  */
24 // -------------------------------------------------------------------------
25 #include "html_miscimpl.h"
26 #include "html_formimpl.h"
27
28 #include "htmlhashes.h"
29 #include "dom_node.h"
30 using namespace DOM;
31
32 #include <kdebug.h>
33
34 HTMLBaseFontElementImpl::HTMLBaseFontElementImpl(DocumentPtr *doc) : HTMLElementImpl(doc)
35 {
36 }
37
38 HTMLBaseFontElementImpl::~HTMLBaseFontElementImpl()
39 {
40 }
41
42 const DOMString HTMLBaseFontElementImpl::nodeName() const
43 {
44     return "BASEFONT";
45 }
46
47 ushort HTMLBaseFontElementImpl::id() const
48 {
49     return ID_BASEFONT;
50 }
51
52 // -------------------------------------------------------------------------
53
54 HTMLCollectionImpl::HTMLCollectionImpl(NodeImpl *_base, int _type)
55 {
56     base = _base;
57     base->ref();
58     type = _type;
59 }
60
61 HTMLCollectionImpl::~HTMLCollectionImpl()
62 {
63     base->deref();
64 }
65
66 unsigned long HTMLCollectionImpl::calcLength(NodeImpl *current) const
67 {
68     unsigned long len = 0;
69     while(current)
70     {
71         if(current->nodeType() == Node::ELEMENT_NODE)
72         {
73             bool deep = true;
74             HTMLElementImpl *e = static_cast<HTMLElementImpl *>(current);
75             switch(type)
76             {
77             case DOC_IMAGES:
78                 if(e->id() == ID_IMG)
79                     len++;
80                 break;
81             case DOC_FORMS:
82                 if(e->id() == ID_FORM)
83                     len++;
84                 break;
85             case TABLE_TBODIES:
86                 if(e->id() == ID_TBODY)
87                     len++;
88                 else if(e->id() == ID_TABLE)
89                     deep = false;
90                 break;
91             case TR_CELLS:
92                 if(e->id() == ID_TD)
93                     len++;
94                 else if(e->id() == ID_TABLE)
95                     deep = false;
96                 break;
97             case TABLE_ROWS:
98             case TSECTION_ROWS:
99                 if(e->id() == ID_TR || e->id() == ID_TH)
100                     len++;
101                 else if(e->id() == ID_TABLE)
102                     deep = false;
103                 break;
104             case SELECT_OPTIONS:
105                 if(e->id() == ID_OPTION)
106                     len++;
107                 break;
108             case MAP_AREAS:
109                 if(e->id() == ID_AREA)
110                     len++;
111                 break;
112             case DOC_APPLETS:   // all OBJECT and APPLET elements
113                 if(e->id() == ID_OBJECT || e->id() == ID_APPLET)
114                     len++;
115                 break;
116             case DOC_LINKS:     // all A _and_ AREA elements with a value for href
117                 if(e->id() == ID_A || e->id() == ID_AREA)
118                     if(e->getAttribute(ATTR_HREF) != 0)
119                         len++;
120                 break;
121             case DOC_ANCHORS:      // all A elements with a value for name and all elements with an id attribute
122                 if ( e->hasID() )
123                     len++;
124                 else if(e->id() == ID_A) {
125                     if(e->getAttribute(ATTR_NAME) != 0)
126                         len++;
127                 }
128                 break;
129             case DOC_ALL:      // "all" elements
130                 len++;
131                 break;
132             default:
133                 kdDebug( 6030 ) << "Error in HTMLCollection, wrong tagId!" << endl;
134             }
135             if(deep && current->firstChild())
136                 len += calcLength(current->firstChild());
137         }
138         current = current->nextSibling();
139     }
140     return len;
141 }
142
143 // since the collections are to be "live", we have to do the
144 // calculation every time...
145 unsigned long HTMLCollectionImpl::length() const
146 {
147     return calcLength(base->firstChild());
148 }
149
150 NodeImpl *HTMLCollectionImpl::getItem(NodeImpl *current, int index, int &len) const
151 {
152     while(current)
153     {
154         if(current->nodeType() == Node::ELEMENT_NODE)
155         {
156             bool deep = true;
157             HTMLElementImpl *e = static_cast<HTMLElementImpl *>(current);
158             switch(type)
159             {
160             case DOC_IMAGES:
161                 if(e->id() == ID_IMG)
162                     len++;
163                 break;
164             case DOC_FORMS:
165                 if(e->id() == ID_FORM)
166                     len++;
167                 break;
168             case TABLE_TBODIES:
169                 if(e->id() == ID_TBODY)
170                     len++;
171                 else if(e->id() == ID_TABLE)
172                     deep = false;
173                 break;
174             case TR_CELLS:
175                 if(e->id() == ID_TD)
176                     len++;
177                 else if(e->id() == ID_TABLE)
178                     deep = false;
179                 break;
180             case TABLE_ROWS:
181             case TSECTION_ROWS:
182                 if(e->id() == ID_TR || e->id() == ID_TH)
183                     len++;
184                 else if(e->id() == ID_TABLE)
185                     deep = false;
186                 break;
187             case SELECT_OPTIONS:
188                 if(e->id() == ID_OPTION)
189                     len++;
190                 break;
191             case MAP_AREAS:
192                 if(e->id() == ID_AREA)
193                     len++;
194                 break;
195             case DOC_APPLETS:   // all OBJECT and APPLET elements
196                 if(e->id() == ID_OBJECT || e->id() == ID_APPLET)
197                     len++;
198                 break;
199             case DOC_LINKS:     // all A _and_ AREA elements with a value for href
200                 if(e->id() == ID_A || e->id() == ID_AREA)
201                     if(e->getAttribute(ATTR_HREF) != 0)
202                         len++;
203                 break;
204             case DOC_ANCHORS:      // all A elements with a value for name or an id attribute
205                 if( e->hasID() )
206                     len++;
207                 else if(e->id() == ID_A)
208                     if(e->getAttribute(ATTR_NAME) != 0)
209                         len++;
210                 break;
211             case DOC_ALL:
212                 len++;
213                 break;
214             default:
215                 kdDebug( 6030 ) << "Error in HTMLCollection, wrong tagId!" << endl;
216             }
217             if(len == (index + 1)) return current;
218             NodeImpl *retval=0;
219             if(deep && current->firstChild())
220                 retval = getItem(current->firstChild(), index, len);
221             if(retval) return retval;
222         }
223         current = current->nextSibling();
224     }
225     return 0;
226 }
227
228 NodeImpl *HTMLCollectionImpl::item( unsigned long index ) const
229 {
230     int pos = 0;
231     return getItem(base->firstChild(), index, pos);
232 }
233
234 NodeImpl *HTMLCollectionImpl::getNamedItem( NodeImpl *current, int attr_id,
235                                             const DOMString &name ) const
236 {
237     if(name.isEmpty())
238         return 0;
239
240     while(current)
241     {
242         if(current->nodeType() == Node::ELEMENT_NODE)
243         {
244             bool deep = true;
245             bool check = false;
246             HTMLElementImpl *e = static_cast<HTMLElementImpl *>(current);
247             switch(type)
248             {
249             case DOC_IMAGES:
250                 if(e->id() == ID_IMG)
251                     check = true;
252                 break;
253             case DOC_FORMS:
254                 if(e->id() == ID_FORM)
255                     check = true;
256                 break;
257             case TABLE_TBODIES:
258                 if(e->id() == ID_TBODY)
259                     check = true;
260                 else if(e->id() == ID_TABLE)
261                     deep = false;
262                 break;
263             case TR_CELLS:
264                 if(e->id() == ID_TD)
265                     check = true;
266                 else if(e->id() == ID_TABLE)
267                     deep = false;
268                 break;
269             case TABLE_ROWS:
270             case TSECTION_ROWS:
271                 if(e->id() == ID_TR || e->id() == ID_TH)
272                     check = true;
273                 else if(e->id() == ID_TABLE)
274                     deep = false;
275                 break;
276             case SELECT_OPTIONS:
277                 if(e->id() == ID_OPTION)
278                     check = true;
279                 break;
280             case MAP_AREAS:
281                 if(e->id() == ID_AREA)
282                     check = true;
283                 break;
284             case DOC_APPLETS:   // all OBJECT and APPLET elements
285                 if(e->id() == ID_OBJECT || e->id() == ID_APPLET)
286                     check = true;
287                 break;
288             case DOC_LINKS:     // all A _and_ AREA elements with a value for href
289                 if(e->id() == ID_A || e->id() == ID_AREA)
290                     if(e->getAttribute(ATTR_HREF) != 0)
291                         check = true;
292                 break;
293             case DOC_ANCHORS:      // all A elements with a value for name
294                 if( e->hasID() )
295                     check = true;
296                 else if(e->id() == ID_A)
297                     if(e->getAttribute(ATTR_NAME) != 0)
298                         check = true;
299                 break;
300             case DOC_ALL:
301                 check = true;
302                 break;
303             default:
304                 kdDebug( 6030 ) << "Error in HTMLCollection, wrong tagId!" << endl;
305                 break;
306             }
307             if(check && e->getAttribute(attr_id) == name)
308             {
309                 //kdDebug( 6030 ) << "found node: " << e << " " << current << " " << e->id() << endl;
310                 return current;
311             }
312             NodeImpl *retval = 0;
313             if(deep && current->firstChild())
314                 retval = getNamedItem(current->firstChild(), attr_id, name);
315             if(retval)
316             {
317                 //kdDebug( 6030 ) << "got a return value " << retval << endl;
318                 return retval;
319             }
320         }
321         current = current->nextSibling();
322     }
323     return 0;
324 }
325
326 NodeImpl *HTMLCollectionImpl::namedItem( const DOMString &name ) const
327 {
328     NodeImpl *n;
329     n = getNamedItem(base->firstChild(), ATTR_ID, name);
330     if(n) return n;
331     return getNamedItem(base->firstChild(), ATTR_NAME, name);
332 }
333
334
335 // -----------------------------------------------------------------------------
336
337 unsigned long HTMLFormCollectionImpl::calcLength(NodeImpl*) const
338 {
339     QList<HTMLGenericFormElementImpl> l = static_cast<HTMLFormElementImpl*>( base )->formElements;
340
341     int len = 0;
342     for ( unsigned i = 0; i < l.count(); i++ )
343         if ( l.at( i )->isEnumeratable() )
344             ++len;
345
346     return len;
347 }
348
349 NodeImpl* HTMLFormCollectionImpl::getItem(NodeImpl *, int index, int&) const
350 {
351     QList<HTMLGenericFormElementImpl> l = static_cast<HTMLFormElementImpl*>( base )->formElements;
352
353     for ( unsigned i = 0; i < l.count(); i++ ) {
354
355         if( l.at( i )->isEnumeratable() ) {
356             if ( !index )
357                 return l.at( i );
358
359             --index;
360         }
361     }
362
363     return 0;
364 }
365
366 NodeImpl* HTMLFormCollectionImpl::getNamedItem(NodeImpl*, int attr_id, const DOMString& name) const
367 {
368     if(base->nodeType() == Node::ELEMENT_NODE)
369     {
370         HTMLElementImpl* e = static_cast<HTMLElementImpl*>(base);
371         if(e->id() == ID_FORM)
372         {
373             HTMLGenericFormElementImpl* element;
374             HTMLFormElementImpl* f = static_cast<HTMLFormElementImpl*>(e);
375
376             for(element = f->formElements.first(); element; element = f->formElements.next())
377                 if(element->isEnumeratable() && element->getAttribute(attr_id) == name)
378                     return element;
379         }
380     }
381
382     return 0;
383 }