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