Fix for 3478435, <hr> tags should be centered by default. Ditched the 1px margin...
[WebKit-https.git] / WebCore / khtml / html / html_blockimpl.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  * Copyright (C) 2003 Apple Computer, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  */
24 // -------------------------------------------------------------------------
25 //#define DEBUG
26 #include "html_blockimpl.h"
27 #include "html_documentimpl.h"
28 #include "css/cssstyleselector.h"
29
30 #include "css/cssproperties.h"
31 #include "css/cssvalues.h"
32 #include "misc/htmlhashes.h"
33
34 #include <kdebug.h>
35
36 using namespace khtml;
37 using namespace DOM;
38
39 HTMLBlockquoteElementImpl::HTMLBlockquoteElementImpl(DocumentPtr *doc)
40     : HTMLElementImpl(doc)
41 {
42 }
43
44 HTMLBlockquoteElementImpl::~HTMLBlockquoteElementImpl()
45 {
46 }
47
48 NodeImpl::Id HTMLBlockquoteElementImpl::id() const
49 {
50     return ID_BLOCKQUOTE;
51 }
52
53 // -------------------------------------------------------------------------
54
55 HTMLDivElementImpl::HTMLDivElementImpl(DocumentPtr *doc)
56     : HTMLElementImpl(doc)
57 {
58 }
59
60 HTMLDivElementImpl::~HTMLDivElementImpl()
61 {
62 }
63
64 NodeImpl::Id HTMLDivElementImpl::id() const
65 {
66     return ID_DIV;
67 }
68
69 void HTMLDivElementImpl::parseAttribute(AttributeImpl *attr)
70 {
71     switch(attr->id())
72     {
73     case ATTR_ALIGN:
74     {
75         DOMString v = attr->value();
76         if ( strcasecmp( attr->value(), "middle" ) == 0 || strcasecmp( attr->value(), "center" ) == 0 )
77            addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_CENTER);
78         else if (strcasecmp(attr->value(), "left") == 0)
79             addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_LEFT);
80         else if (strcasecmp(attr->value(), "right") == 0)
81             addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_RIGHT);
82         else
83             addCSSProperty(CSS_PROP_TEXT_ALIGN, v);
84         break;
85     }
86     default:
87         HTMLElementImpl::parseAttribute(attr);
88     }
89 }
90
91 // -------------------------------------------------------------------------
92
93 HTMLHRElementImpl::HTMLHRElementImpl(DocumentPtr *doc)
94     : HTMLElementImpl(doc)
95 {
96 }
97
98 HTMLHRElementImpl::~HTMLHRElementImpl()
99 {
100 }
101
102 NodeImpl::Id HTMLHRElementImpl::id() const
103 {
104     return ID_HR;
105 }
106
107 void HTMLHRElementImpl::parseAttribute(AttributeImpl *attr)
108 {
109     switch( attr->id() )
110     {
111     case ATTR_ALIGN: {
112         if (strcasecmp(attr->value(), "left") == 0) {
113             addCSSProperty(CSS_PROP_MARGIN_LEFT, "0");
114             addCSSProperty(CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO);
115         }
116         else if (strcasecmp(attr->value(), "right") == 0) {
117             addCSSProperty(CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO);
118             addCSSProperty(CSS_PROP_MARGIN_RIGHT, "0");
119         }
120         else {
121             addCSSProperty(CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO);
122             addCSSProperty(CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO);
123         }
124         break;
125     }
126     case ATTR_WIDTH:
127     {
128         if(!attr->val()) break;
129         // cheap hack to cause linebreaks
130         // khtmltests/html/strange_hr.html
131         bool ok;
132         int v = attr->val()->toInt(&ok);
133         if(ok && !v)
134             addCSSLength(CSS_PROP_WIDTH, "1");
135         else
136             addCSSLength(CSS_PROP_WIDTH, attr->value());
137     }
138     break;
139     default:
140         HTMLElementImpl::parseAttribute(attr);
141     }
142 }
143
144 // ### make sure we undo what we did during detach
145 void HTMLHRElementImpl::attach()
146 {
147     if (attributes(true /* readonly */)) {
148         // there are some attributes, lets check
149         DOMString color = getAttribute(ATTR_COLOR);
150         DOMStringImpl* si = getAttribute(ATTR_SIZE).implementation();
151         int _s =  si ? si->toInt() : -1;
152         DOMString n("1");
153         if (!color.isNull()) {
154             addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
155             addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
156             addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
157             addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
158             addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, DOMString("0"));
159             addCSSLength(CSS_PROP_BORDER_BOTTOM_WIDTH, DOMString(si));
160             addHTMLColor(CSS_PROP_BORDER_COLOR, color);
161         }
162         else {
163             if (_s > 1 && getAttribute(ATTR_NOSHADE).isNull()) {
164                 addCSSProperty(CSS_PROP_BORDER_BOTTOM_WIDTH, n);
165                 addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, n);
166                 addCSSProperty(CSS_PROP_BORDER_LEFT_WIDTH, n);
167                 addCSSProperty(CSS_PROP_BORDER_RIGHT_WIDTH, n);
168                 addCSSLength(CSS_PROP_HEIGHT, DOMString(QString::number(_s-2)));
169             }
170             else if (_s >= 0) {
171                 addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, DOMString(QString::number(_s)));
172                 addCSSProperty(CSS_PROP_BORDER_BOTTOM_WIDTH, DOMString("0"));
173             }
174         }
175         if (_s == 0)
176             addCSSProperty(CSS_PROP_MARGIN_BOTTOM, n);
177     }
178
179     HTMLElementImpl::attach();
180 }
181
182 // -------------------------------------------------------------------------
183
184 HTMLHeadingElementImpl::HTMLHeadingElementImpl(DocumentPtr *doc, ushort _tagid)
185     : HTMLGenericElementImpl(doc, _tagid)
186 {
187 }
188
189 // -------------------------------------------------------------------------
190
191 HTMLParagraphElementImpl::HTMLParagraphElementImpl(DocumentPtr *doc)
192     : HTMLElementImpl(doc)
193 {
194 }
195
196 NodeImpl::Id HTMLParagraphElementImpl::id() const
197 {
198     return ID_P;
199 }
200
201 void HTMLParagraphElementImpl::parseAttribute(AttributeImpl *attr)
202 {
203     switch(attr->id())
204     {
205         case ATTR_ALIGN:
206         {
207             DOMString v = attr->value();
208             if ( strcasecmp( attr->value(), "middle" ) == 0 || strcasecmp( attr->value(), "center" ) == 0 )
209                 addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_CENTER);
210             else if (strcasecmp(attr->value(), "left") == 0)
211                 addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_LEFT);
212             else if (strcasecmp(attr->value(), "right") == 0)
213                 addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_RIGHT);
214             else
215                 addCSSProperty(CSS_PROP_TEXT_ALIGN, v);
216             break;
217         }
218         default:
219             HTMLElementImpl::parseAttribute(attr);
220     }
221 }
222
223 // -------------------------------------------------------------------------
224
225 HTMLPreElementImpl::HTMLPreElementImpl(DocumentPtr *doc, unsigned short _tagid)
226     : HTMLGenericElementImpl(doc, _tagid)
227 {
228 }
229
230 long HTMLPreElementImpl::width() const
231 {
232     // ###
233     return 0;
234 }
235
236 void HTMLPreElementImpl::setWidth( long /*w*/ )
237 {
238     // ###
239 }
240
241 // -------------------------------------------------------------------------
242
243  // WinIE uses 60ms as the minimum delay by default.
244 const int defaultMinimumDelay = 60;
245
246 HTMLMarqueeElementImpl::HTMLMarqueeElementImpl(DocumentPtr *doc)
247 : HTMLElementImpl(doc),
248   m_minimumDelay(defaultMinimumDelay)
249 {
250 }
251
252 NodeImpl::Id HTMLMarqueeElementImpl::id() const
253 {
254     return ID_MARQUEE;
255 }
256
257 void HTMLMarqueeElementImpl::parseAttribute(AttributeImpl *attr)
258 {
259     switch(attr->id())
260     {
261         case ATTR_WIDTH:
262             if (!attr->value().isEmpty())
263                 addCSSLength(CSS_PROP_WIDTH, attr->value());
264             else
265                 removeCSSProperty(CSS_PROP_WIDTH);
266             break;
267         case ATTR_HEIGHT:
268             if (!attr->value().isEmpty())
269                 addCSSLength(CSS_PROP_HEIGHT, attr->value());
270             else
271                 removeCSSProperty(CSS_PROP_HEIGHT);
272             break;
273         case ATTR_BGCOLOR:
274             if (!attr->value().isEmpty())
275                 addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value());
276             else
277                 removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
278             break;
279         case ATTR_VSPACE:
280             if (!attr->value().isEmpty()) {
281                 addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
282                 addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
283             }
284             else {
285                 removeCSSProperty(CSS_PROP_MARGIN_TOP);
286                 removeCSSProperty(CSS_PROP_MARGIN_BOTTOM);
287             }
288             break;
289         case ATTR_HSPACE:
290             if (!attr->value().isEmpty()) {
291                 addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
292                 addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
293             }
294             else {
295                 removeCSSProperty(CSS_PROP_MARGIN_LEFT);
296                 removeCSSProperty(CSS_PROP_MARGIN_RIGHT);
297             }
298             break;
299         case ATTR_SCROLLAMOUNT:
300             if (!attr->value().isEmpty())
301                 addCSSLength(CSS_PROP__KHTML_MARQUEE_INCREMENT, attr->value());
302             else
303                 removeCSSProperty(CSS_PROP__KHTML_MARQUEE_INCREMENT);
304             break;
305         case ATTR_SCROLLDELAY:
306             if (!attr->value().isEmpty())
307                 addCSSLength(CSS_PROP__KHTML_MARQUEE_SPEED, attr->value());
308             else
309                 removeCSSProperty(CSS_PROP__KHTML_MARQUEE_SPEED);
310             break;
311         case ATTR_LOOP:
312             if (!attr->value().isEmpty()) {
313                 if (attr->value() == "-1" || strcasecmp(attr->value(), "infinite") == 0)
314                     addCSSProperty(CSS_PROP__KHTML_MARQUEE_REPETITION, CSS_VAL_INFINITE);
315                 else
316                     addCSSLength(CSS_PROP__KHTML_MARQUEE_REPETITION, attr->value());
317             }
318             else
319                 removeCSSProperty(CSS_PROP__KHTML_MARQUEE_REPETITION);
320             break;
321         case ATTR_BEHAVIOR:
322             if (!attr->value().isEmpty())
323                 addCSSProperty(CSS_PROP__KHTML_MARQUEE_STYLE, attr->value());
324             else
325                 removeCSSProperty(CSS_PROP__KHTML_MARQUEE_STYLE);
326             break;
327         case ATTR_DIRECTION:
328             if (!attr->value().isEmpty())
329                 addCSSProperty(CSS_PROP__KHTML_MARQUEE_DIRECTION, attr->value());
330             else
331                 removeCSSProperty(CSS_PROP__KHTML_MARQUEE_DIRECTION);
332             break;
333         case ATTR_TRUESPEED:
334             m_minimumDelay = attr->val() ? 0 : defaultMinimumDelay;
335             break;
336         default:
337             HTMLElementImpl::parseAttribute(attr);
338     }
339 }
340
341 // ------------------------------------------------------------------------
342
343 HTMLLayerElementImpl::HTMLLayerElementImpl(DocumentPtr *doc)
344     : HTMLDivElementImpl( doc )
345 {
346 //    addCSSProperty(CSS_PROP_POSITION, CSS_VAL_ABSOLUTE);
347 //    fixed = false;
348 }
349
350 HTMLLayerElementImpl::~HTMLLayerElementImpl()
351 {
352 }
353
354 NodeImpl::Id HTMLLayerElementImpl::id() const
355 {
356     return ID_LAYER;
357 }
358
359
360 void HTMLLayerElementImpl::parseAttribute(AttributeImpl *attr)
361 {
362     HTMLElementImpl::parseAttribute(attr);
363
364     // layers are evil
365 /*    int cssprop;
366     bool page = false;
367     switch(attr->id()) {
368         case ATTR_PAGEX:
369             page = true;
370         case ATTR_LEFT:
371             cssprop = CSS_PROP_LEFT;
372             break;
373         case ATTR_PAGEY:
374             page = true;
375         case ATTR_TOP:
376             cssprop = CSS_PROP_TOP;
377             break;
378         case ATTR_WIDTH:
379             cssprop = CSS_PROP_WIDTH;
380             break;
381         case ATTR_HEIGHT:
382             cssprop = CSS_PROP_HEIGHT;
383             break;
384         case ATTR_Z_INDEX:
385             cssprop = CSS_PROP_Z_INDEX;
386             break;
387         case ATTR_VISIBILITY:
388             cssprop = CSS_PROP_VISIBILITY;
389             break;
390         default:
391             HTMLDivElementImpl::parseAttribute(attr);
392             return;
393     }
394     addCSSProperty(cssprop, attr->value());
395     if ( !fixed && page ) {
396         addCSSProperty(CSS_PROP_POSITION, "fixed");
397         fixed = true;
398     }*/
399 }
400