File indexing completed on 2024-05-05 16:10:08

0001 /**
0002  * This file is part of the DOM implementation for KDE.
0003  *
0004  * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
0005  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
0006  *           (C) 2003 Apple Computer, Inc.
0007  *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
0008  *
0009  * This library is free software; you can redistribute it and/or
0010  * modify it under the terms of the GNU Library General Public
0011  * License as published by the Free Software Foundation; either
0012  * version 2 of the License, or (at your option) any later version.
0013  *
0014  * This library is distributed in the hope that it will be useful,
0015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017  * Library General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU Library General Public License
0020  * along with this library; see the file COPYING.LIB.  If not, write to
0021  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0022  * Boston, MA 02110-1301, USA.
0023  *
0024  */
0025 // -------------------------------------------------------------------------
0026 //#define DEBUG
0027 #include "html_blockimpl.h"
0028 #include "html_documentimpl.h"
0029 #include "css/cssstyleselector.h"
0030 
0031 #include "css/cssproperties.h"
0032 #include "css/cssvalues.h"
0033 
0034 using namespace khtml;
0035 using namespace DOM;
0036 
0037 void HTMLDivElementImpl::parseAttribute(AttributeImpl *attr)
0038 {
0039     switch (attr->id()) {
0040     case ATTR_ALIGN: {
0041         DOMString v = attr->value().lower();
0042         if (strcmp(v, "middle") == 0 || strcmp(v, "center") == 0) {
0043             addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_CENTER);
0044         } else if (strcmp(v, "left") == 0) {
0045             addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_LEFT);
0046         } else if (strcmp(v, "right") == 0) {
0047             addCSSProperty(CSS_PROP_TEXT_ALIGN, CSS_VAL__KHTML_RIGHT);
0048         } else {
0049             addCSSProperty(CSS_PROP_TEXT_ALIGN, v);
0050         }
0051         break;
0052     }
0053     default:
0054         HTMLElementImpl::parseAttribute(attr);
0055     }
0056 }
0057 
0058 // -------------------------------------------------------------------------
0059 
0060 NodeImpl::Id HTMLHRElementImpl::id() const
0061 {
0062     return ID_HR;
0063 }
0064 
0065 void HTMLHRElementImpl::parseAttribute(AttributeImpl *attr)
0066 {
0067     switch (attr->id()) {
0068     case ATTR_ALIGN: {
0069         if (strcasecmp(attr->value(), "left") == 0) {
0070             addCSSProperty(CSS_PROP_MARGIN_LEFT, "0");
0071             addCSSProperty(CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO);
0072         } else if (strcasecmp(attr->value(), "right") == 0) {
0073             addCSSProperty(CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO);
0074             addCSSProperty(CSS_PROP_MARGIN_RIGHT, "0");
0075         } else {
0076             addCSSProperty(CSS_PROP_MARGIN_LEFT, CSS_VAL_AUTO);
0077             addCSSProperty(CSS_PROP_MARGIN_RIGHT, CSS_VAL_AUTO);
0078         }
0079         break;
0080     }
0081     case ATTR_WIDTH: {
0082         if (!attr->val()) {
0083             break;
0084         }
0085         // cheap hack to cause linebreaks
0086         // khtmltests/html/strange_hr.html
0087         bool ok;
0088         int v = attr->val()->toInt(&ok);
0089         if (ok && !v) {
0090             addCSSLength(CSS_PROP_WIDTH, "1");
0091         } else {
0092             addCSSLength(CSS_PROP_WIDTH, attr->value());
0093         }
0094     }
0095     break;
0096     default:
0097         HTMLElementImpl::parseAttribute(attr);
0098     }
0099 }
0100 
0101 // ### make sure we undo what we did during detach
0102 void HTMLHRElementImpl::attach()
0103 {
0104     if (attributes(true /* readonly */)) {
0105         // there are some attributes, lets check
0106         DOMString color = getAttribute(ATTR_COLOR);
0107         DOMStringImpl *si = getAttribute(ATTR_SIZE).implementation();
0108         int _s =  si ? si->toInt() : -1;
0109         DOMString n("1");
0110         if (!color.isNull()) {
0111             addCSSProperty(CSS_PROP_BORDER_TOP_STYLE, CSS_VAL_SOLID);
0112             addCSSProperty(CSS_PROP_BORDER_RIGHT_STYLE, CSS_VAL_SOLID);
0113             addCSSProperty(CSS_PROP_BORDER_BOTTOM_STYLE, CSS_VAL_SOLID);
0114             addCSSProperty(CSS_PROP_BORDER_LEFT_STYLE, CSS_VAL_SOLID);
0115             addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, DOMString("0"));
0116             addCSSLength(CSS_PROP_BORDER_BOTTOM_WIDTH, DOMString(si));
0117             addHTMLColor(CSS_PROP_BORDER_COLOR, color);
0118         } else {
0119             if (_s > 1 && getAttribute(ATTR_NOSHADE).isNull()) {
0120                 addCSSProperty(CSS_PROP_BORDER_BOTTOM_WIDTH, n);
0121                 addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, n);
0122                 addCSSProperty(CSS_PROP_BORDER_LEFT_WIDTH, n);
0123                 addCSSProperty(CSS_PROP_BORDER_RIGHT_WIDTH, n);
0124                 addCSSLength(CSS_PROP_HEIGHT, DOMString(QString::number(_s - 2)));
0125             } else if (_s >= 0) {
0126                 addCSSProperty(CSS_PROP_BORDER_TOP_WIDTH, DOMString(QString::number(_s)));
0127                 addCSSProperty(CSS_PROP_BORDER_BOTTOM_WIDTH, DOMString("0"));
0128             }
0129         }
0130         if (_s == 0) {
0131             addCSSProperty(CSS_PROP_MARGIN_BOTTOM, n);
0132         }
0133     }
0134 
0135     HTMLElementImpl::attach();
0136 }
0137 
0138 // -------------------------------------------------------------------------
0139 
0140 long HTMLPreElementImpl::width() const
0141 {
0142     // ###
0143     return 0;
0144 }
0145 
0146 void HTMLPreElementImpl::setWidth(long /*w*/)
0147 {
0148     // ###
0149 }
0150 
0151 // -------------------------------------------------------------------------
0152 
0153 // WinIE uses 60ms as the minimum delay by default.
0154 const int defaultMinimumDelay = 60;
0155 
0156 HTMLMarqueeElementImpl::HTMLMarqueeElementImpl(DocumentImpl *doc)
0157     : HTMLElementImpl(doc),
0158       m_minimumDelay(defaultMinimumDelay)
0159 {
0160 }
0161 
0162 NodeImpl::Id HTMLMarqueeElementImpl::id() const
0163 {
0164     return ID_MARQUEE;
0165 }
0166 
0167 void HTMLMarqueeElementImpl::parseAttribute(AttributeImpl *attr)
0168 {
0169     switch (attr->id()) {
0170     case ATTR_WIDTH:
0171         if (!attr->value().isEmpty()) {
0172             addCSSLength(CSS_PROP_WIDTH, attr->value());
0173         } else {
0174             removeCSSProperty(CSS_PROP_WIDTH);
0175         }
0176         break;
0177     case ATTR_HEIGHT:
0178         if (!attr->value().isEmpty()) {
0179             addCSSLength(CSS_PROP_HEIGHT, attr->value());
0180         } else {
0181             removeCSSProperty(CSS_PROP_HEIGHT);
0182         }
0183         break;
0184     case ATTR_BGCOLOR:
0185         if (!attr->value().isEmpty()) {
0186             addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value());
0187         } else {
0188             removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
0189         }
0190         break;
0191     case ATTR_VSPACE:
0192         if (!attr->value().isEmpty()) {
0193             addCSSLength(CSS_PROP_MARGIN_TOP, attr->value());
0194             addCSSLength(CSS_PROP_MARGIN_BOTTOM, attr->value());
0195         } else {
0196             removeCSSProperty(CSS_PROP_MARGIN_TOP);
0197             removeCSSProperty(CSS_PROP_MARGIN_BOTTOM);
0198         }
0199         break;
0200     case ATTR_HSPACE:
0201         if (!attr->value().isEmpty()) {
0202             addCSSLength(CSS_PROP_MARGIN_LEFT, attr->value());
0203             addCSSLength(CSS_PROP_MARGIN_RIGHT, attr->value());
0204         } else {
0205             removeCSSProperty(CSS_PROP_MARGIN_LEFT);
0206             removeCSSProperty(CSS_PROP_MARGIN_RIGHT);
0207         }
0208         break;
0209     case ATTR_SCROLLAMOUNT:
0210         if (!attr->value().isEmpty()) {
0211             addCSSLength(CSS_PROP__KHTML_MARQUEE_INCREMENT, attr->value());
0212         } else {
0213             removeCSSProperty(CSS_PROP__KHTML_MARQUEE_INCREMENT);
0214         }
0215         break;
0216     case ATTR_SCROLLDELAY:
0217         if (!attr->value().isEmpty()) {
0218             addCSSLength(CSS_PROP__KHTML_MARQUEE_SPEED, attr->value(), true);
0219         } else {
0220             removeCSSProperty(CSS_PROP__KHTML_MARQUEE_SPEED);
0221         }
0222         break;
0223     case ATTR_LOOP:
0224         if (!attr->value().isEmpty()) {
0225             if (attr->value() == "-1" || strcasecmp(attr->value(), "infinite") == 0) {
0226                 addCSSProperty(CSS_PROP__KHTML_MARQUEE_REPETITION, CSS_VAL_INFINITE);
0227             } else {
0228                 addCSSLength(CSS_PROP__KHTML_MARQUEE_REPETITION, attr->value().lower(), true);
0229             }
0230         } else {
0231             removeCSSProperty(CSS_PROP__KHTML_MARQUEE_REPETITION);
0232         }
0233         break;
0234     case ATTR_BEHAVIOR:
0235         if (!attr->value().isEmpty()) {
0236             addCSSProperty(CSS_PROP__KHTML_MARQUEE_STYLE, attr->value().lower());
0237         } else {
0238             removeCSSProperty(CSS_PROP__KHTML_MARQUEE_STYLE);
0239         }
0240         break;
0241     case ATTR_DIRECTION:
0242         if (!attr->value().isEmpty()) {
0243             addCSSProperty(CSS_PROP__KHTML_MARQUEE_DIRECTION, attr->value().lower());
0244         } else {
0245             removeCSSProperty(CSS_PROP__KHTML_MARQUEE_DIRECTION);
0246         }
0247         break;
0248     case ATTR_TRUESPEED:
0249         m_minimumDelay = attr->val() ? 0 : defaultMinimumDelay;
0250         break;
0251     default:
0252         HTMLElementImpl::parseAttribute(attr);
0253     }
0254 }
0255 
0256 // ------------------------------------------------------------------------
0257 
0258 HTMLLayerElementImpl::HTMLLayerElementImpl(DocumentImpl *doc, ushort _tagid)
0259     : HTMLDivElementImpl(doc, _tagid)
0260 {
0261     transparent = fixed = false;
0262 }
0263 
0264 void HTMLLayerElementImpl::parseAttribute(AttributeImpl *attr)
0265 {
0266     // Layers are evil
0267     // They are mainly implemented here to correctly parse the hidden attribute
0268     switch (attr->id()) {
0269     case ATTR_LEFT:
0270         addCSSProperty(CSS_PROP_LEFT, attr->value());
0271         break;
0272     case ATTR_TOP:
0273         addCSSProperty(CSS_PROP_TOP, attr->value());
0274         break;
0275     case ATTR_PAGEX:
0276         if (!transparent && !fixed) {
0277             addCSSProperty(CSS_PROP_POSITION, CSS_VAL_FIXED);
0278             fixed = true;
0279         }
0280         addCSSProperty(CSS_PROP_LEFT, attr->value());
0281         break;
0282     case ATTR_PAGEY:
0283         if (!transparent && !fixed) {
0284             addCSSProperty(CSS_PROP_POSITION, CSS_VAL_FIXED);
0285             fixed = true;
0286         }
0287         addCSSProperty(CSS_PROP_TOP, attr->value());
0288         break;
0289     case ATTR_WIDTH:
0290         if (!attr->value().isEmpty()) {
0291             addCSSLength(CSS_PROP_WIDTH, attr->value());
0292         } else {
0293             removeCSSProperty(CSS_PROP_WIDTH);
0294         }
0295         break;
0296     case ATTR_HEIGHT:
0297         if (!attr->value().isEmpty()) {
0298             addCSSLength(CSS_PROP_HEIGHT, attr->value());
0299         } else {
0300             removeCSSProperty(CSS_PROP_HEIGHT);
0301         }
0302         break;
0303     case ATTR_BGCOLOR:
0304         if (!attr->value().isEmpty()) {
0305             addHTMLColor(CSS_PROP_BACKGROUND_COLOR, attr->value());
0306         } else {
0307             removeCSSProperty(CSS_PROP_BACKGROUND_COLOR);
0308         }
0309         break;
0310     case ATTR_Z_INDEX:
0311         if (!attr->value().isEmpty()) {
0312             addCSSProperty(CSS_PROP_Z_INDEX, attr->value());
0313         } else {
0314             removeCSSProperty(CSS_PROP_Z_INDEX);
0315         }
0316         break;
0317     case ATTR_VISIBILITY:
0318         if (attr->value().lower() == "show") {
0319             addCSSProperty(CSS_PROP_VISIBILITY, CSS_VAL_VISIBLE);
0320         } else if (attr->value().lower() == "hide") {
0321             addCSSProperty(CSS_PROP_VISIBILITY, CSS_VAL_HIDDEN);
0322         } else if (attr->value().lower() == "inherit") {
0323             addCSSProperty(CSS_PROP_VISIBILITY, CSS_VAL_INHERIT);
0324         }
0325         break;
0326     case ATTR_NAME:
0327         if (id() == ID_LAYER && inDocument() && m_name != attr->value()) {
0328             document()->underDocNamedCache().remove(m_name,        this);
0329             document()->underDocNamedCache().add(attr->value(), this);
0330         }
0331     //fallthrough
0332     default:
0333         HTMLElementImpl::parseAttribute(attr);
0334     }
0335 }
0336 
0337 void HTMLLayerElementImpl::removedFromDocument()
0338 {
0339     if (id() == ID_LAYER) {
0340         document()->underDocNamedCache().remove(m_name, this);
0341     }
0342     HTMLDivElementImpl::removedFromDocument();
0343 }
0344 
0345 void HTMLLayerElementImpl::insertedIntoDocument()
0346 {
0347     if (id() == ID_LAYER) {
0348         document()->underDocNamedCache().add(m_name, this);
0349     }
0350     HTMLDivElementImpl::insertedIntoDocument();
0351 }
0352 
0353 void HTMLLayerElementImpl::removeId(const DOMString &id)
0354 {
0355     document()->underDocNamedCache().remove(id, this);
0356     HTMLDivElementImpl::removeId(id);
0357 }
0358 
0359 void HTMLLayerElementImpl::addId(const DOMString &id)
0360 {
0361     document()->underDocNamedCache().add(id, this);
0362     HTMLDivElementImpl::addId(id);
0363 }
0364 
0365 NodeImpl *HTMLLayerElementImpl::addChild(NodeImpl *child)
0366 {
0367     NodeImpl *retval = HTMLDivElementImpl::addChild(child);
0368     // When someone adds standard layers, we make sure not to interfere
0369     if (retval && retval->id() == ID_DIV) {
0370         if (!transparent) {
0371             addCSSProperty(CSS_PROP_POSITION, CSS_VAL_STATIC);
0372         }
0373         transparent = true;
0374     }
0375     return retval;
0376 }