diff --git a/khtml/css/css_renderstyledeclarationimpl.cpp b/khtml/css/css_renderstyledeclarationimpl.cpp index d75ad8594d..cd26c7b8d4 100644 --- a/khtml/css/css_renderstyledeclarationimpl.cpp +++ b/khtml/css/css_renderstyledeclarationimpl.cpp @@ -1,1162 +1,1192 @@ /** * css_renderstyledeclarationimpl.cpp * * Copyright 2004 Zack Rusin * Copyright 2004,2005 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ #include "css_renderstyledeclarationimpl.h" #include "rendering/render_style.h" #include "rendering/render_object.h" #include "cssproperties.h" #include "cssvalues.h" #include using namespace DOM; using namespace khtml; // List of all properties we know how to compute, omitting shorthands. static const int computedProperties[] = { CSS_PROP_BACKGROUND_COLOR, CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT, CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, CSS_PROP_BACKGROUND_POSITION_X, CSS_PROP_BACKGROUND_POSITION_Y, CSS_PROP_BORDER_COLLAPSE, CSS_PROP_BORDER_SPACING, CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING, CSS_PROP__KHTML_BORDER_VERTICAL_SPACING, CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR, CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR, CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE, CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BOTTOM, CSS_PROP_CAPTION_SIDE, CSS_PROP_CLEAR, CSS_PROP_COLOR, CSS_PROP_CURSOR, CSS_PROP_DIRECTION, CSS_PROP_DISPLAY, CSS_PROP_EMPTY_CELLS, CSS_PROP_FLOAT, CSS_PROP_FONT_FAMILY, CSS_PROP_FONT_SIZE, CSS_PROP_FONT_STYLE, CSS_PROP_FONT_VARIANT, CSS_PROP_FONT_WEIGHT, CSS_PROP_HEIGHT, CSS_PROP_LEFT, CSS_PROP_LETTER_SPACING, CSS_PROP_LINE_HEIGHT, CSS_PROP_LIST_STYLE_IMAGE, CSS_PROP_LIST_STYLE_POSITION, CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT, CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT, CSS_PROP__KHTML_MARQUEE_DIRECTION, CSS_PROP__KHTML_MARQUEE_INCREMENT, CSS_PROP__KHTML_MARQUEE_REPETITION, CSS_PROP__KHTML_MARQUEE_STYLE, CSS_PROP_MAX_HEIGHT, CSS_PROP_MAX_WIDTH, CSS_PROP_MIN_HEIGHT, CSS_PROP_MIN_WIDTH, CSS_PROP_OPACITY, CSS_PROP_ORPHANS, CSS_PROP_OUTLINE_STYLE, CSS_PROP_OVERFLOW, CSS_PROP_OVERFLOW_X, CSS_PROP_OVERFLOW_Y, CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT, CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT, CSS_PROP_PAGE_BREAK_AFTER, CSS_PROP_PAGE_BREAK_BEFORE, CSS_PROP_PAGE_BREAK_INSIDE, CSS_PROP_POSITION, CSS_PROP_RIGHT, CSS_PROP_TABLE_LAYOUT, CSS_PROP_TEXT_ALIGN, CSS_PROP_TEXT_DECORATION, CSS_PROP_TEXT_INDENT, CSS_PROP_TEXT_SHADOW, CSS_PROP_TEXT_TRANSFORM, CSS_PROP_TOP, CSS_PROP_UNICODE_BIDI, CSS_PROP_VERTICAL_ALIGN, CSS_PROP_VISIBILITY, CSS_PROP_WHITE_SPACE, CSS_PROP_WIDOWS, CSS_PROP_WIDTH, CSS_PROP_WORD_SPACING, CSS_PROP_Z_INDEX, }; const unsigned numComputedProperties = sizeof(computedProperties) / sizeof(computedProperties[0]); static CSSValueImpl *valueForLength(const Length &length, int max) { if (length.isPercent()) { return new CSSPrimitiveValueImpl(length.value(), CSSPrimitiveValue::CSS_PERCENTAGE); } else { return new CSSPrimitiveValueImpl(length.minWidth(max), CSSPrimitiveValue::CSS_PX); } } static CSSValueImpl *valueForBorderStyle(EBorderStyle style) { switch (style) { case khtml::BNATIVE: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_NATIVE); case khtml::BNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case khtml::BHIDDEN: return new CSSPrimitiveValueImpl(CSS_VAL_HIDDEN); case khtml::INSET: return new CSSPrimitiveValueImpl(CSS_VAL_INSET); case khtml::GROOVE: return new CSSPrimitiveValueImpl(CSS_VAL_GROOVE); case khtml::RIDGE: return new CSSPrimitiveValueImpl(CSS_VAL_RIDGE); case khtml::OUTSET: return new CSSPrimitiveValueImpl(CSS_VAL_OUTSET); case khtml::DOTTED: return new CSSPrimitiveValueImpl(CSS_VAL_DOTTED); case khtml::DASHED: return new CSSPrimitiveValueImpl(CSS_VAL_DASHED); case khtml::SOLID: return new CSSPrimitiveValueImpl(CSS_VAL_SOLID); case khtml::DOUBLE: return new CSSPrimitiveValueImpl(CSS_VAL_DOUBLE); } Q_ASSERT( 0 ); return 0; } static CSSValueImpl *valueForTextAlign(ETextAlign align) { switch (align) { case khtml::TAAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case khtml::LEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case khtml::RIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); case khtml::CENTER: return new CSSPrimitiveValueImpl(CSS_VAL_CENTER); case khtml::JUSTIFY: return new CSSPrimitiveValueImpl(CSS_VAL_JUSTIFY); case khtml::KHTML_LEFT: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_LEFT); case khtml::KHTML_RIGHT: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_RIGHT); case khtml::KHTML_CENTER: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_CENTER); } Q_ASSERT( 0 ); return 0; } DOMString khtml::stringForListStyleType(EListStyleType type) { switch (type) { case khtml::LDISC: return "disc"; case khtml::LCIRCLE: return "circle"; case khtml::LSQUARE: return "square"; case khtml::LBOX: return "box"; case khtml::LDIAMOND: return "-khtml-diamond"; case khtml::LDECIMAL: return "decimal"; case khtml::DECIMAL_LEADING_ZERO: return "decimal-leading-zero"; case khtml::ARABIC_INDIC: return "-khtml-arabic-indic"; case khtml::LAO: return "-khtml-lao"; case khtml::PERSIAN: return "-khtml-persian"; case khtml::URDU: return "-khtml-urdu"; case khtml::THAI: return "-khtml-thai"; case khtml::TIBETAN: return "-khtml-tibetan"; case khtml::LOWER_ROMAN: return "lower-roman"; case khtml::UPPER_ROMAN: return "upper-roman"; case khtml::HEBREW: return "hebrew"; case khtml::ARMENIAN: return "armenian"; case khtml::GEORGIAN: return "georgian"; case khtml::CJK_IDEOGRAPHIC: return "cjk-ideographic"; case khtml::JAPANESE_FORMAL: return "-khtml-japanese-formal"; case khtml::JAPANESE_INFORMAL: return "-khtml-japanese-informal"; case khtml::SIMP_CHINESE_FORMAL: return "-khtml-simp-chinese-formal"; case khtml::SIMP_CHINESE_INFORMAL: return "-khtml-simp-chinese-informal"; case khtml::TRAD_CHINESE_FORMAL: return "-khtml-trad-chinese-formal"; case khtml::TRAD_CHINESE_INFORMAL: return "-khtml-trad-chinese-informal"; case khtml::LOWER_GREEK: return "lower-greek"; case khtml::UPPER_GREEK: return "-khtml-upper-greek"; case khtml::LOWER_ALPHA: return "lower-alpha"; case khtml::UPPER_ALPHA: return "upper-alpha"; case khtml::LOWER_LATIN: return "lower-latin"; case khtml::UPPER_LATIN: return "upper-latin"; case khtml::HIRAGANA: return "hiragana"; case khtml::KATAKANA: return "katakana"; case khtml::HIRAGANA_IROHA: return "hiragana-iroha"; case khtml::KATAKANA_IROHA: return "katakana_iroha"; case khtml::LNONE: return "none"; } Q_ASSERT( 0 ); return ""; } static CSSPrimitiveValueImpl* valueForColor(QColor color) { if (color.isValid()) return new CSSPrimitiveValueImpl(color.rgba()); else return new CSSPrimitiveValueImpl(khtml::transparentColor); } static CSSValueImpl* valueForShadow(const ShadowData *shadow) { if (!shadow) return new CSSPrimitiveValueImpl(CSS_VAL_NONE); CSSValueListImpl *list = new CSSValueListImpl; for (const ShadowData *s = shadow; s; s = s->next) { CSSPrimitiveValueImpl *x = new CSSPrimitiveValueImpl(s->x, CSSPrimitiveValue::CSS_PX); CSSPrimitiveValueImpl *y = new CSSPrimitiveValueImpl(s->y, CSSPrimitiveValue::CSS_PX); CSSPrimitiveValueImpl *blur = new CSSPrimitiveValueImpl(s->blur, CSSPrimitiveValue::CSS_PX); CSSPrimitiveValueImpl *color = valueForColor(s->color); list->append(new ShadowValueImpl(x, y, blur, color)); } return list; } static CSSValueImpl *getPositionOffsetValue(RenderObject *renderer, int propertyID) { if (!renderer) return 0; RenderStyle *style = renderer->style(); if (!style) return 0; Length l; switch (propertyID) { case CSS_PROP_LEFT: l = style->left(); break; case CSS_PROP_RIGHT: l = style->right(); break; case CSS_PROP_TOP: l = style->top(); break; case CSS_PROP_BOTTOM: l = style->bottom(); break; default: return 0; } if (renderer->isPositioned()) return valueForLength(l, renderer->contentWidth()); if (renderer->isRelPositioned()) // FIXME: It's not enough to simply return "auto" values for one offset if the other side is defined. // In other words if left is auto and right is not auto, then left's computed value is negative right. // So we should get the opposite length unit and see if it is auto. return valueForLength(l, renderer->contentWidth()); return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); } RenderStyleDeclarationImpl::RenderStyleDeclarationImpl( DOM::NodeImpl *node ) : CSSStyleDeclarationImpl(0), m_node(node) { //kDebug() << "Render Style Declaration created"; } RenderStyleDeclarationImpl::~RenderStyleDeclarationImpl() { //kDebug() << "Render Style Declaration destroyed"; } DOM::DOMString RenderStyleDeclarationImpl::cssText() const { DOMString result; for (unsigned i = 0; i < numComputedProperties; i++) { if (i != 0) result += " "; result += getPropertyName(computedProperties[i]); result += ": "; result += getPropertyValue(computedProperties[i]); result += ";"; } return result; } void RenderStyleDeclarationImpl::setCssText( DOM::DOMString ) { // ### report that this sucka is read only } CSSValueImpl *RenderStyleDeclarationImpl::getPropertyCSSValue( int propertyID ) const { NodeImpl *node = m_node.get(); if (!node) return 0; // Make sure our layout is up to date before we allow a query on these attributes. DocumentImpl* docimpl = node->getDocument(); if (docimpl) { docimpl->updateLayout(); } RenderObject *renderer = m_node->renderer(); if (!renderer) { // Handle display:none at the very least. By definition if we don't have a renderer // we are considered to have no display. if (propertyID == CSS_PROP_DISPLAY) return new CSSPrimitiveValueImpl(CSS_VAL_NONE); return 0; } RenderStyle *style = renderer->style(); if (!style) return 0; switch(propertyID) { case CSS_PROP_BACKGROUND_COLOR: return valueForColor(style->backgroundColor()); case CSS_PROP_BACKGROUND_IMAGE: if (style->backgroundImage()) return new CSSPrimitiveValueImpl(style->backgroundImage()->url(), CSSPrimitiveValue::CSS_URI); return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case CSS_PROP_BACKGROUND_REPEAT: switch (style->backgroundRepeat()) { case khtml::REPEAT: return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT); case khtml::REPEAT_X: return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT_X); case khtml::REPEAT_Y: return new CSSPrimitiveValueImpl(CSS_VAL_REPEAT_Y); case khtml::NO_REPEAT: return new CSSPrimitiveValueImpl(CSS_VAL_NO_REPEAT); default: Q_ASSERT( 0 ); } case CSS_PROP_BACKGROUND_ATTACHMENT: if (style->backgroundAttachment()) return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL); else return new CSSPrimitiveValueImpl(CSS_VAL_FIXED); case CSS_PROP_BACKGROUND_POSITION: { DOMString string; Length length(style->backgroundXPosition()); if (length.isPercent()) string = QString::number(length.value()) + "%"; else string = QString::number(length.minWidth(renderer->contentWidth())); string += " "; length = style->backgroundYPosition(); if (length.isPercent()) string += QString::number(length.value()) + "%"; else string += QString::number(length.minWidth(renderer->contentWidth())); return new CSSPrimitiveValueImpl(string, CSSPrimitiveValue::CSS_STRING); } case CSS_PROP_BACKGROUND_POSITION_X: return valueForLength(style->backgroundXPosition(), renderer->contentWidth()); case CSS_PROP_BACKGROUND_POSITION_Y: return valueForLength(style->backgroundYPosition(), renderer->contentHeight()); case CSS_PROP_BORDER_COLLAPSE: if (style->borderCollapse()) return new CSSPrimitiveValueImpl(CSS_VAL_COLLAPSE); else return new CSSPrimitiveValueImpl(CSS_VAL_SEPARATE); case CSS_PROP_BORDER_SPACING: { QString string(QString::number(style->borderHorizontalSpacing()) + "px " + QString::number(style->borderVerticalSpacing()) + "px"); return new CSSPrimitiveValueImpl(DOMString(string), CSSPrimitiveValue::CSS_STRING); } case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: return new CSSPrimitiveValueImpl(style->borderHorizontalSpacing(), CSSPrimitiveValue::CSS_PX); case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: return new CSSPrimitiveValueImpl(style->borderVerticalSpacing(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_BORDER_TOP_COLOR: return valueForColor(style->borderTopColor()); case CSS_PROP_BORDER_RIGHT_COLOR: return valueForColor(style->borderRightColor()); case CSS_PROP_BORDER_BOTTOM_COLOR: return valueForColor(style->borderBottomColor()); case CSS_PROP_BORDER_LEFT_COLOR: return valueForColor(style->borderLeftColor()); case CSS_PROP_BORDER_TOP_STYLE: return valueForBorderStyle(style->borderTopStyle()); case CSS_PROP_BORDER_RIGHT_STYLE: return valueForBorderStyle(style->borderRightStyle()); case CSS_PROP_BORDER_BOTTOM_STYLE: return valueForBorderStyle(style->borderBottomStyle()); case CSS_PROP_BORDER_LEFT_STYLE: return valueForBorderStyle(style->borderLeftStyle()); case CSS_PROP_BORDER_TOP_WIDTH: return new CSSPrimitiveValueImpl( style->borderTopWidth(), CSSPrimitiveValue::CSS_PX ); case CSS_PROP_BORDER_RIGHT_WIDTH: return new CSSPrimitiveValueImpl( style->borderRightWidth(), CSSPrimitiveValue::CSS_PX ); case CSS_PROP_BORDER_BOTTOM_WIDTH: return new CSSPrimitiveValueImpl( style->borderBottomWidth(), CSSPrimitiveValue::CSS_PX ); case CSS_PROP_BORDER_LEFT_WIDTH: return new CSSPrimitiveValueImpl( style->borderLeftWidth(), CSSPrimitiveValue::CSS_PX ); case CSS_PROP_BOTTOM: return getPositionOffsetValue(renderer, CSS_PROP_BOTTOM); case CSS_PROP_CAPTION_SIDE: switch (style->captionSide()) { case CAPLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case CAPRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); case CAPTOP: return new CSSPrimitiveValueImpl(CSS_VAL_TOP); case CAPBOTTOM: return new CSSPrimitiveValueImpl(CSS_VAL_BOTTOM); } Q_ASSERT(0); break; case CSS_PROP_CLEAR: switch (style->clear()) { case CNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case CLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case CRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); case CBOTH: return new CSSPrimitiveValueImpl(CSS_VAL_BOTH); } Q_ASSERT(0); break; case CSS_PROP_CLIP: break; case CSS_PROP_COLOR: return valueForColor(style->color()); case CSS_PROP_CONTENT: break; case CSS_PROP_COUNTER_INCREMENT: break; case CSS_PROP_COUNTER_RESET: break; case CSS_PROP_CURSOR: switch (style->cursor()) { case CURSOR_AUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); - case CURSOR_CROSS: - return new CSSPrimitiveValueImpl(CSS_VAL_CROSSHAIR); case CURSOR_DEFAULT: return new CSSPrimitiveValueImpl(CSS_VAL_DEFAULT); + case CURSOR_NONE: + return new CSSPrimitiveValueImpl(CSS_VAL_NONE); + case CURSOR_CONTEXT_MENU: + return new CSSPrimitiveValueImpl(CSS_VAL_CONTEXT_MENU); + case CURSOR_HELP: + return new CSSPrimitiveValueImpl(CSS_VAL_HELP); case CURSOR_POINTER: return new CSSPrimitiveValueImpl(CSS_VAL_POINTER); - case CURSOR_MOVE: - return new CSSPrimitiveValueImpl(CSS_VAL_MOVE); case CURSOR_PROGRESS: return new CSSPrimitiveValueImpl(CSS_VAL_PROGRESS); + case CURSOR_WAIT: + return new CSSPrimitiveValueImpl(CSS_VAL_WAIT); + case CURSOR_CELL: + return new CSSPrimitiveValueImpl(CSS_VAL_CELL); + case CURSOR_CROSS: + return new CSSPrimitiveValueImpl(CSS_VAL_CROSSHAIR); + case CURSOR_TEXT: + return new CSSPrimitiveValueImpl(CSS_VAL_TEXT); + case CURSOR_VERTICAL_TEXT: + return new CSSPrimitiveValueImpl(CSS_VAL_VERTICAL_TEXT); + case CURSOR_ALIAS: + return new CSSPrimitiveValueImpl(CSS_VAL_ALIAS); + case CURSOR_COPY: + return new CSSPrimitiveValueImpl(CSS_VAL_COPY); + case CURSOR_MOVE: + return new CSSPrimitiveValueImpl(CSS_VAL_MOVE); + case CURSOR_NO_DROP: + return new CSSPrimitiveValueImpl(CSS_VAL_NO_DROP); + case CURSOR_NOT_ALLOWED: + return new CSSPrimitiveValueImpl(CSS_VAL_NOT_ALLOWED); case CURSOR_E_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_E_RESIZE); + case CURSOR_N_RESIZE: + return new CSSPrimitiveValueImpl(CSS_VAL_N_RESIZE); case CURSOR_NE_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_NE_RESIZE); case CURSOR_NW_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_NW_RESIZE); - case CURSOR_N_RESIZE: - return new CSSPrimitiveValueImpl(CSS_VAL_N_RESIZE); + case CURSOR_S_RESIZE: + return new CSSPrimitiveValueImpl(CSS_VAL_S_RESIZE); case CURSOR_SE_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_SE_RESIZE); case CURSOR_SW_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_SW_RESIZE); - case CURSOR_S_RESIZE: - return new CSSPrimitiveValueImpl(CSS_VAL_S_RESIZE); case CURSOR_W_RESIZE: return new CSSPrimitiveValueImpl(CSS_VAL_W_RESIZE); - case CURSOR_TEXT: - return new CSSPrimitiveValueImpl(CSS_VAL_TEXT); - case CURSOR_WAIT: - return new CSSPrimitiveValueImpl(CSS_VAL_WAIT); - case CURSOR_HELP: - return new CSSPrimitiveValueImpl(CSS_VAL_HELP); + case CURSOR_EW_RESIZE: + return new CSSPrimitiveValueImpl(CSS_VAL_EW_RESIZE); + case CURSOR_NS_RESIZE: + return new CSSPrimitiveValueImpl(CSS_VAL_NS_RESIZE); + case CURSOR_NESW_RESIZE: + return new CSSPrimitiveValueImpl(CSS_VAL_NESW_RESIZE); + case CURSOR_NWSE_RESIZE: + return new CSSPrimitiveValueImpl(CSS_VAL_NWSE_RESIZE); + case CURSOR_COL_RESIZE: + return new CSSPrimitiveValueImpl(CSS_VAL_COL_RESIZE); + case CURSOR_ROW_RESIZE: + return new CSSPrimitiveValueImpl(CSS_VAL_ROW_RESIZE); + case CURSOR_ALL_SCROLL: + return new CSSPrimitiveValueImpl(CSS_VAL_ALL_SCROLL); } Q_ASSERT(0); break; case CSS_PROP_DIRECTION: switch (style->direction()) { case LTR: return new CSSPrimitiveValueImpl(CSS_VAL_LTR); case RTL: return new CSSPrimitiveValueImpl(CSS_VAL_RTL); } Q_ASSERT(0); break; case CSS_PROP_DISPLAY: switch (style->display()) { case INLINE: return new CSSPrimitiveValueImpl(CSS_VAL_INLINE); case BLOCK: return new CSSPrimitiveValueImpl(CSS_VAL_BLOCK); case LIST_ITEM: return new CSSPrimitiveValueImpl(CSS_VAL_LIST_ITEM); case RUN_IN: return new CSSPrimitiveValueImpl(CSS_VAL_RUN_IN); case COMPACT: return new CSSPrimitiveValueImpl(CSS_VAL_COMPACT); case INLINE_BLOCK: return new CSSPrimitiveValueImpl(CSS_VAL_INLINE_BLOCK); case TABLE: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE); case INLINE_TABLE: return new CSSPrimitiveValueImpl(CSS_VAL_INLINE_TABLE); case TABLE_ROW_GROUP: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_ROW_GROUP); case TABLE_HEADER_GROUP: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_HEADER_GROUP); case TABLE_FOOTER_GROUP: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_FOOTER_GROUP); case TABLE_ROW: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_ROW); case TABLE_COLUMN_GROUP: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_COLUMN_GROUP); case TABLE_COLUMN: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_COLUMN); case TABLE_CELL: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_CELL); case TABLE_CAPTION: return new CSSPrimitiveValueImpl(CSS_VAL_TABLE_CAPTION); case NONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); } Q_ASSERT( 0 ); break; case CSS_PROP_EMPTY_CELLS: switch (style->emptyCells()) { case SHOW: return new CSSPrimitiveValueImpl(CSS_VAL_SHOW); case HIDE: return new CSSPrimitiveValueImpl(CSS_VAL_HIDE); } Q_ASSERT( 0 ); break; case CSS_PROP_FLOAT: { switch (style->floating()) { case FNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case FLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case FRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); case FLEFT_ALIGN: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_LEFT); case FRIGHT_ALIGN: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_RIGHT); } } case CSS_PROP_FONT_FAMILY: { FontDef def = style->htmlFont().getFontDef(); return new CSSPrimitiveValueImpl(DOMString(def.family), CSSPrimitiveValue::CSS_STRING); } case CSS_PROP_FONT_SIZE: { FontDef def = style->htmlFont().getFontDef(); return new CSSPrimitiveValueImpl(def.size, CSSPrimitiveValue::CSS_PX); } case CSS_PROP_FONT_STYLE: { // FIXME: handle oblique FontDef def = style->htmlFont().getFontDef(); if (def.italic) return new CSSPrimitiveValueImpl(CSS_VAL_ITALIC); else return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); } case CSS_PROP_FONT_VARIANT: { FontDef def = style->htmlFont().getFontDef(); if (def.smallCaps) return new CSSPrimitiveValueImpl(CSS_VAL_SMALL_CAPS); else return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); } case CSS_PROP_FONT_WEIGHT: { // FIXME: this does not reflect the full range of weights // that can be expressed with CSS FontDef def = style->htmlFont().getFontDef(); if (def.weight == QFont::Bold) return new CSSPrimitiveValueImpl(CSS_VAL_BOLD); else return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); } case CSS_PROP_HEIGHT: return new CSSPrimitiveValueImpl(renderer->contentHeight(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_LEFT: return getPositionOffsetValue(renderer, CSS_PROP_LEFT); case CSS_PROP_LETTER_SPACING: if (style->letterSpacing() == 0) return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); return new CSSPrimitiveValueImpl(style->letterSpacing(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_LINE_HEIGHT: { // Note: internally a specified value gets encoded as a percentage, // so the isPercent() case corresponds to the case; // values < 0 are used to mark "normal"; and specified %% // get computed down to px by the time they get to RenderStyle // already Length length(style->lineHeight()); if (length.value() < 0) return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); if (length.isPercent()) { //XXX: merge from webcore the computedStyle/specifiedStyle distinction in rendering/font.h float computedSize = style->htmlFont().getFontDef().size; return new CSSPrimitiveValueImpl((int)(length.value() * computedSize) / 100, CSSPrimitiveValue::CSS_PX); } else { return new CSSPrimitiveValueImpl(length.value(), CSSPrimitiveValue::CSS_PX); } } case CSS_PROP_LIST_STYLE_IMAGE: if (style->listStyleImage()) return new CSSPrimitiveValueImpl(style->listStyleImage()->url(), CSSPrimitiveValue::CSS_URI); return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case CSS_PROP_LIST_STYLE_POSITION: switch (style->listStylePosition()) { case OUTSIDE: return new CSSPrimitiveValueImpl(CSS_VAL_OUTSIDE); case INSIDE: return new CSSPrimitiveValueImpl(CSS_VAL_INSIDE); } Q_ASSERT( 0 ); break; case CSS_PROP_LIST_STYLE_TYPE: return new CSSPrimitiveValueImpl(stringForListStyleType(style->listStyleType()), CSSPrimitiveValue::CSS_STRING); case CSS_PROP_MARGIN_TOP: return valueForLength(style->marginTop(), renderer->contentHeight()); case CSS_PROP_MARGIN_RIGHT: return valueForLength(style->marginRight(), renderer->contentWidth()); case CSS_PROP_MARGIN_BOTTOM: return valueForLength(style->marginBottom(), renderer->contentHeight()); case CSS_PROP_MARGIN_LEFT: return valueForLength(style->marginLeft(), renderer->contentWidth()); case CSS_PROP__KHTML_MARQUEE: // FIXME: unimplemented break; case CSS_PROP__KHTML_MARQUEE_DIRECTION: switch (style->marqueeDirection()) { case MFORWARD: return new CSSPrimitiveValueImpl(CSS_VAL_FORWARDS); case MBACKWARD: return new CSSPrimitiveValueImpl(CSS_VAL_BACKWARDS); case MAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case MUP: return new CSSPrimitiveValueImpl(CSS_VAL_UP); case MDOWN: return new CSSPrimitiveValueImpl(CSS_VAL_DOWN); case MLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case MRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); } Q_ASSERT(0); return 0; case CSS_PROP__KHTML_MARQUEE_INCREMENT: return valueForLength(style->marqueeIncrement(), renderer->contentWidth()); case CSS_PROP__KHTML_MARQUEE_REPETITION: if (style->marqueeLoopCount() < 0) return new CSSPrimitiveValueImpl(CSS_VAL_INFINITE); return new CSSPrimitiveValueImpl(style->marqueeLoopCount(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP__KHTML_MARQUEE_SPEED: // FIXME: unimplemented break; case CSS_PROP__KHTML_MARQUEE_STYLE: switch (style->marqueeBehavior()) { case MNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); case MSCROLL: return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL); case MSLIDE: return new CSSPrimitiveValueImpl(CSS_VAL_SLIDE); case MALTERNATE: return new CSSPrimitiveValueImpl(CSS_VAL_ALTERNATE); case MUNFURL: return new CSSPrimitiveValueImpl(CSS_VAL_UNFURL); } Q_ASSERT(0); return 0; case CSS_PROP_MAX_HEIGHT: return new CSSPrimitiveValueImpl( renderer->availableHeight(), CSSPrimitiveValue::CSS_PX ); break; case CSS_PROP_MAX_WIDTH: return new CSSPrimitiveValueImpl( renderer->maxWidth(), CSSPrimitiveValue::CSS_PX ); break; case CSS_PROP_MIN_HEIGHT: return new CSSPrimitiveValueImpl( renderer->contentHeight(), CSSPrimitiveValue::CSS_PX ); break; case CSS_PROP_MIN_WIDTH: return new CSSPrimitiveValueImpl( renderer->minWidth(), CSSPrimitiveValue::CSS_PX ); break; case CSS_PROP_OPACITY: return new CSSPrimitiveValueImpl(style->opacity(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP_ORPHANS: return new CSSPrimitiveValueImpl(style->orphans(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP_OUTLINE_COLOR: break; case CSS_PROP_OUTLINE_OFFSET: break; case CSS_PROP_OUTLINE_STYLE: if (style->outlineStyleIsAuto()) return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); return valueForBorderStyle(style->outlineStyle()); case CSS_PROP_OUTLINE_WIDTH: break; case CSS_PROP_OVERFLOW: case CSS_PROP_OVERFLOW_X: case CSS_PROP_OVERFLOW_Y: { EOverflow overflow; switch (propertyID) { case CSS_PROP_OVERFLOW_X: overflow = style->overflowX(); break; case CSS_PROP_OVERFLOW_Y: overflow = style->overflowY(); break; default: overflow = qMax(style->overflowX(), style->overflowY()); } switch (overflow) { case OVISIBLE: return new CSSPrimitiveValueImpl(CSS_VAL_VISIBLE); case OHIDDEN: return new CSSPrimitiveValueImpl(CSS_VAL_HIDDEN); case OSCROLL: return new CSSPrimitiveValueImpl(CSS_VAL_SCROLL); case OAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case OMARQUEE: return new CSSPrimitiveValueImpl(CSS_VAL_MARQUEE); } Q_ASSERT(0); return 0; } case CSS_PROP_PADDING_TOP: return valueForLength(style->paddingTop(), renderer->contentHeight()); case CSS_PROP_PADDING_RIGHT: return valueForLength(style->paddingRight(), renderer->contentWidth()); case CSS_PROP_PADDING_BOTTOM: return valueForLength(style->paddingBottom(), renderer->contentHeight()); case CSS_PROP_PADDING_LEFT: return valueForLength(style->paddingLeft(), renderer->contentWidth()); case CSS_PROP_PAGE_BREAK_AFTER: switch (style->pageBreakAfter()) { case PBAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case PBALWAYS: return new CSSPrimitiveValueImpl(CSS_VAL_ALWAYS); case PBAVOID: return new CSSPrimitiveValueImpl(CSS_VAL_AVOID); case PBLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case PBRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); } Q_ASSERT(0); break; case CSS_PROP_PAGE_BREAK_BEFORE: switch (style->pageBreakBefore()) { case PBAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case PBALWAYS: return new CSSPrimitiveValueImpl(CSS_VAL_ALWAYS); case PBAVOID: return new CSSPrimitiveValueImpl(CSS_VAL_AVOID); case PBLEFT: return new CSSPrimitiveValueImpl(CSS_VAL_LEFT); case PBRIGHT: return new CSSPrimitiveValueImpl(CSS_VAL_RIGHT); } Q_ASSERT(0); break; case CSS_PROP_PAGE_BREAK_INSIDE: if (style->pageBreakInside()) return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); else return new CSSPrimitiveValueImpl(CSS_VAL_AVOID); Q_ASSERT(0); break; case CSS_PROP_POSITION: switch (style->position()) { case STATIC: return new CSSPrimitiveValueImpl(CSS_VAL_STATIC); case RELATIVE: return new CSSPrimitiveValueImpl(CSS_VAL_RELATIVE); case ABSOLUTE: return new CSSPrimitiveValueImpl(CSS_VAL_ABSOLUTE); case FIXED: return new CSSPrimitiveValueImpl(CSS_VAL_FIXED); } Q_ASSERT(0); break; case CSS_PROP_QUOTES: break; case CSS_PROP_RIGHT: return getPositionOffsetValue(renderer, CSS_PROP_RIGHT); case CSS_PROP_SIZE: break; case CSS_PROP_TABLE_LAYOUT: switch (style->tableLayout()) { case TAUTO: return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); case TFIXED: return new CSSPrimitiveValueImpl(CSS_VAL_FIXED); } Q_ASSERT(0); break; case CSS_PROP_TEXT_ALIGN: return valueForTextAlign(style->textAlign()); case CSS_PROP_TEXT_DECORATION: { QString string; if (style->textDecoration() & khtml::UNDERLINE) string += "underline"; if (style->textDecoration() & khtml::OVERLINE) { if (string.length() > 0) string += " "; string += "overline"; } if (style->textDecoration() & khtml::LINE_THROUGH) { if (string.length() > 0) string += " "; string += "line-through"; } if (style->textDecoration() & khtml::BLINK) { if (string.length() > 0) string += " "; string += "blink"; } if (string.length() == 0) string = "none"; return new CSSPrimitiveValueImpl(DOMString(string), CSSPrimitiveValue::CSS_STRING); } case CSS_PROP_TEXT_INDENT: return valueForLength(style->textIndent(), renderer->contentWidth()); case CSS_PROP_TEXT_SHADOW: return valueForShadow(style->textShadow()); case CSS_PROP_TEXT_TRANSFORM: switch (style->textTransform()) { case CAPITALIZE: return new CSSPrimitiveValueImpl(CSS_VAL_CAPITALIZE); case UPPERCASE: return new CSSPrimitiveValueImpl(CSS_VAL_UPPERCASE); case LOWERCASE: return new CSSPrimitiveValueImpl(CSS_VAL_LOWERCASE); case TTNONE: return new CSSPrimitiveValueImpl(CSS_VAL_NONE); } Q_ASSERT(0); break; case CSS_PROP_TOP: return getPositionOffsetValue(renderer, CSS_PROP_TOP); case CSS_PROP_UNICODE_BIDI: switch (style->unicodeBidi()) { case UBNormal: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case Embed: return new CSSPrimitiveValueImpl(CSS_VAL_EMBED); case Override: return new CSSPrimitiveValueImpl(CSS_VAL_BIDI_OVERRIDE); } Q_ASSERT(0); break; case CSS_PROP_VERTICAL_ALIGN: { switch (style->verticalAlign()) { case BASELINE: return new CSSPrimitiveValueImpl(CSS_VAL_BASELINE); case MIDDLE: return new CSSPrimitiveValueImpl(CSS_VAL_MIDDLE); case SUB: return new CSSPrimitiveValueImpl(CSS_VAL_SUB); case SUPER: return new CSSPrimitiveValueImpl(CSS_VAL_SUPER); case TEXT_TOP: return new CSSPrimitiveValueImpl(CSS_VAL_TEXT_TOP); case TEXT_BOTTOM: return new CSSPrimitiveValueImpl(CSS_VAL_TEXT_BOTTOM); case TOP: return new CSSPrimitiveValueImpl(CSS_VAL_TOP); case BOTTOM: return new CSSPrimitiveValueImpl(CSS_VAL_BOTTOM); case BASELINE_MIDDLE: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_BASELINE_MIDDLE); case LENGTH: return valueForLength(style->verticalAlignLength(), renderer->contentWidth()); } Q_ASSERT(0); break; } case CSS_PROP_VISIBILITY: switch (style->visibility()) { case khtml::VISIBLE: return new CSSPrimitiveValueImpl(CSS_VAL_VISIBLE); case khtml::HIDDEN: return new CSSPrimitiveValueImpl(CSS_VAL_HIDDEN); case khtml::COLLAPSE: return new CSSPrimitiveValueImpl(CSS_VAL_COLLAPSE); } Q_ASSERT(0); break; case CSS_PROP_WHITE_SPACE: { switch (style->whiteSpace()) { case NORMAL: return new CSSPrimitiveValueImpl(CSS_VAL_NORMAL); case PRE: return new CSSPrimitiveValueImpl(CSS_VAL_PRE); case PRE_WRAP: return new CSSPrimitiveValueImpl(CSS_VAL_PRE_WRAP); case PRE_LINE: return new CSSPrimitiveValueImpl(CSS_VAL_PRE_LINE); case NOWRAP: return new CSSPrimitiveValueImpl(CSS_VAL_NOWRAP); case KHTML_NOWRAP: return new CSSPrimitiveValueImpl(CSS_VAL__KHTML_NOWRAP); } Q_ASSERT(0); break; } case CSS_PROP_WIDOWS: return new CSSPrimitiveValueImpl(style->widows(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP_WIDTH: return new CSSPrimitiveValueImpl( renderer->contentWidth(), CSSPrimitiveValue::CSS_PX ); case CSS_PROP_WORD_SPACING: return new CSSPrimitiveValueImpl(style->wordSpacing(), CSSPrimitiveValue::CSS_PX); case CSS_PROP_Z_INDEX: if (style->hasAutoZIndex()) return new CSSPrimitiveValueImpl(CSS_VAL_AUTO); return new CSSPrimitiveValueImpl(style->zIndex(), CSSPrimitiveValue::CSS_NUMBER); case CSS_PROP_BACKGROUND: break; case CSS_PROP_BORDER: break; case CSS_PROP_BORDER_COLOR: break; case CSS_PROP_BORDER_STYLE: break; case CSS_PROP_BORDER_TOP: return new CSSPrimitiveValueImpl( renderer->borderTop(), CSSPrimitiveValue::CSS_PX ); break; case CSS_PROP_BORDER_RIGHT: return new CSSPrimitiveValueImpl( renderer->borderRight(), CSSPrimitiveValue::CSS_PX ); break; case CSS_PROP_BORDER_BOTTOM: return new CSSPrimitiveValueImpl( renderer->borderBottom(), CSSPrimitiveValue::CSS_PX ); break; case CSS_PROP_BORDER_LEFT: return new CSSPrimitiveValueImpl( renderer->borderLeft(), CSSPrimitiveValue::CSS_PX ); break; case CSS_PROP_BORDER_WIDTH: break; case CSS_PROP_FONT: break; case CSS_PROP_LIST_STYLE: break; case CSS_PROP_MARGIN: break; case CSS_PROP_OUTLINE: break; case CSS_PROP_PADDING: break; case CSS_PROP_SCROLLBAR_BASE_COLOR: break; case CSS_PROP_SCROLLBAR_FACE_COLOR: break; case CSS_PROP_SCROLLBAR_SHADOW_COLOR: break; case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: break; case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: break; case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: break; case CSS_PROP_SCROLLBAR_TRACK_COLOR: break; case CSS_PROP_SCROLLBAR_ARROW_COLOR: break; case CSS_PROP__KHTML_FLOW_MODE: break; case CSS_PROP__KHTML_USER_INPUT: break; default: Q_ASSERT( 0 ); break; } return 0; } DOMString RenderStyleDeclarationImpl::getPropertyValue( int propertyID ) const { CSSValueImpl* value = getPropertyCSSValue(propertyID); if (value) { DOMString val = value->cssText(); delete value; return val; } return ""; } bool RenderStyleDeclarationImpl::getPropertyPriority( int ) const { // All computed styles have a priority of false (not "important"). return false; } DOM::DOMString RenderStyleDeclarationImpl::removeProperty( int ) { // ### emit error since we're read-only return DOMString(); } void RenderStyleDeclarationImpl::removePropertiesInSet(const int* set, unsigned length) { // ### emit error since we're read-only } bool RenderStyleDeclarationImpl::setProperty ( int, const DOM::DOMString &, bool, int &ec) { ec = DOMException::NO_MODIFICATION_ALLOWED_ERR; return false; } bool RenderStyleDeclarationImpl::setProperty ( int, const DOM::DOMString&, bool ) { // ### emit error since we're read-only return false; } void RenderStyleDeclarationImpl::setProperty ( int, int, bool ) { // ### emit error since we're read-only } void RenderStyleDeclarationImpl::setLengthProperty( int, const DOM::DOMString&, bool, bool ) { // ### emit error since we're read-only } void RenderStyleDeclarationImpl::setProperty( const DOMString& ) { // ### emit error since we're read-only } unsigned long RenderStyleDeclarationImpl::length() const { return numComputedProperties; } DOM::DOMString RenderStyleDeclarationImpl::item( unsigned long i ) const { if (i >= numComputedProperties) return DOMString(); return getPropertyName(computedProperties[i]); } CSSProperty RenderStyleDeclarationImpl::property( int id ) const { CSSProperty prop; prop.m_id = id; prop.m_important = false; CSSValueImpl* v = getPropertyCSSValue( id ); if ( !v ) v = new CSSPrimitiveValueImpl; prop.setValue( v ); return prop; } diff --git a/khtml/css/cssparser.cpp b/khtml/css/cssparser.cpp index e26ae44f9a..9d50adba05 100644 --- a/khtml/css/cssparser.cpp +++ b/khtml/css/cssparser.cpp @@ -1,2595 +1,2600 @@ /* * This file is part of the DOM implementation for KDE. * * Copyright 2003 Lars Knoll (knoll@kde.org) * Copyright 2005 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright (C) 2004, 2005, 2006 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. */ // #define CSS_DEBUG // #define TOKEN_DEBUG #define YYDEBUG 0 #include "cssparser.h" #include #include #include #include "css_valueimpl.h" #include "css_ruleimpl.h" #include "css_stylesheetimpl.h" #include "cssproperties.h" #include "cssvalues.h" #include "csshelper.h" #include #include #include using namespace DOM; // used to promote background: left to left center #define BACKGROUND_SKIP_CENTER( num ) \ if ( !pos_ok[ num ] && expected != 1 ) { \ pos_ok[num] = true; \ pos[num] = 0; \ skip_next = false; \ } ValueList::~ValueList() { unsigned numValues = m_values.size(); for (unsigned i = 0; i < numValues; i++) if (m_values[i].unit == Value::Function) delete m_values[i].function; } namespace { class ShorthandScope { public: ShorthandScope(CSSParser* parser, int propId) : m_parser(parser) { if (!(m_parser->m_inParseShorthand++)) m_parser->m_currentShorthand = propId; } ~ShorthandScope() { if (!(--m_parser->m_inParseShorthand)) m_parser->m_currentShorthand = 0; } private: CSSParser* m_parser; }; } using namespace DOM; #if YYDEBUG > 0 extern int cssyydebug; #endif extern int cssyyparse( void * parser ); CSSParser *CSSParser::currentParser = 0; CSSParser::CSSParser( bool strictParsing ) { #ifdef CSS_DEBUG kDebug( 6080 ) << "CSSParser::CSSParser this=" << this; #endif strict = strictParsing; parsedProperties = (CSSProperty **) malloc( 32 * sizeof( CSSProperty * ) ); numParsedProperties = 0; maxParsedProperties = 32; data = 0; valueList = 0; rule = 0; id = 0; important = false; m_inParseShorthand = 0; m_currentShorthand = 0; m_implicitShorthand = false; yy_start = 1; #if YYDEBUG > 0 cssyydebug = 1; #endif } CSSParser::~CSSParser() { if ( numParsedProperties ) clearProperties(); free( parsedProperties ); delete valueList; #ifdef CSS_DEBUG kDebug( 6080 ) << "CSSParser::~CSSParser this=" << this; #endif free( data ); } unsigned int CSSParser::defaultNamespace() { if (styleElement && styleElement->isCSSStyleSheet()) return static_cast(styleElement)->defaultNamespace(); else return anyNamespace; } void CSSParser::runParser(int length) { data[length-1] = 0; data[length-2] = 0; data[length-3] = ' '; yyTok = -1; block_nesting = 0; yy_hold_char = 0; yyleng = 0; yytext = yy_c_buf_p = data; yy_hold_char = *yy_c_buf_p; CSSParser *old = currentParser; currentParser = this; cssyyparse( this ); currentParser = old; } void CSSParser::parseSheet( CSSStyleSheetImpl *sheet, const DOMString &string ) { styleElement = sheet; int length = string.length() + 3; data = (unsigned short *)malloc( length *sizeof( unsigned short ) ); memcpy( data, string.unicode(), string.length()*sizeof( unsigned short) ); #ifdef CSS_DEBUG kDebug( 6080 ) << ">>>>>>> start parsing style sheet"; #endif runParser(length); #ifdef CSS_DEBUG kDebug( 6080 ) << "<<<<<<< done parsing style sheet"; #endif delete rule; rule = 0; } CSSRuleImpl *CSSParser::parseRule( DOM::CSSStyleSheetImpl *sheet, const DOM::DOMString &string ) { styleElement = sheet; const char khtml_rule[] = "@-khtml-rule{"; int length = string.length() + 4 + strlen(khtml_rule); assert( !data ); data = (unsigned short *)malloc( length *sizeof( unsigned short ) ); for ( unsigned int i = 0; i < strlen(khtml_rule); i++ ) data[i] = khtml_rule[i]; memcpy( data + strlen( khtml_rule ), string.unicode(), string.length()*sizeof( unsigned short) ); // qDebug("parse string = '%s'", QString::fromRawData( (const QChar *)data, length ).toLatin1().constData() ); data[length-4] = '}'; runParser(length); CSSRuleImpl *result = rule; rule = 0; return result; } static void addParsedProperties( DOM::CSSStyleDeclarationImpl *declaration, CSSProperty** parsedProperties, int numProperties) { for ( int i = 0; i < numProperties; i++ ) { // Only add properties that have no !important counterpart present if (!declaration->getPropertyPriority(parsedProperties[i]->id()) || parsedProperties[i]->isImportant()) { declaration->removeProperty(parsedProperties[i]->m_id); declaration->values()->append( parsedProperties[i] ); } } } bool CSSParser::parseValue( DOM::CSSStyleDeclarationImpl *declaration, int _id, const DOM::DOMString &string, bool _important) { #ifdef CSS_DEBUG kDebug( 6080 ) << "CSSParser::parseValue: id=" << _id << " important=" << _important << " value='" << string.string() << "'" << endl; #endif styleElement = declaration->stylesheet(); const char khtml_value[] = "@-khtml-value{"; int length = string.length() + 4 + strlen(khtml_value); assert( !data ); data = (unsigned short *)malloc( length *sizeof( unsigned short ) ); for ( unsigned int i = 0; i < strlen(khtml_value); i++ ) data[i] = khtml_value[i]; memcpy( data + strlen( khtml_value ), string.unicode(), string.length()*sizeof( unsigned short) ); data[length-4] = '}'; // qDebug("parse string = '%s'", QString::fromRawData( (const QChar *)data, length ).toLatin1().constData() ); id = _id; important = _important; runParser(length); delete rule; rule = 0; bool ok = false; if ( numParsedProperties ) { ok = true; addParsedProperties(declaration, parsedProperties, numParsedProperties); numParsedProperties = 0; } return ok; } bool CSSParser::parseDeclaration( DOM::CSSStyleDeclarationImpl *declaration, const DOM::DOMString &string) { #ifdef CSS_DEBUG kDebug( 6080 ) << "CSSParser::parseDeclaration:" << " value='" << string.string() << "'" << endl; #endif styleElement = declaration->stylesheet(); const char khtml_decls[] = "@-khtml-decls{"; int length = string.length() + 4 + strlen(khtml_decls); assert( !data ); data = (unsigned short *)malloc( length *sizeof( unsigned short ) ); for ( unsigned int i = 0; i < strlen(khtml_decls); i++ ) data[i] = khtml_decls[i]; memcpy( data + strlen( khtml_decls ), string.unicode(), string.length()*sizeof( unsigned short) ); data[length-4] = '}'; runParser(length); delete rule; rule = 0; bool ok = false; if ( numParsedProperties ) { ok = true; addParsedProperties(declaration, parsedProperties, numParsedProperties); numParsedProperties = 0; } return ok; } void CSSParser::addProperty( int propId, CSSValueImpl *value, bool important ) { CSSProperty *prop = new CSSProperty; prop->m_id = propId; prop->setValue( value ); prop->m_important = important; if ( numParsedProperties >= maxParsedProperties ) { maxParsedProperties += 32; parsedProperties = (CSSProperty **) realloc( parsedProperties, maxParsedProperties*sizeof( CSSProperty * ) ); } parsedProperties[numParsedProperties++] = prop; } CSSStyleDeclarationImpl *CSSParser::createStyleDeclaration( CSSStyleRuleImpl *rule ) { QList *propList = new QList; for ( int i = 0; i < numParsedProperties; i++ ) propList->append( parsedProperties[i] ); numParsedProperties = 0; return new CSSStyleDeclarationImpl(rule, propList); } void CSSParser::clearProperties() { for ( int i = 0; i < numParsedProperties; i++ ) delete parsedProperties[i]; numParsedProperties = 0; } DOM::DocumentImpl *CSSParser::document() const { const StyleBaseImpl* root = styleElement; DocumentImpl *doc = 0; while (root->parent()) root = root->parent(); if (root->isCSSStyleSheet()) doc = static_cast(root)->doc(); return doc; } bool CSSParser::validUnit( Value *value, int unitflags, bool strict ) { if ( unitflags & FNonNeg && value->fValue < 0 ) return false; bool b = false; switch( value->unit ) { case CSSPrimitiveValue::CSS_NUMBER: b = (unitflags & FNumber); if ( !b && ( (unitflags & FLength) && (value->fValue == 0 || !strict ) ) ) { value->unit = CSSPrimitiveValue::CSS_PX; b = true; } if (!b && (unitflags & FInteger) && value->isInt) b = true; break; case CSSPrimitiveValue::CSS_PERCENTAGE: b = (unitflags & FPercent); break; case Value::Q_EMS: case CSSPrimitiveValue::CSS_EMS: case CSSPrimitiveValue::CSS_EXS: case CSSPrimitiveValue::CSS_PX: case CSSPrimitiveValue::CSS_CM: case CSSPrimitiveValue::CSS_MM: case CSSPrimitiveValue::CSS_IN: case CSSPrimitiveValue::CSS_PT: case CSSPrimitiveValue::CSS_PC: b = (unitflags & FLength); break; case CSSPrimitiveValue::CSS_MS: case CSSPrimitiveValue::CSS_S: b = (unitflags & FTime); break; case CSSPrimitiveValue::CSS_DEG: case CSSPrimitiveValue::CSS_RAD: case CSSPrimitiveValue::CSS_GRAD: case CSSPrimitiveValue::CSS_HZ: case CSSPrimitiveValue::CSS_KHZ: case CSSPrimitiveValue::CSS_DIMENSION: default: break; } return b; } bool CSSParser::parseValue( int propId, bool important ) { if ( !valueList ) return false; Value *value = valueList->current(); if ( !value ) return false; int id = value->id; int num = inShorthand() ? 1 : valueList->size(); if ( id == CSS_VAL_INHERIT ) { if (num != 1) return false; addProperty( propId, new CSSInheritedValueImpl(), important ); return true; } else if (id == CSS_VAL_INITIAL ) { if (num != 1) return false; addProperty(propId, new CSSInitialValueImpl(false/*implicit initial*/), important); return true; } bool valid_primitive = false; CSSValueImpl *parsedValue = 0; switch(propId) { /* The comment to the left defines all valid value of this properties as defined * in CSS 2, Appendix F. Property index */ /* All the CSS properties are not supported by the renderer at the moment. * Note that all the CSS2 Aural properties are only checked, if CSS_AURAL is defined * (see parseAuralValues). As we don't support them at all this seems reasonable. */ case CSS_PROP_SIZE: // {1,2} | auto | portrait | landscape | inherit // case CSS_PROP_PAGE: // | auto // ### CHECK // ### To be done if (id) valid_primitive = true; break; case CSS_PROP_UNICODE_BIDI: // normal | embed | bidi-override | inherit if ( id == CSS_VAL_NORMAL || id == CSS_VAL_EMBED || id == CSS_VAL_BIDI_OVERRIDE ) valid_primitive = true; break; case CSS_PROP_POSITION: // static | relative | absolute | fixed | inherit if ( id == CSS_VAL_STATIC || id == CSS_VAL_RELATIVE || id == CSS_VAL_ABSOLUTE || id == CSS_VAL_FIXED ) valid_primitive = true; break; case CSS_PROP_PAGE_BREAK_AFTER: // auto | always | avoid | left | right | inherit case CSS_PROP_PAGE_BREAK_BEFORE: // auto | always | avoid | left | right | inherit if ( id == CSS_VAL_AUTO || id == CSS_VAL_ALWAYS || id == CSS_VAL_AVOID || id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT ) valid_primitive = true; break; case CSS_PROP_PAGE_BREAK_INSIDE: // avoid | auto | inherit if ( id == CSS_VAL_AUTO || id == CSS_VAL_AVOID ) valid_primitive = true; break; case CSS_PROP_EMPTY_CELLS: // show | hide | inherit if ( id == CSS_VAL_SHOW || id == CSS_VAL_HIDE ) valid_primitive = true; break; case CSS_PROP_QUOTES: // [ ]+ | none | inherit if (id == CSS_VAL_NONE) { valid_primitive = true; } else { QuotesValueImpl *quotes = new QuotesValueImpl; bool is_valid = true; QString open, close; Value *val=valueList->current(); while (val) { if (val->unit == CSSPrimitiveValue::CSS_STRING) open = qString(val->string); else { is_valid = false; break; } valueList->next(); val=valueList->current(); if (val && val->unit == CSSPrimitiveValue::CSS_STRING) close = qString(val->string); else { is_valid = false; break; } quotes->addLevel(open, close); valueList->next(); val=valueList->current(); } if (is_valid) parsedValue = quotes; else delete quotes; } break; case CSS_PROP_CONTENT: // normal | none | inherit | // [ | | | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ if ( id == CSS_VAL_NORMAL || id == CSS_VAL_NONE) valid_primitive = true; else return parseContent( propId, important ); break; case CSS_PROP_WHITE_SPACE: // normal | pre | nowrap | pre-wrap | pre-line | inherit if ( id == CSS_VAL_NORMAL || id == CSS_VAL_PRE || id == CSS_VAL_PRE_WRAP || id == CSS_VAL_PRE_LINE || id == CSS_VAL_NOWRAP ) valid_primitive = true; break; case CSS_PROP_CLIP: // | auto | inherit if ( id == CSS_VAL_AUTO ) valid_primitive = true; else if ( value->unit == Value::Function ) return parseShape( propId, important ); break; /* Start of supported CSS properties with validation. This is needed for parseShortHand to work * correctly and allows optimization in khtml::applyRule(..) */ case CSS_PROP_CAPTION_SIDE: // top | bottom | left | right | inherit // Left and right were deprecated in CSS 2.1 and never supported by KHTML if ( /* id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || */ id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM) valid_primitive = true; break; case CSS_PROP_BORDER_COLLAPSE: // collapse | separate | inherit if ( id == CSS_VAL_COLLAPSE || id == CSS_VAL_SEPARATE ) valid_primitive = true; break; case CSS_PROP_VISIBILITY: // visible | hidden | collapse | inherit if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_COLLAPSE) valid_primitive = true; break; case CSS_PROP_OVERFLOW: // visible | hidden | scroll | auto | marquee | inherit case CSS_PROP_OVERFLOW_X: case CSS_PROP_OVERFLOW_Y: if (id == CSS_VAL_VISIBLE || id == CSS_VAL_HIDDEN || id == CSS_VAL_SCROLL || id == CSS_VAL_AUTO || id == CSS_VAL_MARQUEE) valid_primitive = true; break; case CSS_PROP_LIST_STYLE_POSITION: // inside | outside | inherit if ( id == CSS_VAL_INSIDE || id == CSS_VAL_OUTSIDE ) valid_primitive = true; break; case CSS_PROP_LIST_STYLE_TYPE: // disc | circle | square | decimal | decimal-leading-zero | lower-roman | // upper-roman | lower-greek | lower-alpha | lower-latin | upper-alpha | // upper-latin | hebrew | armenian | georgian | cjk-ideographic | hiragana | // katakana | hiragana-iroha | katakana-iroha | none | inherit if ((id >= CSS_VAL_DISC && id <= CSS_VAL__KHTML_CLOSE_QUOTE) || id == CSS_VAL_NONE) valid_primitive = true; break; case CSS_PROP_DISPLAY: // inline | block | list-item | run-in | inline-block | -khtml-ruler | table | // inline-table | table-row-group | table-header-group | table-footer-group | table-row | // table-column-group | table-column | table-cell | table-caption | none | inherit if ((id >= CSS_VAL_INLINE && id <= CSS_VAL_TABLE_CAPTION) || id == CSS_VAL_NONE) valid_primitive = true; break; case CSS_PROP_DIRECTION: // ltr | rtl | inherit if ( id == CSS_VAL_LTR || id == CSS_VAL_RTL ) valid_primitive = true; break; case CSS_PROP_TEXT_TRANSFORM: // capitalize | uppercase | lowercase | none | inherit if ((id >= CSS_VAL_CAPITALIZE && id <= CSS_VAL_LOWERCASE) || id == CSS_VAL_NONE) valid_primitive = true; break; case CSS_PROP_FLOAT: // left | right | none | khtml_left | khtml_right | inherit + center for buggy CSS if ( id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || id == CSS_VAL__KHTML_LEFT || id == CSS_VAL__KHTML_RIGHT ||id == CSS_VAL_NONE || id == CSS_VAL_CENTER) valid_primitive = true; break; case CSS_PROP_CLEAR: // none | left | right | both | inherit if ( id == CSS_VAL_NONE || id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT|| id == CSS_VAL_BOTH) valid_primitive = true; break; case CSS_PROP_TEXT_ALIGN: // left | right | center | justify | khtml_left | khtml_right | khtml_center | | inherit if ( ( id >= CSS_VAL__KHTML_AUTO && id <= CSS_VAL__KHTML_CENTER ) || value->unit == CSSPrimitiveValue::CSS_STRING ) valid_primitive = true; break; case CSS_PROP_OUTLINE_STYLE: // | inherit case CSS_PROP_BORDER_TOP_STYLE: //// | inherit case CSS_PROP_BORDER_RIGHT_STYLE: // Defined as: none | hidden | dotted | dashed | case CSS_PROP_BORDER_BOTTOM_STYLE: // solid | double | groove | ridge | inset | outset | -khtml-native case CSS_PROP_BORDER_LEFT_STYLE: //// if (id >= CSS_VAL__KHTML_NATIVE && id <= CSS_VAL_DOUBLE) valid_primitive = true; break; case CSS_PROP_FONT_WEIGHT: // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | // 500 | 600 | 700 | 800 | 900 | inherit if (id >= CSS_VAL_NORMAL && id <= CSS_VAL_900) { // Allready correct id valid_primitive = true; } else if ( validUnit( value, FInteger|FNonNeg, false ) ) { int weight = (int)value->fValue; if ( (weight % 100) ) break; weight /= 100; if ( weight >= 1 && weight <= 9 ) { id = CSS_VAL_100 + weight - 1; valid_primitive = true; } } break; case CSS_PROP_BORDER_SPACING: { const int properties[2] = { CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING, CSS_PROP__KHTML_BORDER_VERTICAL_SPACING }; if (num == 1) { ShorthandScope scope(this, CSS_PROP_BORDER_SPACING); if (!parseValue(properties[0], important)) return false; CSSValueImpl* value = parsedProperties[numParsedProperties-1]->value(); addProperty(properties[1], value, important); return true; } else if (num == 2) { ShorthandScope scope(this, CSS_PROP_BORDER_SPACING); if (!parseValue(properties[0], important)) return false; if (!parseValue(properties[1], important)) return false; return true; } return false; } case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: valid_primitive = validUnit(value, FLength|FNonNeg, strict); break; case CSS_PROP_SCROLLBAR_FACE_COLOR: // IE5.5 case CSS_PROP_SCROLLBAR_SHADOW_COLOR: // IE5.5 case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: // IE5.5 case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: // IE5.5 case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: // IE5.5 case CSS_PROP_SCROLLBAR_TRACK_COLOR: // IE5.5 case CSS_PROP_SCROLLBAR_ARROW_COLOR: // IE5.5 case CSS_PROP_SCROLLBAR_BASE_COLOR: // IE5.5 if ( strict ) break; /* nobreak */ case CSS_PROP_OUTLINE_COLOR: // | invert | inherit // outline has "invert" as additional keyword. if ( propId == CSS_PROP_OUTLINE_COLOR && id == CSS_VAL_INVERT ) { valid_primitive = true; break; } /* nobreak */ case CSS_PROP_BACKGROUND_COLOR: // | inherit case CSS_PROP_BORDER_TOP_COLOR: // | inherit case CSS_PROP_BORDER_RIGHT_COLOR: // | inherit case CSS_PROP_BORDER_BOTTOM_COLOR: // | inherit case CSS_PROP_BORDER_LEFT_COLOR: // | inherit case CSS_PROP_COLOR: // | inherit if ( id == CSS_VAL__KHTML_TEXT || id == CSS_VAL_MENU || (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT ) || id == CSS_VAL_TRANSPARENT || (id >= CSS_VAL_GREY && id < CSS_VAL__KHTML_TEXT && !strict ) ) { valid_primitive = true; } else { parsedValue = parseColor(); if ( parsedValue ) valueList->next(); } break; case CSS_PROP_CURSOR: - // [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize | - // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | text | - // wait | help ] ] | inherit + // [ auto | default | none | + // context-menu | help | pointer | progress | wait | + // cell | crosshair | text | vertical-text | + // alias | copy | move | no-drop | not-allowed | + // e-resize | ne-resize | nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | + // ew-resize | ns-resize | nesw-resize | nwse-resize | + // col-resize | row-resize | all-scroll + // ] ] | inherit // MSIE 5 compatibility :/ if ( !strict && id == CSS_VAL_HAND ) { id = CSS_VAL_POINTER; valid_primitive = true; - } else if ( id >= CSS_VAL_AUTO && id <= CSS_VAL_HELP ) + } else if (( id >= CSS_VAL_AUTO && id <= CSS_VAL_ALL_SCROLL ) || id == CSS_VAL_NONE ) valid_primitive = true; break; case CSS_PROP_BACKGROUND_ATTACHMENT: case CSS_PROP__KHTML_BACKGROUND_CLIP: case CSS_PROP_BACKGROUND_IMAGE: case CSS_PROP__KHTML_BACKGROUND_ORIGIN: case CSS_PROP_BACKGROUND_POSITION: case CSS_PROP_BACKGROUND_POSITION_X: case CSS_PROP_BACKGROUND_POSITION_Y: case CSS_PROP__KHTML_BACKGROUND_SIZE: case CSS_PROP_BACKGROUND_REPEAT: { CSSValueImpl *val1 = 0, *val2 = 0; int propId1, propId2; if (parseBackgroundProperty(propId, propId1, propId2, val1, val2)) { addProperty(propId1, val1, important); if (val2) addProperty(propId2, val2, important); return true; } return false; } case CSS_PROP_LIST_STYLE_IMAGE: // | none | inherit if (id == CSS_VAL_NONE) { parsedValue = new CSSImageValueImpl(); valueList->next(); } else if (value->unit == CSSPrimitiveValue::CSS_URI ) { // ### allow string in non strict mode? DOMString uri = khtml::parseURL( domString( value->string ) ); if (!uri.isEmpty()) { parsedValue = new CSSImageValueImpl( DOMString(KUrl( styleElement->baseURL(), uri.string()).url()), styleElement ); valueList->next(); } } break; case CSS_PROP_OUTLINE_WIDTH: // | inherit case CSS_PROP_BORDER_TOP_WIDTH: //// | inherit case CSS_PROP_BORDER_RIGHT_WIDTH: // Which is defined as case CSS_PROP_BORDER_BOTTOM_WIDTH: // thin | medium | thick | case CSS_PROP_BORDER_LEFT_WIDTH: //// if (id == CSS_VAL_THIN || id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK) valid_primitive = true; else valid_primitive = ( validUnit( value, FLength, strict ) ); break; case CSS_PROP_LETTER_SPACING: // normal | | inherit case CSS_PROP_WORD_SPACING: // normal | | inherit if ( id == CSS_VAL_NORMAL ) valid_primitive = true; else valid_primitive = validUnit( value, FLength, strict ); break; case CSS_PROP_TEXT_INDENT: // | | inherit valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict ) ); break; case CSS_PROP_PADDING_TOP: // | | inherit case CSS_PROP_PADDING_RIGHT: // | inherit case CSS_PROP_PADDING_BOTTOM: // Which is defined as case CSS_PROP_PADDING_LEFT: // | case CSS_PROP__KHTML_PADDING_START: valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict ) ); break; case CSS_PROP_MAX_HEIGHT: // | | none | inherit case CSS_PROP_MAX_WIDTH: // | | none | inherit if ( id == CSS_VAL_NONE ) { valid_primitive = true; break; } /* nobreak */ case CSS_PROP_MIN_HEIGHT: // | | inherit case CSS_PROP_MIN_WIDTH: // | | inherit valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict ) ); break; case CSS_PROP_FONT_SIZE: // | | | | inherit if (id >= CSS_VAL_XX_SMALL && id <= CSS_VAL_LARGER) valid_primitive = true; else valid_primitive = ( validUnit( value, FLength|FPercent, strict ) ); break; case CSS_PROP_FONT_STYLE: // normal | italic | oblique | inherit if ( id == CSS_VAL_NORMAL || id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE) valid_primitive = true; break; case CSS_PROP_FONT_VARIANT: // normal | small-caps | inherit if ( id == CSS_VAL_NORMAL || id == CSS_VAL_SMALL_CAPS) valid_primitive = true; break; case CSS_PROP_VERTICAL_ALIGN: // baseline | sub | super | top | text-top | middle | bottom | text-bottom | // | | inherit if ( id >= CSS_VAL_BASELINE && id <= CSS_VAL__KHTML_BASELINE_MIDDLE ) valid_primitive = true; else valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict ) ); break; case CSS_PROP_HEIGHT: // | | auto | inherit case CSS_PROP_WIDTH: // | | auto | inherit if ( id == CSS_VAL_AUTO ) valid_primitive = true; else // ### handle multilength case where we allow relative units valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict ) ); break; case CSS_PROP_BOTTOM: // | | auto | inherit case CSS_PROP_LEFT: // | | auto | inherit case CSS_PROP_RIGHT: // | | auto | inherit case CSS_PROP_TOP: // | | auto | inherit case CSS_PROP_MARGIN_TOP: //// | inherit case CSS_PROP_MARGIN_RIGHT: // Which is defined as case CSS_PROP_MARGIN_BOTTOM: // | | auto | inherit case CSS_PROP_MARGIN_LEFT: //// case CSS_PROP__KHTML_MARGIN_START: if ( id == CSS_VAL_AUTO ) valid_primitive = true; else valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict ) ); break; case CSS_PROP_Z_INDEX: // auto | | inherit // qDebug("parsing z-index: id=%d, fValue=%f", id, value->fValue ); if ( id == CSS_VAL_AUTO ) { valid_primitive = true; break; } /* nobreak */ case CSS_PROP_ORPHANS: // | inherit case CSS_PROP_WIDOWS: // | inherit // ### not supported later on valid_primitive = ( !id && validUnit( value, FInteger, false ) ); break; case CSS_PROP_LINE_HEIGHT: // normal | | | | inherit if ( id == CSS_VAL_NORMAL ) valid_primitive = true; else valid_primitive = ( !id && validUnit( value, FNumber|FLength|FPercent, strict ) ); break; case CSS_PROP_COUNTER_INCREMENT: // [ ? ]+ | none | inherit if ( id == CSS_VAL_NONE ) valid_primitive = true; else return parseCounter(propId, true, important); break; case CSS_PROP_COUNTER_RESET: // [ ? ]+ | none | inherit if ( id == CSS_VAL_NONE ) valid_primitive = true; else return parseCounter(propId, false, important); break; case CSS_PROP_FONT_FAMILY: // [[ | ],]* [ | ] | inherit { parsedValue = parseFontFamily(); break; } case CSS_PROP_TEXT_DECORATION: // none | [ underline || overline || line-through || blink ] | inherit if (id == CSS_VAL_NONE) { valid_primitive = true; } else { CSSValueListImpl *list = new CSSValueListImpl; bool is_valid = true; while( is_valid && value ) { switch ( value->id ) { case CSS_VAL_BLINK: break; case CSS_VAL_UNDERLINE: case CSS_VAL_OVERLINE: case CSS_VAL_LINE_THROUGH: list->append( new CSSPrimitiveValueImpl( value->id ) ); break; default: is_valid = false; } value = valueList->next(); } //kDebug( 6080 ) << "got " << list->length() << "d decorations"; if(list->length() && is_valid) { parsedValue = list; valueList->next(); } else { delete list; } } break; case CSS_PROP_TABLE_LAYOUT: // auto | fixed | inherit if ( id == CSS_VAL_AUTO || id == CSS_VAL_FIXED ) valid_primitive = true; break; case CSS_PROP__KHTML_FLOW_MODE: if ( id == CSS_VAL__KHTML_NORMAL || id == CSS_VAL__KHTML_AROUND_FLOATS ) valid_primitive = true; break; /* CSS3 properties */ case CSS_PROP_BOX_SIZING: // border-box | content-box | inherit if ( id == CSS_VAL_BORDER_BOX || id == CSS_VAL_CONTENT_BOX ) valid_primitive = true; break; case CSS_PROP_OUTLINE_OFFSET: valid_primitive = validUnit(value, FLength, strict); break; case CSS_PROP_TEXT_SHADOW: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3 if (id == CSS_VAL_NONE) valid_primitive = true; else return parseShadow(propId, important); break; case CSS_PROP_OPACITY: valid_primitive = validUnit(value, FNumber, strict); break; case CSS_PROP__KHTML_USER_INPUT: // none | enabled | disabled | inherit if ( id == CSS_VAL_NONE || id == CSS_VAL_ENABLED || id == CSS_VAL_DISABLED ) valid_primitive = true; // kDebug(6080) << "CSS_PROP__KHTML_USER_INPUT: " << valid_primitive; break; case CSS_PROP__KHTML_MARQUEE: { const int properties[5] = { CSS_PROP__KHTML_MARQUEE_DIRECTION, CSS_PROP__KHTML_MARQUEE_INCREMENT, CSS_PROP__KHTML_MARQUEE_REPETITION, CSS_PROP__KHTML_MARQUEE_STYLE, CSS_PROP__KHTML_MARQUEE_SPEED }; return parseShortHand(propId, properties, 5, important); } case CSS_PROP__KHTML_MARQUEE_DIRECTION: if (id == CSS_VAL_FORWARDS || id == CSS_VAL_BACKWARDS || id == CSS_VAL_AHEAD || id == CSS_VAL_REVERSE || id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT || id == CSS_VAL_DOWN || id == CSS_VAL_UP || id == CSS_VAL_AUTO) valid_primitive = true; break; case CSS_PROP__KHTML_MARQUEE_INCREMENT: if (id == CSS_VAL_SMALL || id == CSS_VAL_LARGE || id == CSS_VAL_MEDIUM) valid_primitive = true; else valid_primitive = validUnit(value, FLength|FPercent, strict); break; case CSS_PROP__KHTML_MARQUEE_STYLE: if (id == CSS_VAL_NONE || id == CSS_VAL_SLIDE || id == CSS_VAL_SCROLL || id == CSS_VAL_ALTERNATE || id == CSS_VAL_UNFURL) valid_primitive = true; break; case CSS_PROP__KHTML_MARQUEE_REPETITION: if (id == CSS_VAL_INFINITE) valid_primitive = true; else valid_primitive = validUnit(value, FInteger|FNonNeg, strict); break; case CSS_PROP__KHTML_MARQUEE_SPEED: if (id == CSS_VAL_NORMAL || id == CSS_VAL_SLOW || id == CSS_VAL_FAST) valid_primitive = true; else valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict); break; case CSS_PROP_TEXT_OVERFLOW: // clip | ellipsis if (id == CSS_VAL_CLIP || id == CSS_VAL_ELLIPSIS) valid_primitive = true; break; // End of CSS3 properties /* shorthand properties */ case CSS_PROP_BACKGROUND: // ['background-color' || 'background-image' ||'background-repeat' || // 'background-attachment' || 'background-position'] | inherit return parseBackgroundShorthand(important); case CSS_PROP_BORDER: // [ 'border-width' || 'border-style' || ] | inherit { const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE, CSS_PROP_BORDER_COLOR }; return parseShortHand(propId, properties, 3, important); } case CSS_PROP_BORDER_TOP: // [ 'border-top-width' || 'border-style' || ] | inherit { const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_TOP_COLOR}; return parseShortHand(propId, properties, 3, important); } case CSS_PROP_BORDER_RIGHT: // [ 'border-right-width' || 'border-style' || ] | inherit { const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE, CSS_PROP_BORDER_RIGHT_COLOR }; return parseShortHand(propId, properties, 3, important); } case CSS_PROP_BORDER_BOTTOM: // [ 'border-bottom-width' || 'border-style' || ] | inherit { const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_BOTTOM_COLOR }; return parseShortHand(propId, properties, 3, important); } case CSS_PROP_BORDER_LEFT: // [ 'border-left-width' || 'border-style' || ] | inherit { const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE, CSS_PROP_BORDER_LEFT_COLOR }; return parseShortHand(propId, properties, 3, important); } case CSS_PROP_OUTLINE: // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit { const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE, CSS_PROP_OUTLINE_COLOR }; return parseShortHand(propId, properties, 3, important); } case CSS_PROP_BORDER_COLOR: // {1,4} | inherit { const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR, CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR }; return parse4Values(propId, properties, important); } case CSS_PROP_BORDER_WIDTH: // {1,4} | inherit { const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH }; return parse4Values(propId, properties, important); } case CSS_PROP_BORDER_STYLE: // {1,4} | inherit { const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE }; return parse4Values(propId, properties, important); } case CSS_PROP_MARGIN: // {1,4} | inherit { const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT, CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT }; return parse4Values(propId, properties, important); } case CSS_PROP_PADDING: // {1,4} | inherit { const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT, CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT }; return parse4Values(propId, properties, important); } case CSS_PROP_FONT: // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit if ( id >= CSS_VAL_CAPTION && id <= CSS_VAL_STATUS_BAR ) valid_primitive = true; else return parseFont(important); case CSS_PROP_LIST_STYLE: { const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION, CSS_PROP_LIST_STYLE_IMAGE }; return parseShortHand(propId, properties, 3, important); } default: // #ifdef CSS_DEBUG // kDebug( 6080 ) << "illegal or CSS2 Aural property: " << val; // #endif break; } if ( valid_primitive ) { if ( id != 0 ) { parsedValue = new CSSPrimitiveValueImpl( id ); } else if ( value->unit == CSSPrimitiveValue::CSS_STRING ) parsedValue = new CSSPrimitiveValueImpl( domString( value->string ), (CSSPrimitiveValue::UnitTypes) value->unit ); else if ( value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ ) { parsedValue = new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit ); } else if ( value->unit >= Value::Q_EMS ) { parsedValue = new CSSQuirkPrimitiveValueImpl( value->fValue, CSSPrimitiveValue::CSS_EMS ); } valueList->next(); } if ( parsedValue ) { if (!valueList->current() || inShorthand()) { addProperty( propId, parsedValue, important ); return true; } delete parsedValue; } return false; } void CSSParser::addBackgroundValue(CSSValueImpl*& lval, CSSValueImpl* rval) { if (lval) { if (lval->isValueList()) static_cast(lval)->append(rval); else { CSSValueImpl* oldVal = lval; CSSValueListImpl* list = new CSSValueListImpl(); lval = list; list->append(oldVal); list->append(rval); } } else lval = rval; } bool CSSParser::parseBackgroundShorthand(bool important) { // Position must come before color in this array because a plain old "0" is a legal color // in quirks mode but it's usually the X coordinate of a position. // FIXME: Add CSS_PROP__KHTML_BACKGROUND_SIZE to the shorthand. const int numProperties = 7; const int properties[numProperties] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT, CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION, CSS_PROP__KHTML_BACKGROUND_CLIP, CSS_PROP__KHTML_BACKGROUND_ORIGIN, CSS_PROP_BACKGROUND_COLOR }; ShorthandScope scope(this, CSS_PROP_BACKGROUND); bool parsedProperty[numProperties] = { false }; // compiler will repeat false as necessary CSSValueImpl* values[numProperties] = { 0 }; // compiler will repeat 0 as necessary CSSValueImpl* positionYValue = 0; int i; while (valueList->current()) { Value* val = valueList->current(); if (val->unit == Value::Operator && val->iValue == ',') { // We hit the end. Fill in all remaining values with the initial value. valueList->next(); for (i = 0; i < numProperties; ++i) { if (properties[i] == CSS_PROP_BACKGROUND_COLOR && parsedProperty[i]) // Color is not allowed except as the last item in a list. Reject the entire // property. goto fail; if (!parsedProperty[i] && properties[i] != CSS_PROP_BACKGROUND_COLOR) { addBackgroundValue(values[i], new CSSInitialValueImpl(true/*implicit initial*/)); if (properties[i] == CSS_PROP_BACKGROUND_POSITION) addBackgroundValue(positionYValue, new CSSInitialValueImpl(true/*implicit initial*/)); } parsedProperty[i] = false; } if (!valueList->current()) break; } bool found = false; for (i = 0; !found && i < numProperties; ++i) { if (!parsedProperty[i]) { CSSValueImpl *val1 = 0, *val2 = 0; int propId1, propId2; if (parseBackgroundProperty(properties[i], propId1, propId2, val1, val2)) { parsedProperty[i] = found = true; addBackgroundValue(values[i], val1); if (properties[i] == CSS_PROP_BACKGROUND_POSITION) addBackgroundValue(positionYValue, val2); } } } // if we didn't find at least one match, this is an // invalid shorthand and we have to ignore it if (!found) goto fail; } // Fill in any remaining properties with the initial value. for (i = 0; i < numProperties; ++i) { if (!parsedProperty[i]) { addBackgroundValue(values[i], new CSSInitialValueImpl(true/*implicit initial*/)); if (properties[i] == CSS_PROP_BACKGROUND_POSITION) addBackgroundValue(positionYValue, new CSSInitialValueImpl(true/*implicit initial*/)); } } // Now add all of the properties we found. for (i = 0; i < numProperties; i++) { if (properties[i] == CSS_PROP_BACKGROUND_POSITION) { addProperty(CSS_PROP_BACKGROUND_POSITION_X, values[i], important); addProperty(CSS_PROP_BACKGROUND_POSITION_Y, positionYValue, important); } else addProperty(properties[i], values[i], important); } return true; fail: for (int k = 0; k < numProperties; k++) delete values[k]; delete positionYValue; return false; } bool CSSParser::parseShortHand(int propId, const int *properties, int numProperties, bool important ) { /* We try to match as many properties as possible * We setup an array of booleans to mark which property has been found, * and we try to search for properties until it makes no longer any sense */ ShorthandScope scope(this, propId); bool found = false; bool fnd[6]; //Trust me ;) for( int i = 0; i < numProperties; i++ ) fnd[i] = false; while ( valueList->current() ) { found = false; for (int propIndex = 0; !found && propIndex < numProperties; ++propIndex) { if (!fnd[propIndex]) { if ( parseValue( properties[propIndex], important ) ) { fnd[propIndex] = found = true; } } } // if we didn't find at least one match, this is an // invalid shorthand and we have to ignore it if (!found) return false; } // Fill in any remaining properties with the initial value. m_implicitShorthand = true; for (int i = 0; i < numProperties; ++i) { if (!fnd[i]) addProperty(properties[i], new CSSInitialValueImpl(true/*implicit initial*/), important); } m_implicitShorthand = false; return true; } bool CSSParser::parse4Values(int propId, const int *properties, bool important ) { /* From the CSS 2 specs, 8.3 * If there is only one value, it applies to all sides. If there are two values, the top and * bottom margins are set to the first value and the right and left margins are set to the second. * If there are three values, the top is set to the first value, the left and right are set to the * second, and the bottom is set to the third. If there are four values, they apply to the top, * right, bottom, and left, respectively. */ int num = inShorthand() ? 1 : valueList->size(); //qDebug("parse4Values: num=%d %d", num, valueList->numValues ); ShorthandScope scope(this, propId); // the order is top, right, bottom, left switch (num) { case 1: { if (!parseValue(properties[0], important)) return false; CSSValueImpl *value = parsedProperties[numParsedProperties-1]->value(); m_implicitShorthand = true; addProperty(properties[1], value, important); addProperty(properties[2], value, important); addProperty(properties[3], value, important); m_implicitShorthand = false; break; } case 2: { if (!parseValue(properties[0], important) || !parseValue(properties[1], important)) return false; CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value(); m_implicitShorthand = true; addProperty(properties[2], value, important); value = parsedProperties[numParsedProperties-2]->value(); addProperty(properties[3], value, important); m_implicitShorthand = false; break; } case 3: { if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important)) return false; CSSValueImpl *value = parsedProperties[numParsedProperties-2]->value(); m_implicitShorthand = true; addProperty(properties[3], value, important); m_implicitShorthand = false; break; } case 4: { if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important) || !parseValue(properties[3], important)) return false; break; } default: { return false; } } return true; } // [ | | | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit // in CSS 2.1 this got somewhat reduced: // [ | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit bool CSSParser::parseContent( int propId, bool important ) { CSSValueListImpl* values = new CSSValueListImpl(); bool isValid = true; Value *val; CSSValueImpl *parsedValue = 0; while ( (val = valueList->current()) ) { parsedValue = 0; if ( val->unit == CSSPrimitiveValue::CSS_URI ) { // url DOMString value = khtml::parseURL(domString(val->string)); parsedValue = new CSSImageValueImpl( DOMString(KUrl( styleElement->baseURL(), value.string()).url() ), styleElement ); #ifdef CSS_DEBUG kDebug( 6080 ) << "content, url=" << value.string() << " base=" << styleElement->baseURL().url( ); #endif } else if ( val->unit == Value::Function ) { // attr( X ) | counter( X [,Y] ) | counters( X, Y, [,Z] ) ValueList *args = val->function->args; QString fname = qString( val->function->name ).toLower(); if (!args) return false; if (fname == "attr(") { if ( args->size() != 1) return false; Value *a = args->current(); parsedValue = new CSSPrimitiveValueImpl(domString(a->string), CSSPrimitiveValue::CSS_ATTR); } else if (fname == "counter(") { parsedValue = parseCounterContent(args, false); if (!parsedValue) return false; } else if (fname == "counters(") { parsedValue = parseCounterContent(args, true); if (!parsedValue) return false; } else return false; } else if ( val->unit == CSSPrimitiveValue::CSS_IDENT ) { // open-quote | close-quote | no-open-quote | no-close-quote if ( val->id == CSS_VAL_OPEN_QUOTE || val->id == CSS_VAL_CLOSE_QUOTE || val->id == CSS_VAL_NO_OPEN_QUOTE || val->id == CSS_VAL_NO_CLOSE_QUOTE ) { parsedValue = new CSSPrimitiveValueImpl(val->id); } } else if ( val->unit == CSSPrimitiveValue::CSS_STRING ) { parsedValue = new CSSPrimitiveValueImpl(domString(val->string), CSSPrimitiveValue::CSS_STRING); } if (parsedValue) values->append(parsedValue); else { isValid = false; break; } valueList->next(); } if ( isValid && values->length() ) { addProperty( propId, values, important ); valueList->next(); return true; } delete values; // also frees any content by deref return false; } CSSValueImpl* CSSParser::parseCounterContent(ValueList *args, bool counters) { if (counters || (args->size() != 1 && args->size() != 3)) if (!counters || (args->size() != 3 && args->size() != 5)) return 0; CounterImpl *counter = new CounterImpl; Value *i = args->current(); // if (i->unit != CSSPrimitiveValue::CSS_IDENT) goto invalid; counter->m_identifier = domString(i->string); if (counters) { i = args->next(); if (i->unit != Value::Operator || i->iValue != ',') goto invalid; i = args->next(); if (i->unit != CSSPrimitiveValue::CSS_STRING) goto invalid; counter->m_separator = domString(i->string); } counter->m_listStyle = CSS_VAL_DECIMAL - CSS_VAL_DISC; i = args->next(); if (i) { if (i->unit != Value::Operator || i->iValue != ',') goto invalid; i = args->next(); if (i->unit != CSSPrimitiveValue::CSS_IDENT) goto invalid; if (i->id < CSS_VAL_DISC || i->id > CSS_VAL__KHTML_CLOSE_QUOTE) goto invalid; counter->m_listStyle = i->id - CSS_VAL_DISC; } return new CSSPrimitiveValueImpl(counter); invalid: delete counter; return 0; } CSSValueImpl* CSSParser::parseBackgroundColor() { int id = valueList->current()->id; if (id == CSS_VAL__KHTML_TEXT || id == CSS_VAL_TRANSPARENT || (id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT) || id == CSS_VAL_MENU || (id >= CSS_VAL_GREY && id < CSS_VAL__KHTML_TEXT && !strict)) return new CSSPrimitiveValueImpl(id); return parseColor(); } CSSValueImpl* CSSParser::parseBackgroundImage(bool& didParse) { didParse = false; if (valueList->current()->id == CSS_VAL_NONE) { didParse = true; return new CSSImageValueImpl(); } if (valueList->current()->unit == CSSPrimitiveValue::CSS_URI) { didParse = true; DOMString uri = khtml::parseURL(domString(valueList->current()->string)); if (!uri.isEmpty()) return new CSSImageValueImpl(DOMString(KUrl(styleElement->baseURL(), uri.string()).url()), styleElement); } return 0; } CSSValueImpl* CSSParser::parseBackgroundPositionXY(bool& xFound, bool& yFound) { int id = valueList->current()->id; if (id == CSS_VAL_LEFT || id == CSS_VAL_TOP || id == CSS_VAL_RIGHT || id == CSS_VAL_BOTTOM || id == CSS_VAL_CENTER) { int percent = 0; if (id == CSS_VAL_LEFT || id == CSS_VAL_RIGHT) { if (xFound) return 0; xFound = true; if (id == CSS_VAL_RIGHT) percent = 100; } else if (id == CSS_VAL_TOP || id == CSS_VAL_BOTTOM) { if (yFound) return 0; yFound = true; if (id == CSS_VAL_BOTTOM) percent = 100; } else if (id == CSS_VAL_CENTER) // Center is ambiguous, so we're not sure which position we've found yet, an x or a y. percent = 50; return new CSSPrimitiveValueImpl(percent, CSSPrimitiveValue::CSS_PERCENTAGE); } if (validUnit(valueList->current(), FPercent|FLength, strict)) return new CSSPrimitiveValueImpl(valueList->current()->fValue, (CSSPrimitiveValue::UnitTypes)valueList->current()->unit); return 0; } void CSSParser::parseBackgroundPosition(CSSValueImpl*& value1, CSSValueImpl*& value2) { value1 = value2 = 0; Value* value = valueList->current(); // Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length. bool value1IsX = false, value1IsY = false; value1 = parseBackgroundPositionXY(value1IsX, value1IsY); if (!value1) return; // It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we // can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the // value was explicitly specified for our property. value = valueList->next(); // First check for the comma. If so, we are finished parsing this value or value pair. if (value && value->unit == Value::Operator && value->iValue == ',') value = 0; bool value2IsX = false, value2IsY = false; if (value) { value2 = parseBackgroundPositionXY(value2IsX, value2IsY); if (value2) valueList->next(); else { if (!inShorthand()) { delete value1; value1 = 0; return; } } } if (!value2) // Only one value was specified. If that value was not a keyword, then it sets the x position, and the y position // is simply 50%. This is our default. // For keywords, the keyword was either an x-keyword (left/right), a y-keyword (top/bottom), or an ambiguous keyword (center). // For left/right/center, the default of 50% in the y is still correct. value2 = new CSSPrimitiveValueImpl(50, CSSPrimitiveValue::CSS_PERCENTAGE); if (value1IsY || value2IsX) { // Swap our two values. CSSValueImpl* val = value2; value2 = value1; value1 = val; } } CSSValueImpl* CSSParser::parseBackgroundSize() { Value* value = valueList->current(); CSSPrimitiveValueImpl* parsedValue1; if (value->id == CSS_VAL_AUTO) parsedValue1 = new CSSPrimitiveValueImpl(0, CSSPrimitiveValue::CSS_UNKNOWN); else { if (!validUnit(value, FLength|FPercent, strict)) return 0; parsedValue1 = new CSSPrimitiveValueImpl(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); } CSSPrimitiveValueImpl* parsedValue2 = parsedValue1; if ((value = valueList->next())) { if (value->id == CSS_VAL_AUTO) parsedValue2 = new CSSPrimitiveValueImpl(0, CSSPrimitiveValue::CSS_UNKNOWN); else { if (!validUnit(value, FLength|FPercent, strict)) { delete parsedValue1; return 0; } parsedValue2 = new CSSPrimitiveValueImpl(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); } } PairImpl* pair = new PairImpl(parsedValue1, parsedValue2); return new CSSPrimitiveValueImpl(pair); } bool CSSParser::parseBackgroundProperty(int propId, int& propId1, int& propId2, CSSValueImpl*& retValue1, CSSValueImpl*& retValue2) { #ifdef CSS_DEBUG kDebug(6080) << "parseBackgroundProperty()"; kDebug(6080) << "LOOKING FOR: " << getPropertyName(propId).string(); #endif CSSValueListImpl *values = 0, *values2 = 0; Value* val; CSSValueImpl *value = 0, *value2 = 0; bool allowComma = false; retValue1 = retValue2 = 0; propId1 = propId; propId2 = propId; if (propId == CSS_PROP_BACKGROUND_POSITION) { propId1 = CSS_PROP_BACKGROUND_POSITION_X; propId2 = CSS_PROP_BACKGROUND_POSITION_Y; } while ((val = valueList->current())) { CSSValueImpl *currValue = 0, *currValue2 = 0; if (allowComma) { if (val->unit != Value::Operator || val->iValue != ',') goto failed; valueList->next(); allowComma = false; } else { switch (propId) { case CSS_PROP_BACKGROUND_ATTACHMENT: if (val->id == CSS_VAL_SCROLL || val->id == CSS_VAL_FIXED) { currValue = new CSSPrimitiveValueImpl(val->id); valueList->next(); } break; case CSS_PROP_BACKGROUND_COLOR: currValue = parseBackgroundColor(); if (currValue) valueList->next(); break; case CSS_PROP_BACKGROUND_IMAGE: { bool didParse=false; currValue = parseBackgroundImage(didParse); if (didParse) valueList->next(); break; } case CSS_PROP__KHTML_BACKGROUND_CLIP: case CSS_PROP__KHTML_BACKGROUND_ORIGIN: if (val->id == CSS_VAL_BORDER || val->id == CSS_VAL_PADDING || val->id == CSS_VAL_CONTENT) { currValue = new CSSPrimitiveValueImpl(val->id); valueList->next(); } break; case CSS_PROP_BACKGROUND_POSITION: parseBackgroundPosition(currValue, currValue2); // unlike the other functions, parseBackgroundPosition advances the valueList pointer break; case CSS_PROP_BACKGROUND_POSITION_X: { bool xFound = false, yFound = true; currValue = parseBackgroundPositionXY(xFound, yFound); if (currValue) valueList->next(); break; } case CSS_PROP_BACKGROUND_POSITION_Y: { bool xFound = true, yFound = false; currValue = parseBackgroundPositionXY(xFound, yFound); if (currValue) valueList->next(); break; } case CSS_PROP_BACKGROUND_REPEAT: if (val->id >= CSS_VAL_REPEAT && val->id <= CSS_VAL_NO_REPEAT) { currValue = new CSSPrimitiveValueImpl(val->id); valueList->next(); } break; case CSS_PROP__KHTML_BACKGROUND_SIZE: currValue = parseBackgroundSize(); if (currValue) valueList->next(); break; } if (!currValue) goto failed; if (value && !values) { values = new CSSValueListImpl(); values->append(value); value = 0; } if (value2 && !values2) { values2 = new CSSValueListImpl(); values2->append(value2); value2 = 0; } if (values) values->append(currValue); else value = currValue; if (currValue2) { if (values2) values2->append(currValue2); else value2 = currValue2; } allowComma = true; } // When parsing the 'background' shorthand property, we let it handle building up the lists for all // properties. if (inShorthand()) break; } if (values && values->length()) { retValue1 = values; if (values2 && values2->length()) retValue2 = values2; return true; } if (value) { retValue1 = value; retValue2 = value2; return true; } failed: delete values; delete values2; delete value; delete value2; return false; } bool CSSParser::parseShape( int propId, bool important ) { Value *value = valueList->current(); ValueList *args = value->function->args; QString fname = qString( value->function->name ).toLower(); //qDebug( "parseShape: fname: %d", fname.toLatin1().constData() ); if ( fname != "rect(" || !args ) return false; // rect( t, r, b, l ) || rect( t r b l ) if ( args->size() != 4 && args->size() != 7 ) return false; RectImpl *rect = new RectImpl(); bool valid = true; int i = 0; Value *a = args->current(); while ( a ) { valid = validUnit( a, FLength, strict ); if ( !valid ) break; CSSPrimitiveValueImpl *length = new CSSPrimitiveValueImpl( a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit ); if ( i == 0 ) rect->setTop( length ); else if ( i == 1 ) rect->setRight( length ); else if ( i == 2 ) rect->setBottom( length ); else rect->setLeft( length ); a = args->next(); if ( a && args->size() == 7 ) { if ( a->unit == Value::Operator && a->iValue == ',' ) { a = args->next(); } else { valid = false; break; } } i++; } if ( valid ) { addProperty( propId, new CSSPrimitiveValueImpl( rect ), important ); valueList->next(); return true; } delete rect; return false; } // [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]? 'font-family' bool CSSParser::parseFont( bool important ) { // kDebug(6080) << "parsing font property current=" << valueList->currentValue; bool valid = true; Value *value = valueList->current(); CSSValueListImpl* family = 0; CSSPrimitiveValueImpl *style = 0, *variant = 0, *weight = 0, *size = 0, *lineHeight = 0; // optional font-style, font-variant and font-weight while ( value ) { // kDebug( 6080 ) << "got value " << value->id << " / " << (value->unit == CSSPrimitiveValue::CSS_STRING || // value->unit == CSSPrimitiveValue::CSS_IDENT ? qString( value->string ) : QString() ) // << endl; int id = value->id; if ( id ) { if ( id == CSS_VAL_NORMAL ) { // do nothing, it's the initial value for all three } /* else if ( id == CSS_VAL_INHERIT ) { // set all non set ones to inherit // This is not that simple as the inherit could also apply to the following font-size. // very ahrd to tell without looking ahead. inherit = true; } */ else if ( id == CSS_VAL_ITALIC || id == CSS_VAL_OBLIQUE ) { if ( style ) goto invalid; style = new CSSPrimitiveValueImpl( id ); } else if ( id == CSS_VAL_SMALL_CAPS ) { if ( variant ) goto invalid; variant = new CSSPrimitiveValueImpl( id ); } else if ( id >= CSS_VAL_BOLD && id <= CSS_VAL_LIGHTER ) { if ( weight ) goto invalid; weight = new CSSPrimitiveValueImpl( id ); } else { valid = false; } } else if ( !weight && validUnit( value, FInteger|FNonNeg, true ) ) { int w = (int)value->fValue; int val = 0; if ( w == 100 ) val = CSS_VAL_100; else if ( w == 200 ) val = CSS_VAL_200; else if ( w == 300 ) val = CSS_VAL_300; else if ( w == 400 ) val = CSS_VAL_400; else if ( w == 500 ) val = CSS_VAL_500; else if ( w == 600 ) val = CSS_VAL_600; else if ( w == 700 ) val = CSS_VAL_700; else if ( w == 800 ) val = CSS_VAL_800; else if ( w == 900 ) val = CSS_VAL_900; if ( val ) weight = new CSSPrimitiveValueImpl( val ); else valid = false; } else { valid = false; } if ( !valid ) break; value = valueList->next(); } if ( !value ) goto invalid; // set undefined values to default if ( !style ) style = new CSSPrimitiveValueImpl( CSS_VAL_NORMAL ); if ( !variant ) variant = new CSSPrimitiveValueImpl( CSS_VAL_NORMAL ); if ( !weight ) weight = new CSSPrimitiveValueImpl( CSS_VAL_NORMAL ); // kDebug( 6080 ) << " got style, variant and weight current=" << valueList->currentValue; // now a font size _must_ come // | | | | inherit if ( value->id >= CSS_VAL_XX_SMALL && value->id <= CSS_VAL_LARGER ) size = new CSSPrimitiveValueImpl( value->id ); else if ( validUnit( value, FLength|FPercent, strict ) ) { size = new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit ); } value = valueList->next(); if ( !size || !value ) goto invalid; // kDebug( 6080 ) << " got size"; if ( value->unit == Value::Operator && value->iValue == '/' ) { // line-height value = valueList->next(); if ( !value ) goto invalid; if ( value->id == CSS_VAL_NORMAL ) { // default value, nothing to do } else if ( validUnit( value, FNumber|FLength|FPercent, strict ) ) { lineHeight = new CSSPrimitiveValueImpl( value->fValue, (CSSPrimitiveValue::UnitTypes) value->unit ); } else { goto invalid; } value = valueList->next(); if ( !value ) goto invalid; } if ( !lineHeight ) lineHeight = new CSSPrimitiveValueImpl( CSS_VAL_NORMAL ); // kDebug( 6080 ) << " got line height current=" << valueList->currentValue; // font family must come now family = parseFontFamily(); if ( valueList->current() || !family ) goto invalid; //kDebug( 6080 ) << " got family, parsing ok!"; addProperty( CSS_PROP_FONT_FAMILY, family, important ); addProperty( CSS_PROP_FONT_STYLE, style, important ); addProperty( CSS_PROP_FONT_VARIANT, variant, important ); addProperty( CSS_PROP_FONT_WEIGHT, weight, important ); addProperty( CSS_PROP_FONT_SIZE, size, important ); addProperty( CSS_PROP_LINE_HEIGHT, lineHeight, important ); return true; invalid: //kDebug(6080) << " -> invalid"; delete family; delete style; delete variant; delete weight; delete size; delete lineHeight; return false; } CSSValueListImpl *CSSParser::parseFontFamily() { // kDebug( 6080 ) << "CSSParser::parseFontFamily current=" << valueList->currentValue; CSSValueListImpl *list = new CSSValueListImpl; Value *value = valueList->current(); QString currFace; while ( value ) { // kDebug( 6080 ) << "got value " << value->id << " / " // << (value->unit == CSSPrimitiveValue::CSS_STRING || // value->unit == CSSPrimitiveValue::CSS_IDENT ? qString( value->string ) : QString() ) // << endl; Value* nextValue = valueList->next(); bool nextValBreaksFont = !nextValue || (nextValue->unit == Value::Operator && nextValue->iValue == ','); bool nextValIsFontName = nextValue && ((nextValue->id >= CSS_VAL_SERIF && nextValue->id <= CSS_VAL_MONOSPACE) || (nextValue->unit == CSSPrimitiveValue::CSS_STRING || nextValue->unit == CSSPrimitiveValue::CSS_IDENT)); if (value->id >= CSS_VAL_SERIF && value->id <= CSS_VAL_MONOSPACE) { if (!currFace.isNull()) { currFace += ' '; currFace += qString(value->string); } else if (nextValBreaksFont || !nextValIsFontName) { if ( !currFace.isNull() ) { list->append( new FontFamilyValueImpl( currFace ) ); currFace.clear(); } list->append(new CSSPrimitiveValueImpl(value->id)); } else { currFace = qString( value->string ); } } else if (value->unit == CSSPrimitiveValue::CSS_STRING) { // Strings never share in a family name. currFace.clear(); list->append(new FontFamilyValueImpl(qString( value->string) ) ); } else if (value->unit == CSSPrimitiveValue::CSS_IDENT) { if (!currFace.isNull()) { currFace += ' '; currFace += qString(value->string); } else if (nextValBreaksFont || !nextValIsFontName) { if ( !currFace.isNull() ) { list->append( new FontFamilyValueImpl( currFace ) ); currFace.clear(); } list->append(new FontFamilyValueImpl( qString( value->string ) ) ); } else { currFace = qString( value->string); } } else { //kDebug( 6080 ) << "invalid family part"; break; } if (!nextValue) break; if (nextValBreaksFont) { value = valueList->next(); if ( !currFace.isNull() ) list->append( new FontFamilyValueImpl( currFace ) ); currFace.clear(); } else if (nextValIsFontName) value = nextValue; else break; } if ( !currFace.isNull() ) list->append( new FontFamilyValueImpl( currFace ) ); if ( !list->length() ) { delete list; list = 0; } return list; } bool CSSParser::parseColorParameters(Value* value, int* colorArray, bool parseAlpha) { ValueList* args = value->function->args; Value* v = args->current(); // Get the first value if (!validUnit(v, FInteger | FPercent, true)) return false; colorArray[0] = static_cast(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0)); for (int i = 1; i < 3; i++) { v = args->next(); if (v->unit != Value::Operator && v->iValue != ',') return false; v = args->next(); if (!validUnit(v, FInteger | FPercent, true)) return false; colorArray[i] = static_cast(v->fValue * (v->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 256.0 / 100.0 : 1.0)); } if (parseAlpha) { v = args->next(); if (v->unit != Value::Operator && v->iValue != ',') return false; v = args->next(); if (!validUnit(v, FNumber, true)) return false; colorArray[3] = static_cast(qMax(0.0, qMin(1.0, v->fValue)) * 255); } return true; } // CSS3 specification defines the format of a HSL color as // hsl(, , ) // and with alpha, the format is // hsla(, , , ) // The first value, HUE, is in an angle with a value between 0 and 360 bool CSSParser::parseHSLParameters(Value* value, double* colorArray, bool parseAlpha) { ValueList* args = value->function->args; Value* v = args->current(); // Get the first value if (!validUnit(v, FInteger, true)) return false; // normalize the Hue value and change it to be between 0 and 1.0 colorArray[0] = (((static_cast(v->fValue) % 360) + 360) % 360) / 360.0; for (int i = 1; i < 3; i++) { v = args->next(); if (v->unit != Value::Operator && v->iValue != ',') return false; v = args->next(); if (!validUnit(v, FPercent, true)) return false; colorArray[i] = qMax(0.0, qMin(100.0, v->fValue)) / 100.0; // needs to be value between 0 and 1.0 } if (parseAlpha) { v = args->next(); if (v->unit != Value::Operator && v->iValue != ',') return false; v = args->next(); if (!validUnit(v, FNumber, true)) return false; colorArray[3] = qMax(0.0, qMin(1.0, v->fValue)); } return true; } static bool parseColor(int unit, const QString &name, QRgb& rgb) { int len = name.length(); if ( !len ) return false; bool ok; if ( len == 3 || len == 6 ) { int val = name.toInt(&ok, 16); if ( ok ) { if (len == 6) { rgb = (0xff << 24) | val; return true; } else if ( len == 3 ) { // #abc converts to #aabbcc according to the specs rgb = (0xff << 24) | (val&0xf00)<<12 | (val&0xf00)<<8 | (val&0xf0)<<8 | (val&0xf0)<<4 | (val&0xf)<<4 | (val&0xf); return true; } } } if ( unit == CSSPrimitiveValue::CSS_IDENT ) { // try a little harder QColor tc; tc.setNamedColor(name.toLower()); if ( tc.isValid() ) { rgb = tc.rgba(); return true; } } return false; } //Needed by the Canvas stuff --- it needs way of using rgba(), etc., parsing as well bool CSSParser::parseColor(const QString &name, QRgb& rgb) { return ::parseColor(CSSPrimitiveValue::CSS_IDENT, name, rgb); } CSSPrimitiveValueImpl *CSSParser::parseColor() { return parseColorFromValue(valueList->current()); } CSSPrimitiveValueImpl *CSSParser::parseColorFromValue(Value* value) { QRgb c = khtml::transparentColor; if ( !strict && value->unit == CSSPrimitiveValue::CSS_NUMBER && value->fValue >= 0. && value->fValue < 1000000. ) { QString str; str.sprintf( "%06d", (int)(value->fValue+.5) ); if ( !::parseColor( value->unit, str, c ) ) return 0; } else if (value->unit == CSSPrimitiveValue::CSS_RGBCOLOR || value->unit == CSSPrimitiveValue::CSS_IDENT || (!strict && value->unit == CSSPrimitiveValue::CSS_DIMENSION)) { if ( !::parseColor( value->unit, qString( value->string ), c) ) return 0; } else if ( value->unit == Value::Function && value->function->args != 0 && value->function->args->size() == 5 /* rgb + two commas */ && qString( value->function->name ).toLower() == "rgb(" ) { int colorValues[3]; if (!parseColorParameters(value, colorValues, false)) return 0; colorValues[0] = qMax( 0, qMin( 255, colorValues[0] ) ); colorValues[1] = qMax( 0, qMin( 255, colorValues[1] ) ); colorValues[2] = qMax( 0, qMin( 255, colorValues[2] ) ); c = qRgb(colorValues[0], colorValues[1], colorValues[2]); } else if (value->unit == Value::Function && value->function->args != 0 && value->function->args->size() == 7 /* rgba + three commas */ && domString(value->function->name).lower() == "rgba(") { int colorValues[4]; if (!parseColorParameters(value, colorValues, true)) return 0; colorValues[0] = qMax( 0, qMin( 255, colorValues[0] ) ); colorValues[1] = qMax( 0, qMin( 255, colorValues[1] ) ); colorValues[2] = qMax( 0, qMin( 255, colorValues[2] ) ); c = qRgba(colorValues[0], colorValues[1], colorValues[2], colorValues[3]); } else if (value->unit == Value::Function && value->function->args != 0 && value->function->args->size() == 5 /* hsl + two commas */ && domString(value->function->name).lower() == "hsl(") { double colorValues[3]; if (!parseHSLParameters(value, colorValues, false)) return 0; c = khtml::qRgbaFromHsla(colorValues[0], colorValues[1], colorValues[2], 1.0); } else if (value->unit == Value::Function && value->function->args != 0 && value->function->args->size() == 7 /* hsla + three commas */ && domString(value->function->name).lower() == "hsla(") { double colorValues[4]; if (!parseHSLParameters(value, colorValues, true)) return 0; c = khtml::qRgbaFromHsla(colorValues[0], colorValues[1], colorValues[2], colorValues[3]); } else return 0; return new CSSPrimitiveValueImpl(c); } // This class tracks parsing state for shadow values. If it goes out of scope (e.g., due to an early return) // without the allowBreak bit being set, then it will clean up all of the objects and destroy them. struct ShadowParseContext { ShadowParseContext() :values(0), x(0), y(0), blur(0), color(0), allowX(true), allowY(false), allowBlur(false), allowColor(true), allowBreak(true) {} ~ShadowParseContext() { if (!allowBreak) { delete values; delete x; delete y; delete blur; delete color; } } bool allowLength() { return allowX || allowY || allowBlur; } bool failed() { return allowBreak = false; } void commitValue() { // Handle the ,, case gracefully by doing nothing. if (x || y || blur || color) { if (!values) values = new CSSValueListImpl(); // Construct the current shadow value and add it to the list. values->append(new ShadowValueImpl(x, y, blur, color)); } // Now reset for the next shadow value. x = y = blur = color = 0; allowX = allowColor = allowBreak = true; allowY = allowBlur = false; } void commitLength(Value* v) { CSSPrimitiveValueImpl* val = new CSSPrimitiveValueImpl(v->fValue, (CSSPrimitiveValue::UnitTypes)v->unit); if (allowX) { x = val; allowX = false; allowY = true; allowColor = false; allowBreak = false; } else if (allowY) { y = val; allowY = false; allowBlur = true; allowColor = true; allowBreak = true; } else if (allowBlur) { blur = val; allowBlur = false; } else delete val; } void commitColor(CSSPrimitiveValueImpl* val) { color = val; allowColor = false; if (allowX) allowBreak = false; else allowBlur = false; } CSSValueListImpl* values; CSSPrimitiveValueImpl* x; CSSPrimitiveValueImpl* y; CSSPrimitiveValueImpl* blur; CSSPrimitiveValueImpl* color; bool allowX; bool allowY; bool allowBlur; bool allowColor; bool allowBreak; }; bool CSSParser::parseShadow(int propId, bool important) { ShadowParseContext context; Value* val; while ((val = valueList->current())) { // Check for a comma break first. if (val->unit == Value::Operator) { if (val->iValue != ',' || !context.allowBreak) // Other operators aren't legal or we aren't done with the current shadow // value. Treat as invalid. return context.failed(); // The value is good. Commit it. context.commitValue(); } // Check to see if we're a length. else if (validUnit(val, FLength, true)) { // We required a length and didn't get one. Invalid. if (!context.allowLength()) return context.failed(); // A length is allowed here. Construct the value and add it. context.commitLength(val); } else { // The only other type of value that's ok is a color value. CSSPrimitiveValueImpl* parsedColor = 0; bool isColor = (val->id >= CSS_VAL_AQUA && val->id <= CSS_VAL_WINDOWTEXT || val->id == CSS_VAL_MENU || (val->id >= CSS_VAL_GREY && val->id <= CSS_VAL__KHTML_TEXT && !strict)); if (!context.allowColor) return context.failed(); if (isColor) parsedColor = new CSSPrimitiveValueImpl(val->id); if (!parsedColor) // It's not built-in. Try to parse it as a color. parsedColor = parseColorFromValue(val); if (!parsedColor) return context.failed(); context.commitColor(parsedColor); } valueList->next(); } if (context.allowBreak) { context.commitValue(); if (context.values->length()) { addProperty(propId, context.values, important); valueList->next(); return true; } } return context.failed(); } bool CSSParser::parseCounter(int propId, bool increment, bool important) { enum { ID, VAL, COMMA } state = ID; CSSValueListImpl *list = new CSSValueListImpl; DOMString c; Value* val; while (true) { val = valueList->current(); switch (state) { // Commas are not allowed according to the standard, but Opera allows them and being the only // other browser with counter support we need to match their behavior to work with current use case COMMA: state = ID; if (val && val->unit == Value::Operator && val->iValue == ',') { valueList->next(); continue; } // no break case ID: if (val && val->unit == CSSPrimitiveValue::CSS_IDENT) { c = qString(val->string); state = VAL; valueList->next(); continue; } break; case VAL: { short i = 0; if (val && val->unit == CSSPrimitiveValue::CSS_NUMBER) { i = (short)val->fValue; valueList->next(); } else i = (increment) ? 1 : 0; CounterActImpl *cv = new CounterActImpl(c,i); list->append(cv); state = COMMA; continue; } } break; } if(list->length() > 0) { addProperty( propId, list, important ); return true; } delete list; return false; } static inline int yyerror( const char *str ) { // assert( 0 ); #ifdef CSS_DEBUG kDebug( 6080 ) << "CSS parse error " << str; #else Q_UNUSED( str ); #endif return 1; } #define END 0 #include "parser.h" int DOM::CSSParser::lex( void *_yylval ) { YYSTYPE *yylval = (YYSTYPE *)_yylval; int token = lex(); int length; unsigned short *t = text( &length ); #ifdef TOKEN_DEBUG qDebug("CSSTokenizer: got token %d: '%s'", token, token == END ? "" : QString( (QChar *)t, length ).toLatin1().constData() ); #endif switch( token ) { case '{': block_nesting++; break; case '}': if ( block_nesting ) block_nesting--; break; case END: if ( block_nesting ) { block_nesting--; return '}'; } break; case S: case SGML_CD: case INCLUDES: case DASHMATCH: break; case URI: case STRING: case IDENT: case NTH: case HASH: case DIMEN: case UNICODERANGE: case NOTFUNCTION: case FUNCTION: yylval->string.string = t; yylval->string.length = length; break; case IMPORT_SYM: case PAGE_SYM: case MEDIA_SYM: case FONT_FACE_SYM: case CHARSET_SYM: case NAMESPACE_SYM: case IMPORTANT_SYM: break; case QEMS: length--; case GRADS: length--; case DEGS: case RADS: case KHERZ: length--; case MSECS: case HERZ: case EMS: case EXS: case PXS: case CMS: case MMS: case INS: case PTS: case PCS: length--; case SECS: case PERCENTAGE: length--; case FLOAT: case INTEGER: yylval->val = QString( (QChar *)t, length ).toDouble(); //qDebug("value = %s, converted=%.2f", QString( (QChar *)t, length ).toLatin1().constData(), yylval->val ); break; default: break; } return token; } static inline int toHex( char c ) { if ( '0' <= c && c <= '9' ) return c - '0'; if ( 'a' <= c && c <= 'f' ) return c - 'a' + 10; if ( 'A' <= c && c<= 'F' ) return c - 'A' + 10; return 0; } unsigned short *DOM::CSSParser::text(int *length) { unsigned short *start = yytext; int l = yyleng; switch( yyTok ) { case STRING: l--; /* nobreak */ case HASH: start++; l--; break; case URI: // "url("{w}{string}{w}")" // "url("{w}{url}{w}")" // strip "url(" and ")" start += 4; l -= 5; // strip {w} while ( l && (*start == ' ' || *start == '\t' || *start == '\r' || *start == '\n' || *start == '\f' ) ) { start++; l--; } if ( *start == '"' || *start == '\'' ) { start++; l--; } while ( l && (start[l-1] == ' ' || start[l-1] == '\t' || start[l-1] == '\r' || start[l-1] == '\n' || start[l-1] == '\f' ) ) { l--; } if ( l && (start[l-1] == '\"' || start[l-1] == '\'' ) ) l--; default: break; } // process escapes unsigned short *out = start; unsigned short *escape = 0; for ( int i = 0; i < l; i++ ) { unsigned short *current = start+i; if ( escape == current - 1 ) { if ( ( *current >= '0' && *current <= '9' ) || ( *current >= 'a' && *current <= 'f' ) || ( *current >= 'A' && *current <= 'F' ) ) continue; if ( yyTok == STRING && ( *current == '\n' || *current == '\r' || *current == '\f' ) ) { // ### handle \r\n case if ( *current != '\r' ) escape = 0; continue; } // in all other cases copy the char to output // ### *out++ = *current; escape = 0; continue; } if ( escape == current - 2 && yyTok == STRING && *(current-1) == '\r' && *current == '\n' ) { escape = 0; continue; } if ( escape > current - 7 && ( ( *current >= '0' && *current <= '9' ) || ( *current >= 'a' && *current <= 'f' ) || ( *current >= 'A' && *current <= 'F' ) ) ) continue; if ( escape ) { // add escaped char int uc = 0; escape++; while ( escape < current ) { // qDebug("toHex( %c = %x", (char)*escape, toHex( *escape ) ); uc *= 16; uc += toHex( *escape ); escape++; } // qDebug(" converting escape: string='%s', value=0x%x", QString( (QChar *)e, current-e ).toLatin1().constData(), uc ); // can't handle chars outside utf16 if ( uc > 0xffff ) uc = 0xfffd; *(out++) = (unsigned short)uc; escape = 0; if ( *current == ' ' || *current == '\t' || *current == '\r' || *current == '\n' || *current == '\f' ) continue; } if ( !escape && *current == '\\' ) { escape = current; continue; } *(out++) = *current; } if ( escape ) { // add escaped char int uc = 0; escape++; while ( escape < start+l ) { // qDebug("toHex( %c = %x", (char)*escape, toHex( *escape ) ); uc *= 16; uc += toHex( *escape ); escape++; } // qDebug(" converting escape: string='%s', value=0x%x", QString( (QChar *)e, current-e ).toLatin1().constData(), uc ); // can't handle chars outside utf16 if ( uc > 0xffff ) uc = 0xfffd; *(out++) = (unsigned short)uc; } *length = out - start; return start; } #define YY_DECL int DOM::CSSParser::lex() #define yyconst const typedef int yy_state_type; typedef unsigned int YY_CHAR; // this line makes sure we treat all Unicode chars correctly. #define YY_SC_TO_UI(c) (c > 0xff ? 0xff : c) #define YY_DO_BEFORE_ACTION \ yytext = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yy_hold_char = *yy_cp; \ *yy_cp = 0; \ yy_c_buf_p = yy_cp; #define YY_BREAK break; #define ECHO qDebug( "%s", QString( (QChar *)yytext, yyleng ).toLatin1().constData() ) #define YY_RULE_SETUP #define INITIAL 0 #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) #define YY_START ((yy_start - 1) / 2) #define yyterminate() yyTok = END; return yyTok #define YY_FATAL_ERROR(a) qFatal(a) #define BEGIN yy_start = 1 + 2 * #define COMMENT 1 #include "tokenizer.cpp" diff --git a/khtml/css/cssstyleselector.cpp b/khtml/css/cssstyleselector.cpp index 694e91230b..335e0c810c 100644 --- a/khtml/css/cssstyleselector.cpp +++ b/khtml/css/cssstyleselector.cpp @@ -1,4123 +1,4131 @@ /** * This file is part of the CSS implementation for KDE. * * Copyright 1999-2003 Lars Knoll (knoll@kde.org) * Copyright 2003-2004 Apple Computer, Inc. * Copyright 2004-2006 Allan Sandfeld Jensen (kde@carewolf.com) * Copyright 2004 Germain Garand (germain@ebooksfrance.org) * (C) 2005, 2006 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. */ #include "css/cssstyleselector.h" #include "rendering/render_style.h" #include "css/css_stylesheetimpl.h" #include "css/css_ruleimpl.h" #include "css/css_valueimpl.h" #include "css/csshelper.h" #include "rendering/render_object.h" #include "html/html_documentimpl.h" #include "html/html_elementimpl.h" #include "xml/dom_elementimpl.h" #include "xml/dom_restyler.h" #include "dom/css_rule.h" #include "dom/css_value.h" #include "khtml_global.h" #include "khtmlpart_p.h" using namespace khtml; using namespace DOM; #include "css/cssproperties.h" #include "css/cssvalues.h" #include "misc/khtmllayout.h" #include "khtml_settings.h" #include "misc/htmlhashes.h" #include "misc/helper.h" #include "misc/loader.h" #include "rendering/font.h" #include "khtmlview.h" #include "khtml_part.h" #include #include #include #include #include #include #include #include #include #include #undef RELATIVE #undef ABSOLUTE // handle value "inherit" on a default inherited property #define HANDLE_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) \ if (isInherit) \ {\ style->set##Prop(parentStyle->prop());\ return;\ } // handle value "inherit" on a default non-inherited property #define HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \ if (isInherit) \ {\ style->setInheritedNoninherited(true);\ style->set##Prop(parentStyle->prop());\ return;\ } #define HANDLE_INITIAL(prop, Prop) \ if (isInitial) \ {\ style->set##Prop(RenderStyle::initial##Prop());\ return;\ } #define HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \ HANDLE_INITIAL(prop, Prop) \ else \ HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) #define HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) \ HANDLE_INITIAL(prop, Prop) \ else \ HANDLE_INHERIT_ON_INHERITED_PROPERTY(prop, Prop) // all non-inherited properties #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \ HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(prop, Prop) \ else if (isInitial) \ {\ style->set##Prop(RenderStyle::initial##Value());\ return;\ } #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \ if (isInherit) { \ BackgroundLayer* currChild = style->accessBackgroundLayers(); \ BackgroundLayer* prevChild = 0; \ const BackgroundLayer* currParent = parentStyle->backgroundLayers(); \ while (currParent && currParent->is##Prop##Set()) { \ if (!currChild) { \ /* Need to make a new layer.*/ \ currChild = new BackgroundLayer(); \ prevChild->setNext(currChild); \ } \ currChild->set##Prop(currParent->prop()); \ prevChild = currChild; \ currChild = prevChild->next(); \ currParent = currParent->next(); \ } \ \ while (currChild) { \ /* Reset any remaining layers to not have the property set. */ \ currChild->clear##Prop(); \ currChild = currChild->next(); \ } \ return; \ } \ if (isInitial) { \ BackgroundLayer* currChild = style->accessBackgroundLayers(); \ currChild->set##Prop(RenderStyle::initial##Prop()); \ for (currChild = currChild->next(); currChild; currChild = currChild->next()) \ currChild->clear##Prop(); \ return; \ } #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) { \ HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \ if (!value->isPrimitiveValue() && !value->isValueList()) \ return; \ BackgroundLayer* currChild = style->accessBackgroundLayers(); \ BackgroundLayer* prevChild = 0; \ if (value->isPrimitiveValue()) { \ map##Prop(currChild, value); \ currChild = currChild->next(); \ } \ else { \ /* Walk each value and put it into a layer, creating new layers as needed. */ \ CSSValueListImpl* valueList = static_cast(value); \ for (unsigned int i = 0; i < valueList->length(); i++) { \ if (!currChild) { \ /* Need to make a new layer to hold this value */ \ currChild = new BackgroundLayer(); \ prevChild->setNext(currChild); \ } \ map##Prop(currChild, valueList->item(i)); \ prevChild = currChild; \ currChild = currChild->next(); \ } \ } \ while (currChild) { \ /* Reset all remaining layers to not have the property set. */ \ currChild->clear##Prop(); \ currChild = currChild->next(); \ } } #define HANDLE_INHERIT_COND(propID, prop, Prop) \ if (id == propID) \ {\ style->set##Prop(parentStyle->prop());\ return;\ } #define HANDLE_INITIAL_COND(propID, Prop) \ if (id == propID) \ {\ style->set##Prop(RenderStyle::initial##Prop());\ return;\ } #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \ if (id == propID) \ {\ style->set##Prop(RenderStyle::initial##Value());\ return;\ } namespace khtml { CSSStyleSelectorList *CSSStyleSelector::s_defaultStyle; CSSStyleSelectorList *CSSStyleSelector::s_defaultQuirksStyle; CSSStyleSelectorList *CSSStyleSelector::s_defaultNonCSSHintsStyle; CSSStyleSelectorList *CSSStyleSelector::s_defaultPrintStyle; CSSStyleSheetImpl *CSSStyleSelector::s_defaultSheet; CSSStyleSheetImpl *CSSStyleSelector::s_defaultNonCSSHintsSheet; RenderStyle* CSSStyleSelector::styleNotYetAvailable; CSSStyleSheetImpl *CSSStyleSelector::s_quirksSheet; enum PseudoState { PseudoUnknown, PseudoNone, PseudoLink, PseudoVisited}; static PseudoState pseudoState; CSSStyleSelector::CSSStyleSelector( DocumentImpl* doc, QString userStyleSheet, StyleSheetListImpl *styleSheets, const KUrl &url, bool _strictParsing ) { KHTMLView* view = doc->view(); init(view ? view->part()->settings() : 0, doc); strictParsing = _strictParsing; m_medium = view ? view->mediaType() : QString("all"); selectors = 0; selectorCache = 0; properties = 0; userStyle = 0; userSheet = 0; logicalDpiY = doc->logicalDpiY(); if(logicalDpiY) // this may be null, not everyone uses khtmlview (Niko) computeFontSizes(logicalDpiY, view ? view->part()->fontScaleFactor() : 100); if ( !userStyleSheet.isEmpty() ) { userSheet = new DOM::CSSStyleSheetImpl(doc); userSheet->parseString( DOMString( userStyleSheet ) ); userStyle = new CSSStyleSelectorList(); userStyle->append( userSheet, m_medium ); } // add stylesheets from document authorStyle = 0; implicitStyle = 0; foreach (StyleSheetImpl* sh, styleSheets->styleSheets) { if ( sh->isCSSStyleSheet() ) { if ( static_cast(sh)->implicit() ) { if (!implicitStyle) implicitStyle = new CSSStyleSelectorList(); implicitStyle->append( static_cast( sh ), m_medium ); } else if ( sh->isCSSStyleSheet() && !sh->disabled()) { if (!authorStyle) authorStyle = new CSSStyleSelectorList(); authorStyle->append( static_cast( sh ), m_medium ); } } } buildLists(); //kDebug( 6080 ) << "number of style sheets in document " << authorStyleSheets.count(); //kDebug( 6080 ) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements"; KUrl u = url; u.setQuery( QString() ); u.setRef( QString() ); encodedurl.file = u.url(); int pos = encodedurl.file.lastIndexOf('/'); encodedurl.path = encodedurl.file; if ( pos > 0 ) { encodedurl.path.truncate( pos ); encodedurl.path += '/'; } u.setPath( QString() ); encodedurl.host = u.url(); //kDebug() << "CSSStyleSelector::CSSStyleSelector encoded url " << encodedurl.path; } CSSStyleSelector::CSSStyleSelector( CSSStyleSheetImpl *sheet ) { init(0L, 0L); KHTMLView *view = sheet->doc()->view(); m_medium = view ? view->mediaType() : "screen"; if (sheet->implicit()) { implicitStyle = new CSSStyleSelectorList(); implicitStyle->append( sheet, m_medium ); } else { authorStyle = new CSSStyleSelectorList(); authorStyle->append( sheet, m_medium ); } } void CSSStyleSelector::init(const KHTMLSettings* _settings, DocumentImpl* doc) { element = 0; settings = _settings; logicalDpiY = 0; propsToApply = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *)); pseudoProps = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *)); propsToApplySize = 128; pseudoPropsSize = 128; if(!s_defaultStyle) loadDefaultStyle(settings, doc); defaultStyle = s_defaultStyle; defaultPrintStyle = s_defaultPrintStyle; defaultQuirksStyle = s_defaultQuirksStyle; defaultNonCSSHintsStyle = s_defaultNonCSSHintsStyle; } CSSStyleSelector::~CSSStyleSelector() { clearLists(); delete authorStyle; delete implicitStyle; delete userStyle; delete userSheet; free(propsToApply); free(pseudoProps); } void CSSStyleSelector::addSheet( CSSStyleSheetImpl *sheet ) { KHTMLView *view = sheet->doc()->view(); m_medium = view ? view->mediaType() : "screen"; if (sheet->implicit()) { if (!implicitStyle) implicitStyle = new CSSStyleSelectorList(); implicitStyle->append( sheet, m_medium ); } else { if (!authorStyle) authorStyle = new CSSStyleSelectorList(); authorStyle->append( sheet, m_medium ); } } void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s, DocumentImpl *doc) { if(s_defaultStyle) return; { QFile f(KStandardDirs::locate( "data", "khtml/css/html4.css" ) ); f.open(QIODevice::ReadOnly); QByteArray file( f.size()+1, 0 ); int readbytes = f.read( file.data(), f.size() ); f.close(); if ( readbytes >= 0 ) file[readbytes] = '\0'; QString style = QLatin1String( file.data() ); if(s) style += s->settingsToCSS(); DOMString str(style); s_defaultSheet = new DOM::CSSStyleSheetImpl(doc); s_defaultSheet->parseString( str ); // Collect only strict-mode rules. s_defaultStyle = new CSSStyleSelectorList(); s_defaultStyle->append( s_defaultSheet, "screen" ); s_defaultPrintStyle = new CSSStyleSelectorList(); s_defaultPrintStyle->append( s_defaultSheet, "print" ); } { QFile f(KStandardDirs::locate( "data", "khtml/css/quirks.css" ) ); f.open(QIODevice::ReadOnly); QByteArray file( f.size()+1, 0 ); int readbytes = f.read( file.data(), f.size() ); f.close(); if ( readbytes >= 0 ) file[readbytes] = '\0'; QString style = QLatin1String( file.data() ); DOMString str(style); s_quirksSheet = new DOM::CSSStyleSheetImpl(doc); s_quirksSheet->parseString( str ); // Collect only quirks-mode rules. s_defaultQuirksStyle = new CSSStyleSelectorList(); s_defaultQuirksStyle->append( s_quirksSheet, "screen" ); } { QFile f(KStandardDirs::locate( "data", "khtml/css/presentational.css" ) ); f.open(QIODevice::ReadOnly); QByteArray file( f.size()+1, 0 ); int readbytes = f.read( file.data(), f.size() ); f.close(); if ( readbytes >= 0 ) file[readbytes] = '\0'; QString style = QLatin1String( file.data() ); DOMString str(style); s_defaultNonCSSHintsSheet = new DOM::CSSStyleSheetImpl(doc); s_defaultNonCSSHintsSheet->parseString( str ); s_defaultNonCSSHintsStyle = new CSSStyleSelectorList(); s_defaultNonCSSHintsStyle->append( s_defaultNonCSSHintsSheet, "screen" ); } //kDebug() << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements"; } void CSSStyleSelector::clear() { delete s_defaultStyle; delete s_defaultQuirksStyle; delete s_defaultPrintStyle; delete s_defaultNonCSSHintsStyle; delete s_defaultSheet; delete s_defaultNonCSSHintsSheet; delete styleNotYetAvailable; s_defaultStyle = 0; s_defaultQuirksStyle = 0; s_defaultPrintStyle = 0; s_defaultNonCSSHintsStyle = 0; s_defaultSheet = 0; s_defaultNonCSSHintsSheet = 0; styleNotYetAvailable = 0; } void CSSStyleSelector::reparseConfiguration() { // nice leak, but best we can do right now. hopefully its only rare. s_defaultStyle = 0; s_defaultQuirksStyle = 0; s_defaultPrintStyle = 0; s_defaultNonCSSHintsStyle = 0; s_defaultSheet = 0; } #define MAXFONTSIZES 8 void CSSStyleSelector::computeFontSizes(int logicalDpiY, int zoomFactor) { computeFontSizesFor(logicalDpiY, zoomFactor, m_fontSizes, false); computeFontSizesFor(logicalDpiY, zoomFactor, m_fixedFontSizes, true); } void CSSStyleSelector::computeFontSizesFor(int logicalDpiY, int zoomFactor, QVector& fontSizes, bool isFixed) { #ifdef APPLE_CHANGES // We don't want to scale the settings by the dpi. const float toPix = 1.0; #else Q_UNUSED( isFixed ); // ### get rid of float / double float toPix = logicalDpiY/72.0f; if (toPix < 96.0f/72.0f) toPix = 96.0f/72.0f; #endif // ######### fix isFixed code again. fontSizes.resize( MAXFONTSIZES ); float scale = 1.0; static const float fontFactors[] = {3.0f/5.0f, 3.0f/4.0f, 8.0f/9.0f, 1.0f, 6.0f/5.0f, 3.0f/2.0f, 2.0f, 3.0f}; static const float smallFontFactors[] = {3.0f/4.0f, 5.0f/6.0f, 8.0f/9.0f, 1.0f, 6.0f/5.0f, 3.0f/2.0f, 2.0f, 3.0f}; float mediumFontSize, minFontSize, factor; if (!khtml::printpainter) { scale *= zoomFactor / 100.0; #ifdef APPLE_CHANGES if (isFixed) mediumFontSize = settings->mediumFixedFontSize() * toPix; else #endif mediumFontSize = settings->mediumFontSize() * toPix; minFontSize = settings->minFontSize() * toPix; } else { // ### depending on something / configurable ? mediumFontSize = 12; minFontSize = 6; } const float* factors = scale*mediumFontSize >= 12.5 ? fontFactors : smallFontFactors; for ( int i = 0; i < MAXFONTSIZES; i++ ) { factor = scale*factors[i]; fontSizes[i] = int(qMax( mediumFontSize*factor +.5f, minFontSize)); //kDebug( 6080 ) << "index: " << i << " factor: " << factors[i] << " font pix size: " << int(qMax( mediumFontSize*factor +.5f, minFontSize)); } } #undef MAXFONTSIZES static inline void bubbleSort( CSSOrderedProperty **b, CSSOrderedProperty **e ) { while( b < e ) { bool swapped = false; CSSOrderedProperty **y = e+1; CSSOrderedProperty **x = e; CSSOrderedProperty **swappedPos = 0; do { if ( !((**(--x)) < (**(--y))) ) { swapped = true; swappedPos = x; CSSOrderedProperty *tmp = *y; *y = *x; *x = tmp; } } while( x != b ); if ( !swapped ) break; b = swappedPos + 1; } } RenderStyle *CSSStyleSelector::styleForElement(ElementImpl *e) { if (!e->getDocument()->haveStylesheetsLoaded() || !e->getDocument()->view()) { if (!styleNotYetAvailable) { styleNotYetAvailable = new RenderStyle(); styleNotYetAvailable->setDisplay(NONE); styleNotYetAvailable->ref(); } return styleNotYetAvailable; } // set some variables we will need pseudoState = PseudoUnknown; element = e; parentNode = e->parentNode(); parentStyle = ( parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0; view = element->getDocument()->view(); part = view->part(); settings = part->settings(); logicalDpiY = element->getDocument()->logicalDpiY(); // reset dynamic DOM dependencies e->getDocument()->dynamicDomRestyler().resetDependencies(e); style = new RenderStyle(); if( parentStyle ) style->inheritFrom( parentStyle ); else parentStyle = style; unsigned int numPropsToApply = 0; unsigned int numPseudoProps = 0; // try to sort out most style rules as early as possible. quint16 cssTagId = localNamePart(element->id()); int smatch = 0; int schecked = 0; for ( unsigned int i = 0; i < selectors_size; i++ ) { quint16 tag = localNamePart(selectors[i]->tag); if ( cssTagId == tag || tag == anyLocalName ) { ++schecked; checkSelector( i, e ); if ( selectorCache[i].state == Applies ) { ++smatch; // qDebug("adding property" ); for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 ) for ( unsigned int j = 0; j < (unsigned int )selectorCache[i].props[p+1]; ++j ) { if (numPropsToApply >= propsToApplySize ) { propsToApplySize *= 2; propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) ); } propsToApply[numPropsToApply++] = properties[selectorCache[i].props[p]+j]; } } else if ( selectorCache[i].state == AppliesPseudo ) { for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 ) for ( unsigned int j = 0; j < (unsigned int) selectorCache[i].props[p+1]; ++j ) { if (numPseudoProps >= pseudoPropsSize ) { pseudoPropsSize *= 2; pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, pseudoPropsSize*sizeof( CSSOrderedProperty * ) ); } pseudoProps[numPseudoProps++] = properties[selectorCache[i].props[p]+j]; properties[selectorCache[i].props[p]+j]->pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId; } } } else selectorCache[i].state = Invalid; } // Inline style declarations, after all others. // Non-css hints from presentational attributes will also be collected here // receiving the proper priority so has to cascade from before author rules (cf.CSS 2.1-6.4.4). numPropsToApply = addInlineDeclarations( e, numPropsToApply ); // qDebug( "styleForElement( %s )", e->tagName().string().toLatin1().constData() ); // qDebug( "%d selectors, %d checked, %d match, %d properties ( of %d )", // selectors_size, schecked, smatch, numPropsToApply, properties_size ); bubbleSort( propsToApply, propsToApply+numPropsToApply-1 ); bubbleSort( pseudoProps, pseudoProps+numPseudoProps-1 ); // we can't apply style rules without a view() and a part. This // tends to happen on delayed destruction of widget Renderobjects if ( part ) { fontDirty = false; if (numPropsToApply ) { CSSStyleSelector::style = style; for (unsigned int i = 0; i < numPropsToApply; ++i) { if ( fontDirty && propsToApply[i]->priority >= (1 << 30) ) { // we are past the font properties, time to update to the // correct font #ifdef APPLE_CHANGES checkForGenericFamilyChange(style, parentStyle); #endif CSSStyleSelector::style->htmlFont().update( logicalDpiY ); fontDirty = false; } DOM::CSSProperty *prop = propsToApply[i]->prop; // if (prop->m_id == CSS_PROP__KONQ_USER_INPUT) kDebug(6080) << "El: "<nodeName().string() << " user-input: "<<((CSSPrimitiveValueImpl *)prop->value())->getIdent(); // if (prop->m_id == CSS_PROP_TEXT_TRANSFORM) kDebug(6080) << "El: "<nodeName().string(); applyRule( prop->m_id, prop->value() ); } if ( fontDirty ) { #ifdef APPLE_CHANGES checkForGenericFamilyChange(style, parentStyle); #endif CSSStyleSelector::style->htmlFont().update( logicalDpiY ); } } // Clean up our style object's display and text decorations (among other fixups). adjustRenderStyle(style, e); if ( numPseudoProps ) { fontDirty = false; //qDebug("%d applying %d pseudo props", e->cssTagId(), pseudoProps->count() ); for (unsigned int i = 0; i < numPseudoProps; ++i) { if ( fontDirty && pseudoProps[i]->priority >= (1 << 30) ) { // we are past the font properties, time to update to the // correct font //We have to do this for all pseudo styles RenderStyle *pseudoStyle = style->pseudoStyle; while ( pseudoStyle ) { pseudoStyle->htmlFont().update( logicalDpiY ); pseudoStyle = pseudoStyle->pseudoStyle; } fontDirty = false; } RenderStyle *pseudoStyle; pseudoStyle = style->getPseudoStyle(pseudoProps[i]->pseudoId); if (!pseudoStyle) { pseudoStyle = style->addPseudoStyle(pseudoProps[i]->pseudoId); if (pseudoStyle) pseudoStyle->inheritFrom( style ); } RenderStyle* oldStyle = style; RenderStyle* oldParentStyle = parentStyle; parentStyle = style; style = pseudoStyle; if ( pseudoStyle ) { DOM::CSSProperty *prop = pseudoProps[i]->prop; applyRule( prop->m_id, prop->value() ); } style = oldStyle; parentStyle = oldParentStyle; } if ( fontDirty ) { RenderStyle *pseudoStyle = style->pseudoStyle; while ( pseudoStyle ) { pseudoStyle->htmlFont().update( logicalDpiY ); pseudoStyle = pseudoStyle->pseudoStyle; } } } } // Now adjust all our pseudo-styles. RenderStyle *pseudoStyle = style->pseudoStyle; while (pseudoStyle) { adjustRenderStyle(pseudoStyle, 0); pseudoStyle = pseudoStyle->pseudoStyle; } // Now return the style. return style; } void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e) { // Cache our original display. style->setOriginalDisplay(style->display()); if (style->display() != NONE) { // If we have a that specifies a float property, in quirks mode we just drop the float // property. // Sites also commonly use display:inline/block on s and s. In quirks mode we force // these tags to retain their display types. if (!strictParsing && e) { if (e->id() == ID_TD) { style->setDisplay(TABLE_CELL); style->setFloating(FNONE); } else if (e->id() == ID_TABLE) style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE); } // Table headers with a text-align of auto will change the text-align to center. if (e && e->id() == ID_TH && style->textAlign() == TAAUTO) style->setTextAlign(CENTER); // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to // position or float an inline, compact, or run-in. Cache the original display, since it // may be needed for positioned elements that have to compute their static normal flow // positions. We also force inline-level roots to be block-level. if (style->display() != BLOCK && style->display() != TABLE /*&& style->display() != BOX*/ && (style->position() == ABSOLUTE || style->position() == FIXED || style->floating() != FNONE || (e && e->getDocument()->documentElement() == e))) { if (style->display() == INLINE_TABLE) style->setDisplay(TABLE); // else if (style->display() == INLINE_BOX) // style->setDisplay(BOX); else if (style->display() == LIST_ITEM) { // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, // but only in quirks mode. if (!strictParsing && style->floating() != FNONE) style->setDisplay(BLOCK); } else style->setDisplay(BLOCK); } // After performing the display mutation, check our position. We do not honor position:relative on // table rows and some other table displays. This is undefined behaviour in CSS2.1 (cf. 9.3.1) if (style->position() == RELATIVE) { switch (style->display()) { case TABLE_ROW_GROUP: case TABLE_HEADER_GROUP: case TABLE_FOOTER_GROUP: case TABLE_ROW: style->setPosition(STATIC); default: break; } } } // Frames and framesets never honor position:relative or position:absolute. This is necessary to // fix a crash where a site tries to position these objects. if ( e ) { // ignore display: none for if ( e->id() == ID_FRAME ) { style->setPosition( STATIC ); style->setDisplay( BLOCK ); } else if ( e->id() == ID_FRAMESET ) { style->setPosition( STATIC ); } } // Finally update our text decorations in effect, but don't allow text-decoration to percolate through // tables, inline blocks, inline tables, or run-ins. if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN || style->display() == INLINE_BLOCK /*|| style->display() == INLINE_BOX*/) style->setTextDecorationsInEffect(style->textDecoration()); else style->addToTextDecorationsInEffect(style->textDecoration()); // If either overflow value is not visible, change to auto. if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE) style->setOverflowY(OMARQUEE); else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE) style->setOverflowX(OMARQUEE); else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) style->setOverflowX(OAUTO); else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE) style->setOverflowY(OAUTO); // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto. // FIXME: Eventually table sections will support auto and scroll. if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) { if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN) style->setOverflowX(OVISIBLE); if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN) style->setOverflowY(OVISIBLE); } // Cull out any useless layers and also repeat patterns into additional layers. style->adjustBackgroundLayers(); // Only use slow repaints if we actually have a background image. // FIXME: We only need to invalidate the fixed regions when scrolling. It's total overkill to // prevent the entire view from blitting on a scroll. if (style->hasFixedBackgroundImage() && view) view->setHasStaticBackground(); } unsigned int CSSStyleSelector::addInlineDeclarations(DOM::ElementImpl* e, unsigned int numProps) { CSSStyleDeclarationImpl* inlineDecls = e->inlineStyleDecls(); CSSStyleDeclarationImpl* nonCSSDecls = e->nonCSSStyleDecls(); if (!inlineDecls && !nonCSSDecls) return numProps; QList* values = inlineDecls ? inlineDecls->values() : 0; QList* nonCSSValues = nonCSSDecls ? nonCSSDecls->values() : 0; if (!values && !nonCSSValues) return numProps; int firstLen = values ? values->count() : 0; int secondLen = nonCSSValues ? nonCSSValues->count() : 0; uint totalLen = firstLen + secondLen; if ((unsigned)inlineProps.size() < totalLen) { inlineProps.resize(totalLen + 1); } if (numProps + totalLen >= propsToApplySize ) { propsToApplySize += propsToApplySize; propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) ); } bool inNonCSSDecls = false; CSSOrderedProperty *array = (CSSOrderedProperty *)inlineProps.data(); for(int i = 0; i < (int)totalLen; i++) { if (i == firstLen) { values = nonCSSValues; inNonCSSDecls = true; } CSSProperty *prop = values->at(i >= firstLen ? i - firstLen : i); Source source = Inline; if( prop->m_important ) source = InlineImportant; if( inNonCSSDecls ) source = NonCSSHint; bool first; // give special priority to font-xxx, color properties switch(prop->m_id) { case CSS_PROP_FONT_STYLE: case CSS_PROP_FONT_SIZE: case CSS_PROP_FONT_WEIGHT: case CSS_PROP_FONT_FAMILY: case CSS_PROP_FONT_VARIANT: case CSS_PROP_FONT: case CSS_PROP_COLOR: case CSS_PROP_DIRECTION: case CSS_PROP_DISPLAY: // these have to be applied first, because other properties use the computed // values of these properties. first = true; break; default: first = false; break; } array->prop = prop; array->pseudoId = RenderStyle::NOPSEUDO; array->selector = 0; array->position = i; array->priority = (!first << 30) | (source << 24); propsToApply[numProps++] = array++; } return numProps; } // modified version of the one in kurl.cpp static void cleanpath(QString &path) { int pos; while ( (pos = path.indexOf( "/../" )) != -1 ) { int prev = 0; if ( pos > 0 ) prev = path.lastIndexOf( "/", pos -1 ); // don't remove the host, i.e. http://foo.org/../foo.html if (prev < 0 || (prev > 3 && path.lastIndexOf("://", prev-1) == prev-2)) path.remove( pos, 3); else // matching directory found ? path.remove( prev, pos- prev + 3 ); } pos = 0; // Don't remove "//" from an anchor identifier. -rjw // Set refPos to -2 to mean "I haven't looked for the anchor yet". // We don't want to waste a function call on the search for the anchor // in the vast majority of cases where there is no "//" in the path. int refPos = -2; while ( (pos = path.indexOf( "//", pos )) != -1) { if (refPos == -2) refPos = path.indexOf("#", 0); if (refPos > 0 && pos >= refPos) break; if ( pos == 0 || path[pos-1] != ':' ) path.remove( pos, 1 ); else pos += 2; } while ( (pos = path.indexOf( "/./" )) != -1) path.remove( pos, 2 ); //kDebug() << "checkPseudoState " << path; } static PseudoState checkPseudoState( const CSSStyleSelector::Encodedurl& encodedurl, DOM::ElementImpl *e ) { if( e->id() != ID_A ) { return PseudoNone; } DOMString attr = e->getAttribute(ATTR_HREF); if( attr.isNull() ) { return PseudoNone; } QString u = QString::fromRawData(attr.unicode(), attr.length()); if ( !u.contains("://") ) { if ( u[0] == '/' ) u = encodedurl.host + u; else if ( u[0] == '#' ) u = encodedurl.file + u; else u = encodedurl.path + u; cleanpath( u ); } //completeURL( attr.string() ); bool contains = KHTMLGlobal::vLinks()->contains( u ); if ( !contains && u.count('/')==2 ) contains = KHTMLGlobal::vLinks()->contains( u+'/' ); return contains ? PseudoVisited : PseudoLink; } // a helper function for parsing nth-arguments static bool matchNth(int count, const QString& nth) { if (nth.isEmpty()) return false; int a = 0; int b = 0; if (nth == "odd") { a = 2; b = 1; } else if (nth == "even") { a = 2; b = 0; } else { int n = nth.indexOf('n'); if (n != -1) { if (nth[0] == '-') if (n==1) a = -1; else a = nth.mid(1,n-1).toInt(); else if (n==0) a = 1; else a = nth.left(n).toInt(); int p = nth.indexOf('+'); if (p != -1) b = nth.mid(p+1).toInt(); else { p = nth.indexOf('-'); b = -nth.mid(p+1).toInt(); } } else { b = nth.toInt(); } } if (a == 0) return count == b; else if (a > 0) if (count < b) return false; else return (count - b) % a == 0; else if (a < 0) { if (count > b) return false; else return (b - count) % (-a) == 0; } return false; } // Recursively work the combinator to compute static attribute dependency, similar to //structure of checkSubSelectors static void precomputeAttributeDependenciesAux(DOM::DocumentImpl* doc, DOM::CSSSelector* sel, bool isAncestor, bool isSubject) { if(sel->attr) { // Sets up global dependencies of attributes if (isSubject) doc->dynamicDomRestyler().addDependency(sel->attr, PersonalDependency); else if (isAncestor) doc->dynamicDomRestyler().addDependency(sel->attr, AncestorDependency); else doc->dynamicDomRestyler().addDependency(sel->attr, PredecessorDependency); } if(sel->match == CSSSelector::PseudoClass) { switch (sel->pseudoType()) { case CSSSelector::PseudoNot: precomputeAttributeDependenciesAux(doc, sel->simpleSelector, isAncestor, true); break; default: break; } } CSSSelector::Relation relation = KDE_CAST_BF_ENUM(CSSSelector::Relation, sel->relation); sel = sel->tagHistory; if (!sel) return; switch(relation) { case CSSSelector::Descendant: case CSSSelector::Child: precomputeAttributeDependenciesAux(doc, sel, true, false); break; case CSSSelector::IndirectAdjacent: case CSSSelector::DirectAdjacent: precomputeAttributeDependenciesAux(doc, sel, false, false); break; case CSSSelector::SubSelector: precomputeAttributeDependenciesAux(doc, sel, isAncestor, isSubject); break; } } void CSSStyleSelector::precomputeAttributeDependencies(DOM::DocumentImpl* doc, DOM::CSSSelector* sel) { precomputeAttributeDependenciesAux(doc, sel, false, true); } // Recursive check of selectors and combinators // It can return 3 different values: // * SelectorMatches - the selector is match for the node e // * SelectorFailsLocal - the selector fails for the node e // * SelectorFails - the selector fails for e and any sibling or ancestor of e CSSStyleSelector::SelectorMatch CSSStyleSelector::checkSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector) { // The simple selector has to match if(!checkSimpleSelector(sel, e, isAncestor, isSubSelector)) return SelectorFailsLocal; // The rest of the selectors has to match CSSSelector::Relation relation = KDE_CAST_BF_ENUM(CSSSelector::Relation, sel->relation); // Prepare next sel sel = sel->tagHistory; if (!sel) return SelectorMatches; switch(relation) { case CSSSelector::Descendant: { while(true) { DOM::NodeImpl* n = e->parentNode(); if(!n || !n->isElementNode()) return SelectorFails; e = static_cast(n); SelectorMatch match = checkSelector(sel, e, true); if (match != SelectorFailsLocal) return match; } break; } case CSSSelector::Child: { DOM::NodeImpl* n = e->parentNode(); if (!strictParsing) while (n && n->implicitNode()) n = n->parentNode(); if(!n || !n->isElementNode()) return SelectorFails; e = static_cast(n); return checkSelector(sel, e, true); } case CSSSelector::IndirectAdjacent: { // Sibling selectors always generate structural dependencies // because newly inserted element might fullfill them. if (e->parentNode()->isElementNode()) addDependency(StructuralDependency, static_cast(e->parentNode())); while(true) { DOM::NodeImpl* n = e->previousSibling(); while( n && !n->isElementNode() ) n = n->previousSibling(); if( !n ) return SelectorFailsLocal; e = static_cast(n); SelectorMatch match = checkSelector(sel, e, false); if (match != SelectorFailsLocal) return match; }; break; } case CSSSelector::DirectAdjacent: { if (e->parentNode()->isElementNode()) addDependency(StructuralDependency, static_cast(e->parentNode())); DOM::NodeImpl* n = e->previousSibling(); while( n && !n->isElementNode() ) n = n->previousSibling(); if( !n ) return SelectorFailsLocal; e = static_cast(n); return checkSelector(sel, e, false); } case CSSSelector::SubSelector: return checkSelector(sel, e, isAncestor, true); } assert(false); // never reached return SelectorFails; } void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl * e) { assert(e == element); // yes, actually dynamicPseudo = RenderStyle::NOPSEUDO; selectorCache[ selIndex ].state = Invalid; CSSSelector *sel = selectors[ selIndex ]; // Check the selector SelectorMatch match = checkSelector(sel, e, true); if(match != SelectorMatches) return; if ( dynamicPseudo != RenderStyle::NOPSEUDO ) { selectorCache[selIndex].state = AppliesPseudo; selectors[ selIndex ]->pseudoId = dynamicPseudo; } else selectorCache[ selIndex ].state = Applies; //qDebug( "selector %d applies", selIndex ); //selectors[ selIndex ]->print(); return; } void CSSStyleSelector::addDependency(StructuralDependencyType dependencyType, ElementImpl* dependency) { element->getDocument()->dynamicDomRestyler().addDependency(element, dependency, dependencyType); } bool CSSStyleSelector::checkSimpleSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e, bool isAncestor, bool isSubSelector) { if(!e) return false; if (sel->tag != anyQName) { int eltID = e->id(); quint16 localName = localNamePart(eltID); quint16 ns = namespacePart(eltID); quint16 selLocalName = localNamePart(sel->tag); quint16 selNS = namespacePart(sel->tag); if (localName <= ID_LAST_TAG && ns == defaultNamespace) { assert(e->isHTMLElement()); ns = xhtmlNamespace; } // match on local if (selLocalName != anyLocalName && localName != selLocalName) return false; // match on namespace if (selNS != anyNamespace && ns != selNS) return false; } if(sel->attr) { quint16 selLocalName = localNamePart(sel->attr); quint16 selNS = namespacePart(sel->attr); bool nsAware = (selNS != anyNamespace); if (selNS == emptyNamespace) selNS = defaultNamespace; DOMStringImpl* value = e->getAttributeImpl(makeId(selNS, selLocalName), nsAware); if(!value) return false; // attribute is not set // attributes are always case-sensitive in XHTML // attributes are sometimes case-sensitive in HTML // we only treat id and class selectors as case-sensitive in HTML strict // for compatibility reasons bool caseSensitive = e->getDocument()->htmlMode() == DocumentImpl::XHtml; bool caseSensitive_alt = strictParsing || caseSensitive; caseSensitive |= (sel->attr > ATTR_LAST_CI_ATTR); switch(sel->match) { case CSSSelector::Set: // True if we make it this far break; case CSSSelector::Id: caseSensitive = caseSensitive_alt; // no break case CSSSelector::Exact: return (caseSensitive && !strcmp(sel->value, value)) || (!caseSensitive && !strcasecmp(sel->value, value)); break; case CSSSelector::Class: caseSensitive = caseSensitive_alt; // no break case CSSSelector::List: { int sel_len = sel->value.length(); int val_len = value->length(); // Be smart compare on length first if (sel_len > val_len) return false; // Selector string may not contain spaces if ((sel->attr != ATTR_CLASS || e->hasClassList()) && sel->value.find(' ') != -1) return false; if (sel_len == val_len) return (caseSensitive && !strcmp(sel->value, value)) || (!caseSensitive && !strcasecmp(sel->value, value)); // else the value is longer and can be a list if ( sel->match == CSSSelector::Class && !e->hasClassList() ) return false; QChar* sel_uc = sel->value.unicode(); QChar* val_uc = value->unicode(); QString sel_str = QString::fromRawData(sel_uc, sel_len); QString val_str = QString::fromRawData(val_uc, val_len); int pos = 0; for ( ;; ) { pos = val_str.indexOf(sel_str, pos, strictParsing?Qt::CaseSensitive:Qt::CaseInsensitive); if ( pos == -1 ) return false; if ( pos == 0 || val_uc[pos-1].isSpace() ) { int endpos = pos + sel_len; if ( endpos >= val_len || val_uc[endpos].isSpace() ) break; // We have a match. } ++pos; } break; } case CSSSelector::Contain: { //kDebug( 6080 ) << "checking for contains match"; QString val_str = QString::fromRawData(value->unicode(), value->length()); QString sel_str = QString::fromRawData(sel->value.unicode(), sel->value.length()); return val_str.contains(sel_str, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); } case CSSSelector::Begin: { //kDebug( 6080 ) << "checking for beginswith match"; QString val_str = QString::fromRawData(value->unicode(), value->length()); QString sel_str = QString::fromRawData(sel->value.unicode(), sel->value.length()); return val_str.startsWith(sel_str, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); } case CSSSelector::End: { //kDebug( 6080 ) << "checking for endswith match"; QString val_str = QString::fromRawData(value->unicode(), value->length()); QString sel_str = QString::fromRawData(sel->value.unicode(), sel->value.length()); return val_str.endsWith(sel_str, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive); } case CSSSelector::Hyphen: { //kDebug( 6080 ) << "checking for hyphen match"; QString val_str = QString::fromRawData(value->unicode(), value->length()); QString sel_str = QString::fromRawData(sel->value.unicode(), sel->value.length()); const QString& str = val_str; const QString& selStr = sel_str; if(str.length() < selStr.length()) return false; // Check if str begins with selStr: if(str.indexOf(selStr, 0, (caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive)) != 0) return false; // It does. Check for exact match or following '-': if(str.length() != selStr.length() && str[selStr.length()] != '-') return false; break; } case CSSSelector::PseudoClass: case CSSSelector::PseudoElement: case CSSSelector::None: break; } } if(sel->match == CSSSelector::PseudoClass || sel->match == CSSSelector::PseudoElement) { switch (sel->pseudoType()) { // Pseudo classes: case CSSSelector::PseudoEmpty: addDependency(BackwardsStructuralDependency, e); // If e is not closed yet we don't know the number of children if (!e->closed()) { return false; } if (!e->firstChild()) return true; else { NodeImpl *t = e->firstChild(); // check for empty text nodes and comments while (t && (t->nodeType() == Node::COMMENT_NODE || (t->isTextNode() && static_cast(t)->length() == 0))) t = t->nextSibling(); if (t == 0) return true; else return false; } break; case CSSSelector::PseudoFirstChild: { // first-child matches the first child that is an element! if (e->parentNode() && e->parentNode()->isElementNode()) { // Handle dynamic DOM changes addDependency(StructuralDependency, static_cast(e->parentNode())); DOM::NodeImpl* n = e->previousSibling(); while ( n && !n->isElementNode() ) n = n->previousSibling(); if ( !n ) return true; } break; } case CSSSelector::PseudoLastChild: { // last-child matches the last child that is an element! if (e->parentNode() && e->parentNode()->isElementNode()) { // Handle unfinished parsing and dynamic DOM changes addDependency(BackwardsStructuralDependency, static_cast(e->parentNode())); if (!e->parentNode()->closed()) { // kDebug(6080) << e->nodeName().string() << "::last-child: Parent unclosed"; return false; } DOM::NodeImpl* n = e->nextSibling(); while ( n && !n->isElementNode() ) n = n->nextSibling(); if ( !n ) return true; } break; } case CSSSelector::PseudoOnlyChild: { // If both first-child and last-child apply, then only-child applies. if (e->parentNode() && e->parentNode()->isElementNode()) { addDependency(BackwardsStructuralDependency, static_cast(e->parentNode())); if (!e->parentNode()->closed()) { return false; } DOM::NodeImpl* n = e->previousSibling(); while ( n && !n->isElementNode() ) n = n->previousSibling(); if ( !n ) { n = e->nextSibling(); while ( n && !n->isElementNode() ) n = n->nextSibling(); if ( !n ) return true; } } break; } case CSSSelector::PseudoNthChild: { // nth-child matches every (a*n+b)th element! if (e->parentNode() && e->parentNode()->isElementNode()) { addDependency(StructuralDependency, static_cast(e->parentNode())); int count = 1; DOM::NodeImpl* n = e->previousSibling(); while ( n ) { if (n->isElementNode()) count++; n = n->previousSibling(); } // kDebug(6080) << "NthChild " << count << "=" << sel->string_arg; if (matchNth(count,sel->string_arg.string())) return true; } break; } case CSSSelector::PseudoNthLastChild: { if (e->parentNode() && e->parentNode()->isElementNode()) { addDependency(BackwardsStructuralDependency, static_cast(e->parentNode())); if (!e->parentNode()->closed()) { return false; } int count = 1; DOM::NodeImpl* n = e->nextSibling(); while ( n ) { if (n->isElementNode()) count++; n = n->nextSibling(); } // kDebug(6080) << "NthLastChild " << count << "=" << sel->string_arg; if (matchNth(count,sel->string_arg.string())) return true; } break; } case CSSSelector::PseudoFirstOfType: { // first-of-type matches the first element of its type! if (e->parentNode() && e->parentNode()->isElementNode()) { addDependency(StructuralDependency, static_cast(e->parentNode())); const DOMString& type = e->tagName(); DOM::NodeImpl* n = e->previousSibling(); while ( n ) { if (n->isElementNode()) if (static_cast(n)->tagName() == type) break; n = n->previousSibling(); } if ( !n ) return true; } break; } case CSSSelector::PseudoLastOfType: { // last-child matches the last child that is an element! if (e->parentNode() && e->parentNode()->isElementNode()) { addDependency(BackwardsStructuralDependency, static_cast(e->parentNode())); if (!e->parentNode()->closed()) { return false; } const DOMString& type = e->tagName(); DOM::NodeImpl* n = e->nextSibling(); while ( n ) { if (n->isElementNode()) if (static_cast(n)->tagName() == type) break; n = n->nextSibling(); } if ( !n ) return true; } break; } case CSSSelector::PseudoOnlyOfType: { // If both first-of-type and last-of-type apply, then only-of-type applies. if (e->parentNode() && e->parentNode()->isElementNode()) { addDependency(BackwardsStructuralDependency, static_cast(e->parentNode())); if (!e->parentNode()->closed()) { return false; } const DOMString& type = e->tagName(); DOM::NodeImpl* n = e->previousSibling(); while ( n && !(n->isElementNode() && static_cast(n)->tagName() == type)) n = n->previousSibling(); if ( !n ) { n = e->nextSibling(); while ( n && !(n->isElementNode() && static_cast(n)->tagName() == type)) n = n->nextSibling(); if ( !n ) return true; } } break; } case CSSSelector::PseudoNthOfType: { // nth-of-type matches every (a*n+b)th element of this type! if (e->parentNode() && e->parentNode()->isElementNode()) { addDependency(StructuralDependency, static_cast(e->parentNode())); int count = 1; const DOMString& type = e->tagName(); DOM::NodeImpl* n = e->previousSibling(); while ( n ) { if (n->isElementNode() && static_cast(n)->tagName() == type) count++; n = n->previousSibling(); } // kDebug(6080) << "NthOfType " << count << "=" << sel->string_arg; if (matchNth(count,sel->string_arg.string())) return true; } break; } case CSSSelector::PseudoNthLastOfType: { if (e->parentNode() && e->parentNode()->isElementNode()) { addDependency(BackwardsStructuralDependency, static_cast(e->parentNode())); if (!e->parentNode()->closed()) { return false; } int count = 1; const DOMString& type = e->tagName(); DOM::NodeImpl* n = e->nextSibling(); while ( n ) { if (n->isElementNode() && static_cast(n)->tagName() == type) count++; n = n->nextSibling(); } // kDebug(6080) << "NthLastOfType " << count << "=" << sel->string_arg; if (matchNth(count,sel->string_arg.string())) return true; } break; } case CSSSelector::PseudoTarget: if (e == e->getDocument()->getCSSTarget()) return true; break; case CSSSelector::PseudoRoot: if (e == e->getDocument()->documentElement()) return true; break; case CSSSelector::PseudoLink: if (e == element) { // cache pseudoState if ( pseudoState == PseudoUnknown ) pseudoState = checkPseudoState( encodedurl, e ); if ( pseudoState == PseudoLink ) return true; } else return checkPseudoState( encodedurl, e ) == PseudoLink; break; case CSSSelector::PseudoVisited: if (e == element) { // cache pseudoState if ( pseudoState == PseudoUnknown ) pseudoState = checkPseudoState( encodedurl, e ); if ( pseudoState == PseudoVisited ) return true; } else return checkPseudoState( encodedurl, e ) == PseudoVisited; break; case CSSSelector::PseudoHover: { // If we're in quirks mode, then *:hover should only match focusable elements. if (strictParsing || (sel->tag != anyQName) || isSubSelector || e->isFocusable() ) { addDependency(HoverDependency, e); if (e->hovered()) return true; } break; } case CSSSelector::PseudoActive: // If we're in quirks mode, then *:active should only match focusable elements if (strictParsing || (sel->tag != anyQName) || isSubSelector || e->isFocusable()) { addDependency(ActiveDependency, e); if (e->active()) return true; } break; case CSSSelector::PseudoFocus: if (e != element && e->isFocusable()) { // *:focus is a default style, no need to track it. addDependency(OtherStateDependency, e); } if (e->focused()) return true; break; case CSSSelector::PseudoLang: { // Set dynamic attribute dependency if (e == element) { e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, PersonalDependency); e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency); } else if (isAncestor) e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, AncestorDependency); else e->getDocument()->dynamicDomRestyler().addDependency(ATTR_LANG, PredecessorDependency); // ### check xml:lang attribute in XML and XHTML documents DOMString value = e->getAttribute(ATTR_LANG); // The LANG attribute is inherited like a property NodeImpl *n = e->parent();; while (n && value.isEmpty()) { if (n->isElementNode()) { value = static_cast(n)->getAttribute(ATTR_LANG); } else if (n->isDocumentNode()) { value = static_cast(n)->contentLanguage(); } n = n->parent(); } if (value.isEmpty()) return false; QString langAttr = value.string(); QString langSel = sel->string_arg.string(); if(langAttr.length() < langSel.length()) return false; langAttr = langAttr.toLower(); langSel = langSel.toLower(); // kDebug(6080) << ":lang " << langAttr << "=" << langSel << "?"; return (langAttr == langSel || langAttr.startsWith(langSel+'-')); } case CSSSelector::PseudoNot: { // check the simple selector for (CSSSelector* subSel = sel->simpleSelector; subSel; subSel = subSel->tagHistory) { // :not cannot nest. I don't really know why this is a restriction in CSS3, // but it is, so let's honor it. if (subSel->simpleSelector) break; if (!checkSimpleSelector(subSel, e, isAncestor, true)) return true; } break; } case CSSSelector::PseudoEnabled: { if (e->isGenericFormElement()) { addDependency(OtherStateDependency, e); HTMLGenericFormElementImpl *form; form = static_cast(e); return !form->disabled(); } break; } case CSSSelector::PseudoDisabled: { if (e->isGenericFormElement()) { addDependency(OtherStateDependency, e); HTMLGenericFormElementImpl *form; form = static_cast(e); return form->disabled(); } break; } case CSSSelector::PseudoContains: { if (e->isHTMLElement()) { addDependency(BackwardsStructuralDependency, e); if (!e->closed()) { return false; } HTMLElementImpl *elem; elem = static_cast(e); DOMString s = elem->innerText(); QString selStr = sel->string_arg.string(); // kDebug(6080) << ":contains(\"" << selStr << "\")" << " on \"" << s << "\""; return s.string().contains(selStr); } break; } case CSSSelector::PseudoChecked: { if (e->isHTMLElement() && e->id() == ID_INPUT) { addDependency(OtherStateDependency, e); return (static_cast(e)->checked()); } return false; } case CSSSelector::PseudoIndeterminate: { #if 0 if (e->isHTMLElement() && e->id() == ID_INPUT) { return (static_cast(e)->indeterminate() && !static_cast(e)->checked()); } return false; #endif } case CSSSelector::PseudoOther: break; // Pseudo-elements: case CSSSelector::PseudoFirstLine: case CSSSelector::PseudoFirstLetter: case CSSSelector::PseudoSelection: case CSSSelector::PseudoBefore: case CSSSelector::PseudoAfter: case CSSSelector::PseudoMarker: case CSSSelector::PseudoReplaced: // Pseudo-elements can only apply to subject if ( e == element ) { // Pseudo-elements has to be the last sub-selector on subject if (sel->tagHistory && sel->relation == CSSSelector::SubSelector) return false; assert(dynamicPseudo == RenderStyle::NOPSEUDO); switch (sel->pseudoType()) { case CSSSelector::PseudoFirstLine: dynamicPseudo = RenderStyle::FIRST_LINE; break; case CSSSelector::PseudoFirstLetter: dynamicPseudo = RenderStyle::FIRST_LETTER; break; case CSSSelector::PseudoSelection: dynamicPseudo = RenderStyle::SELECTION; break; case CSSSelector::PseudoBefore: dynamicPseudo = RenderStyle::BEFORE; break; case CSSSelector::PseudoAfter: dynamicPseudo = RenderStyle::AFTER; break; case CSSSelector::PseudoMarker: dynamicPseudo = RenderStyle::MARKER; break; case CSSSelector::PseudoReplaced: dynamicPseudo = RenderStyle::REPLACED; break; default: assert(false); } return true; } break; case CSSSelector::PseudoNotParsed: assert(false); break; } return false; } // ### add the rest of the checks... return true; } void CSSStyleSelector::clearLists() { delete [] selectors; if ( selectorCache ) { for ( unsigned int i = 0; i < selectors_size; i++ ) delete [] selectorCache[i].props; delete [] selectorCache; } if ( properties ) { CSSOrderedProperty **prop = properties; while ( *prop ) { delete (*prop); prop++; } delete [] properties; } selectors = 0; properties = 0; selectorCache = 0; } void CSSStyleSelector::buildLists() { clearLists(); // collect all selectors and Properties in lists. Then transfer them to the array for faster lookup. QList selectorList; CSSOrderedPropertyList propertyList; if(m_medium == "print" && defaultPrintStyle) defaultPrintStyle->collect( &selectorList, &propertyList, Default, Default ); else if(defaultStyle) defaultStyle->collect( &selectorList, &propertyList, Default, Default ); if (!strictParsing && defaultQuirksStyle) defaultQuirksStyle->collect( &selectorList, &propertyList, Default, Default ); if(userStyle) userStyle->collect(&selectorList, &propertyList, User, UserImportant ); if (defaultNonCSSHintsStyle) defaultNonCSSHintsStyle->collect(&selectorList, &propertyList, NonCSSHint, NonCSSHint); // Implicit styles are gathered from hidden, dynamically generated, implicit stylesheets. // They have the same priority as presentational attributes. if (implicitStyle) implicitStyle->collect(&selectorList, &propertyList, NonCSSHint, NonCSSHint); if (authorStyle) authorStyle->collect(&selectorList, &propertyList, Author, AuthorImportant ); selectors_size = selectorList.count(); selectors = new CSSSelector *[selectors_size]; CSSSelector **sel = selectors; for (QListIterator sit(selectorList); sit.hasNext(); ++sel) *sel = sit.next(); selectorCache = new SelectorCache[selectors_size]; for ( unsigned int i = 0; i < selectors_size; i++ ) { selectorCache[i].state = Unknown; selectorCache[i].props_size = 0; selectorCache[i].props = 0; } // presort properties. Should make the sort() calls in styleForElement faster. qSort(propertyList.begin(), propertyList.end(), CSSOrderedPropertyList::compareItems); properties_size = propertyList.count() + 1; properties = new CSSOrderedProperty *[ properties_size ]; CSSOrderedProperty **prop = properties; for (QListIterator pit(propertyList); pit.hasNext(); ++prop) *prop = pit.next(); *prop = 0; unsigned int* offsets = new unsigned int[selectors_size]; if(properties[0]) offsets[properties[0]->selector] = 0; for(unsigned int p = 1; p < properties_size; ++p) { if(!properties[p] || (properties[p]->selector != properties[p - 1]->selector)) { unsigned int sel = properties[p - 1]->selector; int* newprops = new int[selectorCache[sel].props_size+2]; for ( unsigned int i=0; i < selectorCache[sel].props_size; i++ ) newprops[i] = selectorCache[sel].props[i]; newprops[selectorCache[sel].props_size] = offsets[sel]; newprops[selectorCache[sel].props_size+1] = p - offsets[sel]; delete [] selectorCache[sel].props; selectorCache[sel].props = newprops; selectorCache[sel].props_size += 2; if(properties[p]) { sel = properties[p]->selector; offsets[sel] = p; } } } delete [] offsets; } // ---------------------------------------------------------------------- CSSOrderedRule::CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index) { rule = r; if(rule) r->ref(); index = _index; selector = s; } CSSOrderedRule::~CSSOrderedRule() { if(rule) rule->deref(); } // ----------------------------------------------------------------- CSSStyleSelectorList::CSSStyleSelectorList() : QList() { } CSSStyleSelectorList::~CSSStyleSelectorList() { qDeleteAll(*this); clear(); } void CSSStyleSelectorList::append( CSSStyleSheetImpl *sheet, const DOMString &medium ) { if(!sheet || !sheet->isCSSStyleSheet()) return; // No media implies "all", but if a medialist exists it must // contain our current medium if( sheet->media() && !sheet->media()->contains( medium ) ) return; // style sheet not applicable for this medium int len = sheet->length(); for(int i = 0; i< len; i++) { StyleBaseImpl *item = sheet->item(i); if(item->isStyleRule()) { CSSStyleRuleImpl *r = static_cast(item); QList *s = r->selector(); for(int j = 0; j < (int)s->count(); j++) { CSSOrderedRule *rule = new CSSOrderedRule(r, s->at(j), count()); QList::append(rule); //kDebug( 6080 ) << "appending StyleRule!"; } } else if(item->isImportRule()) { CSSImportRuleImpl *import = static_cast(item); //kDebug( 6080 ) << "@import: Media: " // << import->media()->mediaText().string() << endl; if( !import->media() || import->media()->contains( medium ) ) { CSSStyleSheetImpl *importedSheet = import->styleSheet(); append( importedSheet, medium ); } } else if( item->isMediaRule() ) { CSSMediaRuleImpl *r = static_cast( item ); CSSRuleListImpl *rules = r->cssRules(); //DOMString mediaText = media->mediaText(); //kDebug( 6080 ) << "@media: Media: " // << r->media()->mediaText().string() << endl; if( ( !r->media() || r->media()->contains( medium ) ) && rules) { // Traverse child elements of the @import rule. Since // many elements are not allowed as child we do not use // a recursive call to append() here for( unsigned j = 0; j < rules->length(); j++ ) { //kDebug( 6080 ) << "*** Rule #" << j; CSSRuleImpl *childItem = rules->item( j ); if( childItem->isStyleRule() ) { // It is a StyleRule, so append it to our list CSSStyleRuleImpl *styleRule = static_cast( childItem ); QList *s = styleRule->selector(); for( int j = 0; j < ( int ) s->count(); j++ ) { CSSOrderedRule *orderedRule = new CSSOrderedRule( styleRule, s->at( j ), count() ); QList::append( orderedRule ); } } else { //kDebug( 6080 ) << "Ignoring child rule of " // "ImportRule: rule is not a StyleRule!" << endl; } } // for rules } // if rules else { //kDebug( 6080 ) << "CSSMediaRule not rendered: " // << "rule empty or wrong medium!" << endl; } } // ### include other rules } } void CSSStyleSelectorList::collect( QList *selectorList, CSSOrderedPropertyList *propList, Source regular, Source important ) { CSSOrderedRule *r; QListIterator tIt(*this); CSSSelector *sel; while( tIt.hasNext() ) { r = tIt.next(); int selectorNum = 0; sel = 0; bool found = false; // already in list? QListIterator it(*selectorList); while( it.hasNext() ) { sel = it.next(); if ( *sel == *(r->selector) ) { found = true; break; } selectorNum++; } if ( !found ) // nope. selectorList->append( r->selector ); propList->append(r->rule->declaration(), selectorNum, r->selector->specificity(), regular, important ); } } // ------------------------------------------------------------------------- bool CSSOrderedPropertyList::compareItems(const CSSOrderedProperty * i1, const CSSOrderedProperty *i2) { return *i1 < *i2; } void CSSOrderedPropertyList::append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity, Source regular, Source important ) { QList *values = decl->values(); if(!values) return; int len = values->count(); for(int i = 0; i < len; i++) { CSSProperty *prop = values->at(i); Source source = regular; if( prop->m_important ) source = important; bool first = false; // give special priority to font-xxx, color properties switch(prop->m_id) { case CSS_PROP_FONT_STYLE: case CSS_PROP_FONT_SIZE: case CSS_PROP_FONT_WEIGHT: case CSS_PROP_FONT_FAMILY: case CSS_PROP_FONT_VARIANT: case CSS_PROP_FONT: case CSS_PROP_COLOR: case CSS_PROP_DIRECTION: case CSS_PROP_DISPLAY: // these have to be applied first, because other properties use the computed // values of these porperties. first = true; break; default: break; } QList::append(new CSSOrderedProperty(prop, selector, first, source, specificity, count() )); } } // ------------------------------------------------------------------------------------- // this is mostly boring stuff on how to apply a certain rule to the renderstyle... static Length convertToLength( CSSPrimitiveValueImpl *primitiveValue, RenderStyle *style, int logicalDpiY, bool *ok = 0 ) { Length l; if ( !primitiveValue ) { if ( ok ) *ok = false; } else { int type = primitiveValue->primitiveType(); if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) l = Length(primitiveValue->computeLength(style, logicalDpiY), Fixed); else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)), Percent); else if(type == CSSPrimitiveValue::CSS_NUMBER) l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent); else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE) l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative); else if ( ok ) *ok = false; } return l; } static inline int nextFontSize(const QVector& a, int v, bool smaller) { // return the nearest bigger/smaller value in scale a, when v is in range. // otherwise increase/decrease value using a 1.2 fixed ratio int m, l = 0, r = a.count()-1; while (l <= r) { m = (l+r)/2; if (a[m] == v) return smaller ? ( m ? a[m-1] : (v*5)/6 ) : ( m+1isPrimitiveValue()) primitiveValue = static_cast(value); Length l; bool apply = false; bool isInherit = (parentNode && value->cssValueType() == CSSValue::CSS_INHERIT); bool isInitial = (value->cssValueType() == CSSValue::CSS_INITIAL) || (!parentNode && value->cssValueType() == CSSValue::CSS_INHERIT); // These properties are used to set the correct margins/padding on RTL lists. if (id == CSS_PROP__KHTML_MARGIN_START) id = style->direction() == LTR ? CSS_PROP_MARGIN_LEFT : CSS_PROP_MARGIN_RIGHT; else if (id == CSS_PROP__KHTML_PADDING_START) id = style->direction() == LTR ? CSS_PROP_PADDING_LEFT : CSS_PROP_PADDING_RIGHT; // What follows is a list that maps the CSS properties into their corresponding front-end // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and // are only hit when mapping "inherit" or "initial" into front-end values. switch(id) { // ident only properties case CSS_PROP_BACKGROUND_ATTACHMENT: HANDLE_BACKGROUND_VALUE(backgroundAttachment, BackgroundAttachment, value) break; case CSS_PROP__KHTML_BACKGROUND_CLIP: HANDLE_BACKGROUND_VALUE(backgroundClip, BackgroundClip, value) break; case CSS_PROP__KHTML_BACKGROUND_ORIGIN: HANDLE_BACKGROUND_VALUE(backgroundOrigin, BackgroundOrigin, value) break; case CSS_PROP_BACKGROUND_REPEAT: HANDLE_BACKGROUND_VALUE(backgroundRepeat, BackgroundRepeat, value) break; case CSS_PROP__KHTML_BACKGROUND_SIZE: HANDLE_BACKGROUND_VALUE(backgroundSize, BackgroundSize, value) break; case CSS_PROP_BORDER_COLLAPSE: HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(borderCollapse, BorderCollapse) if(!primitiveValue) break; switch(primitiveValue->getIdent()) { case CSS_VAL_COLLAPSE: style->setBorderCollapse(true); break; case CSS_VAL_SEPARATE: style->setBorderCollapse(false); break; default: return; } break; case CSS_PROP_BORDER_TOP_STYLE: HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle) if (!primitiveValue) return; style->setBorderTopStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE)); break; case CSS_PROP_BORDER_RIGHT_STYLE: HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle) if (!primitiveValue) return; style->setBorderRightStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE)); break; case CSS_PROP_BORDER_BOTTOM_STYLE: HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle) if (!primitiveValue) return; style->setBorderBottomStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE)); break; case CSS_PROP_BORDER_LEFT_STYLE: HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle) if (!primitiveValue) return; style->setBorderLeftStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE)); break; case CSS_PROP_OUTLINE_STYLE: HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle) if (!primitiveValue) return; style->setOutlineStyle((EBorderStyle)(primitiveValue->getIdent() - CSS_VAL__KHTML_NATIVE)); break; case CSS_PROP_CAPTION_SIDE: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(captionSide, CaptionSide) if(!primitiveValue) break; ECaptionSide c = RenderStyle::initialCaptionSide(); switch(primitiveValue->getIdent()) { case CSS_VAL_LEFT: c = CAPLEFT; break; case CSS_VAL_RIGHT: c = CAPRIGHT; break; case CSS_VAL_TOP: c = CAPTOP; break; case CSS_VAL_BOTTOM: c = CAPBOTTOM; break; default: return; } style->setCaptionSide(c); return; } case CSS_PROP_CLEAR: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(clear, Clear) if(!primitiveValue) break; EClear c = CNONE; switch(primitiveValue->getIdent()) { case CSS_VAL_LEFT: c = CLEFT; break; case CSS_VAL_RIGHT: c = CRIGHT; break; case CSS_VAL_BOTH: c = CBOTH; break; case CSS_VAL_NONE: c = CNONE; break; default: return; } style->setClear(c); return; } case CSS_PROP_DIRECTION: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(direction, Direction) if(!primitiveValue) break; style->setDirection( (EDirection) (primitiveValue->getIdent() - CSS_VAL_LTR) ); return; } case CSS_PROP_DISPLAY: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(display, Display) if(!primitiveValue) break; int id = primitiveValue->getIdent(); style->setDisplay( id == CSS_VAL_NONE ? NONE : EDisplay(id - CSS_VAL_INLINE) ); break; } case CSS_PROP_EMPTY_CELLS: { HANDLE_INHERIT_ON_INHERITED_PROPERTY(emptyCells, EmptyCells); if (!primitiveValue) break; int id = primitiveValue->getIdent(); if (id == CSS_VAL_SHOW) style->setEmptyCells(SHOW); else if (id == CSS_VAL_HIDE) style->setEmptyCells(HIDE); break; } case CSS_PROP_FLOAT: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(floating, Floating) if(!primitiveValue) return; EFloat f; switch(primitiveValue->getIdent()) { case CSS_VAL__KHTML_LEFT: f = FLEFT_ALIGN; break; case CSS_VAL_LEFT: f = FLEFT; break; case CSS_VAL__KHTML_RIGHT: f = FRIGHT_ALIGN; break; case CSS_VAL_RIGHT: f = FRIGHT; break; case CSS_VAL_NONE: case CSS_VAL_CENTER: //Non standart CSS-Value f = FNONE; break; default: return; } if (f!=FNONE && style->display()==LIST_ITEM) style->setDisplay(BLOCK); style->setFloating(f); break; } case CSS_PROP_FONT_STYLE: { FontDef fontDef = style->htmlFont().fontDef; if (isInherit) fontDef.italic = parentStyle->htmlFont().fontDef.italic; else if (isInitial) fontDef.italic = false; else { if(!primitiveValue) return; switch(primitiveValue->getIdent()) { case CSS_VAL_OBLIQUE: // ### oblique is the same as italic for the moment... case CSS_VAL_ITALIC: fontDef.italic = true; break; case CSS_VAL_NORMAL: fontDef.italic = false; break; default: return; } } fontDirty |= style->setFontDef( fontDef ); break; } case CSS_PROP_FONT_VARIANT: { FontDef fontDef = style->htmlFont().fontDef; if (isInherit) fontDef.smallCaps = parentStyle->htmlFont().fontDef.smallCaps; else if (isInitial) fontDef.smallCaps = false; else { if(!primitiveValue) return; int id = primitiveValue->getIdent(); if ( id == CSS_VAL_NORMAL ) fontDef.smallCaps = false; else if ( id == CSS_VAL_SMALL_CAPS ) fontDef.smallCaps = true; else return; } fontDirty |= style->setFontDef( fontDef ); break; } case CSS_PROP_FONT_WEIGHT: { FontDef fontDef = style->htmlFont().fontDef; if (isInherit) fontDef.weight = parentStyle->htmlFont().fontDef.weight; else if (isInitial) fontDef.weight = QFont::Normal; else { if(!primitiveValue) return; if(primitiveValue->getIdent()) { switch(primitiveValue->getIdent()) { // ### we just support normal and bold fonts at the moment... // setWeight can actually accept values between 0 and 99... case CSS_VAL_BOLD: case CSS_VAL_BOLDER: case CSS_VAL_600: case CSS_VAL_700: case CSS_VAL_800: case CSS_VAL_900: fontDef.weight = QFont::Bold; break; case CSS_VAL_NORMAL: case CSS_VAL_LIGHTER: case CSS_VAL_100: case CSS_VAL_200: case CSS_VAL_300: case CSS_VAL_400: case CSS_VAL_500: fontDef.weight = QFont::Normal; break; default: return; } } else { // ### fix parsing of 100-900 values in parser, apply them here } } fontDirty |= style->setFontDef( fontDef ); break; } case CSS_PROP_LIST_STYLE_POSITION: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(listStylePosition, ListStylePosition) if (!primitiveValue) return; if (primitiveValue->getIdent()) style->setListStylePosition( (EListStylePosition) (primitiveValue->getIdent() - CSS_VAL_OUTSIDE) ); return; } case CSS_PROP_LIST_STYLE_TYPE: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(listStyleType, ListStyleType) if (!primitiveValue) return; if (primitiveValue->getIdent()) { EListStyleType t; int id = primitiveValue->getIdent(); if ( id == CSS_VAL_NONE) { // important!! t = LNONE; } else { t = EListStyleType(id - CSS_VAL_DISC); } style->setListStyleType(t); } return; } case CSS_PROP_OVERFLOW: { if (isInherit) { style->setOverflowX(parentStyle->overflowX()); style->setOverflowY(parentStyle->overflowY()); style->setInheritedNoninherited(true); return; } if (isInitial) { style->setOverflowX(RenderStyle::initialOverflowX()); style->setOverflowY(RenderStyle::initialOverflowY()); return; } if (!primitiveValue) return; EOverflow o; switch(primitiveValue->getIdent()) { case CSS_VAL_VISIBLE: o = OVISIBLE; break; case CSS_VAL_HIDDEN: o = OHIDDEN; break; case CSS_VAL_SCROLL: o = OSCROLL; break; case CSS_VAL_AUTO: o = OAUTO; break; case CSS_VAL_MARQUEE: o = OMARQUEE; break; default: return; } style->setOverflowX(o); style->setOverflowY(o); return; } case CSS_PROP_OVERFLOW_X: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(overflowX, OverflowX) if (!primitiveValue) return; EOverflow o; switch(primitiveValue->getIdent()) { case CSS_VAL_VISIBLE: o = OVISIBLE; break; case CSS_VAL_HIDDEN: o = OHIDDEN; break; case CSS_VAL_SCROLL: o = OSCROLL; break; case CSS_VAL_AUTO: o = OAUTO; break; default: return; } style->setOverflowX(o); return; } case CSS_PROP_OVERFLOW_Y: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(overflowY, OverflowY) if (!primitiveValue) return; EOverflow o; switch(primitiveValue->getIdent()) { case CSS_VAL_VISIBLE: o = OVISIBLE; break; case CSS_VAL_HIDDEN: o = OHIDDEN; break; case CSS_VAL_SCROLL: o = OSCROLL; break; case CSS_VAL_AUTO: o = OAUTO; break; default: return; } style->setOverflowY(o); return; } case CSS_PROP_PAGE_BREAK_BEFORE: { HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak) if (!primitiveValue) return; switch (primitiveValue->getIdent()) { case CSS_VAL_AUTO: style->setPageBreakBefore(PBAUTO); break; case CSS_VAL_LEFT: case CSS_VAL_RIGHT: // CSS2.1: "Conforming user agents may map left/right to always." case CSS_VAL_ALWAYS: style->setPageBreakBefore(PBALWAYS); break; case CSS_VAL_AVOID: style->setPageBreakBefore(PBAVOID); break; } break; } case CSS_PROP_PAGE_BREAK_AFTER: { HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak) if (!primitiveValue) return; switch (primitiveValue->getIdent()) { case CSS_VAL_AUTO: style->setPageBreakAfter(PBAUTO); break; case CSS_VAL_LEFT: case CSS_VAL_RIGHT: // CSS2.1: "Conforming user agents may map left/right to always." case CSS_VAL_ALWAYS: style->setPageBreakAfter(PBALWAYS); break; case CSS_VAL_AVOID: style->setPageBreakAfter(PBAVOID); break; } break; } case CSS_PROP_PAGE_BREAK_INSIDE: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(pageBreakInside, PageBreakInside) if (!primitiveValue) return; if (primitiveValue->getIdent() == CSS_VAL_AUTO) style->setPageBreakInside(true); else if (primitiveValue->getIdent() == CSS_VAL_AVOID) style->setPageBreakInside(false); return; } // case CSS_PROP_PAUSE_AFTER: // case CSS_PROP_PAUSE_BEFORE: break; case CSS_PROP_POSITION: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(position, Position) if (!primitiveValue) return; EPosition p; switch(primitiveValue->getIdent()) { case CSS_VAL_STATIC: p = STATIC; break; case CSS_VAL_RELATIVE: p = RELATIVE; break; case CSS_VAL_ABSOLUTE: p = ABSOLUTE; break; case CSS_VAL_FIXED: { view->setHasStaticBackground(); p = FIXED; break; } default: return; } style->setPosition(p); return; } case CSS_PROP_TABLE_LAYOUT: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(tableLayout, TableLayout) if ( !primitiveValue ) return; ETableLayout l = RenderStyle::initialTableLayout(); switch( primitiveValue->getIdent() ) { case CSS_VAL_FIXED: l = TFIXED; // fall through case CSS_VAL_AUTO: style->setTableLayout( l ); default: break; } break; } case CSS_PROP_UNICODE_BIDI: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(unicodeBidi, UnicodeBidi) if(!primitiveValue) break; switch (primitiveValue->getIdent()) { case CSS_VAL_NORMAL: style->setUnicodeBidi(UBNormal); break; case CSS_VAL_EMBED: style->setUnicodeBidi(Embed); break; case CSS_VAL_BIDI_OVERRIDE: style->setUnicodeBidi(Override); break; default: return; } break; } case CSS_PROP_TEXT_TRANSFORM: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(textTransform, TextTransform) if(!primitiveValue) break; if(!primitiveValue->getIdent()) return; ETextTransform tt; switch(primitiveValue->getIdent()) { case CSS_VAL_CAPITALIZE: tt = CAPITALIZE; break; case CSS_VAL_UPPERCASE: tt = UPPERCASE; break; case CSS_VAL_LOWERCASE: tt = LOWERCASE; break; case CSS_VAL_NONE: default: tt = TTNONE; break; } style->setTextTransform(tt); break; } case CSS_PROP_VISIBILITY: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(visibility, Visibility) if(!primitiveValue) break; switch( primitiveValue->getIdent() ) { case CSS_VAL_HIDDEN: style->setVisibility( HIDDEN ); break; case CSS_VAL_VISIBLE: style->setVisibility( VISIBLE ); break; case CSS_VAL_COLLAPSE: style->setVisibility( COLLAPSE ); default: break; } break; } case CSS_PROP_WHITE_SPACE: HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(whiteSpace, WhiteSpace) if(!primitiveValue) break; if(!primitiveValue->getIdent()) return; EWhiteSpace s; switch(primitiveValue->getIdent()) { case CSS_VAL__KHTML_NOWRAP: s = KHTML_NOWRAP; break; case CSS_VAL_NOWRAP: s = NOWRAP; break; case CSS_VAL_PRE: s = PRE; break; case CSS_VAL_PRE_WRAP: s = PRE_WRAP; break; case CSS_VAL_PRE_LINE: s = PRE_LINE; break; case CSS_VAL_NORMAL: default: s = NORMAL; break; } style->setWhiteSpace(s); break; case CSS_PROP_BACKGROUND_POSITION: HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundXPosition, BackgroundXPosition); HANDLE_BACKGROUND_INHERIT_AND_INITIAL(backgroundYPosition, BackgroundYPosition); break; case CSS_PROP_BACKGROUND_POSITION_X: { HANDLE_BACKGROUND_VALUE(backgroundXPosition, BackgroundXPosition, value) break; } case CSS_PROP_BACKGROUND_POSITION_Y: { HANDLE_BACKGROUND_VALUE(backgroundYPosition, BackgroundYPosition, value) break; } case CSS_PROP_BORDER_SPACING: { if(value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return; style->setBorderHorizontalSpacing(parentStyle->borderHorizontalSpacing()); style->setBorderVerticalSpacing(parentStyle->borderVerticalSpacing()); break; } case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(borderHorizontalSpacing, BorderHorizontalSpacing) if (!primitiveValue) break; short spacing = primitiveValue->computeLength(style, logicalDpiY); style->setBorderHorizontalSpacing(spacing); break; } case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(borderVerticalSpacing, BorderVerticalSpacing) if (!primitiveValue) break; short spacing = primitiveValue->computeLength(style, logicalDpiY); style->setBorderVerticalSpacing(spacing); break; } case CSS_PROP_CURSOR: HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(cursor, Cursor) - if(primitiveValue) - style->setCursor( (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO) ); + if (!primitiveValue) break; + ECursor cursor; + switch(primitiveValue->getIdent()) { + case CSS_VAL_NONE: + cursor = CURSOR_NONE; + break; + default: + cursor = (ECursor) (primitiveValue->getIdent() - CSS_VAL_AUTO); + } + style->setCursor(cursor); break; // colors || inherit case CSS_PROP_BACKGROUND_COLOR: case CSS_PROP_BORDER_TOP_COLOR: case CSS_PROP_BORDER_RIGHT_COLOR: case CSS_PROP_BORDER_BOTTOM_COLOR: case CSS_PROP_BORDER_LEFT_COLOR: case CSS_PROP_COLOR: case CSS_PROP_OUTLINE_COLOR: // this property is an extension used to get HTML4 right. case CSS_PROP_SCROLLBAR_BASE_COLOR: case CSS_PROP_SCROLLBAR_FACE_COLOR: case CSS_PROP_SCROLLBAR_SHADOW_COLOR: case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: case CSS_PROP_SCROLLBAR_TRACK_COLOR: case CSS_PROP_SCROLLBAR_ARROW_COLOR: { QColor col; if (isInherit) { if (id != CSS_PROP_COLOR) style->setInheritedNoninherited(true); HANDLE_INHERIT_COND(CSS_PROP_BACKGROUND_COLOR, backgroundColor, BackgroundColor) HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_COLOR, borderTopColor, BorderTopColor) HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_COLOR, borderBottomColor, BorderBottomColor) HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_COLOR, borderRightColor, BorderRightColor) HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_COLOR, borderLeftColor, BorderLeftColor) HANDLE_INHERIT_COND(CSS_PROP_COLOR, color, Color) HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_COLOR, outlineColor, OutlineColor) return; } else if (isInitial) { // The border/outline colors will just map to the invalid color |col| above. This will have the // effect of forcing the use of the currentColor when it comes time to draw the borders (and of // not painting the background since the color won't be valid). if (id == CSS_PROP_COLOR) col = RenderStyle::initialColor(); } else { if(!primitiveValue ) return; int ident = primitiveValue->getIdent(); if ( ident ) { if ( ident == CSS_VAL__KHTML_TEXT ) col = element->getDocument()->textColor(); else col = colorForCSSValue( ident ); } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR ) { col.setRgba(primitiveValue->getRGBColorValue()); } else { return; } } //kDebug( 6080 ) << "applying color " << col.isValid(); switch(id) { case CSS_PROP_BACKGROUND_COLOR: style->setBackgroundColor(col); break; case CSS_PROP_BORDER_TOP_COLOR: style->setBorderTopColor(col); break; case CSS_PROP_BORDER_RIGHT_COLOR: style->setBorderRightColor(col); break; case CSS_PROP_BORDER_BOTTOM_COLOR: style->setBorderBottomColor(col); break; case CSS_PROP_BORDER_LEFT_COLOR: style->setBorderLeftColor(col); break; case CSS_PROP_COLOR: style->setColor(col); break; case CSS_PROP_OUTLINE_COLOR: style->setOutlineColor(col); break; #ifndef APPLE_CHANGES case CSS_PROP_SCROLLBAR_FACE_COLOR: style->setPaletteColor(QPalette::Active, QPalette::Button, col); style->setPaletteColor(QPalette::Inactive, QPalette::Button, col); break; case CSS_PROP_SCROLLBAR_SHADOW_COLOR: style->setPaletteColor(QPalette::Active, QPalette::Shadow, col); style->setPaletteColor(QPalette::Inactive, QPalette::Shadow, col); break; case CSS_PROP_SCROLLBAR_HIGHLIGHT_COLOR: style->setPaletteColor(QPalette::Active, QPalette::Light, col); style->setPaletteColor(QPalette::Inactive, QPalette::Light, col); break; case CSS_PROP_SCROLLBAR_3DLIGHT_COLOR: break; case CSS_PROP_SCROLLBAR_DARKSHADOW_COLOR: style->setPaletteColor(QPalette::Active, QPalette::Dark, col); style->setPaletteColor(QPalette::Inactive, QPalette::Dark, col); break; case CSS_PROP_SCROLLBAR_TRACK_COLOR: style->setPaletteColor(QPalette::Active, QPalette::Mid, col); style->setPaletteColor(QPalette::Inactive, QPalette::Mid, col); style->setPaletteColor(QPalette::Active, QPalette::Background, col); style->setPaletteColor(QPalette::Inactive, QPalette::Background, col); // fall through case CSS_PROP_SCROLLBAR_BASE_COLOR: style->setPaletteColor(QPalette::Active, QPalette::Base, col); style->setPaletteColor(QPalette::Inactive, QPalette::Base, col); break; case CSS_PROP_SCROLLBAR_ARROW_COLOR: style->setPaletteColor(QPalette::Active, QPalette::ButtonText, col); style->setPaletteColor(QPalette::Inactive, QPalette::ButtonText, col); break; #endif default: return; } return; } break; // uri || inherit case CSS_PROP_BACKGROUND_IMAGE: HANDLE_BACKGROUND_VALUE(backgroundImage, BackgroundImage, value) break; case CSS_PROP_LIST_STYLE_IMAGE: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(listStyleImage, ListStyleImage) if (!primitiveValue) return; style->setListStyleImage(static_cast(primitiveValue)->image()); //kDebug( 6080 ) << "setting image in list to " << image->image(); break; } // length case CSS_PROP_BORDER_TOP_WIDTH: case CSS_PROP_BORDER_RIGHT_WIDTH: case CSS_PROP_BORDER_BOTTOM_WIDTH: case CSS_PROP_BORDER_LEFT_WIDTH: case CSS_PROP_OUTLINE_WIDTH: { if (isInherit) { style->setInheritedNoninherited(true); HANDLE_INHERIT_COND(CSS_PROP_BORDER_TOP_WIDTH, borderTopWidth, BorderTopWidth) HANDLE_INHERIT_COND(CSS_PROP_BORDER_RIGHT_WIDTH, borderRightWidth, BorderRightWidth) HANDLE_INHERIT_COND(CSS_PROP_BORDER_BOTTOM_WIDTH, borderBottomWidth, BorderBottomWidth) HANDLE_INHERIT_COND(CSS_PROP_BORDER_LEFT_WIDTH, borderLeftWidth, BorderLeftWidth) HANDLE_INHERIT_COND(CSS_PROP_OUTLINE_WIDTH, outlineWidth, OutlineWidth) return; } else if (isInitial) { HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_TOP_WIDTH, BorderTopWidth, BorderWidth) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_RIGHT_WIDTH, BorderRightWidth, BorderWidth) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_BOTTOM_WIDTH, BorderBottomWidth, BorderWidth) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BORDER_LEFT_WIDTH, BorderLeftWidth, BorderWidth) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_OUTLINE_WIDTH, OutlineWidth, BorderWidth) return; } if(!primitiveValue) break; short width = 3; switch(primitiveValue->getIdent()) { case CSS_VAL_THIN: width = 1; break; case CSS_VAL_MEDIUM: width = 3; break; case CSS_VAL_THICK: width = 5; break; case CSS_VAL_INVALID: { double widthd = primitiveValue->computeLengthFloat(style, logicalDpiY); width = (int)widthd; // somewhat resemble Mozilla's granularity // this makes border-width: 0.5pt borders visible if (width == 0 && widthd >= 0.025) width++; break; } default: return; } if(width < 0) return; switch(id) { case CSS_PROP_BORDER_TOP_WIDTH: style->setBorderTopWidth(width); break; case CSS_PROP_BORDER_RIGHT_WIDTH: style->setBorderRightWidth(width); break; case CSS_PROP_BORDER_BOTTOM_WIDTH: style->setBorderBottomWidth(width); break; case CSS_PROP_BORDER_LEFT_WIDTH: style->setBorderLeftWidth(width); break; case CSS_PROP_OUTLINE_WIDTH: style->setOutlineWidth(width); break; default: return; } return; } case CSS_PROP_LETTER_SPACING: case CSS_PROP_WORD_SPACING: { if (isInherit) { HANDLE_INHERIT_COND(CSS_PROP_LETTER_SPACING, letterSpacing, LetterSpacing) HANDLE_INHERIT_COND(CSS_PROP_WORD_SPACING, wordSpacing, WordSpacing) return; } else if (isInitial) { HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LETTER_SPACING, LetterSpacing, LetterWordSpacing) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WORD_SPACING, WordSpacing, LetterWordSpacing) return; } if(!primitiveValue) return; int width = 0; if (primitiveValue->getIdent() != CSS_VAL_NORMAL) width = primitiveValue->computeLength(style, logicalDpiY); switch(id) { case CSS_PROP_LETTER_SPACING: style->setLetterSpacing(width); break; case CSS_PROP_WORD_SPACING: style->setWordSpacing(width); break; // ### needs the definitions in renderstyle default: break; } return; } // length, percent case CSS_PROP_MAX_WIDTH: // +none +inherit if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { apply = true; l = Length(UNDEFINED, Fixed); } case CSS_PROP_TOP: case CSS_PROP_LEFT: case CSS_PROP_RIGHT: case CSS_PROP_BOTTOM: case CSS_PROP_WIDTH: case CSS_PROP_MIN_WIDTH: case CSS_PROP_MARGIN_TOP: case CSS_PROP_MARGIN_RIGHT: case CSS_PROP_MARGIN_BOTTOM: case CSS_PROP_MARGIN_LEFT: // +inherit +auto if(id != CSS_PROP_MAX_WIDTH && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO) { //kDebug( 6080 ) << "found value=auto"; apply = true; } case CSS_PROP_PADDING_TOP: case CSS_PROP_PADDING_RIGHT: case CSS_PROP_PADDING_BOTTOM: case CSS_PROP_PADDING_LEFT: case CSS_PROP_TEXT_INDENT: // +inherit { if (isInherit) { if (id != CSS_PROP_TEXT_INDENT) style->setInheritedNoninherited(true); HANDLE_INHERIT_COND(CSS_PROP_MAX_WIDTH, maxWidth, MaxWidth) HANDLE_INHERIT_COND(CSS_PROP_BOTTOM, bottom, Bottom) HANDLE_INHERIT_COND(CSS_PROP_TOP, top, Top) HANDLE_INHERIT_COND(CSS_PROP_LEFT, left, Left) HANDLE_INHERIT_COND(CSS_PROP_RIGHT, right, Right) HANDLE_INHERIT_COND(CSS_PROP_WIDTH, width, Width) HANDLE_INHERIT_COND(CSS_PROP_MIN_WIDTH, minWidth, MinWidth) HANDLE_INHERIT_COND(CSS_PROP_PADDING_TOP, paddingTop, PaddingTop) HANDLE_INHERIT_COND(CSS_PROP_PADDING_RIGHT, paddingRight, PaddingRight) HANDLE_INHERIT_COND(CSS_PROP_PADDING_BOTTOM, paddingBottom, PaddingBottom) HANDLE_INHERIT_COND(CSS_PROP_PADDING_LEFT, paddingLeft, PaddingLeft) HANDLE_INHERIT_COND(CSS_PROP_MARGIN_TOP, marginTop, MarginTop) HANDLE_INHERIT_COND(CSS_PROP_MARGIN_RIGHT, marginRight, MarginRight) HANDLE_INHERIT_COND(CSS_PROP_MARGIN_BOTTOM, marginBottom, MarginBottom) HANDLE_INHERIT_COND(CSS_PROP_MARGIN_LEFT, marginLeft, MarginLeft) HANDLE_INHERIT_COND(CSS_PROP_TEXT_INDENT, textIndent, TextIndent) return; } else if (isInitial) { HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_WIDTH, MaxWidth, MaxSize) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_BOTTOM, Bottom, Offset) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_TOP, Top, Offset) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_LEFT, Left, Offset) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_RIGHT, Right, Offset) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_WIDTH, Width, Size) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_WIDTH, MinWidth, MinSize) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_TOP, PaddingTop, Padding) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_RIGHT, PaddingRight, Padding) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_BOTTOM, PaddingBottom, Padding) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_PADDING_LEFT, PaddingLeft, Padding) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_TOP, MarginTop, Margin) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_RIGHT, MarginRight, Margin) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_BOTTOM, MarginBottom, Margin) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MARGIN_LEFT, MarginLeft, Margin) HANDLE_INITIAL_COND(CSS_PROP_TEXT_INDENT, TextIndent) return; } if (primitiveValue && !apply) { int type = primitiveValue->primitiveType(); if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) // Handle our quirky margin units if we have them. l = Length(primitiveValue->computeLength(style, logicalDpiY), Fixed, primitiveValue->isQuirkValue()); else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else if (type == CSSPrimitiveValue::CSS_HTML_RELATIVE) l = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_HTML_RELATIVE)), Relative); else return; apply = true; } if(!apply) return; switch(id) { case CSS_PROP_MAX_WIDTH: style->setMaxWidth(l); break; case CSS_PROP_BOTTOM: style->setBottom(l); break; case CSS_PROP_TOP: style->setTop(l); break; case CSS_PROP_LEFT: style->setLeft(l); break; case CSS_PROP_RIGHT: style->setRight(l); break; case CSS_PROP_WIDTH: style->setWidth(l); break; case CSS_PROP_MIN_WIDTH: style->setMinWidth(l); break; case CSS_PROP_PADDING_TOP: style->setPaddingTop(l); break; case CSS_PROP_PADDING_RIGHT: style->setPaddingRight(l); break; case CSS_PROP_PADDING_BOTTOM: style->setPaddingBottom(l); break; case CSS_PROP_PADDING_LEFT: style->setPaddingLeft(l); break; case CSS_PROP_MARGIN_TOP: style->setMarginTop(l); break; case CSS_PROP_MARGIN_RIGHT: style->setMarginRight(l); break; case CSS_PROP_MARGIN_BOTTOM: style->setMarginBottom(l); break; case CSS_PROP_MARGIN_LEFT: style->setMarginLeft(l); break; case CSS_PROP_TEXT_INDENT: style->setTextIndent(l); break; default: break; } return; } case CSS_PROP_MAX_HEIGHT: if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { apply = true; l = Length(UNDEFINED, Fixed); } case CSS_PROP_HEIGHT: case CSS_PROP_MIN_HEIGHT: if(id != CSS_PROP_MAX_HEIGHT && primitiveValue && primitiveValue->getIdent() == CSS_VAL_AUTO) apply = true; if (isInherit) { style->setInheritedNoninherited(true); HANDLE_INHERIT_COND(CSS_PROP_MAX_HEIGHT, maxHeight, MaxHeight) HANDLE_INHERIT_COND(CSS_PROP_HEIGHT, height, Height) HANDLE_INHERIT_COND(CSS_PROP_MIN_HEIGHT, minHeight, MinHeight) return; } else if (isInitial) { HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MAX_HEIGHT, MaxHeight, MaxSize) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_HEIGHT, Height, Size) HANDLE_INITIAL_COND_WITH_VALUE(CSS_PROP_MIN_HEIGHT, MinHeight, MinSize) return; } if (primitiveValue && !apply) { int type = primitiveValue->primitiveType(); if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) l = Length(primitiveValue->computeLength(style, logicalDpiY), Fixed); else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else return; apply = true; } if(!apply) return; switch(id) { case CSS_PROP_MAX_HEIGHT: style->setMaxHeight(l); break; case CSS_PROP_HEIGHT: style->setHeight(l); break; case CSS_PROP_MIN_HEIGHT: style->setMinHeight(l); break; default: return; } return; break; case CSS_PROP_VERTICAL_ALIGN: HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(verticalAlign, VerticalAlign) if (!primitiveValue) return; if (primitiveValue->getIdent()) { khtml::EVerticalAlign align; switch(primitiveValue->getIdent()) { case CSS_VAL_TOP: align = TOP; break; case CSS_VAL_BOTTOM: align = BOTTOM; break; case CSS_VAL_MIDDLE: align = MIDDLE; break; case CSS_VAL_BASELINE: align = BASELINE; break; case CSS_VAL_TEXT_BOTTOM: align = TEXT_BOTTOM; break; case CSS_VAL_TEXT_TOP: align = TEXT_TOP; break; case CSS_VAL_SUB: align = SUB; break; case CSS_VAL_SUPER: align = SUPER; break; case CSS_VAL__KHTML_BASELINE_MIDDLE: align = BASELINE_MIDDLE; break; default: return; } style->setVerticalAlign(align); return; } else { int type = primitiveValue->primitiveType(); Length l; if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) l = Length(primitiveValue->computeLength(style, logicalDpiY), Fixed ); else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) l = Length( int( primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE) ), Percent ); style->setVerticalAlign( LENGTH ); style->setVerticalAlignLength( l ); } break; case CSS_PROP_FONT_SIZE: { FontDef fontDef = style->htmlFont().fontDef; int oldSize; int size = 0; float toPix = logicalDpiY/72.0f; if (toPix < 96.0f/72.0f) toPix = 96.0f/72.0f; int minFontSize = int(settings->minFontSize() * toPix); if(parentNode) { oldSize = parentStyle->font().pixelSize(); } else oldSize = m_fontSizes[3]; if (isInherit ) size = oldSize; else if (isInitial) size = m_fontSizes[3]; else if(primitiveValue->getIdent()) { // keywords are being used. Pick the correct default // based off the font family. #ifdef APPLE_CHANGES const QVector& fontSizes = (fontDef.genericFamily == FontDef::eMonospace) ? m_fixedFontSizes : m_fontSizes; #else const QVector& fontSizes = m_fontSizes; #endif switch(primitiveValue->getIdent()) { case CSS_VAL_XX_SMALL: size = int( fontSizes[0] ); break; case CSS_VAL_X_SMALL: size = int( fontSizes[1] ); break; case CSS_VAL_SMALL: size = int( fontSizes[2] ); break; case CSS_VAL_MEDIUM: size = int( fontSizes[3] ); break; case CSS_VAL_LARGE: size = int( fontSizes[4] ); break; case CSS_VAL_X_LARGE: size = int( fontSizes[5] ); break; case CSS_VAL_XX_LARGE: size = int( fontSizes[6] ); break; case CSS_VAL__KHTML_XXX_LARGE: size = int( fontSizes[7] ); break; case CSS_VAL_LARGER: size = nextFontSize(fontSizes, oldSize, false); break; case CSS_VAL_SMALLER: size = nextFontSize(fontSizes, oldSize, true); break; default: return; } } else { int type = primitiveValue->primitiveType(); if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) { if ( !khtml::printpainter && type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->part()) size = int( primitiveValue->computeLengthFloat(parentStyle, logicalDpiY) * view->part()->fontScaleFactor() ) / 100; else size = int( primitiveValue->computeLengthFloat(parentStyle, logicalDpiY) ); } else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) size = int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE) * parentStyle->font().pixelSize()) / 100; else return; } if (size < 0) return; // we never want to get smaller than the minimum font size to keep fonts readable // do not however maximize zero as that is commonly used for fancy layouting purposes if (size && size < minFontSize) size = minFontSize; //kDebug( 6080 ) << "computed raw font size: " << size; fontDef.size = size; fontDirty |= style->setFontDef( fontDef ); return; } case CSS_PROP_Z_INDEX: { HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(zIndex, ZIndex) else if (isInitial) { style->setHasAutoZIndex(); return; } if (!primitiveValue) return; if (primitiveValue->getIdent() == CSS_VAL_AUTO) { style->setHasAutoZIndex(); return; } if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) return; // Error case. style->setZIndex((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)); return; } case CSS_PROP_WIDOWS: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(widows, Widows) if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) return; style->setWidows((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)); break; } case CSS_PROP_ORPHANS: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(orphans, Orphans) if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) return; style->setOrphans((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)); break; } // length, percent, number case CSS_PROP_LINE_HEIGHT: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(lineHeight, LineHeight) if(!primitiveValue) return; Length lineHeight; int type = primitiveValue->primitiveType(); if (primitiveValue->getIdent() == CSS_VAL_NORMAL) lineHeight = Length( -100, Percent ); else if (type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) { // Scale for the font zoom factor only for types other than "em" and "ex", since those are // already based on the font size. if ( !khtml::printpainter && type != CSSPrimitiveValue::CSS_EMS && type != CSSPrimitiveValue::CSS_EXS && view && view->part()) lineHeight = Length(primitiveValue->computeLength(style, logicalDpiY) * view->part()->fontScaleFactor()/100, Fixed ); else lineHeight = Length(primitiveValue->computeLength(style, logicalDpiY), Fixed ); } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) lineHeight = Length( ( style->font().pixelSize() * int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE)) ) / 100, Fixed ); else if (type == CSSPrimitiveValue::CSS_NUMBER) lineHeight = Length(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)*100), Percent); else return; style->setLineHeight(lineHeight); return; } // string case CSS_PROP_TEXT_ALIGN: { HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(textAlign, TextAlign) if (!primitiveValue) return; if (primitiveValue->getIdent()) style->setTextAlign( (ETextAlign) (primitiveValue->getIdent() - CSS_VAL__KHTML_AUTO) ); return; } // rect case CSS_PROP_CLIP: { Length top = Length(); Length right = Length(); Length bottom = Length(); Length left = Length(); bool hasClip = false; if (isInherit && parentStyle->hasClip()) { hasClip = true; top = parentStyle->clipTop(); right = parentStyle->clipRight(); bottom = parentStyle->clipBottom(); left = parentStyle->clipLeft(); } else if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) { RectImpl *rect = primitiveValue->getRectValue(); if (rect) { hasClip = true; top = convertToLength( rect->top(), style, logicalDpiY ); right = convertToLength( rect->right(), style, logicalDpiY ); bottom = convertToLength( rect->bottom(), style, logicalDpiY ); left = convertToLength( rect->left(), style, logicalDpiY ); } } style->setClip(top, right, bottom, left); style->setHasClip(hasClip); // rect, ident break; } // lists case CSS_PROP_CONTENT: // list of string, uri, counter, attr, i { // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This // note is a reminder that eventually "inherit" needs to be supported. // not allowed on non-generated pseudo-elements: if ( style->styleType()==RenderStyle::FIRST_LETTER || style->styleType()==RenderStyle::FIRST_LINE || style->styleType()==RenderStyle::SELECTION ) break; if (isInitial) { style->setContentNormal(); return; } if (primitiveValue && primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT) { // normal | none if (primitiveValue->getIdent() == CSS_VAL_NORMAL) style->setContentNormal(); else if (primitiveValue->getIdent() == CSS_VAL_NONE) style->setContentNone(); else assert(false); return; } if(!value->isValueList()) return; CSSValueListImpl *list = static_cast(value); int len = list->length(); style->setContentNormal(); // clear the content for(int i = 0; i < len; i++) { CSSValueImpl *item = list->item(i); if(!item->isPrimitiveValue()) continue; CSSPrimitiveValueImpl *val = static_cast(item); if(val->primitiveType()==CSSPrimitiveValue::CSS_STRING) { style->addContent(val->getStringValue()); } else if (val->primitiveType()==CSSPrimitiveValue::CSS_ATTR) { // TODO: setup dynamic attribute dependencies int attrID = element->getDocument()->getId(NodeImpl::AttributeId, val->getStringValue(), false, true); if (attrID) style->addContent(element->getAttribute(attrID).implementation()); else kDebug(6080) << "Attribute \"" << val->getStringValue() << "\" not found"; } else if (val->primitiveType()==CSSPrimitiveValue::CSS_URI) { CSSImageValueImpl *image = static_cast(val); style->addContent(image->image()); } else if (val->primitiveType()==CSSPrimitiveValue::CSS_COUNTER) { style->addContent(val->getCounterValue()); } else if (val->primitiveType()==CSSPrimitiveValue::CSS_IDENT) { EQuoteContent quote; switch (val->getIdent()) { case CSS_VAL_OPEN_QUOTE: quote = OPEN_QUOTE; break; case CSS_VAL_NO_OPEN_QUOTE: quote = NO_OPEN_QUOTE; break; case CSS_VAL_CLOSE_QUOTE: quote = CLOSE_QUOTE; break; case CSS_VAL_NO_CLOSE_QUOTE: quote = NO_CLOSE_QUOTE; break; default: assert(false); } style->addContent(quote); } else kDebug(6080) << "Unrecognized CSS content"; } break; } case CSS_PROP_COUNTER_INCREMENT: { if(!value->isValueList()) return; CSSValueListImpl *list = static_cast(value); style->setCounterIncrement(list); break; } case CSS_PROP_COUNTER_RESET: { if(!value->isValueList()) return; CSSValueListImpl *list = static_cast(value); style->setCounterReset(list); break; } case CSS_PROP_FONT_FAMILY: // list of strings and ids { if (isInherit) { FontDef parentFontDef = parentStyle->htmlFont().fontDef; FontDef fontDef = style->htmlFont().fontDef; fontDef.family = parentFontDef.family; if (style->setFontDef(fontDef)) fontDirty = true; return; } else if (isInitial) { FontDef fontDef = style->htmlFont().fontDef; FontDef initialDef = FontDef(); #ifdef APPLE_CHANGES fontDef.family = initialDef.firstFamily(); #else fontDef.family.clear(); #endif if (style->setFontDef(fontDef)) fontDirty = true; return; } if(!value->isValueList()) return; FontDef fontDef = style->htmlFont().fontDef; CSSValueListImpl *list = static_cast(value); int len = list->length(); for(int i = 0; i < len; i++) { CSSValueImpl *item = list->item(i); if(!item->isPrimitiveValue()) continue; CSSPrimitiveValueImpl *val = static_cast(item); QString face; if( val->primitiveType() == CSSPrimitiveValue::CSS_STRING ) face = static_cast(val)->fontName(); else if ( val->primitiveType() == CSSPrimitiveValue::CSS_IDENT ) { switch( val->getIdent() ) { case CSS_VAL_SERIF: face = settings->serifFontName(); break; case CSS_VAL_SANS_SERIF: face = settings->sansSerifFontName(); break; case CSS_VAL_CURSIVE: face = settings->cursiveFontName(); break; case CSS_VAL_FANTASY: face = settings->fantasyFontName(); break; case CSS_VAL_MONOSPACE: face = settings->fixedFontName(); break; default: return; } } else { return; } if ( !face.isEmpty() ) { fontDef.family = face; fontDirty |= style->setFontDef( fontDef ); return; } } break; } case CSS_PROP_QUOTES: HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(quotes, Quotes) if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { // set a set of empty quotes QuotesValueImpl* quotes = new QuotesValueImpl(); style->setQuotes(quotes); } else { QuotesValueImpl* quotes = static_cast(value); style->setQuotes(quotes); } break; case CSS_PROP_SIZE: // ### look up break; case CSS_PROP_TEXT_DECORATION: { // list of ident HANDLE_INITIAL_AND_INHERIT_ON_INHERITED_PROPERTY(textDecoration, TextDecoration) int t = RenderStyle::initialTextDecoration(); if(primitiveValue && primitiveValue->getIdent() == CSS_VAL_NONE) { // do nothing } else { if(!value->isValueList()) return; CSSValueListImpl *list = static_cast(value); int len = list->length(); for(int i = 0; i < len; i++) { CSSValueImpl *item = list->item(i); if(!item->isPrimitiveValue()) continue; primitiveValue = static_cast(item); switch(primitiveValue->getIdent()) { case CSS_VAL_NONE: t = TDNONE; break; case CSS_VAL_UNDERLINE: t |= UNDERLINE; break; case CSS_VAL_OVERLINE: t |= OVERLINE; break; case CSS_VAL_LINE_THROUGH: t |= LINE_THROUGH; break; case CSS_VAL_BLINK: t |= BLINK; break; default: return; } } } style->setTextDecoration(t); break; } case CSS_PROP__KHTML_FLOW_MODE: HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(flowAroundFloats, FlowAroundFloats) if (!primitiveValue) return; if (primitiveValue->getIdent()) { style->setFlowAroundFloats( primitiveValue->getIdent() == CSS_VAL__KHTML_AROUND_FLOATS ); return; } break; case CSS_PROP__KHTML_USER_INPUT: { if(value->cssValueType() == CSSValue::CSS_INHERIT) { if(!parentNode) return; style->setUserInput(parentStyle->userInput()); // kDebug() << "UI erm"; return; } if(!primitiveValue) return; int id = primitiveValue->getIdent(); if (id == CSS_VAL_NONE) style->setUserInput(UI_NONE); else style->setUserInput(EUserInput(id - CSS_VAL_ENABLED)); // kDebug(6080) << "userInput: " << style->userEdit(); return; } // shorthand properties case CSS_PROP_BACKGROUND: if (isInitial) { style->setBackgroundColor(QColor()); return; } else if (isInherit) { style->inheritBackgroundLayers(*parentStyle->backgroundLayers()); style->setBackgroundColor(parentStyle->backgroundColor()); } break; case CSS_PROP_BORDER: case CSS_PROP_BORDER_STYLE: case CSS_PROP_BORDER_WIDTH: case CSS_PROP_BORDER_COLOR: if (isInherit) style->setInheritedNoninherited(true); if(id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_COLOR) { if (isInherit) { style->setBorderTopColor(parentStyle->borderTopColor()); style->setBorderBottomColor(parentStyle->borderBottomColor()); style->setBorderLeftColor(parentStyle->borderLeftColor()); style->setBorderRightColor(parentStyle->borderRightColor()); } else if (isInitial) { style->setBorderTopColor(QColor()); // Reset to invalid color so currentColor is used instead. style->setBorderBottomColor(QColor()); style->setBorderLeftColor(QColor()); style->setBorderRightColor(QColor()); } } if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_STYLE) { if (isInherit) { style->setBorderTopStyle(parentStyle->borderTopStyle()); style->setBorderBottomStyle(parentStyle->borderBottomStyle()); style->setBorderLeftStyle(parentStyle->borderLeftStyle()); style->setBorderRightStyle(parentStyle->borderRightStyle()); } else if (isInitial) { style->setBorderTopStyle(RenderStyle::initialBorderStyle()); style->setBorderBottomStyle(RenderStyle::initialBorderStyle()); style->setBorderLeftStyle(RenderStyle::initialBorderStyle()); style->setBorderRightStyle(RenderStyle::initialBorderStyle()); } } if (id == CSS_PROP_BORDER || id == CSS_PROP_BORDER_WIDTH) { if (isInherit) { style->setBorderTopWidth(parentStyle->borderTopWidth()); style->setBorderBottomWidth(parentStyle->borderBottomWidth()); style->setBorderLeftWidth(parentStyle->borderLeftWidth()); style->setBorderRightWidth(parentStyle->borderRightWidth()); } else if (isInitial) { style->setBorderTopWidth(RenderStyle::initialBorderWidth()); style->setBorderBottomWidth(RenderStyle::initialBorderWidth()); style->setBorderLeftWidth(RenderStyle::initialBorderWidth()); style->setBorderRightWidth(RenderStyle::initialBorderWidth()); } } return; case CSS_PROP_BORDER_TOP: if ( isInherit ) { style->setInheritedNoninherited(true); style->setBorderTopColor(parentStyle->borderTopColor()); style->setBorderTopStyle(parentStyle->borderTopStyle()); style->setBorderTopWidth(parentStyle->borderTopWidth()); } else if (isInitial) style->resetBorderTop(); return; case CSS_PROP_BORDER_RIGHT: if (isInherit) { style->setInheritedNoninherited(true); style->setBorderRightColor(parentStyle->borderRightColor()); style->setBorderRightStyle(parentStyle->borderRightStyle()); style->setBorderRightWidth(parentStyle->borderRightWidth()); } else if (isInitial) style->resetBorderRight(); return; case CSS_PROP_BORDER_BOTTOM: if (isInherit) { style->setInheritedNoninherited(true); style->setBorderBottomColor(parentStyle->borderBottomColor()); style->setBorderBottomStyle(parentStyle->borderBottomStyle()); style->setBorderBottomWidth(parentStyle->borderBottomWidth()); } else if (isInitial) style->resetBorderBottom(); return; case CSS_PROP_BORDER_LEFT: if (isInherit) { style->setInheritedNoninherited(true); style->setBorderLeftColor(parentStyle->borderLeftColor()); style->setBorderLeftStyle(parentStyle->borderLeftStyle()); style->setBorderLeftWidth(parentStyle->borderLeftWidth()); } else if (isInitial) style->resetBorderLeft(); return; case CSS_PROP_MARGIN: if (isInherit) { style->setInheritedNoninherited(true); style->setMarginTop(parentStyle->marginTop()); style->setMarginBottom(parentStyle->marginBottom()); style->setMarginLeft(parentStyle->marginLeft()); style->setMarginRight(parentStyle->marginRight()); } else if (isInitial) style->resetMargin(); return; case CSS_PROP_PADDING: if (isInherit) { style->setInheritedNoninherited(true); style->setPaddingTop(parentStyle->paddingTop()); style->setPaddingBottom(parentStyle->paddingBottom()); style->setPaddingLeft(parentStyle->paddingLeft()); style->setPaddingRight(parentStyle->paddingRight()); } else if (isInitial) style->resetPadding(); return; case CSS_PROP_FONT: if ( isInherit ) { FontDef fontDef = parentStyle->htmlFont().fontDef; style->setLineHeight( parentStyle->lineHeight() ); fontDirty |= style->setFontDef( fontDef ); } else if (isInitial) { FontDef fontDef; style->setLineHeight(RenderStyle::initialLineHeight()); if (style->setFontDef( fontDef )) fontDirty = true; } else if ( value->isFontValue() ) { FontValueImpl *font = static_cast(value); if ( !font->style || !font->variant || !font->weight || !font->size || !font->lineHeight || !font->family ) return; applyRule( CSS_PROP_FONT_STYLE, font->style ); applyRule( CSS_PROP_FONT_VARIANT, font->variant ); applyRule( CSS_PROP_FONT_WEIGHT, font->weight ); applyRule( CSS_PROP_FONT_SIZE, font->size ); // Line-height can depend on font().pixelSize(), so we have to update the font // before we evaluate line-height, e.g., font: 1em/1em. FIXME: Still not // good enough: style="font:1em/1em; font-size:36px" should have a line-height of 36px. if (fontDirty) CSSStyleSelector::style->htmlFont().update( logicalDpiY ); applyRule( CSS_PROP_LINE_HEIGHT, font->lineHeight ); applyRule( CSS_PROP_FONT_FAMILY, font->family ); } return; case CSS_PROP_LIST_STYLE: if (isInherit) { style->setListStyleType(parentStyle->listStyleType()); style->setListStyleImage(parentStyle->listStyleImage()); style->setListStylePosition(parentStyle->listStylePosition()); } else if (isInitial) { style->setListStyleType(RenderStyle::initialListStyleType()); style->setListStyleImage(RenderStyle::initialListStyleImage()); style->setListStylePosition(RenderStyle::initialListStylePosition()); } break; case CSS_PROP_OUTLINE: if (isInherit) { style->setOutlineWidth(parentStyle->outlineWidth()); style->setOutlineColor(parentStyle->outlineColor()); style->setOutlineStyle(parentStyle->outlineStyle()); } else if (isInitial) style->resetOutline(); break; /* CSS3 properties */ case CSS_PROP_BOX_SIZING: HANDLE_INHERIT_ON_NONINHERITED_PROPERTY(boxSizing, BoxSizing) if (!primitiveValue) return; if (primitiveValue->getIdent() == CSS_VAL_CONTENT_BOX) style->setBoxSizing(CONTENT_BOX); else if (primitiveValue->getIdent() == CSS_VAL_BORDER_BOX) style->setBoxSizing(BORDER_BOX); break; case CSS_PROP_OUTLINE_OFFSET: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(outlineOffset, OutlineOffset) int offset = primitiveValue->computeLength(style, logicalDpiY); if (offset < 0) return; style->setOutlineOffset(offset); break; } case CSS_PROP_TEXT_SHADOW: { if (isInherit) { style->setTextShadow(parentStyle->textShadow() ? new ShadowData(*parentStyle->textShadow()) : 0); return; } else if (isInitial) { style->setTextShadow(0); return; } if (primitiveValue) { // none style->setTextShadow(0); return; } if (!value->isValueList()) return; CSSValueListImpl *list = static_cast(value); int len = list->length(); for (int i = 0; i < len; i++) { ShadowValueImpl *item = static_cast(list->item(i)); int x = item->x->computeLength(style, logicalDpiY); int y = item->y->computeLength(style, logicalDpiY); int blur = item->blur ? item->blur->computeLength(style, logicalDpiY) : 0; QColor col = khtml::transparentColor; if (item->color) { int ident = item->color->getIdent(); if (ident) col = colorForCSSValue( ident ); else if (item->color->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR) col.setRgb(item->color->getRGBColorValue()); } ShadowData* shadowData = new ShadowData(x, y, blur, col); style->setTextShadow(shadowData, i != 0); } break; } case CSS_PROP_OPACITY: HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(opacity, Opacity) if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER) return; // Error case. // Clamp opacity to the range 0-1 style->setOpacity(qMin(1.0f, qMax(0.0f, (float)primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER)))); break; case CSS_PROP__KHTML_MARQUEE: if (value->cssValueType() != CSSValue::CSS_INHERIT || !parentNode) return; style->setMarqueeDirection(parentStyle->marqueeDirection()); style->setMarqueeIncrement(parentStyle->marqueeIncrement()); style->setMarqueeSpeed(parentStyle->marqueeSpeed()); style->setMarqueeLoopCount(parentStyle->marqueeLoopCount()); style->setMarqueeBehavior(parentStyle->marqueeBehavior()); break; case CSS_PROP__KHTML_MARQUEE_REPETITION: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeLoopCount, MarqueeLoopCount) if (!primitiveValue) return; if (primitiveValue->getIdent() == CSS_VAL_INFINITE) style->setMarqueeLoopCount(-1); // -1 means repeat forever. else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) style->setMarqueeLoopCount((int)(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER))); break; } case CSS_PROP__KHTML_MARQUEE_SPEED: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeSpeed, MarqueeSpeed) if (!primitiveValue) return; if (primitiveValue->getIdent()) { switch (primitiveValue->getIdent()) { case CSS_VAL_SLOW: style->setMarqueeSpeed(500); // 500 msec. break; case CSS_VAL_NORMAL: style->setMarqueeSpeed(85); // 85msec. The WinIE default. break; case CSS_VAL_FAST: style->setMarqueeSpeed(10); // 10msec. Super fast. break; } } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) style->setMarqueeSpeed(int(1000*primitiveValue->floatValue(CSSPrimitiveValue::CSS_S))); else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_MS))); else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support. style->setMarqueeSpeed(int(primitiveValue->floatValue(CSSPrimitiveValue::CSS_NUMBER))); break; } case CSS_PROP__KHTML_MARQUEE_INCREMENT: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeIncrement, MarqueeIncrement) if (!primitiveValue) return; if (primitiveValue->getIdent()) { switch (primitiveValue->getIdent()) { case CSS_VAL_SMALL: style->setMarqueeIncrement(Length(1, Fixed)); // 1px. break; case CSS_VAL_NORMAL: style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default. break; case CSS_VAL_LARGE: style->setMarqueeIncrement(Length(36, Fixed)); // 36px. break; } } else { bool ok = true; Length l = convertToLength(primitiveValue, style, logicalDpiY, &ok); if (ok) style->setMarqueeIncrement(l); } break; } case CSS_PROP__KHTML_MARQUEE_STYLE: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeBehavior, MarqueeBehavior) if (!primitiveValue || !primitiveValue->getIdent()) return; switch (primitiveValue->getIdent()) { case CSS_VAL_NONE: style->setMarqueeBehavior(MNONE); break; case CSS_VAL_SCROLL: style->setMarqueeBehavior(MSCROLL); break; case CSS_VAL_SLIDE: style->setMarqueeBehavior(MSLIDE); break; case CSS_VAL_ALTERNATE: style->setMarqueeBehavior(MALTERNATE); break; case CSS_VAL_UNFURL: style->setMarqueeBehavior(MUNFURL); break; } break; } case CSS_PROP__KHTML_MARQUEE_DIRECTION: { HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(marqueeDirection, MarqueeDirection) if (!primitiveValue || !primitiveValue->getIdent()) return; switch (primitiveValue->getIdent()) { case CSS_VAL_FORWARDS: style->setMarqueeDirection(MFORWARD); break; case CSS_VAL_BACKWARDS: style->setMarqueeDirection(MBACKWARD); break; case CSS_VAL_AUTO: style->setMarqueeDirection(MAUTO); break; case CSS_VAL_AHEAD: case CSS_VAL_UP: // We don't support vertical languages, so AHEAD just maps to UP. style->setMarqueeDirection(MUP); break; case CSS_VAL_REVERSE: case CSS_VAL_DOWN: // REVERSE just maps to DOWN, since we don't do vertical text. style->setMarqueeDirection(MDOWN); break; case CSS_VAL_LEFT: style->setMarqueeDirection(MLEFT); break; case CSS_VAL_RIGHT: style->setMarqueeDirection(MRIGHT); break; } break; case CSS_PROP_TEXT_OVERFLOW: { // This property is supported by WinIE, and so we leave off the "-khtml-" in order to // work with WinIE-specific pages that use the property. HANDLE_INITIAL_AND_INHERIT_ON_NONINHERITED_PROPERTY(textOverflow, TextOverflow) if (!primitiveValue || !primitiveValue->getIdent()) return; style->setTextOverflow(primitiveValue->getIdent() == CSS_VAL_ELLIPSIS); break; } } default: return; } } void CSSStyleSelector::mapBackgroundAttachment(BackgroundLayer* layer, DOM::CSSValueImpl* value) { if (value->cssValueType() == CSSValue::CSS_INITIAL) { layer->setBackgroundAttachment(RenderStyle::initialBackgroundAttachment()); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValueImpl* primitiveValue = static_cast(value); switch (primitiveValue->getIdent()) { case CSS_VAL_FIXED: layer->setBackgroundAttachment(false); break; case CSS_VAL_SCROLL: layer->setBackgroundAttachment(true); break; default: return; } } void CSSStyleSelector::mapBackgroundClip(BackgroundLayer* layer, CSSValueImpl* value) { if (value->cssValueType() == CSSValue::CSS_INITIAL) { layer->setBackgroundClip(RenderStyle::initialBackgroundClip()); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValueImpl* primitiveValue = static_cast(value); switch (primitiveValue->getIdent()) { case CSS_VAL_BORDER: layer->setBackgroundClip(BGBORDER); break; case CSS_VAL_PADDING: layer->setBackgroundClip(BGPADDING); break; default: // CSS_VAL_CONTENT layer->setBackgroundClip(BGCONTENT); break; } } void CSSStyleSelector::mapBackgroundOrigin(BackgroundLayer* layer, CSSValueImpl* value) { if (value->cssValueType() == CSSValue::CSS_INITIAL) { layer->setBackgroundOrigin(RenderStyle::initialBackgroundOrigin()); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValueImpl* primitiveValue = static_cast(value); switch (primitiveValue->getIdent()) { case CSS_VAL_BORDER: layer->setBackgroundOrigin(BGBORDER); break; case CSS_VAL_PADDING: layer->setBackgroundOrigin(BGPADDING); break; default: // CSS_VAL_CONTENT layer->setBackgroundOrigin(BGCONTENT); break; } } void CSSStyleSelector::mapBackgroundImage(BackgroundLayer* layer, DOM::CSSValueImpl* value) { if (value->cssValueType() == CSSValue::CSS_INITIAL) { layer->setBackgroundImage(RenderStyle::initialBackgroundImage()); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValueImpl* primitiveValue = static_cast(value); layer->setBackgroundImage(static_cast(primitiveValue)->image()); } void CSSStyleSelector::mapBackgroundRepeat(BackgroundLayer* layer, DOM::CSSValueImpl* value) { if (value->cssValueType() == CSSValue::CSS_INITIAL) { layer->setBackgroundRepeat(RenderStyle::initialBackgroundRepeat()); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValueImpl* primitiveValue = static_cast(value); switch(primitiveValue->getIdent()) { case CSS_VAL_REPEAT: layer->setBackgroundRepeat(REPEAT); break; case CSS_VAL_REPEAT_X: layer->setBackgroundRepeat(REPEAT_X); break; case CSS_VAL_REPEAT_Y: layer->setBackgroundRepeat(REPEAT_Y); break; case CSS_VAL_NO_REPEAT: layer->setBackgroundRepeat(NO_REPEAT); break; default: return; } } void CSSStyleSelector::mapBackgroundSize(BackgroundLayer* layer, CSSValueImpl* value) { LengthSize b = RenderStyle::initialBackgroundSize(); if (value->cssValueType() == CSSValue::CSS_INITIAL) { layer->setBackgroundSize(b); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValueImpl* primitiveValue = static_cast(value); PairImpl* pair = primitiveValue->getPairValue(); if (!pair) return; CSSPrimitiveValueImpl* first = static_cast(pair->first()); CSSPrimitiveValueImpl* second = static_cast(pair->second()); if (!first || !second) return; Length firstLength, secondLength; int firstType = first->primitiveType(); int secondType = second->primitiveType(); if (firstType == CSSPrimitiveValue::CSS_UNKNOWN) firstLength = Length(Variable); else if (firstType > CSSPrimitiveValue::CSS_PERCENTAGE && firstType < CSSPrimitiveValue::CSS_DEG) firstLength = Length(first->computeLength(style, logicalDpiY), Fixed); else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE) firstLength = Length((int)first->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else return; if (secondType == CSSPrimitiveValue::CSS_UNKNOWN) secondLength = Length(Variable); else if (secondType > CSSPrimitiveValue::CSS_PERCENTAGE && secondType < CSSPrimitiveValue::CSS_DEG) secondLength = Length(second->computeLength(style, logicalDpiY), Fixed); else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE) secondLength = Length((int)second->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else return; b.width = firstLength; b.height = secondLength; layer->setBackgroundSize(b); } void CSSStyleSelector::mapBackgroundXPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value) { if (value->cssValueType() == CSSValue::CSS_INITIAL) { layer->setBackgroundXPosition(RenderStyle::initialBackgroundXPosition()); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValueImpl* primitiveValue = static_cast(value); Length l; int type = primitiveValue->primitiveType(); if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) l = Length(primitiveValue->computeLength(style, logicalDpiY), Fixed); else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else return; layer->setBackgroundXPosition(l); } void CSSStyleSelector::mapBackgroundYPosition(BackgroundLayer* layer, DOM::CSSValueImpl* value) { if (value->cssValueType() == CSSValue::CSS_INITIAL) { layer->setBackgroundYPosition(RenderStyle::initialBackgroundYPosition()); return; } if (!value->isPrimitiveValue()) return; CSSPrimitiveValueImpl* primitiveValue = static_cast(value); Length l; int type = primitiveValue->primitiveType(); if(type > CSSPrimitiveValue::CSS_PERCENTAGE && type < CSSPrimitiveValue::CSS_DEG) l = Length(primitiveValue->computeLength(style, logicalDpiY), Fixed); else if(type == CSSPrimitiveValue::CSS_PERCENTAGE) l = Length((int)primitiveValue->floatValue(CSSPrimitiveValue::CSS_PERCENTAGE), Percent); else return; layer->setBackgroundYPosition(l); } #ifdef APPLE_CHANGES void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* aStyle, RenderStyle* aParentStyle) { const FontDef& childFont = aStyle->htmlFont().fontDef; if (childFont.sizeSpecified || !aParentStyle) return; const FontDef& parentFont = aParentStyle->htmlFont().fontDef; if (childFont.genericFamily == parentFont.genericFamily) return; // For now, lump all families but monospace together. if (childFont.genericFamily != FontDef::eMonospace && parentFont.genericFamily != FontDef::eMonospace) return; // We know the parent is monospace or the child is monospace, and that font // size was unspecified. We want to alter our font size to use the correct // "medium" font for our family. float size = 0; int minFontSize = settings->minFontSize(); size = (childFont.genericFamily == FontDef::eMonospace) ? m_fixedFontSizes[3] : m_fontSizes[3]; int isize = (int)size; if (isize < minFontSize) isize = minFontSize; FontDef newFontDef(childFont); newFontDef.size = isize; aStyle->setFontDef(newFontDef); } #endif } // namespace khtml // kate: space-indent on; indent-width 4; tab-width 8; diff --git a/khtml/css/cssvalues.c b/khtml/css/cssvalues.c index 03e5fa6c7c..45beff59aa 100644 --- a/khtml/css/cssvalues.c +++ b/khtml/css/cssvalues.c @@ -1,1359 +1,1263 @@ -/* ANSI-C code produced by gperf version 3.0.1 */ +/* ANSI-C code produced by gperf version 3.0.2 */ /* Command-line: gperf -L ANSI-C -E -c -C -n -o -t -k '*' -NfindValue -Hhash_val -Wwordlist_value -D cssvalues.gperf */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif #line 1 "cssvalues.gperf" /* This file is automatically generated from cssvalues.in by makevalues, do not edit */ /* Copyright 1999 W. Bastian */ #include "cssvalues.h" #line 6 "cssvalues.gperf" struct css_value { const char *name; int id; }; static const css_value * findValue (register const char *str, register unsigned int len); -/* maximum key range = 3056, duplicates = 0 */ +/* maximum key range = 1680, duplicates = 0 */ #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static unsigned int hash_val (register const char *str, register unsigned int len) { static const unsigned short asso_values[] = { - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 420, 225, 3056, 0, 0, - 105, 100, 40, 35, 20, 15, 10, 5, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 175, 60, 0, - 20, 45, 235, 380, 270, 5, 113, 65, 0, 35, - 0, 5, 265, 465, 100, 20, 5, 195, 223, 13, - 3, 68, 10, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, 3056, - 3056, 3056, 3056, 3056, 3056, 3056, 3056 + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 70, 378, 1680, 0, 0, + 160, 80, 55, 50, 35, 30, 20, 5, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 0, 55, 10, + 95, 5, 190, 435, 3, 80, 113, 70, 0, 5, + 130, 20, 0, 16, 5, 0, 120, 105, 166, 238, + 38, 290, 390, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, 1680, + 1680, 1680, 1680, 1680, 1680, 1680, 1680 }; register int hval = 0; switch (len) { default: hval += asso_values[(unsigned char)str[27]]; /*FALLTHROUGH*/ case 27: hval += asso_values[(unsigned char)str[26]]; /*FALLTHROUGH*/ case 26: hval += asso_values[(unsigned char)str[25]]; /*FALLTHROUGH*/ case 25: hval += asso_values[(unsigned char)str[24]]; /*FALLTHROUGH*/ case 24: hval += asso_values[(unsigned char)str[23]]; /*FALLTHROUGH*/ case 23: hval += asso_values[(unsigned char)str[22]]; /*FALLTHROUGH*/ case 22: hval += asso_values[(unsigned char)str[21]]; /*FALLTHROUGH*/ case 21: hval += asso_values[(unsigned char)str[20]]; /*FALLTHROUGH*/ case 20: hval += asso_values[(unsigned char)str[19]]; /*FALLTHROUGH*/ case 19: hval += asso_values[(unsigned char)str[18]]; /*FALLTHROUGH*/ case 18: hval += asso_values[(unsigned char)str[17]]; /*FALLTHROUGH*/ case 17: hval += asso_values[(unsigned char)str[16]]; /*FALLTHROUGH*/ case 16: hval += asso_values[(unsigned char)str[15]]; /*FALLTHROUGH*/ case 15: hval += asso_values[(unsigned char)str[14]]; /*FALLTHROUGH*/ case 14: hval += asso_values[(unsigned char)str[13]]; /*FALLTHROUGH*/ case 13: hval += asso_values[(unsigned char)str[12]]; /*FALLTHROUGH*/ case 12: hval += asso_values[(unsigned char)str[11]]; /*FALLTHROUGH*/ case 11: hval += asso_values[(unsigned char)str[10]]; /*FALLTHROUGH*/ case 10: hval += asso_values[(unsigned char)str[9]]; /*FALLTHROUGH*/ case 9: hval += asso_values[(unsigned char)str[8]]; /*FALLTHROUGH*/ case 8: hval += asso_values[(unsigned char)str[7]]; /*FALLTHROUGH*/ case 7: hval += asso_values[(unsigned char)str[6]]; /*FALLTHROUGH*/ case 6: hval += asso_values[(unsigned char)str[5]]; /*FALLTHROUGH*/ case 5: hval += asso_values[(unsigned char)str[4]]; /*FALLTHROUGH*/ case 4: - hval += asso_values[(unsigned char)str[3]]; + hval += asso_values[(unsigned char)str[3]+1]; /*FALLTHROUGH*/ case 3: hval += asso_values[(unsigned char)str[2]+1]; /*FALLTHROUGH*/ case 2: hval += asso_values[(unsigned char)str[1]]; /*FALLTHROUGH*/ case 1: hval += asso_values[(unsigned char)str[0]]; break; } return hval; } #ifdef __GNUC__ __inline #endif const struct css_value * findValue (register const char *str, register unsigned int len) { enum { - TOTAL_KEYWORDS = 274, + TOTAL_KEYWORDS = 288, MIN_WORD_LENGTH = 2, MAX_WORD_LENGTH = 28, MIN_HASH_VALUE = 0, - MAX_HASH_VALUE = 3055 + MAX_HASH_VALUE = 1679 }; static const struct css_value wordlist_value[] = { #line 40 "cssvalues.gperf" {"100", CSS_VAL_100}, #line 48 "cssvalues.gperf" {"900", CSS_VAL_900}, +#line 53 "cssvalues.gperf" + {"large", CSS_VAL_LARGE}, +#line 272 "cssvalues.gperf" + {"scroll", CSS_VAL_SCROLL}, +#line 58 "cssvalues.gperf" + {"larger", CSS_VAL_LARGER}, +#line 89 "cssvalues.gperf" + {"red", CSS_VAL_RED}, +#line 204 "cssvalues.gperf" + {"progress", CSS_VAL_PROGRESS}, #line 47 "cssvalues.gperf" {"800", CSS_VAL_800}, +#line 206 "cssvalues.gperf" + {"cell", CSS_VAL_CELL}, +#line 258 "cssvalues.gperf" + {"hand", CSS_VAL_HAND}, +#line 202 "cssvalues.gperf" + {"help", CSS_VAL_HELP}, #line 46 "cssvalues.gperf" {"700", CSS_VAL_700}, +#line 254 "cssvalues.gperf" + {"crop", CSS_VAL_CROP}, #line 45 "cssvalues.gperf" {"600", CSS_VAL_600}, -#line 216 "cssvalues.gperf" - {"ltr", CSS_VAL_LTR}, -#line 276 "cssvalues.gperf" - {"down", CSS_VAL_DOWN}, -#line 146 "cssvalues.gperf" - {"disc", CSS_VAL_DISC}, +#line 291 "cssvalues.gperf" + {"slow", CSS_VAL_SLOW}, +#line 262 "cssvalues.gperf" + {"landscape", CSS_VAL_LANDSCAPE}, +#line 274 "cssvalues.gperf" + {"show", CSS_VAL_SHOW}, +#line 236 "cssvalues.gperf" + {"collapse", CSS_VAL_COLLAPSE}, #line 44 "cssvalues.gperf" {"500", CSS_VAL_500}, #line 43 "cssvalues.gperf" {"400", CSS_VAL_400}, -#line 258 "cssvalues.gperf" - {"scroll", CSS_VAL_SCROLL}, -#line 83 "cssvalues.gperf" - {"lime", CSS_VAL_LIME}, -#line 17 "cssvalues.gperf" - {"none", CSS_VAL_NONE}, -#line 19 "cssvalues.gperf" - {"inset", CSS_VAL_INSET}, -#line 118 "cssvalues.gperf" - {"window", CSS_VAL_WINDOW}, -#line 286 "cssvalues.gperf" - {"content", CSS_VAL_CONTENT}, -#line 147 "cssvalues.gperf" - {"circle", CSS_VAL_CIRCLE}, -#line 33 "cssvalues.gperf" - {"italic", CSS_VAL_ITALIC}, -#line 145 "cssvalues.gperf" - {"inside", CSS_VAL_INSIDE}, -#line 25 "cssvalues.gperf" - {"solid", CSS_VAL_SOLID}, -#line 183 "cssvalues.gperf" - {"inline", CSS_VAL_INLINE}, -#line 261 "cssvalues.gperf" - {"static", CSS_VAL_STATIC}, -#line 204 "cssvalues.gperf" - {"move", CSS_VAL_MOVE}, -#line 42 "cssvalues.gperf" - {"300", CSS_VAL_300}, -#line 249 "cssvalues.gperf" - {"level", CSS_VAL_LEVEL}, -#line 41 "cssvalues.gperf" - {"200", CSS_VAL_200}, -#line 254 "cssvalues.gperf" - {"mix", CSS_VAL_MIX}, -#line 91 "cssvalues.gperf" - {"teal", CSS_VAL_TEAL}, +#line 73 "cssvalues.gperf" + {"monospace", CSS_VAL_MONOSPACE}, #line 51 "cssvalues.gperf" {"small", CSS_VAL_SMALL}, -#line 120 "cssvalues.gperf" - {"windowtext", CSS_VAL_WINDOWTEXT}, +#line 112 "cssvalues.gperf" + {"scrollbar", CSS_VAL_SCROLLBAR}, +#line 57 "cssvalues.gperf" + {"smaller", CSS_VAL_SMALLER}, +#line 42 "cssvalues.gperf" + {"300", CSS_VAL_300}, #line 37 "cssvalues.gperf" {"bold", CSS_VAL_BOLD}, -#line 213 "cssvalues.gperf" - {"text", CSS_VAL_TEXT}, -#line 149 "cssvalues.gperf" - {"box", CSS_VAL_BOX}, -#line 217 "cssvalues.gperf" - {"rtl", CSS_VAL_RTL}, -#line 242 "cssvalues.gperf" - {"embed", CSS_VAL_EMBED}, +#line 299 "cssvalues.gperf" + {"border", CSS_VAL_BORDER}, +#line 38 "cssvalues.gperf" + {"bolder", CSS_VAL_BOLDER}, +#line 21 "cssvalues.gperf" + {"ridge", CSS_VAL_RIDGE}, #line 128 "cssvalues.gperf" {"middle", CSS_VAL_MIDDLE}, -#line 252 "cssvalues.gperf" - {"lower", CSS_VAL_LOWER}, -#line 236 "cssvalues.gperf" - {"below", CSS_VAL_BELOW}, -#line 63 "cssvalues.gperf" - {"condensed", CSS_VAL_CONDENSED}, -#line 14 "cssvalues.gperf" - {"inherit", CSS_VAL_INHERIT}, -#line 93 "cssvalues.gperf" - {"yellow", CSS_VAL_YELLOW}, -#line 247 "cssvalues.gperf" - {"invert", CSS_VAL_INVERT}, -#line 76 "cssvalues.gperf" - {"black", CSS_VAL_BLACK}, -#line 89 "cssvalues.gperf" - {"red", CSS_VAL_RED}, -#line 280 "cssvalues.gperf" - {"slide", CSS_VAL_SLIDE}, -#line 139 "cssvalues.gperf" - {"center", CSS_VAL_CENTER}, -#line 59 "cssvalues.gperf" - {"wider", CSS_VAL_WIDER}, +#line 289 "cssvalues.gperf" + {"up", CSS_VAL_UP}, +#line 28 "cssvalues.gperf" + {"icon", CSS_VAL_ICON}, #line 129 "cssvalues.gperf" {"sub", CSS_VAL_SUB}, +#line 230 "cssvalues.gperf" + {"ltr", CSS_VAL_LTR}, +#line 294 "cssvalues.gperf" + {"slide", CSS_VAL_SLIDE}, +#line 267 "cssvalues.gperf" + {"marquee", CSS_VAL_MARQUEE}, +#line 88 "cssvalues.gperf" + {"purple", CSS_VAL_PURPLE}, +#line 231 "cssvalues.gperf" + {"rtl", CSS_VAL_RTL}, +#line 255 "cssvalues.gperf" + {"cross", CSS_VAL_CROSS}, +#line 297 "cssvalues.gperf" + {"clip", CSS_VAL_CLIP}, #line 189 "cssvalues.gperf" {"table", CSS_VAL_TABLE}, -#line 269 "cssvalues.gperf" - {"enabled", CSS_VAL_ENABLED}, -#line 36 "cssvalues.gperf" - {"normal", CSS_VAL_NORMAL}, -#line 238 "cssvalues.gperf" - {"blink", CSS_VAL_BLINK}, +#line 35 "cssvalues.gperf" + {"small-caps", CSS_VAL_SMALL_CAPS}, +#line 139 "cssvalues.gperf" + {"center", CSS_VAL_CENTER}, #line 84 "cssvalues.gperf" {"maroon", CSS_VAL_MAROON}, -#line 251 "cssvalues.gperf" +#line 133 "cssvalues.gperf" + {"top", CSS_VAL_TOP}, +#line 41 "cssvalues.gperf" + {"200", CSS_VAL_200}, +#line 96 "cssvalues.gperf" + {"appworkspace", CSS_VAL_APPWORKSPACE}, +#line 210 "cssvalues.gperf" + {"alias", CSS_VAL_ALIAS}, +#line 290 "cssvalues.gperf" + {"down", CSS_VAL_DOWN}, +#line 260 "cssvalues.gperf" + {"higher", CSS_VAL_HIGHER}, +#line 91 "cssvalues.gperf" + {"teal", CSS_VAL_TEAL}, +#line 241 "cssvalues.gperf" + {"nowrap", CSS_VAL_NOWRAP}, +#line 147 "cssvalues.gperf" + {"circle", CSS_VAL_CIRCLE}, +#line 265 "cssvalues.gperf" {"loud", CSS_VAL_LOUD}, -#line 285 "cssvalues.gperf" - {"border", CSS_VAL_BORDER}, -#line 85 "cssvalues.gperf" - {"navy", CSS_VAL_NAVY}, -#line 57 "cssvalues.gperf" - {"smaller", CSS_VAL_SMALLER}, -#line 38 "cssvalues.gperf" - {"bolder", CSS_VAL_BOLDER}, -#line 28 "cssvalues.gperf" - {"icon", CSS_VAL_ICON}, -#line 78 "cssvalues.gperf" - {"crimson", CSS_VAL_CRIMSON}, +#line 242 "cssvalues.gperf" + {"pre", CSS_VAL_PRE}, #line 29 "cssvalues.gperf" {"menu", CSS_VAL_MENU}, -#line 23 "cssvalues.gperf" - {"dotted", CSS_VAL_DOTTED}, -#line 277 "cssvalues.gperf" - {"slow", CSS_VAL_SLOW}, -#line 151 "cssvalues.gperf" - {"decimal", CSS_VAL_DECIMAL}, -#line 15 "cssvalues.gperf" - {"initial", CSS_VAL_INITIAL}, -#line 134 "cssvalues.gperf" - {"bottom", CSS_VAL_BOTTOM}, -#line 214 "cssvalues.gperf" - {"wait", CSS_VAL_WAIT}, -#line 69 "cssvalues.gperf" - {"serif", CSS_VAL_SERIF}, -#line 77 "cssvalues.gperf" - {"blue", CSS_VAL_BLUE}, -#line 270 "cssvalues.gperf" - {"disabled", CSS_VAL_DISABLED}, -#line 127 "cssvalues.gperf" - {"baseline", CSS_VAL_BASELINE}, -#line 111 "cssvalues.gperf" - {"menutext", CSS_VAL_MENUTEXT}, -#line 221 "cssvalues.gperf" - {"visible", CSS_VAL_VISIBLE}, -#line 26 "cssvalues.gperf" - {"double", CSS_VAL_DOUBLE}, -#line 52 "cssvalues.gperf" - {"medium", CSS_VAL_MEDIUM}, -#line 245 "cssvalues.gperf" - {"hide", CSS_VAL_HIDE}, -#line 274 "cssvalues.gperf" - {"reverse", CSS_VAL_REVERSE}, -#line 243 "cssvalues.gperf" - {"fixed", CSS_VAL_FIXED}, -#line 283 "cssvalues.gperf" - {"clip", CSS_VAL_CLIP}, -#line 112 "cssvalues.gperf" - {"scrollbar", CSS_VAL_SCROLLBAR}, +#line 298 "cssvalues.gperf" + {"ellipsis", CSS_VAL_ELLIPSIS}, +#line 273 "cssvalues.gperf" + {"separate", CSS_VAL_SEPARATE}, +#line 199 "cssvalues.gperf" + {"auto", CSS_VAL_AUTO}, +#line 184 "cssvalues.gperf" + {"block", CSS_VAL_BLOCK}, +#line 207 "cssvalues.gperf" + {"crosshair", CSS_VAL_CROSSHAIR}, +#line 197 "cssvalues.gperf" + {"table-cell", CSS_VAL_TABLE_CELL}, #line 18 "cssvalues.gperf" {"hidden", CSS_VAL_HIDDEN}, -#line 86 "cssvalues.gperf" - {"olive", CSS_VAL_OLIVE}, -#line 263 "cssvalues.gperf" +#line 25 "cssvalues.gperf" + {"solid", CSS_VAL_SOLID}, +#line 75 "cssvalues.gperf" + {"aqua", CSS_VAL_AQUA}, +#line 52 "cssvalues.gperf" + {"medium", CSS_VAL_MEDIUM}, +#line 148 "cssvalues.gperf" + {"square", CSS_VAL_SQUARE}, +#line 266 "cssvalues.gperf" + {"lower", CSS_VAL_LOWER}, +#line 277 "cssvalues.gperf" {"thin", CSS_VAL_THIN}, -#line 184 "cssvalues.gperf" - {"block", CSS_VAL_BLOCK}, -#line 220 "cssvalues.gperf" - {"lowercase", CSS_VAL_LOWERCASE}, -#line 284 "cssvalues.gperf" - {"ellipsis", CSS_VAL_ELLIPSIS}, -#line 241 "cssvalues.gperf" - {"cross", CSS_VAL_CROSS}, -#line 278 "cssvalues.gperf" - {"fast", CSS_VAL_FAST}, -#line 90 "cssvalues.gperf" - {"silver", CSS_VAL_SILVER}, -#line 137 "cssvalues.gperf" - {"left", CSS_VAL_LEFT}, -#line 264 "cssvalues.gperf" - {"underline", CSS_VAL_UNDERLINE}, -#line 82 "cssvalues.gperf" - {"indigo", CSS_VAL_INDIGO}, +#line 252 "cssvalues.gperf" + {"blink", CSS_VAL_BLINK}, +#line 253 "cssvalues.gperf" + {"both", CSS_VAL_BOTH}, +#line 161 "cssvalues.gperf" + {"hebrew", CSS_VAL_HEBREW}, #line 234 "cssvalues.gperf" - {"always", CSS_VAL_ALWAYS}, -#line 279 "cssvalues.gperf" - {"infinite", CSS_VAL_INFINITE}, -#line 92 "cssvalues.gperf" - {"white", CSS_VAL_WHITE}, -#line 110 "cssvalues.gperf" - {"infotext", CSS_VAL_INFOTEXT}, -#line 187 "cssvalues.gperf" - {"compact", CSS_VAL_COMPACT}, -#line 262 "cssvalues.gperf" - {"thick", CSS_VAL_THICK}, -#line 60 "cssvalues.gperf" - {"narrower", CSS_VAL_NARROWER}, -#line 275 "cssvalues.gperf" - {"up", CSS_VAL_UP}, -#line 49 "cssvalues.gperf" - {"xx-small", CSS_VAL_XX_SMALL}, -#line 207 "cssvalues.gperf" - {"nw-resize", CSS_VAL_NW_RESIZE}, -#line 22 "cssvalues.gperf" - {"outset", CSS_VAL_OUTSET}, -#line 244 "cssvalues.gperf" - {"hand", CSS_VAL_HAND}, -#line 161 "cssvalues.gperf" - {"hebrew", CSS_VAL_HEBREW}, -#line 133 "cssvalues.gperf" - {"top", CSS_VAL_TOP}, -#line 210 "cssvalues.gperf" - {"sw-resize", CSS_VAL_SW_RESIZE}, -#line 144 "cssvalues.gperf" - {"outside", CSS_VAL_OUTSIDE}, -#line 233 "cssvalues.gperf" - {"absolute", CSS_VAL_ABSOLUTE}, -#line 206 "cssvalues.gperf" - {"ne-resize", CSS_VAL_NE_RESIZE}, -#line 162 "cssvalues.gperf" - {"armenian", CSS_VAL_ARMENIAN}, -#line 71 "cssvalues.gperf" - {"cursive", CSS_VAL_CURSIVE}, -#line 209 "cssvalues.gperf" - {"se-resize", CSS_VAL_SE_RESIZE}, -#line 101 "cssvalues.gperf" - {"buttontext", CSS_VAL_BUTTONTEXT}, -#line 185 "cssvalues.gperf" - {"list-item", CSS_VAL_LIST_ITEM}, -#line 239 "cssvalues.gperf" - {"both", CSS_VAL_BOTH}, -#line 202 "cssvalues.gperf" + {"lowercase", CSS_VAL_LOWERCASE}, +#line 281 "cssvalues.gperf" + {"border-box", CSS_VAL_BORDER_BOX}, +#line 76 "cssvalues.gperf" + {"black", CSS_VAL_BLACK}, +#line 259 "cssvalues.gperf" + {"hide", CSS_VAL_HIDE}, +#line 36 "cssvalues.gperf" + {"normal", CSS_VAL_NORMAL}, +#line 203 "cssvalues.gperf" {"pointer", CSS_VAL_POINTER}, -#line 24 "cssvalues.gperf" - {"dashed", CSS_VAL_DASHED}, -#line 222 "cssvalues.gperf" - {"collapse", CSS_VAL_COLLAPSE}, -#line 227 "cssvalues.gperf" - {"nowrap", CSS_VAL_NOWRAP}, -#line 268 "cssvalues.gperf" - {"content-box", CSS_VAL_CONTENT_BOX}, -#line 73 "cssvalues.gperf" - {"monospace", CSS_VAL_MONOSPACE}, -#line 208 "cssvalues.gperf" - {"n-resize", CSS_VAL_N_RESIZE}, -#line 260 "cssvalues.gperf" - {"show", CSS_VAL_SHOW}, -#line 199 "cssvalues.gperf" - {"auto", CSS_VAL_AUTO}, -#line 21 "cssvalues.gperf" - {"ridge", CSS_VAL_RIDGE}, -#line 212 "cssvalues.gperf" - {"w-resize", CSS_VAL_W_RESIZE}, +#line 138 "cssvalues.gperf" + {"right", CSS_VAL_RIGHT}, +#line 63 "cssvalues.gperf" + {"condensed", CSS_VAL_CONDENSED}, +#line 39 "cssvalues.gperf" + {"lighter", CSS_VAL_LIGHTER}, +#line 26 "cssvalues.gperf" + {"double", CSS_VAL_DOUBLE}, +#line 246 "cssvalues.gperf" + {"above", CSS_VAL_ABOVE}, +#line 283 "cssvalues.gperf" + {"enabled", CSS_VAL_ENABLED}, +#line 250 "cssvalues.gperf" + {"below", CSS_VAL_BELOW}, #line 256 "cssvalues.gperf" + {"embed", CSS_VAL_EMBED}, +#line 187 "cssvalues.gperf" + {"compact", CSS_VAL_COMPACT}, +#line 69 "cssvalues.gperf" + {"serif", CSS_VAL_SERIF}, +#line 134 "cssvalues.gperf" + {"bottom", CSS_VAL_BOTTOM}, +#line 151 "cssvalues.gperf" + {"decimal", CSS_VAL_DECIMAL}, +#line 130 "cssvalues.gperf" + {"super", CSS_VAL_SUPER}, +#line 34 "cssvalues.gperf" + {"oblique", CSS_VAL_OBLIQUE}, +#line 173 "cssvalues.gperf" + {"lower-alpha", CSS_VAL_LOWER_ALPHA}, +#line 270 "cssvalues.gperf" {"portrait", CSS_VAL_PORTRAIT}, -#line 211 "cssvalues.gperf" - {"s-resize", CSS_VAL_S_RESIZE}, -#line 271 "cssvalues.gperf" +#line 233 "cssvalues.gperf" + {"uppercase", CSS_VAL_UPPERCASE}, +#line 90 "cssvalues.gperf" + {"silver", CSS_VAL_SILVER}, +#line 123 "cssvalues.gperf" + {"repeat", CSS_VAL_REPEAT}, +#line 287 "cssvalues.gperf" + {"ahead", CSS_VAL_AHEAD}, +#line 285 "cssvalues.gperf" {"forwards", CSS_VAL_FORWARDS}, -#line 87 "cssvalues.gperf" - {"orange", CSS_VAL_ORANGE}, -#line 228 "cssvalues.gperf" - {"pre", CSS_VAL_PRE}, -#line 80 "cssvalues.gperf" - {"gray", CSS_VAL_GRAY}, -#line 205 "cssvalues.gperf" - {"e-resize", CSS_VAL_E_RESIZE}, -#line 255 "cssvalues.gperf" - {"overline", CSS_VAL_OVERLINE}, -#line 215 "cssvalues.gperf" - {"help", CSS_VAL_HELP}, -#line 53 "cssvalues.gperf" - {"large", CSS_VAL_LARGE}, -#line 140 "cssvalues.gperf" - {"justify", CSS_VAL_JUSTIFY}, -#line 240 "cssvalues.gperf" - {"crop", CSS_VAL_CROP}, -#line 257 "cssvalues.gperf" - {"relative", CSS_VAL_RELATIVE}, +#line 33 "cssvalues.gperf" + {"italic", CSS_VAL_ITALIC}, #line 50 "cssvalues.gperf" {"x-small", CSS_VAL_X_SMALL}, -#line 188 "cssvalues.gperf" - {"inline-block", CSS_VAL_INLINE_BLOCK}, -#line 64 "cssvalues.gperf" - {"semi-condensed", CSS_VAL_SEMI_CONDENSED}, -#line 272 "cssvalues.gperf" - {"backwards", CSS_VAL_BACKWARDS}, -#line 138 "cssvalues.gperf" - {"right", CSS_VAL_RIGHT}, -#line 119 "cssvalues.gperf" - {"windowframe", CSS_VAL_WINDOWFRAME}, +#line 17 "cssvalues.gperf" + {"none", CSS_VAL_NONE}, #line 27 "cssvalues.gperf" {"caption", CSS_VAL_CAPTION}, -#line 132 "cssvalues.gperf" - {"text-bottom", CSS_VAL_TEXT_BOTTOM}, -#line 103 "cssvalues.gperf" - {"graytext", CSS_VAL_GRAYTEXT}, -#line 106 "cssvalues.gperf" - {"inactiveborder", CSS_VAL_INACTIVEBORDER}, -#line 72 "cssvalues.gperf" - {"fantasy", CSS_VAL_FANTASY}, -#line 235 "cssvalues.gperf" +#line 149 "cssvalues.gperf" + {"box", CSS_VAL_BOX}, +#line 275 "cssvalues.gperf" + {"static", CSS_VAL_STATIC}, +#line 249 "cssvalues.gperf" {"avoid", CSS_VAL_AVOID}, -#line 197 "cssvalues.gperf" - {"table-cell", CSS_VAL_TABLE_CELL}, -#line 39 "cssvalues.gperf" - {"lighter", CSS_VAL_LIGHTER}, +#line 268 "cssvalues.gperf" + {"mix", CSS_VAL_MIX}, +#line 86 "cssvalues.gperf" + {"olive", CSS_VAL_OLIVE}, #line 248 "cssvalues.gperf" - {"landscape", CSS_VAL_LANDSCAPE}, -#line 102 "cssvalues.gperf" - {"captiontext", CSS_VAL_CAPTIONTEXT}, -#line 58 "cssvalues.gperf" - {"larger", CSS_VAL_LARGER}, -#line 186 "cssvalues.gperf" - {"run-in", CSS_VAL_RUN_IN}, -#line 267 "cssvalues.gperf" - {"border-box", CSS_VAL_BORDER_BOX}, -#line 281 "cssvalues.gperf" - {"alternate", CSS_VAL_ALTERNATE}, -#line 174 "cssvalues.gperf" - {"lower-latin", CSS_VAL_LOWER_LATIN}, -#line 81 "cssvalues.gperf" - {"green", CSS_VAL_GREEN}, -#line 194 "cssvalues.gperf" - {"table-row", CSS_VAL_TABLE_ROW}, -#line 232 "cssvalues.gperf" - {"above", CSS_VAL_ABOVE}, + {"always", CSS_VAL_ALWAYS}, +#line 175 "cssvalues.gperf" + {"upper-alpha", CSS_VAL_UPPER_ALPHA}, +#line 146 "cssvalues.gperf" + {"disc", CSS_VAL_DISC}, +#line 24 "cssvalues.gperf" + {"dashed", CSS_VAL_DASHED}, +#line 60 "cssvalues.gperf" + {"narrower", CSS_VAL_NARROWER}, +#line 83 "cssvalues.gperf" + {"lime", CSS_VAL_LIME}, +#line 276 "cssvalues.gperf" + {"thick", CSS_VAL_THICK}, +#line 247 "cssvalues.gperf" + {"absolute", CSS_VAL_ABSOLUTE}, +#line 78 "cssvalues.gperf" + {"crimson", CSS_VAL_CRIMSON}, +#line 300 "cssvalues.gperf" + {"content", CSS_VAL_CONTENT}, +#line 77 "cssvalues.gperf" + {"blue", CSS_VAL_BLUE}, +#line 292 "cssvalues.gperf" + {"fast", CSS_VAL_FAST}, +#line 229 "cssvalues.gperf" + {"all-scroll", CSS_VAL_ALL_SCROLL}, +#line 154 "cssvalues.gperf" + {"-khtml-lao", CSS_VAL__KHTML_LAO}, +#line 23 "cssvalues.gperf" + {"dotted", CSS_VAL_DOTTED}, +#line 178 "cssvalues.gperf" + {"katakana", CSS_VAL_KATAKANA}, +#line 263 "cssvalues.gperf" + {"level", CSS_VAL_LEVEL}, +#line 211 "cssvalues.gperf" + {"copy", CSS_VAL_COPY}, #line 66 "cssvalues.gperf" {"expanded", CSS_VAL_EXPANDED}, +#line 271 "cssvalues.gperf" + {"relative", CSS_VAL_RELATIVE}, +#line 124 "cssvalues.gperf" + {"repeat-x", CSS_VAL_REPEAT_X}, +#line 288 "cssvalues.gperf" + {"reverse", CSS_VAL_REVERSE}, +#line 212 "cssvalues.gperf" + {"move", CSS_VAL_MOVE}, +#line 205 "cssvalues.gperf" + {"wait", CSS_VAL_WAIT}, #line 74 "cssvalues.gperf" {"transparent", CSS_VAL_TRANSPARENT}, -#line 121 "cssvalues.gperf" - {"grey", CSS_VAL_GREY}, -#line 88 "cssvalues.gperf" - {"purple", CSS_VAL_PURPLE}, -#line 190 "cssvalues.gperf" - {"inline-table", CSS_VAL_INLINE_TABLE}, -#line 107 "cssvalues.gperf" - {"inactivecaption", CSS_VAL_INACTIVECAPTION}, -#line 34 "cssvalues.gperf" - {"oblique", CSS_VAL_OBLIQUE}, -#line 131 "cssvalues.gperf" - {"text-top", CSS_VAL_TEXT_TOP}, -#line 201 "cssvalues.gperf" - {"default", CSS_VAL_DEFAULT}, -#line 130 "cssvalues.gperf" - {"super", CSS_VAL_SUPER}, -#line 123 "cssvalues.gperf" - {"repeat", CSS_VAL_REPEAT}, -#line 108 "cssvalues.gperf" - {"inactivecaptiontext", CSS_VAL_INACTIVECAPTIONTEXT}, -#line 114 "cssvalues.gperf" - {"threedface", CSS_VAL_THREEDFACE}, -#line 126 "cssvalues.gperf" - {"no-repeat", CSS_VAL_NO_REPEAT}, -#line 282 "cssvalues.gperf" - {"unfurl", CSS_VAL_UNFURL}, -#line 273 "cssvalues.gperf" - {"ahead", CSS_VAL_AHEAD}, +#line 183 "cssvalues.gperf" + {"inline", CSS_VAL_INLINE}, +#line 92 "cssvalues.gperf" + {"white", CSS_VAL_WHITE}, +#line 237 "cssvalues.gperf" + {"close-quote", CSS_VAL_CLOSE_QUOTE}, +#line 194 "cssvalues.gperf" + {"table-row", CSS_VAL_TABLE_ROW}, +#line 22 "cssvalues.gperf" + {"outset", CSS_VAL_OUTSET}, +#line 111 "cssvalues.gperf" + {"menutext", CSS_VAL_MENUTEXT}, #line 196 "cssvalues.gperf" {"table-column", CSS_VAL_TABLE_COLUMN}, -#line 218 "cssvalues.gperf" - {"capitalize", CSS_VAL_CAPITALIZE}, #line 159 "cssvalues.gperf" {"lower-roman", CSS_VAL_LOWER_ROMAN}, -#line 287 "cssvalues.gperf" - {"padding", CSS_VAL_PADDING}, -#line 117 "cssvalues.gperf" - {"threedshadow", CSS_VAL_THREEDSHADOW}, -#line 98 "cssvalues.gperf" - {"buttonface", CSS_VAL_BUTTONFACE}, +#line 71 "cssvalues.gperf" + {"cursive", CSS_VAL_CURSIVE}, +#line 286 "cssvalues.gperf" + {"backwards", CSS_VAL_BACKWARDS}, +#line 70 "cssvalues.gperf" + {"sans-serif", CSS_VAL_SANS_SERIF}, +#line 31 "cssvalues.gperf" + {"small-caption", CSS_VAL_SMALL_CAPTION}, +#line 284 "cssvalues.gperf" + {"disabled", CSS_VAL_DISABLED}, +#line 15 "cssvalues.gperf" + {"initial", CSS_VAL_INITIAL}, +#line 32 "cssvalues.gperf" + {"status-bar", CSS_VAL_STATUS_BAR}, +#line 59 "cssvalues.gperf" + {"wider", CSS_VAL_WIDER}, +#line 208 "cssvalues.gperf" + {"text", CSS_VAL_TEXT}, +#line 144 "cssvalues.gperf" + {"outside", CSS_VAL_OUTSIDE}, +#line 235 "cssvalues.gperf" + {"visible", CSS_VAL_VISIBLE}, +#line 87 "cssvalues.gperf" + {"orange", CSS_VAL_ORANGE}, +#line 145 "cssvalues.gperf" + {"inside", CSS_VAL_INSIDE}, +#line 137 "cssvalues.gperf" + {"left", CSS_VAL_LEFT}, +#line 160 "cssvalues.gperf" + {"upper-roman", CSS_VAL_UPPER_ROMAN}, #line 79 "cssvalues.gperf" {"fuchsia", CSS_VAL_FUCHSIA}, -#line 55 "cssvalues.gperf" - {"xx-large", CSS_VAL_XX_LARGE}, -#line 200 "cssvalues.gperf" - {"crosshair", CSS_VAL_CROSSHAIR}, -#line 246 "cssvalues.gperf" - {"higher", CSS_VAL_HIGHER}, -#line 100 "cssvalues.gperf" - {"buttonshadow", CSS_VAL_BUTTONSHADOW}, +#line 295 "cssvalues.gperf" + {"alternate", CSS_VAL_ALTERNATE}, +#line 213 "cssvalues.gperf" + {"no-drop", CSS_VAL_NO_DROP}, +#line 279 "cssvalues.gperf" + {"-khtml-normal", CSS_VAL__KHTML_NORMAL}, +#line 93 "cssvalues.gperf" + {"yellow", CSS_VAL_YELLOW}, +#line 240 "cssvalues.gperf" + {"open-quote", CSS_VAL_OPEN_QUOTE}, +#line 198 "cssvalues.gperf" + {"table-caption", CSS_VAL_TABLE_CAPTION}, +#line 49 "cssvalues.gperf" + {"xx-small", CSS_VAL_XX_SMALL}, +#line 127 "cssvalues.gperf" + {"baseline", CSS_VAL_BASELINE}, #line 94 "cssvalues.gperf" {"activeborder", CSS_VAL_ACTIVEBORDER}, -#line 253 "cssvalues.gperf" - {"marquee", CSS_VAL_MARQUEE}, -#line 31 "cssvalues.gperf" - {"small-caption", CSS_VAL_SMALL_CAPTION}, -#line 35 "cssvalues.gperf" - {"small-caps", CSS_VAL_SMALL_CAPS}, -#line 122 "cssvalues.gperf" - {"-khtml-text", CSS_VAL__KHTML_TEXT}, +#line 185 "cssvalues.gperf" + {"list-item", CSS_VAL_LIST_ITEM}, +#line 67 "cssvalues.gperf" + {"extra-expanded", CSS_VAL_EXTRA_EXPANDED}, +#line 269 "cssvalues.gperf" + {"overline", CSS_VAL_OVERLINE}, +#line 282 "cssvalues.gperf" + {"content-box", CSS_VAL_CONTENT_BOX}, +#line 118 "cssvalues.gperf" + {"window", CSS_VAL_WINDOW}, +#line 157 "cssvalues.gperf" + {"-khtml-thai", CSS_VAL__KHTML_THAI}, +#line 72 "cssvalues.gperf" + {"fantasy", CSS_VAL_FANTASY}, +#line 180 "cssvalues.gperf" + {"katakana-iroha", CSS_VAL_KATAKANA_IROHA}, #line 20 "cssvalues.gperf" {"groove", CSS_VAL_GROOVE}, -#line 97 "cssvalues.gperf" - {"background", CSS_VAL_BACKGROUND}, -#line 178 "cssvalues.gperf" - {"katakana", CSS_VAL_KATAKANA}, -#line 148 "cssvalues.gperf" - {"square", CSS_VAL_SQUARE}, -#line 259 "cssvalues.gperf" - {"separate", CSS_VAL_SEPARATE}, -#line 75 "cssvalues.gperf" - {"aqua", CSS_VAL_AQUA}, -#line 70 "cssvalues.gperf" - {"sans-serif", CSS_VAL_SANS_SERIF}, -#line 32 "cssvalues.gperf" - {"status-bar", CSS_VAL_STATUS_BAR}, +#line 54 "cssvalues.gperf" + {"x-large", CSS_VAL_X_LARGE}, +#line 114 "cssvalues.gperf" + {"threedface", CSS_VAL_THREEDFACE}, +#line 155 "cssvalues.gperf" + {"-khtml-persian", CSS_VAL__KHTML_PERSIAN}, +#line 201 "cssvalues.gperf" + {"context-menu", CSS_VAL_CONTEXT_MENU}, +#line 19 "cssvalues.gperf" + {"inset", CSS_VAL_INSET}, +#line 102 "cssvalues.gperf" + {"captiontext", CSS_VAL_CAPTIONTEXT}, +#line 136 "cssvalues.gperf" + {"-khtml-auto", CSS_VAL__KHTML_AUTO}, +#line 68 "cssvalues.gperf" + {"ultra-expanded", CSS_VAL_ULTRA_EXPANDED}, +#line 278 "cssvalues.gperf" + {"underline", CSS_VAL_UNDERLINE}, +#line 174 "cssvalues.gperf" + {"lower-latin", CSS_VAL_LOWER_LATIN}, +#line 301 "cssvalues.gperf" + {"padding", CSS_VAL_PADDING}, +#line 126 "cssvalues.gperf" + {"no-repeat", CSS_VAL_NO_REPEAT}, +#line 162 "cssvalues.gperf" + {"armenian", CSS_VAL_ARMENIAN}, +#line 143 "cssvalues.gperf" + {"-khtml-center", CSS_VAL__KHTML_CENTER}, +#line 122 "cssvalues.gperf" + {"-khtml-text", CSS_VAL__KHTML_TEXT}, +#line 14 "cssvalues.gperf" + {"inherit", CSS_VAL_INHERIT}, #line 65 "cssvalues.gperf" {"semi-expanded", CSS_VAL_SEMI_EXPANDED}, -#line 230 "cssvalues.gperf" - {"pre-line", CSS_VAL_PRE_LINE}, -#line 237 "cssvalues.gperf" +#line 188 "cssvalues.gperf" + {"inline-block", CSS_VAL_INLINE_BLOCK}, +#line 125 "cssvalues.gperf" + {"repeat-y", CSS_VAL_REPEAT_Y}, +#line 177 "cssvalues.gperf" + {"hiragana", CSS_VAL_HIRAGANA}, +#line 251 "cssvalues.gperf" {"bidi-override", CSS_VAL_BIDI_OVERRIDE}, #line 62 "cssvalues.gperf" {"extra-condensed", CSS_VAL_EXTRA_CONDENSED}, -#line 95 "cssvalues.gperf" - {"activecaption", CSS_VAL_ACTIVECAPTION}, -#line 198 "cssvalues.gperf" - {"table-caption", CSS_VAL_TABLE_CAPTION}, -#line 154 "cssvalues.gperf" - {"-khtml-lao", CSS_VAL__KHTML_LAO}, -#line 143 "cssvalues.gperf" - {"-khtml-center", CSS_VAL__KHTML_CENTER}, -#line 54 "cssvalues.gperf" - {"x-large", CSS_VAL_X_LARGE}, -#line 30 "cssvalues.gperf" - {"message-box", CSS_VAL_MESSAGE_BOX}, -#line 203 "cssvalues.gperf" - {"progress", CSS_VAL_PROGRESS}, -#line 177 "cssvalues.gperf" - {"hiragana", CSS_VAL_HIRAGANA}, -#line 171 "cssvalues.gperf" - {"lower-greek", CSS_VAL_LOWER_GREEK}, -#line 150 "cssvalues.gperf" - {"-khtml-diamond", CSS_VAL__KHTML_DIAMOND}, +#line 156 "cssvalues.gperf" + {"-khtml-urdu", CSS_VAL__KHTML_URDU}, +#line 190 "cssvalues.gperf" + {"inline-table", CSS_VAL_INLINE_TABLE}, #line 141 "cssvalues.gperf" {"-khtml-left", CSS_VAL__KHTML_LEFT}, +#line 176 "cssvalues.gperf" + {"upper-latin", CSS_VAL_UPPER_LATIN}, +#line 186 "cssvalues.gperf" + {"run-in", CSS_VAL_RUN_IN}, +#line 209 "cssvalues.gperf" + {"vertical-text", CSS_VAL_VERTICAL_TEXT}, +#line 98 "cssvalues.gperf" + {"buttonface", CSS_VAL_BUTTONFACE}, +#line 131 "cssvalues.gperf" + {"text-top", CSS_VAL_TEXT_TOP}, +#line 232 "cssvalues.gperf" + {"capitalize", CSS_VAL_CAPITALIZE}, +#line 219 "cssvalues.gperf" + {"s-resize", CSS_VAL_S_RESIZE}, +#line 215 "cssvalues.gperf" + {"e-resize", CSS_VAL_E_RESIZE}, +#line 85 "cssvalues.gperf" + {"navy", CSS_VAL_NAVY}, +#line 95 "cssvalues.gperf" + {"activecaption", CSS_VAL_ACTIVECAPTION}, +#line 261 "cssvalues.gperf" + {"invert", CSS_VAL_INVERT}, +#line 117 "cssvalues.gperf" + {"threedshadow", CSS_VAL_THREEDSHADOW}, #line 61 "cssvalues.gperf" {"ultra-condensed", CSS_VAL_ULTRA_CONDENSED}, -#line 158 "cssvalues.gperf" - {"-khtml-tibetan", CSS_VAL__KHTML_TIBETAN}, -#line 124 "cssvalues.gperf" - {"repeat-x", CSS_VAL_REPEAT_X}, -#line 265 "cssvalues.gperf" - {"-khtml-normal", CSS_VAL__KHTML_NORMAL}, -#line 113 "cssvalues.gperf" - {"threeddarkshadow", CSS_VAL_THREEDDARKSHADOW}, -#line 219 "cssvalues.gperf" - {"uppercase", CSS_VAL_UPPERCASE}, -#line 125 "cssvalues.gperf" - {"repeat-y", CSS_VAL_REPEAT_Y}, -#line 136 "cssvalues.gperf" - {"-khtml-auto", CSS_VAL__KHTML_AUTO}, -#line 163 "cssvalues.gperf" - {"georgian", CSS_VAL_GEORGIAN}, -#line 109 "cssvalues.gperf" - {"infobackground", CSS_VAL_INFOBACKGROUND}, -#line 16 "cssvalues.gperf" - {"-khtml-native", CSS_VAL__KHTML_NATIVE}, -#line 157 "cssvalues.gperf" - {"-khtml-thai", CSS_VAL__KHTML_THAI}, -#line 224 "cssvalues.gperf" - {"no-close-quote", CSS_VAL_NO_CLOSE_QUOTE}, -#line 173 "cssvalues.gperf" - {"lower-alpha", CSS_VAL_LOWER_ALPHA}, -#line 156 "cssvalues.gperf" - {"-khtml-urdu", CSS_VAL__KHTML_URDU}, -#line 223 "cssvalues.gperf" - {"close-quote", CSS_VAL_CLOSE_QUOTE}, +#line 182 "cssvalues.gperf" + {"-khtml-close-quote", CSS_VAL__KHTML_CLOSE_QUOTE}, +#line 82 "cssvalues.gperf" + {"indigo", CSS_VAL_INDIGO}, +#line 244 "cssvalues.gperf" + {"pre-line", CSS_VAL_PRE_LINE}, +#line 245 "cssvalues.gperf" + {"-khtml-nowrap", CSS_VAL__KHTML_NOWRAP}, +#line 101 "cssvalues.gperf" + {"buttontext", CSS_VAL_BUTTONTEXT}, #line 104 "cssvalues.gperf" {"highlight", CSS_VAL_HIGHLIGHT}, -#line 231 "cssvalues.gperf" - {"-khtml-nowrap", CSS_VAL__KHTML_NOWRAP}, -#line 67 "cssvalues.gperf" - {"extra-expanded", CSS_VAL_EXTRA_EXPANDED}, -#line 105 "cssvalues.gperf" - {"highlighttext", CSS_VAL_HIGHLIGHTTEXT}, -#line 155 "cssvalues.gperf" - {"-khtml-persian", CSS_VAL__KHTML_PERSIAN}, -#line 116 "cssvalues.gperf" - {"threedlightshadow", CSS_VAL_THREEDLIGHTSHADOW}, -#line 229 "cssvalues.gperf" +#line 119 "cssvalues.gperf" + {"windowframe", CSS_VAL_WINDOWFRAME}, +#line 64 "cssvalues.gperf" + {"semi-condensed", CSS_VAL_SEMI_CONDENSED}, +#line 200 "cssvalues.gperf" + {"default", CSS_VAL_DEFAULT}, +#line 243 "cssvalues.gperf" {"pre-wrap", CSS_VAL_PRE_WRAP}, -#line 96 "cssvalues.gperf" - {"appworkspace", CSS_VAL_APPWORKSPACE}, -#line 226 "cssvalues.gperf" - {"open-quote", CSS_VAL_OPEN_QUOTE}, -#line 68 "cssvalues.gperf" - {"ultra-expanded", CSS_VAL_ULTRA_EXPANDED}, -#line 176 "cssvalues.gperf" - {"upper-latin", CSS_VAL_UPPER_LATIN}, +#line 150 "cssvalues.gperf" + {"-khtml-diamond", CSS_VAL__KHTML_DIAMOND}, +#line 296 "cssvalues.gperf" + {"unfurl", CSS_VAL_UNFURL}, +#line 171 "cssvalues.gperf" + {"lower-greek", CSS_VAL_LOWER_GREEK}, +#line 257 "cssvalues.gperf" + {"fixed", CSS_VAL_FIXED}, #line 225 "cssvalues.gperf" + {"nesw-resize", CSS_VAL_NESW_RESIZE}, +#line 220 "cssvalues.gperf" + {"se-resize", CSS_VAL_SE_RESIZE}, +#line 216 "cssvalues.gperf" + {"n-resize", CSS_VAL_N_RESIZE}, +#line 30 "cssvalues.gperf" + {"message-box", CSS_VAL_MESSAGE_BOX}, +#line 100 "cssvalues.gperf" + {"buttonshadow", CSS_VAL_BUTTONSHADOW}, +#line 179 "cssvalues.gperf" + {"hiragana-iroha", CSS_VAL_HIRAGANA_IROHA}, +#line 120 "cssvalues.gperf" + {"windowtext", CSS_VAL_WINDOWTEXT}, +#line 80 "cssvalues.gperf" + {"gray", CSS_VAL_GRAY}, +#line 181 "cssvalues.gperf" + {"-khtml-open-quote", CSS_VAL__KHTML_OPEN_QUOTE}, +#line 227 "cssvalues.gperf" + {"col-resize", CSS_VAL_COL_RESIZE}, +#line 16 "cssvalues.gperf" + {"-khtml-native", CSS_VAL__KHTML_NATIVE}, +#line 55 "cssvalues.gperf" + {"xx-large", CSS_VAL_XX_LARGE}, +#line 158 "cssvalues.gperf" + {"-khtml-tibetan", CSS_VAL__KHTML_TIBETAN}, +#line 106 "cssvalues.gperf" + {"inactiveborder", CSS_VAL_INACTIVEBORDER}, +#line 228 "cssvalues.gperf" + {"row-resize", CSS_VAL_ROW_RESIZE}, +#line 110 "cssvalues.gperf" + {"infotext", CSS_VAL_INFOTEXT}, +#line 132 "cssvalues.gperf" + {"text-bottom", CSS_VAL_TEXT_BOTTOM}, +#line 113 "cssvalues.gperf" + {"threeddarkshadow", CSS_VAL_THREEDDARKSHADOW}, +#line 97 "cssvalues.gperf" + {"background", CSS_VAL_BACKGROUND}, +#line 165 "cssvalues.gperf" + {"-khtml-japanese-formal", CSS_VAL__KHTML_JAPANESE_FORMAL}, +#line 81 "cssvalues.gperf" + {"green", CSS_VAL_GREEN}, +#line 192 "cssvalues.gperf" + {"table-header-group", CSS_VAL_TABLE_HEADER_GROUP}, +#line 222 "cssvalues.gperf" + {"w-resize", CSS_VAL_W_RESIZE}, +#line 238 "cssvalues.gperf" + {"no-close-quote", CSS_VAL_NO_CLOSE_QUOTE}, +#line 224 "cssvalues.gperf" + {"ns-resize", CSS_VAL_NS_RESIZE}, +#line 214 "cssvalues.gperf" + {"not-allowed", CSS_VAL_NOT_ALLOWED}, +#line 217 "cssvalues.gperf" + {"ne-resize", CSS_VAL_NE_RESIZE}, +#line 239 "cssvalues.gperf" {"no-open-quote", CSS_VAL_NO_OPEN_QUOTE}, -#line 250 "cssvalues.gperf" - {"line-through", CSS_VAL_LINE_THROUGH}, -#line 142 "cssvalues.gperf" - {"-khtml-right", CSS_VAL__KHTML_RIGHT}, -#line 164 "cssvalues.gperf" - {"cjk-ideographic", CSS_VAL_CJK_IDEOGRAPHIC}, -#line 160 "cssvalues.gperf" - {"upper-roman", CSS_VAL_UPPER_ROMAN}, -#line 135 "cssvalues.gperf" - {"-khtml-baseline-middle", CSS_VAL__KHTML_BASELINE_MIDDLE}, +#line 140 "cssvalues.gperf" + {"justify", CSS_VAL_JUSTIFY}, #line 153 "cssvalues.gperf" {"-khtml-arabic-indic", CSS_VAL__KHTML_ARABIC_INDIC}, -#line 152 "cssvalues.gperf" - {"decimal-leading-zero", CSS_VAL_DECIMAL_LEADING_ZERO}, -#line 115 "cssvalues.gperf" - {"threedhighlight", CSS_VAL_THREEDHIGHLIGHT}, -#line 180 "cssvalues.gperf" - {"katakana-iroha", CSS_VAL_KATAKANA_IROHA}, -#line 99 "cssvalues.gperf" - {"buttonhighlight", CSS_VAL_BUTTONHIGHLIGHT}, +#line 121 "cssvalues.gperf" + {"grey", CSS_VAL_GREY}, +#line 135 "cssvalues.gperf" + {"-khtml-baseline-middle", CSS_VAL__KHTML_BASELINE_MIDDLE}, #line 56 "cssvalues.gperf" {"-khtml-xxx-large", CSS_VAL__KHTML_XXX_LARGE}, +#line 142 "cssvalues.gperf" + {"-khtml-right", CSS_VAL__KHTML_RIGHT}, +#line 264 "cssvalues.gperf" + {"line-through", CSS_VAL_LINE_THROUGH}, +#line 167 "cssvalues.gperf" + {"-khtml-simp-chinese-formal", CSS_VAL__KHTML_SIMP_CHINESE_FORMAL}, +#line 163 "cssvalues.gperf" + {"georgian", CSS_VAL_GEORGIAN}, +#line 105 "cssvalues.gperf" + {"highlighttext", CSS_VAL_HIGHLIGHTTEXT}, +#line 107 "cssvalues.gperf" + {"inactivecaption", CSS_VAL_INACTIVECAPTION}, +#line 293 "cssvalues.gperf" + {"infinite", CSS_VAL_INFINITE}, +#line 221 "cssvalues.gperf" + {"sw-resize", CSS_VAL_SW_RESIZE}, +#line 223 "cssvalues.gperf" + {"ew-resize", CSS_VAL_EW_RESIZE}, +#line 172 "cssvalues.gperf" + {"-khtml-upper-greek", CSS_VAL__KHTML_UPPER_GREEK}, #line 191 "cssvalues.gperf" {"table-row-group", CSS_VAL_TABLE_ROW_GROUP}, -#line 182 "cssvalues.gperf" - {"-khtml-close-quote", CSS_VAL__KHTML_CLOSE_QUOTE}, -#line 179 "cssvalues.gperf" - {"hiragana-iroha", CSS_VAL_HIRAGANA_IROHA}, #line 195 "cssvalues.gperf" {"table-column-group", CSS_VAL_TABLE_COLUMN_GROUP}, -#line 266 "cssvalues.gperf" +#line 166 "cssvalues.gperf" + {"-khtml-japanese-informal", CSS_VAL__KHTML_JAPANESE_INFORMAL}, +#line 280 "cssvalues.gperf" {"-khtml-around-floats", CSS_VAL__KHTML_AROUND_FLOATS}, -#line 175 "cssvalues.gperf" - {"upper-alpha", CSS_VAL_UPPER_ALPHA}, -#line 181 "cssvalues.gperf" - {"-khtml-open-quote", CSS_VAL__KHTML_OPEN_QUOTE}, +#line 103 "cssvalues.gperf" + {"graytext", CSS_VAL_GRAYTEXT}, #line 193 "cssvalues.gperf" {"table-footer-group", CSS_VAL_TABLE_FOOTER_GROUP}, -#line 192 "cssvalues.gperf" - {"table-header-group", CSS_VAL_TABLE_HEADER_GROUP}, -#line 165 "cssvalues.gperf" - {"-khtml-japanese-formal", CSS_VAL__KHTML_JAPANESE_FORMAL}, -#line 166 "cssvalues.gperf" - {"-khtml-japanese-informal", CSS_VAL__KHTML_JAPANESE_INFORMAL}, -#line 172 "cssvalues.gperf" - {"-khtml-upper-greek", CSS_VAL__KHTML_UPPER_GREEK}, #line 169 "cssvalues.gperf" {"-khtml-trad-chinese-formal", CSS_VAL__KHTML_TRAD_CHINESE_FORMAL}, +#line 218 "cssvalues.gperf" + {"nw-resize", CSS_VAL_NW_RESIZE}, +#line 226 "cssvalues.gperf" + {"nwse-resize", CSS_VAL_NWSE_RESIZE}, +#line 164 "cssvalues.gperf" + {"cjk-ideographic", CSS_VAL_CJK_IDEOGRAPHIC}, +#line 168 "cssvalues.gperf" + {"-khtml-simp-chinese-informal", CSS_VAL__KHTML_SIMP_CHINESE_INFORMAL}, +#line 108 "cssvalues.gperf" + {"inactivecaptiontext", CSS_VAL_INACTIVECAPTIONTEXT}, +#line 116 "cssvalues.gperf" + {"threedlightshadow", CSS_VAL_THREEDLIGHTSHADOW}, #line 170 "cssvalues.gperf" {"-khtml-trad-chinese-informal", CSS_VAL__KHTML_TRAD_CHINESE_INFORMAL}, -#line 167 "cssvalues.gperf" - {"-khtml-simp-chinese-formal", CSS_VAL__KHTML_SIMP_CHINESE_FORMAL}, -#line 168 "cssvalues.gperf" - {"-khtml-simp-chinese-informal", CSS_VAL__KHTML_SIMP_CHINESE_INFORMAL} +#line 109 "cssvalues.gperf" + {"infobackground", CSS_VAL_INFOBACKGROUND}, +#line 115 "cssvalues.gperf" + {"threedhighlight", CSS_VAL_THREEDHIGHLIGHT}, +#line 152 "cssvalues.gperf" + {"decimal-leading-zero", CSS_VAL_DECIMAL_LEADING_ZERO}, +#line 99 "cssvalues.gperf" + {"buttonhighlight", CSS_VAL_BUTTONHIGHLIGHT} }; static const short lookup[] = { - 0, -1, -1, -1, -1, 1, -1, -1, -1, -1, - 2, -1, -1, -1, -1, 3, -1, -1, -1, -1, - 4, -1, -1, -1, -1, 5, -1, -1, 6, -1, - 7, -1, -1, -1, -1, 8, -1, -1, -1, -1, - 9, -1, -1, -1, -1, 10, -1, -1, -1, -1, - 11, -1, -1, -1, -1, 12, -1, -1, -1, -1, - 13, 14, -1, -1, -1, 15, -1, -1, -1, -1, - 16, -1, -1, -1, -1, 17, -1, -1, -1, -1, + 0, -1, -1, -1, -1, 1, -1, -1, 2, -1, + 3, -1, -1, 4, -1, 5, -1, -1, 6, -1, + 7, -1, -1, -1, -1, 8, -1, -1, 9, 10, + 11, 12, -1, -1, -1, 13, -1, -1, 14, -1, + 15, 16, -1, -1, -1, 17, -1, -1, -1, -1, 18, -1, -1, -1, -1, 19, -1, -1, -1, -1, - 20, -1, -1, -1, -1, 21, -1, -1, 22, -1, - 23, -1, -1, 24, -1, 25, -1, -1, 26, -1, - 27, -1, -1, -1, -1, 28, -1, -1, -1, 29, - 30, -1, -1, 31, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 32, -1, -1, -1, -1, -1, -1, - 33, -1, -1, -1, -1, 34, -1, -1, -1, -1, - 35, -1, -1, 36, -1, -1, -1, -1, 37, -1, - 38, -1, -1, -1, -1, 39, 40, -1, 41, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, - 43, -1, -1, -1, -1, -1, -1, -1, 44, -1, - 45, -1, -1, -1, -1, -1, -1, -1, 46, -1, - -1, -1, -1, -1, -1, 47, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 48, -1, -1, -1, -1, - 49, -1, -1, -1, -1, 50, -1, -1, 51, -1, - 52, -1, -1, -1, -1, -1, -1, -1, 53, -1, - 54, -1, -1, -1, -1, -1, 55, -1, -1, -1, - 56, -1, -1, -1, -1, 57, -1, -1, -1, -1, - 58, -1, -1, 59, -1, -1, -1, -1, -1, -1, - 60, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 61, -1, -1, -1, -1, -1, -1, -1, 62, -1, - 63, -1, -1, 64, -1, 65, 66, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 67, -1, -1, 68, -1, - 69, -1, -1, -1, -1, 70, -1, -1, 71, -1, - -1, -1, -1, 72, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 73, -1, -1, -1, -1, -1, -1, - 74, -1, -1, -1, -1, 75, -1, -1, 76, -1, - -1, -1, -1, 77, -1, -1, -1, -1, 78, -1, - 79, -1, -1, -1, -1, 80, 81, -1, 82, -1, - 83, -1, -1, 84, -1, 85, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 86, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 87, -1, -1, -1, -1, -1, -1, -1, 88, -1, - 89, -1, -1, -1, -1, 90, -1, -1, -1, -1, - 91, 92, -1, -1, -1, 93, 94, -1, 95, -1, - 96, -1, -1, 97, -1, -1, -1, -1, 98, -1, - 99, 100, -1, 101, -1, 102, -1, -1, -1, -1, - 103, -1, -1, 104, -1, 105, -1, -1, -1, -1, - -1, -1, -1, 106, -1, 107, -1, -1, -1, -1, - 108, -1, -1, -1, -1, 109, -1, -1, -1, -1, - 110, -1, -1, -1, -1, -1, -1, -1, 111, -1, - -1, -1, -1, -1, -1, 112, -1, -1, 113, -1, - -1, -1, -1, -1, -1, 114, -1, -1, -1, -1, - 115, -1, -1, 116, -1, 117, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 118, -1, -1, 119, -1, - -1, -1, -1, 120, -1, 121, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 122, -1, -1, 123, -1, - 124, -1, -1, -1, -1, 125, -1, -1, 126, -1, - 127, -1, -1, -1, -1, 128, -1, -1, 129, -1, - 130, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 131, -1, -1, -1, -1, -1, -1, -1, 132, -1, - 133, -1, -1, 134, -1, 135, -1, -1, -1, -1, - 136, -1, -1, -1, -1, -1, 137, -1, -1, -1, - 138, -1, -1, 139, -1, -1, -1, -1, 140, -1, - 141, -1, -1, -1, -1, 142, -1, -1, 143, -1, - 144, 145, -1, -1, -1, 146, -1, -1, 147, -1, - -1, -1, -1, -1, -1, -1, 148, -1, -1, -1, - -1, -1, -1, 149, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 150, -1, -1, -1, -1, 151, -1, - 152, -1, -1, -1, -1, 153, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 154, -1, -1, -1, -1, - -1, -1, -1, 155, -1, -1, -1, -1, -1, -1, - 156, -1, -1, -1, -1, 157, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 158, -1, - 159, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 160, -1, - 161, -1, -1, 162, -1, -1, -1, -1, 163, -1, - -1, -1, -1, 164, -1, 165, -1, -1, -1, -1, - -1, -1, -1, 166, -1, -1, -1, -1, -1, -1, - 167, -1, -1, -1, -1, 168, -1, -1, 169, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 170, -1, -1, -1, -1, -1, -1, -1, 171, -1, - 172, -1, -1, -1, -1, 173, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 174, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 175, -1, -1, -1, - 176, -1, -1, -1, -1, 177, -1, -1, -1, -1, - 178, -1, -1, -1, -1, 179, -1, -1, -1, -1, - 180, -1, -1, -1, -1, 181, -1, -1, 182, -1, - 183, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 184, -1, - -1, -1, -1, -1, -1, 185, -1, -1, -1, -1, - 186, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 187, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 20, -1, -1, -1, -1, 21, -1, -1, -1, -1, + 22, -1, -1, -1, -1, 23, -1, -1, -1, -1, + 24, -1, -1, -1, -1, 25, -1, -1, -1, -1, + 26, -1, -1, -1, -1, 27, -1, -1, 28, -1, + 29, -1, -1, -1, -1, 30, -1, -1, -1, -1, + 31, -1, -1, -1, -1, 32, -1, -1, -1, -1, + 33, -1, -1, 34, -1, 35, 36, -1, -1, -1, + 37, -1, -1, -1, -1, 38, -1, -1, -1, 39, + 40, -1, -1, -1, -1, 41, -1, -1, -1, -1, + 42, -1, -1, -1, -1, 43, 44, -1, -1, -1, + 45, -1, -1, -1, 46, -1, -1, -1, 47, -1, + -1, -1, -1, 48, -1, -1, 49, -1, -1, -1, + -1, -1, -1, -1, -1, 50, -1, -1, 51, -1, + 52, 53, -1, -1, -1, 54, 55, -1, -1, -1, + -1, -1, -1, 56, -1, -1, 57, -1, -1, -1, + 58, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 59, -1, -1, 60, -1, 61, -1, -1, 62, -1, + -1, -1, -1, 63, -1, -1, -1, 64, 65, -1, + -1, -1, -1, -1, -1, -1, -1, 66, -1, -1, + -1, -1, -1, 67, -1, -1, 68, -1, 69, -1, + 70, 71, -1, -1, -1, -1, -1, -1, 72, -1, + -1, -1, -1, 73, -1, 74, -1, -1, 75, -1, + 76, -1, -1, 77, -1, -1, -1, -1, 78, -1, + 79, -1, -1, 80, -1, -1, 81, -1, 82, -1, + 83, -1, -1, 84, -1, 85, 86, -1, 87, -1, + 88, -1, -1, 89, -1, -1, 90, -1, -1, 91, + -1, -1, -1, -1, -1, -1, 92, -1, -1, -1, + 93, 94, -1, 95, -1, -1, 96, -1, -1, -1, + -1, -1, -1, 97, -1, -1, -1, -1, 98, -1, + 99, -1, -1, -1, -1, -1, -1, -1, 100, -1, + 101, 102, -1, -1, -1, 103, -1, -1, -1, -1, + 104, -1, -1, -1, 105, 106, 107, -1, -1, -1, + -1, -1, -1, 108, -1, -1, -1, -1, -1, 109, + 110, -1, -1, -1, -1, 111, -1, -1, 112, -1, + 113, 114, -1, -1, -1, 115, -1, -1, 116, -1, + 117, 118, -1, -1, -1, 119, -1, -1, 120, -1, + 121, -1, -1, -1, -1, 122, -1, -1, -1, -1, + 123, -1, -1, 124, -1, -1, 125, -1, -1, 126, + -1, 127, -1, -1, 128, -1, -1, -1, 129, -1, + -1, -1, -1, 130, -1, -1, 131, -1, -1, -1, + 132, -1, -1, 133, 134, -1, -1, -1, -1, -1, + -1, 135, -1, 136, -1, 137, -1, -1, -1, 138, + 139, -1, -1, 140, -1, -1, 141, -1, 142, -1, + 143, -1, -1, -1, -1, 144, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 145, -1, -1, 146, -1, + -1, -1, -1, -1, -1, 147, -1, -1, 148, -1, + 149, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 150, -1, -1, -1, -1, -1, -1, -1, -1, 151, + 152, -1, -1, 153, -1, 154, 155, -1, -1, -1, + 156, -1, -1, -1, -1, 157, -1, -1, 158, -1, + 159, -1, -1, 160, -1, -1, 161, -1, -1, -1, + 162, -1, -1, -1, -1, -1, -1, -1, -1, 163, + 164, -1, -1, -1, 165, 166, 167, -1, -1, -1, + -1, 168, -1, 169, -1, -1, -1, -1, -1, -1, + -1, 170, -1, 171, -1, 172, -1, -1, 173, -1, + -1, 174, -1, 175, -1, -1, -1, -1, 176, -1, + 177, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 178, -1, -1, -1, -1, -1, -1, + 179, -1, -1, -1, 180, 181, -1, -1, 182, -1, + 183, -1, -1, 184, -1, 185, -1, -1, 186, -1, + -1, -1, -1, -1, -1, 187, -1, -1, -1, -1, -1, -1, -1, -1, -1, 188, -1, -1, -1, -1, - 189, -1, -1, 190, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 191, -1, -1, -1, -1, -1, -1, - 192, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 193, -1, -1, -1, -1, 194, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 195, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 196, -1, - 197, -1, -1, -1, -1, 198, -1, -1, 199, -1, - 200, -1, -1, -1, -1, -1, -1, -1, 201, -1, - -1, -1, -1, -1, -1, 202, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 203, -1, -1, 204, -1, -1, -1, -1, -1, -1, - 205, -1, -1, -1, -1, -1, -1, -1, 206, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 207, -1, -1, -1, -1, 208, -1, - 209, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 210, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 211, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 212, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 213, -1, 214, -1, -1, -1, -1, - 215, -1, -1, -1, -1, -1, -1, -1, 216, -1, - 217, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 218, -1, -1, -1, -1, - 219, -1, -1, -1, -1, 220, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 221, -1, - -1, -1, -1, -1, -1, 222, -1, -1, 223, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 224, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 225, -1, -1, -1, -1, -1, -1, - 226, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 227, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 228, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 229, -1, 230, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 231, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 232, -1, - 233, -1, -1, -1, -1, 234, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 235, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 236, -1, - -1, 237, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 238, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 239, -1, -1, -1, -1, -1, -1, -1, 240, -1, - -1, -1, -1, 241, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 242, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 243, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 244, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 245, -1, -1, -1, -1, - 246, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 247, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 248, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 249, -1, 250, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 251, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 252, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 253, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 254, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 255, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 189, -1, 190, 191, -1, 192, -1, + -1, -1, -1, -1, -1, -1, 193, -1, -1, -1, + -1, -1, -1, 194, 195, -1, -1, -1, 196, -1, + 197, -1, -1, 198, -1, 199, 200, -1, 201, 202, + -1, -1, -1, -1, -1, 203, -1, -1, -1, -1, + 204, -1, -1, -1, 205, 206, -1, -1, -1, -1, + 207, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 208, 209, + -1, -1, -1, 210, -1, -1, -1, -1, -1, 211, + 212, 213, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 214, -1, -1, -1, -1, 215, -1, + -1, -1, -1, 216, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 217, 218, -1, 219, -1, 220, -1, + -1, -1, -1, -1, -1, 221, 222, -1, -1, -1, + -1, -1, -1, -1, -1, 223, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 224, -1, 225, -1, 226, -1, -1, 227, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 228, -1, 229, -1, -1, -1, -1, + -1, -1, -1, 230, -1, -1, 231, -1, -1, -1, + -1, 232, -1, -1, 233, 234, -1, -1, -1, -1, + -1, 235, -1, -1, -1, -1, -1, -1, 236, -1, + -1, 237, -1, -1, 238, -1, -1, -1, -1, -1, + 239, -1, -1, -1, -1, -1, 240, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 241, -1, 242, -1, + 243, -1, -1, -1, -1, -1, -1, -1, -1, 244, + 245, -1, -1, 246, -1, -1, -1, -1, -1, -1, + 247, -1, -1, -1, -1, -1, -1, -1, 248, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 249, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 250, -1, -1, -1, 251, -1, + -1, 252, -1, 253, -1, -1, -1, -1, -1, 254, + -1, -1, -1, 255, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, -1, -1, -1, -1, + 257, -1, -1, -1, -1, 258, -1, -1, -1, 259, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 260, -1, -1, -1, -1, -1, -1, + -1, 261, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 258, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 259, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 260, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 261, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 262, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 262, -1, + -1, -1, -1, -1, -1, 263, -1, 264, -1, -1, + -1, 265, -1, 266, -1, -1, 267, -1, -1, -1, + -1, 268, -1, -1, -1, 269, -1, -1, 270, -1, + -1, -1, -1, -1, -1, 271, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 263, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 272, -1, 273, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 274, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 264, -1, -1, -1, -1, 265, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 275, -1, -1, -1, -1, + -1, -1, -1, 276, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 277, -1, -1, -1, + -1, -1, -1, 278, 279, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 280, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 281, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 282, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 283, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 266, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 284, -1, 285, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 267, -1, - -1, -1, -1, 268, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 286, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 269, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 270, -1, -1, -1, -1, - 271, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 272, -1, -1, -1, -1, 273 + -1, -1, -1, -1, -1, -1, -1, -1, -1, 287 }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register int key = hash_val (str, len); if (key <= MAX_HASH_VALUE && key >= 0) { register int index = lookup[key]; if (index >= 0) { register const char *s = wordlist_value[index].name; if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') return &wordlist_value[index]; } } } return 0; } -#line 288 "cssvalues.gperf" +#line 302 "cssvalues.gperf" static const char * const valueList[] = { "", "inherit", "initial", "-khtml-native", "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double", "caption", "icon", "menu", "message-box", "small-caption", "status-bar", "italic", "oblique", "small-caps", "normal", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900", "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "-khtml-xxx-large", "smaller", "larger", "wider", "narrower", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", "semi-expanded", "expanded", "extra-expanded", "ultra-expanded", "serif", "sans-serif", "cursive", "fantasy", "monospace", "transparent", "aqua", "black", "blue", "crimson", "fuchsia", "gray", "green", "indigo", "lime", "maroon", "navy", "olive", "orange", "purple", "red", "silver", "teal", "white", "yellow", "activeborder", "activecaption", "appworkspace", "background", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "captiontext", "graytext", "highlight", "highlighttext", "inactiveborder", "inactivecaption", "inactivecaptiontext", "infobackground", "infotext", "menutext", "scrollbar", "threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "window", "windowframe", "windowtext", "grey", "-khtml-text", "repeat", "repeat-x", "repeat-y", "no-repeat", "baseline", "middle", "sub", "super", "text-top", "text-bottom", "top", "bottom", "-khtml-baseline-middle", "-khtml-auto", "left", "right", "center", "justify", "-khtml-left", "-khtml-right", "-khtml-center", "outside", "inside", "disc", "circle", "square", "box", "-khtml-diamond", "decimal", "decimal-leading-zero", "-khtml-arabic-indic", "-khtml-lao", "-khtml-persian", "-khtml-urdu", "-khtml-thai", "-khtml-tibetan", "lower-roman", "upper-roman", "hebrew", "armenian", "georgian", "cjk-ideographic", "-khtml-japanese-formal", "-khtml-japanese-informal", "-khtml-simp-chinese-formal", "-khtml-simp-chinese-informal", "-khtml-trad-chinese-formal", "-khtml-trad-chinese-informal", "lower-greek", "-khtml-upper-greek", "lower-alpha", "lower-latin", "upper-alpha", "upper-latin", "hiragana", "katakana", "hiragana-iroha", "katakana-iroha", "-khtml-open-quote", "-khtml-close-quote", "inline", "block", "list-item", "run-in", "compact", "inline-block", "table", "inline-table", "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", "table-column", "table-cell", "table-caption", "auto", -"crosshair", "default", +"context-menu", +"help", "pointer", "progress", +"wait", +"cell", +"crosshair", +"text", +"vertical-text", +"alias", +"copy", "move", +"no-drop", +"not-allowed", "e-resize", +"n-resize", "ne-resize", "nw-resize", -"n-resize", +"s-resize", "se-resize", "sw-resize", -"s-resize", "w-resize", -"text", -"wait", -"help", +"ew-resize", +"ns-resize", +"nesw-resize", +"nwse-resize", +"col-resize", +"row-resize", +"all-scroll", "ltr", "rtl", "capitalize", "uppercase", "lowercase", "visible", "collapse", "close-quote", "no-close-quote", "no-open-quote", "open-quote", "nowrap", "pre", "pre-wrap", "pre-line", "-khtml-nowrap", "above", "absolute", "always", "avoid", "below", "bidi-override", "blink", "both", "crop", "cross", "embed", "fixed", "hand", "hide", "higher", "invert", "landscape", "level", "line-through", "loud", "lower", "marquee", "mix", "overline", "portrait", "relative", "scroll", "separate", "show", "static", "thick", "thin", "underline", "-khtml-normal", "-khtml-around-floats", "border-box", "content-box", "enabled", "disabled", "forwards", "backwards", "ahead", "reverse", "up", "down", "slow", "fast", "infinite", "slide", "alternate", "unfurl", "clip", "ellipsis", "border", "content", "padding", 0 }; DOMString getValueName(unsigned short id) { if(id >= CSS_VAL_TOTAL || id == 0) return DOMString(); else return DOMString(valueList[id]); } diff --git a/khtml/css/cssvalues.h b/khtml/css/cssvalues.h index e185502956..45954fb2cf 100644 --- a/khtml/css/cssvalues.h +++ b/khtml/css/cssvalues.h @@ -1,288 +1,302 @@ /* This file is automatically generated from cssvalues.in by makevalues, do not edit */ /* Copyright 1998 W. Bastian */ #ifndef CSSVALUES_H #define CSSVALUES_H DOM::DOMString getValueName(unsigned short id) KDE_NO_EXPORT; #define CSS_VAL_INVALID 0 #define CSS_VAL_MIN 1 #define CSS_VAL_INHERIT 1 #define CSS_VAL_INITIAL 2 #define CSS_VAL__KHTML_NATIVE 3 #define CSS_VAL_NONE 4 #define CSS_VAL_HIDDEN 5 #define CSS_VAL_INSET 6 #define CSS_VAL_GROOVE 7 #define CSS_VAL_RIDGE 8 #define CSS_VAL_OUTSET 9 #define CSS_VAL_DOTTED 10 #define CSS_VAL_DASHED 11 #define CSS_VAL_SOLID 12 #define CSS_VAL_DOUBLE 13 #define CSS_VAL_CAPTION 14 #define CSS_VAL_ICON 15 #define CSS_VAL_MENU 16 #define CSS_VAL_MESSAGE_BOX 17 #define CSS_VAL_SMALL_CAPTION 18 #define CSS_VAL_STATUS_BAR 19 #define CSS_VAL_ITALIC 20 #define CSS_VAL_OBLIQUE 21 #define CSS_VAL_SMALL_CAPS 22 #define CSS_VAL_NORMAL 23 #define CSS_VAL_BOLD 24 #define CSS_VAL_BOLDER 25 #define CSS_VAL_LIGHTER 26 #define CSS_VAL_100 27 #define CSS_VAL_200 28 #define CSS_VAL_300 29 #define CSS_VAL_400 30 #define CSS_VAL_500 31 #define CSS_VAL_600 32 #define CSS_VAL_700 33 #define CSS_VAL_800 34 #define CSS_VAL_900 35 #define CSS_VAL_XX_SMALL 36 #define CSS_VAL_X_SMALL 37 #define CSS_VAL_SMALL 38 #define CSS_VAL_MEDIUM 39 #define CSS_VAL_LARGE 40 #define CSS_VAL_X_LARGE 41 #define CSS_VAL_XX_LARGE 42 #define CSS_VAL__KHTML_XXX_LARGE 43 #define CSS_VAL_SMALLER 44 #define CSS_VAL_LARGER 45 #define CSS_VAL_WIDER 46 #define CSS_VAL_NARROWER 47 #define CSS_VAL_ULTRA_CONDENSED 48 #define CSS_VAL_EXTRA_CONDENSED 49 #define CSS_VAL_CONDENSED 50 #define CSS_VAL_SEMI_CONDENSED 51 #define CSS_VAL_SEMI_EXPANDED 52 #define CSS_VAL_EXPANDED 53 #define CSS_VAL_EXTRA_EXPANDED 54 #define CSS_VAL_ULTRA_EXPANDED 55 #define CSS_VAL_SERIF 56 #define CSS_VAL_SANS_SERIF 57 #define CSS_VAL_CURSIVE 58 #define CSS_VAL_FANTASY 59 #define CSS_VAL_MONOSPACE 60 #define CSS_VAL_TRANSPARENT 61 #define CSS_VAL_AQUA 62 #define CSS_VAL_BLACK 63 #define CSS_VAL_BLUE 64 #define CSS_VAL_CRIMSON 65 #define CSS_VAL_FUCHSIA 66 #define CSS_VAL_GRAY 67 #define CSS_VAL_GREEN 68 #define CSS_VAL_INDIGO 69 #define CSS_VAL_LIME 70 #define CSS_VAL_MAROON 71 #define CSS_VAL_NAVY 72 #define CSS_VAL_OLIVE 73 #define CSS_VAL_ORANGE 74 #define CSS_VAL_PURPLE 75 #define CSS_VAL_RED 76 #define CSS_VAL_SILVER 77 #define CSS_VAL_TEAL 78 #define CSS_VAL_WHITE 79 #define CSS_VAL_YELLOW 80 #define CSS_VAL_ACTIVEBORDER 81 #define CSS_VAL_ACTIVECAPTION 82 #define CSS_VAL_APPWORKSPACE 83 #define CSS_VAL_BACKGROUND 84 #define CSS_VAL_BUTTONFACE 85 #define CSS_VAL_BUTTONHIGHLIGHT 86 #define CSS_VAL_BUTTONSHADOW 87 #define CSS_VAL_BUTTONTEXT 88 #define CSS_VAL_CAPTIONTEXT 89 #define CSS_VAL_GRAYTEXT 90 #define CSS_VAL_HIGHLIGHT 91 #define CSS_VAL_HIGHLIGHTTEXT 92 #define CSS_VAL_INACTIVEBORDER 93 #define CSS_VAL_INACTIVECAPTION 94 #define CSS_VAL_INACTIVECAPTIONTEXT 95 #define CSS_VAL_INFOBACKGROUND 96 #define CSS_VAL_INFOTEXT 97 #define CSS_VAL_MENUTEXT 98 #define CSS_VAL_SCROLLBAR 99 #define CSS_VAL_THREEDDARKSHADOW 100 #define CSS_VAL_THREEDFACE 101 #define CSS_VAL_THREEDHIGHLIGHT 102 #define CSS_VAL_THREEDLIGHTSHADOW 103 #define CSS_VAL_THREEDSHADOW 104 #define CSS_VAL_WINDOW 105 #define CSS_VAL_WINDOWFRAME 106 #define CSS_VAL_WINDOWTEXT 107 #define CSS_VAL_GREY 108 #define CSS_VAL__KHTML_TEXT 109 #define CSS_VAL_REPEAT 110 #define CSS_VAL_REPEAT_X 111 #define CSS_VAL_REPEAT_Y 112 #define CSS_VAL_NO_REPEAT 113 #define CSS_VAL_BASELINE 114 #define CSS_VAL_MIDDLE 115 #define CSS_VAL_SUB 116 #define CSS_VAL_SUPER 117 #define CSS_VAL_TEXT_TOP 118 #define CSS_VAL_TEXT_BOTTOM 119 #define CSS_VAL_TOP 120 #define CSS_VAL_BOTTOM 121 #define CSS_VAL__KHTML_BASELINE_MIDDLE 122 #define CSS_VAL__KHTML_AUTO 123 #define CSS_VAL_LEFT 124 #define CSS_VAL_RIGHT 125 #define CSS_VAL_CENTER 126 #define CSS_VAL_JUSTIFY 127 #define CSS_VAL__KHTML_LEFT 128 #define CSS_VAL__KHTML_RIGHT 129 #define CSS_VAL__KHTML_CENTER 130 #define CSS_VAL_OUTSIDE 131 #define CSS_VAL_INSIDE 132 #define CSS_VAL_DISC 133 #define CSS_VAL_CIRCLE 134 #define CSS_VAL_SQUARE 135 #define CSS_VAL_BOX 136 #define CSS_VAL__KHTML_DIAMOND 137 #define CSS_VAL_DECIMAL 138 #define CSS_VAL_DECIMAL_LEADING_ZERO 139 #define CSS_VAL__KHTML_ARABIC_INDIC 140 #define CSS_VAL__KHTML_LAO 141 #define CSS_VAL__KHTML_PERSIAN 142 #define CSS_VAL__KHTML_URDU 143 #define CSS_VAL__KHTML_THAI 144 #define CSS_VAL__KHTML_TIBETAN 145 #define CSS_VAL_LOWER_ROMAN 146 #define CSS_VAL_UPPER_ROMAN 147 #define CSS_VAL_HEBREW 148 #define CSS_VAL_ARMENIAN 149 #define CSS_VAL_GEORGIAN 150 #define CSS_VAL_CJK_IDEOGRAPHIC 151 #define CSS_VAL__KHTML_JAPANESE_FORMAL 152 #define CSS_VAL__KHTML_JAPANESE_INFORMAL 153 #define CSS_VAL__KHTML_SIMP_CHINESE_FORMAL 154 #define CSS_VAL__KHTML_SIMP_CHINESE_INFORMAL 155 #define CSS_VAL__KHTML_TRAD_CHINESE_FORMAL 156 #define CSS_VAL__KHTML_TRAD_CHINESE_INFORMAL 157 #define CSS_VAL_LOWER_GREEK 158 #define CSS_VAL__KHTML_UPPER_GREEK 159 #define CSS_VAL_LOWER_ALPHA 160 #define CSS_VAL_LOWER_LATIN 161 #define CSS_VAL_UPPER_ALPHA 162 #define CSS_VAL_UPPER_LATIN 163 #define CSS_VAL_HIRAGANA 164 #define CSS_VAL_KATAKANA 165 #define CSS_VAL_HIRAGANA_IROHA 166 #define CSS_VAL_KATAKANA_IROHA 167 #define CSS_VAL__KHTML_OPEN_QUOTE 168 #define CSS_VAL__KHTML_CLOSE_QUOTE 169 #define CSS_VAL_INLINE 170 #define CSS_VAL_BLOCK 171 #define CSS_VAL_LIST_ITEM 172 #define CSS_VAL_RUN_IN 173 #define CSS_VAL_COMPACT 174 #define CSS_VAL_INLINE_BLOCK 175 #define CSS_VAL_TABLE 176 #define CSS_VAL_INLINE_TABLE 177 #define CSS_VAL_TABLE_ROW_GROUP 178 #define CSS_VAL_TABLE_HEADER_GROUP 179 #define CSS_VAL_TABLE_FOOTER_GROUP 180 #define CSS_VAL_TABLE_ROW 181 #define CSS_VAL_TABLE_COLUMN_GROUP 182 #define CSS_VAL_TABLE_COLUMN 183 #define CSS_VAL_TABLE_CELL 184 #define CSS_VAL_TABLE_CAPTION 185 #define CSS_VAL_AUTO 186 -#define CSS_VAL_CROSSHAIR 187 -#define CSS_VAL_DEFAULT 188 -#define CSS_VAL_POINTER 189 -#define CSS_VAL_PROGRESS 190 -#define CSS_VAL_MOVE 191 -#define CSS_VAL_E_RESIZE 192 -#define CSS_VAL_NE_RESIZE 193 -#define CSS_VAL_NW_RESIZE 194 -#define CSS_VAL_N_RESIZE 195 -#define CSS_VAL_SE_RESIZE 196 -#define CSS_VAL_SW_RESIZE 197 -#define CSS_VAL_S_RESIZE 198 -#define CSS_VAL_W_RESIZE 199 -#define CSS_VAL_TEXT 200 -#define CSS_VAL_WAIT 201 -#define CSS_VAL_HELP 202 -#define CSS_VAL_LTR 203 -#define CSS_VAL_RTL 204 -#define CSS_VAL_CAPITALIZE 205 -#define CSS_VAL_UPPERCASE 206 -#define CSS_VAL_LOWERCASE 207 -#define CSS_VAL_VISIBLE 208 -#define CSS_VAL_COLLAPSE 209 -#define CSS_VAL_CLOSE_QUOTE 210 -#define CSS_VAL_NO_CLOSE_QUOTE 211 -#define CSS_VAL_NO_OPEN_QUOTE 212 -#define CSS_VAL_OPEN_QUOTE 213 -#define CSS_VAL_NOWRAP 214 -#define CSS_VAL_PRE 215 -#define CSS_VAL_PRE_WRAP 216 -#define CSS_VAL_PRE_LINE 217 -#define CSS_VAL__KHTML_NOWRAP 218 -#define CSS_VAL_ABOVE 219 -#define CSS_VAL_ABSOLUTE 220 -#define CSS_VAL_ALWAYS 221 -#define CSS_VAL_AVOID 222 -#define CSS_VAL_BELOW 223 -#define CSS_VAL_BIDI_OVERRIDE 224 -#define CSS_VAL_BLINK 225 -#define CSS_VAL_BOTH 226 -#define CSS_VAL_CROP 227 -#define CSS_VAL_CROSS 228 -#define CSS_VAL_EMBED 229 -#define CSS_VAL_FIXED 230 -#define CSS_VAL_HAND 231 -#define CSS_VAL_HIDE 232 -#define CSS_VAL_HIGHER 233 -#define CSS_VAL_INVERT 234 -#define CSS_VAL_LANDSCAPE 235 -#define CSS_VAL_LEVEL 236 -#define CSS_VAL_LINE_THROUGH 237 -#define CSS_VAL_LOUD 238 -#define CSS_VAL_LOWER 239 -#define CSS_VAL_MARQUEE 240 -#define CSS_VAL_MIX 241 -#define CSS_VAL_OVERLINE 242 -#define CSS_VAL_PORTRAIT 243 -#define CSS_VAL_RELATIVE 244 -#define CSS_VAL_SCROLL 245 -#define CSS_VAL_SEPARATE 246 -#define CSS_VAL_SHOW 247 -#define CSS_VAL_STATIC 248 -#define CSS_VAL_THICK 249 -#define CSS_VAL_THIN 250 -#define CSS_VAL_UNDERLINE 251 -#define CSS_VAL__KHTML_NORMAL 252 -#define CSS_VAL__KHTML_AROUND_FLOATS 253 -#define CSS_VAL_BORDER_BOX 254 -#define CSS_VAL_CONTENT_BOX 255 -#define CSS_VAL_ENABLED 256 -#define CSS_VAL_DISABLED 257 -#define CSS_VAL_FORWARDS 258 -#define CSS_VAL_BACKWARDS 259 -#define CSS_VAL_AHEAD 260 -#define CSS_VAL_REVERSE 261 -#define CSS_VAL_UP 262 -#define CSS_VAL_DOWN 263 -#define CSS_VAL_SLOW 264 -#define CSS_VAL_FAST 265 -#define CSS_VAL_INFINITE 266 -#define CSS_VAL_SLIDE 267 -#define CSS_VAL_ALTERNATE 268 -#define CSS_VAL_UNFURL 269 -#define CSS_VAL_CLIP 270 -#define CSS_VAL_ELLIPSIS 271 -#define CSS_VAL_BORDER 272 -#define CSS_VAL_CONTENT 273 -#define CSS_VAL_PADDING 274 +#define CSS_VAL_DEFAULT 187 +#define CSS_VAL_CONTEXT_MENU 188 +#define CSS_VAL_HELP 189 +#define CSS_VAL_POINTER 190 +#define CSS_VAL_PROGRESS 191 +#define CSS_VAL_WAIT 192 +#define CSS_VAL_CELL 193 +#define CSS_VAL_CROSSHAIR 194 +#define CSS_VAL_TEXT 195 +#define CSS_VAL_VERTICAL_TEXT 196 +#define CSS_VAL_ALIAS 197 +#define CSS_VAL_COPY 198 +#define CSS_VAL_MOVE 199 +#define CSS_VAL_NO_DROP 200 +#define CSS_VAL_NOT_ALLOWED 201 +#define CSS_VAL_E_RESIZE 202 +#define CSS_VAL_N_RESIZE 203 +#define CSS_VAL_NE_RESIZE 204 +#define CSS_VAL_NW_RESIZE 205 +#define CSS_VAL_S_RESIZE 206 +#define CSS_VAL_SE_RESIZE 207 +#define CSS_VAL_SW_RESIZE 208 +#define CSS_VAL_W_RESIZE 209 +#define CSS_VAL_EW_RESIZE 210 +#define CSS_VAL_NS_RESIZE 211 +#define CSS_VAL_NESW_RESIZE 212 +#define CSS_VAL_NWSE_RESIZE 213 +#define CSS_VAL_COL_RESIZE 214 +#define CSS_VAL_ROW_RESIZE 215 +#define CSS_VAL_ALL_SCROLL 216 +#define CSS_VAL_LTR 217 +#define CSS_VAL_RTL 218 +#define CSS_VAL_CAPITALIZE 219 +#define CSS_VAL_UPPERCASE 220 +#define CSS_VAL_LOWERCASE 221 +#define CSS_VAL_VISIBLE 222 +#define CSS_VAL_COLLAPSE 223 +#define CSS_VAL_CLOSE_QUOTE 224 +#define CSS_VAL_NO_CLOSE_QUOTE 225 +#define CSS_VAL_NO_OPEN_QUOTE 226 +#define CSS_VAL_OPEN_QUOTE 227 +#define CSS_VAL_NOWRAP 228 +#define CSS_VAL_PRE 229 +#define CSS_VAL_PRE_WRAP 230 +#define CSS_VAL_PRE_LINE 231 +#define CSS_VAL__KHTML_NOWRAP 232 +#define CSS_VAL_ABOVE 233 +#define CSS_VAL_ABSOLUTE 234 +#define CSS_VAL_ALWAYS 235 +#define CSS_VAL_AVOID 236 +#define CSS_VAL_BELOW 237 +#define CSS_VAL_BIDI_OVERRIDE 238 +#define CSS_VAL_BLINK 239 +#define CSS_VAL_BOTH 240 +#define CSS_VAL_CROP 241 +#define CSS_VAL_CROSS 242 +#define CSS_VAL_EMBED 243 +#define CSS_VAL_FIXED 244 +#define CSS_VAL_HAND 245 +#define CSS_VAL_HIDE 246 +#define CSS_VAL_HIGHER 247 +#define CSS_VAL_INVERT 248 +#define CSS_VAL_LANDSCAPE 249 +#define CSS_VAL_LEVEL 250 +#define CSS_VAL_LINE_THROUGH 251 +#define CSS_VAL_LOUD 252 +#define CSS_VAL_LOWER 253 +#define CSS_VAL_MARQUEE 254 +#define CSS_VAL_MIX 255 +#define CSS_VAL_OVERLINE 256 +#define CSS_VAL_PORTRAIT 257 +#define CSS_VAL_RELATIVE 258 +#define CSS_VAL_SCROLL 259 +#define CSS_VAL_SEPARATE 260 +#define CSS_VAL_SHOW 261 +#define CSS_VAL_STATIC 262 +#define CSS_VAL_THICK 263 +#define CSS_VAL_THIN 264 +#define CSS_VAL_UNDERLINE 265 +#define CSS_VAL__KHTML_NORMAL 266 +#define CSS_VAL__KHTML_AROUND_FLOATS 267 +#define CSS_VAL_BORDER_BOX 268 +#define CSS_VAL_CONTENT_BOX 269 +#define CSS_VAL_ENABLED 270 +#define CSS_VAL_DISABLED 271 +#define CSS_VAL_FORWARDS 272 +#define CSS_VAL_BACKWARDS 273 +#define CSS_VAL_AHEAD 274 +#define CSS_VAL_REVERSE 275 +#define CSS_VAL_UP 276 +#define CSS_VAL_DOWN 277 +#define CSS_VAL_SLOW 278 +#define CSS_VAL_FAST 279 +#define CSS_VAL_INFINITE 280 +#define CSS_VAL_SLIDE 281 +#define CSS_VAL_ALTERNATE 282 +#define CSS_VAL_UNFURL 283 +#define CSS_VAL_CLIP 284 +#define CSS_VAL_ELLIPSIS 285 +#define CSS_VAL_BORDER 286 +#define CSS_VAL_CONTENT 287 +#define CSS_VAL_PADDING 288 -#define CSS_VAL_TOTAL 275 +#define CSS_VAL_TOTAL 289 #endif diff --git a/khtml/css/cssvalues.in b/khtml/css/cssvalues.in index 86db776708..48703fedcb 100644 --- a/khtml/css/cssvalues.in +++ b/khtml/css/cssvalues.in @@ -1,473 +1,487 @@ # These are all values accepted for CSS2. # # WARNING: # -------- # # The Values are sorted according to the properties they belong to, # and have to be in the same order as the enums in render_style.h. # # If not, the optimizations in the cssparser and style selector will fail, # and produce incorrect results. # inherit initial # # CSS_PROP_OUTLINE_STYLE # CSS_PROP_BORDER_TOP_STYLE # CSS_PROP_BORDER_BOTTOM_STYLE # CSS_PROP_BORDER_LEFT_STYLE -khtml-native none hidden inset groove ridge outset dotted dashed solid double # # CSS_PROP_FONT: # caption icon menu message-box small-caption status-bar # # CSS_PROP_FONT_STYLE: # #normal italic oblique # # CSS_PROP_FONT_VARIANT: # #normal small-caps # # CSS_PROP_FONT_WEIGHT: # normal bold bolder lighter 100 200 300 400 500 600 700 800 900 # # CSS_PROP_FONT_SIZE: # xx-small x-small small medium large x-large xx-large -khtml-xxx-large smaller larger # # CSS_PROP_FONT_STRETCH: # #normal wider narrower ultra-condensed extra-condensed condensed semi-condensed semi-expanded expanded extra-expanded ultra-expanded # # CSS_PROP_GENERIC_FONT_FAMILY: # serif sans-serif cursive fantasy monospace # # # CSS_PROP_BACKGROUND_COLOR: # transparent # # # CSS_PROP_*_COLOR # aqua black blue crimson fuchsia gray green indigo lime maroon navy olive orange purple red silver teal white yellow activeborder activecaption appworkspace background buttonface buttonhighlight buttonshadow buttontext captiontext graytext highlight highlighttext inactiveborder inactivecaption inactivecaptiontext infobackground infotext menutext scrollbar threeddarkshadow threedface threedhighlight threedlightshadow threedshadow window windowframe windowtext # # colors in non strict mode grey -khtml-text # # CSS_PROP_BACKGROUND_REPEAT: # repeat repeat-x repeat-y no-repeat # # CSS_PROP_VERTICAL_ALIGN: # baseline middle sub super text-top text-bottom top bottom # HTML alignment MIDDLE has no corresponding CSS alignment -khtml-baseline-middle # # CSS_PROP_TEXT_ALIGN: # -khtml-auto left right center justify -khtml-left -khtml-right -khtml-center # # CSS_PROP_LIST_STYLE_POSITION: # outside inside # # CSS_PROP_LIST_STYLE_TYPE: # disc circle square box -khtml-diamond decimal decimal-leading-zero -khtml-arabic-indic -khtml-lao -khtml-persian -khtml-urdu -khtml-thai -khtml-tibetan lower-roman upper-roman hebrew armenian georgian cjk-ideographic -khtml-japanese-formal -khtml-japanese-informal -khtml-simp-chinese-formal -khtml-simp-chinese-informal -khtml-trad-chinese-formal -khtml-trad-chinese-informal lower-greek -khtml-upper-greek lower-alpha lower-latin upper-alpha upper-latin hiragana katakana hiragana-iroha katakana-iroha -khtml-open-quote -khtml-close-quote #none # # CSS_PROP_DISPLAY: # inline block list-item run-in compact inline-block table inline-table table-row-group table-header-group table-footer-group table-row table-column-group table-column table-cell table-caption #none # # CSS_PROP_CURSOR: # auto -crosshair default +context-menu +help pointer progress +wait +cell +crosshair +text +vertical-text +alias +copy move +no-drop +not-allowed e-resize +n-resize ne-resize nw-resize -n-resize +s-resize se-resize sw-resize -s-resize w-resize -text -wait -help +ew-resize +ns-resize +nesw-resize +nwse-resize +col-resize +row-resize +all-scroll # # CSS_PROP_DIRECTION: # ltr rtl # # CSS_PROP_TEXT_TRANSFORM: # capitalize uppercase lowercase #none # # CSS_PROP_VISIBILITY: # visible #hidden collapse # # CSS_PROP_CONTENT: # close-quote no-close-quote no-open-quote open-quote # # CSS_PROP_WHITE_SPACE: # #normal nowrap pre pre-wrap pre-line -khtml-nowrap # # Unordered rest # above absolute always avoid below bidi-override blink both crop cross embed fixed hand hide higher invert landscape level line-through loud lower marquee mix overline portrait relative scroll separate show static thick thin underline # # CSS_PROP__KHTML_FLOW_MODE -khtml-normal -khtml-around-floats # CSS3 Values # CSS_PROP__KHTML_BOX_SIZING border-box content-box # CSS_PROP__KHTML_USER_INPUT enabled disabled #none # CSS_PROP_MARQUEE_DIRECTION forwards backwards ahead reverse # left # right up down # auto # CSS_PROP_MARQUEE_SPEED slow # normal fast # CSS_PROP_MARQUEE_REPETITION infinite # CSS_PROP_MARQUEE_STYLE # none slide # scroll alternate unfurl # # CSS_PROP_TEXT_OVERFLOW # clip ellipsis # # CSS_PROP_BACKGROUND_CLIP/ORIGIN # border content padding # # Not supported: # # CSS_PROP_BORDER_IMAGE # # stretch # repeat # round # # CSS_PROP_AZIMUTH: # #A left-side #A far-left #A #left #A center-left #A #center #A center-right #A right #A far-right #A right-side #A behind #A leftwards #A rightwards # # CSS_PROP_SPEECH_RATE: # #A x-slow #A slow #A #medium #A x-fast #A fast #A faster #A slower # # CSS_PROP_VOLUME: # #A silent #A x-soft #A soft #A #medium #A high #A x-high #A x-loud # # CSS_PROP_PITCH: # #A x-low #A low #A #medium #A #high #A #x-high # # CSS_PROP_SPEAK: # #A #normal #A #none #A spell-out # # CSS_PROP_SPEAK_HEADER: # #A #once #A always # # CSS_PROP_SPEAK_NUMERAL: # #A digits #A continuous # # CSS_PROP_SPEAK_PUNCTUATION: # #A code #A #none diff --git a/khtml/css/parser.cpp b/khtml/css/parser.cpp index 6320457fce..01dbc4ef22 100644 --- a/khtml/css/parser.cpp +++ b/khtml/css/parser.cpp @@ -1,3223 +1,3223 @@ /* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse cssyyparse #define yylex cssyylex #define yyerror cssyyerror #define yylval cssyylval #define yychar cssyychar #define yydebug cssyydebug #define yynerrs cssyynerrs /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { UNIMPORTANT_TOK = 258, S = 259, SGML_CD = 260, INCLUDES = 261, DASHMATCH = 262, BEGINSWITH = 263, ENDSWITH = 264, CONTAINS = 265, STRING = 266, IDENT = 267, NTH = 268, HASH = 269, IMPORT_SYM = 270, PAGE_SYM = 271, MEDIA_SYM = 272, FONT_FACE_SYM = 273, CHARSET_SYM = 274, NAMESPACE_SYM = 275, KHTML_RULE_SYM = 276, KHTML_DECLS_SYM = 277, KHTML_VALUE_SYM = 278, IMPORTANT_SYM = 279, QEMS = 280, EMS = 281, EXS = 282, PXS = 283, CMS = 284, MMS = 285, INS = 286, PTS = 287, PCS = 288, DEGS = 289, RADS = 290, GRADS = 291, MSECS = 292, SECS = 293, HERZ = 294, KHERZ = 295, DIMEN = 296, PERCENTAGE = 297, FLOAT = 298, INTEGER = 299, URI = 300, FUNCTION = 301, NOTFUNCTION = 302, UNICODERANGE = 303 }; #endif /* Tokens. */ #define UNIMPORTANT_TOK 258 #define S 259 #define SGML_CD 260 #define INCLUDES 261 #define DASHMATCH 262 #define BEGINSWITH 263 #define ENDSWITH 264 #define CONTAINS 265 #define STRING 266 #define IDENT 267 #define NTH 268 #define HASH 269 #define IMPORT_SYM 270 #define PAGE_SYM 271 #define MEDIA_SYM 272 #define FONT_FACE_SYM 273 #define CHARSET_SYM 274 #define NAMESPACE_SYM 275 #define KHTML_RULE_SYM 276 #define KHTML_DECLS_SYM 277 #define KHTML_VALUE_SYM 278 #define IMPORTANT_SYM 279 #define QEMS 280 #define EMS 281 #define EXS 282 #define PXS 283 #define CMS 284 #define MMS 285 #define INS 286 #define PTS 287 #define PCS 288 #define DEGS 289 #define RADS 290 #define GRADS 291 #define MSECS 292 #define SECS 293 #define HERZ 294 #define KHERZ 295 #define DIMEN 296 #define PERCENTAGE 297 #define FLOAT 298 #define INTEGER 299 #define URI 300 #define FUNCTION 301 #define NOTFUNCTION 302 #define UNICODERANGE 303 /* Copy the first part of user declarations. */ /* * This file is part of the KDE libraries * Copyright (C) 2002-2003 Lars Knoll (knoll@kde.org) * Copyright (c) 2003 Apple Computer * Copyright (C) 2003 Dirk Mueller (mueller@kde.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #include #include #include #include #include #include "cssparser.h" #include #include //#define CSS_DEBUG using namespace DOM; // // The following file defines the function // const struct props *findProp(const char *word, int len) // // with 'props->id' a CSS property in the range from CSS_PROP_MIN to // (and including) CSS_PROP_TOTAL-1 // turn off inlining to void warning with newer gcc #undef __inline #define __inline #include "cssproperties.c" #include "cssvalues.c" #undef __inline int DOM::getPropertyID(const char *tagStr, int len) { { // HTML CSS Properties const struct css_prop *prop = findProp(tagStr, len); if (!prop) return 0; return prop->id; } } int DOM::getValueID(const char *tagStr, int len) { { // HTML CSS Values const struct css_value *val = findValue(tagStr, len); if (!val) return 0; return val->id; } } #define YYDEBUG 0 #undef YYMAXDEPTH #define YYPARSE_PARAM parser /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { CSSRuleImpl *rule; CSSSelector *selector; QList *selectorList; bool ok; MediaListImpl *mediaList; CSSMediaRuleImpl *mediaRule; CSSRuleListImpl *ruleList; ParseString string; float val; int prop_id; unsigned int attribute; unsigned int element; unsigned int ns; CSSSelector::Relation relation; CSSSelector::Match match; bool b; char tok; Value value; ValueList *valueList; } -/* Line 193 of yacc.c. */ +/* Line 187 of yacc.c. */ YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ static inline int cssyyerror(const char *x ) { #ifdef CSS_DEBUG qDebug( "%s", x ); #else Q_UNUSED( x ); #endif return 1; } static int cssyylex( YYSTYPE *yylval ) { return CSSParser::current()->lex( yylval ); } #define null 1 /* Line 216 of yacc.c. */ #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int i) #else static int YYID (i) int i; #endif { return i; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 17 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 477 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 67 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 56 /* YYNRULES -- Number of rules. */ #define YYNRULES 165 /* YYNRULES -- Number of states. */ #define YYNSTATES 308 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 303 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 18, 58, 57, 61, 16, 65, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 56, 2, 63, 60, 2, 66, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 2, 62, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 54, 19, 55, 59, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 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 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 9, 12, 15, 18, 20, 22, 29, 32, 38, 39, 42, 43, 46, 49, 50, 52, 58, 62, 66, 67, 71, 78, 82, 86, 87, 91, 98, 102, 106, 107, 110, 111, 115, 117, 119, 121, 123, 125, 127, 130, 132, 134, 135, 137, 139, 144, 147, 155, 156, 160, 163, 167, 171, 175, 179, 182, 185, 188, 189, 191, 193, 196, 198, 203, 206, 208, 212, 215, 217, 220, 223, 226, 230, 233, 237, 242, 246, 248, 250, 252, 255, 258, 260, 262, 264, 266, 269, 272, 277, 286, 292, 302, 304, 306, 308, 310, 312, 314, 316, 318, 321, 325, 330, 335, 340, 345, 351, 356, 361, 366, 372, 378, 382, 386, 391, 396, 402, 405, 408, 411, 412, 414, 418, 421, 424, 425, 427, 430, 433, 436, 439, 442, 445, 447, 449, 452, 455, 458, 461, 464, 467, 470, 473, 476, 479, 482, 485, 488, 491, 494, 497, 500, 503, 506, 512, 516, 519, 523, 527, 530, 536, 540, 542 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 68, 0, -1, 75, 74, 77, 79, 82, -1, 70, 73, -1, 71, 73, -1, 72, 73, -1, 94, -1, 78, -1, 26, 54, 73, 69, 73, 55, -1, 27, 108, -1, 28, 54, 73, 113, 55, -1, -1, 73, 4, -1, -1, 74, 5, -1, 74, 4, -1, -1, 76, -1, 24, 73, 11, 73, 56, -1, 24, 1, 121, -1, 24, 1, 56, -1, -1, 77, 78, 74, -1, 20, 73, 84, 73, 85, 56, -1, 20, 1, 121, -1, 20, 1, 56, -1, -1, 79, 80, 74, -1, 25, 73, 81, 84, 73, 56, -1, 25, 1, 121, -1, 25, 1, 56, -1, -1, 12, 4, -1, -1, 82, 83, 74, -1, 94, -1, 87, -1, 90, -1, 91, -1, 120, -1, 119, -1, 78, 1, -1, 11, -1, 50, -1, -1, 86, -1, 89, -1, 86, 57, 73, 89, -1, 86, 1, -1, 22, 73, 86, 54, 73, 88, 55, -1, -1, 88, 94, 73, -1, 12, 73, -1, 21, 1, 121, -1, 21, 1, 56, -1, 23, 1, 121, -1, 23, 1, 56, -1, 58, 73, -1, 59, 73, -1, 60, 73, -1, -1, 61, -1, 58, -1, 95, 108, -1, 96, -1, 95, 57, 73, 96, -1, 95, 1, -1, 98, -1, 96, 92, 98, -1, 96, 1, -1, 19, -1, 18, 19, -1, 12, 19, -1, 99, 73, -1, 99, 100, 73, -1, 100, 73, -1, 97, 99, 73, -1, 97, 99, 100, 73, -1, 97, 100, 73, -1, 12, -1, 18, -1, 101, -1, 100, 101, -1, 100, 1, -1, 14, -1, 102, -1, 104, -1, 107, -1, 16, 12, -1, 12, 73, -1, 17, 73, 103, 62, -1, 17, 73, 103, 105, 73, 106, 73, 62, -1, 17, 73, 97, 103, 62, -1, 17, 73, 97, 103, 105, 73, 106, 73, 62, -1, 63, -1, 6, -1, 7, -1, 8, -1, 9, -1, 10, -1, 12, -1, 11, -1, 15, 12, -1, 15, 15, 12, -1, 15, 51, 13, 64, -1, 15, 51, 49, 64, -1, 15, 51, 12, 64, -1, 15, 51, 11, 64, -1, 15, 52, 73, 98, 64, -1, 54, 73, 110, 55, -1, 54, 73, 1, 55, -1, 54, 73, 109, 55, -1, 54, 73, 109, 110, 55, -1, 54, 73, 109, 1, 55, -1, 110, 56, 73, -1, 1, 56, 73, -1, 109, 110, 56, 73, -1, 109, 1, 56, 73, -1, 111, 15, 73, 113, 112, -1, 1, 121, -1, 12, 73, -1, 29, 73, -1, -1, 115, -1, 113, 114, 115, -1, 65, 73, -1, 57, 73, -1, -1, 116, -1, 93, 116, -1, 46, 73, -1, 11, 73, -1, 12, 73, -1, 50, 73, -1, 53, 73, -1, 118, -1, 117, -1, 49, 73, -1, 48, 73, -1, 47, 73, -1, 33, 73, -1, 34, 73, -1, 35, 73, -1, 36, 73, -1, 37, 73, -1, 38, 73, -1, 39, 73, -1, 40, 73, -1, 41, 73, -1, 42, 73, -1, 43, 73, -1, 44, 73, -1, 45, 73, -1, 31, 73, -1, 30, 73, -1, 32, 73, -1, 51, 73, 113, 64, 73, -1, 51, 73, 1, -1, 14, 73, -1, 66, 1, 121, -1, 66, 1, 56, -1, 1, 121, -1, 54, 1, 122, 1, 55, -1, 54, 1, 55, -1, 121, -1, 122, 1, 121, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 263, 263, 264, 265, 266, 270, 271, 275, 282, 288, 313, 314, 317, 319, 320, 323, 325, 328, 339, 342, 347, 349, 360, 370, 373, 379, 380, 384, 392, 393, 397, 398, 401, 403, 414, 415, 416, 417, 418, 419, 420, 424, 425, 429, 432, 437, 441, 446, 453, 467, 468, 478, 500, 503, 509, 512, 518, 519, 520, 521, 525, 526, 530, 552, 565, 583, 592, 595, 609, 616, 617, 618, 622, 626, 631, 636, 643, 652, 664, 680, 686, 689, 699, 706, 712, 713, 714, 718, 727, 751, 756, 762, 770, 782, 785, 788, 791, 794, 797, 803, 804, 808, 814, 820, 827, 834, 841, 848, 857, 860, 863, 866, 871, 877, 881, 884, 889, 895, 917, 923, 930, 931, 935, 939, 955, 958, 961, 967, 968, 970, 971, 972, 978, 979, 980, 982, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1011, 1019, 1035, 1042, 1048, 1057, 1083, 1084, 1088, 1089 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "UNIMPORTANT_TOK", "S", "SGML_CD", "INCLUDES", "DASHMATCH", "BEGINSWITH", "ENDSWITH", "CONTAINS", "STRING", "IDENT", "NTH", "HASH", "':'", "'.'", "'['", "'*'", "'|'", "IMPORT_SYM", "PAGE_SYM", "MEDIA_SYM", "FONT_FACE_SYM", "CHARSET_SYM", "NAMESPACE_SYM", "KHTML_RULE_SYM", "KHTML_DECLS_SYM", "KHTML_VALUE_SYM", "IMPORTANT_SYM", "QEMS", "EMS", "EXS", "PXS", "CMS", "MMS", "INS", "PTS", "PCS", "DEGS", "RADS", "GRADS", "MSECS", "SECS", "HERZ", "KHERZ", "DIMEN", "PERCENTAGE", "FLOAT", "INTEGER", "URI", "FUNCTION", "NOTFUNCTION", "UNICODERANGE", "'{'", "'}'", "';'", "','", "'+'", "'~'", "'>'", "'-'", "']'", "'='", "')'", "'/'", "'@'", "$accept", "stylesheet", "ruleset_or_import", "khtml_rule", "khtml_decls", "khtml_value", "maybe_space", "maybe_sgml", "maybe_charset", "charset", "import_list", "import", "namespace_list", "namespace", "maybe_ns_prefix", "rule_list", "rule", "string_or_uri", "maybe_media_list", "media_list", "media", "ruleset_list", "medium", "page", "font_face", "combinator", "unary_operator", "ruleset", "selector_list", "selector", "namespace_selector", "simple_selector", "element_name", "specifier_list", "specifier", "class", "attrib_id", "attrib", "match", "ident_or_string", "pseudo", "declaration_block", "declaration_list", "declaration", "property", "prio", "expr", "operator", "term", "unary_term", "function", "hexcolor", "invalid_at", "invalid_rule", "invalid_block", "invalid_block_list", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 58, 46, 91, 42, 124, 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, 123, 125, 59, 44, 43, 126, 62, 45, 93, 61, 41, 47, 64 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 67, 68, 68, 68, 68, 69, 69, 70, 71, 72, 73, 73, 74, 74, 74, 75, 75, 76, 76, 76, 77, 77, 78, 78, 78, 79, 79, 80, 80, 80, 81, 81, 82, 82, 83, 83, 83, 83, 83, 83, 83, 84, 84, 85, 85, 86, 86, 86, 87, 88, 88, 89, 90, 90, 91, 91, 92, 92, 92, 92, 93, 93, 94, 95, 95, 95, 96, 96, 96, 97, 97, 97, 98, 98, 98, 98, 98, 98, 99, 99, 100, 100, 100, 101, 101, 101, 101, 102, 103, 104, 104, 104, 104, 105, 105, 105, 105, 105, 105, 106, 106, 107, 107, 107, 107, 107, 107, 107, 108, 108, 108, 108, 108, 109, 109, 109, 109, 110, 110, 111, 112, 112, 113, 113, 114, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 115, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 116, 117, 117, 118, 119, 119, 120, 121, 121, 122, 122 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 5, 2, 2, 2, 1, 1, 6, 2, 5, 0, 2, 0, 2, 2, 0, 1, 5, 3, 3, 0, 3, 6, 3, 3, 0, 3, 6, 3, 3, 0, 2, 0, 3, 1, 1, 1, 1, 1, 1, 2, 1, 1, 0, 1, 1, 4, 2, 7, 0, 3, 2, 3, 3, 3, 3, 2, 2, 2, 0, 1, 1, 2, 1, 4, 2, 1, 3, 2, 1, 2, 2, 2, 3, 2, 3, 4, 3, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 4, 8, 5, 9, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 4, 4, 4, 5, 4, 4, 4, 5, 5, 3, 3, 4, 4, 5, 2, 2, 2, 0, 1, 3, 2, 2, 0, 1, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 5, 3, 2, 3, 3, 2, 5, 3, 1, 3 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 16, 0, 0, 0, 0, 0, 11, 11, 11, 13, 17, 0, 0, 11, 11, 9, 11, 1, 3, 4, 5, 21, 0, 20, 19, 12, 11, 0, 0, 0, 15, 14, 26, 0, 0, 79, 84, 0, 0, 11, 80, 70, 0, 11, 7, 6, 0, 0, 0, 67, 11, 0, 81, 85, 86, 87, 0, 11, 0, 0, 0, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 62, 61, 0, 127, 123, 128, 136, 135, 13, 33, 163, 164, 0, 18, 72, 102, 0, 0, 11, 88, 0, 71, 0, 0, 0, 66, 11, 63, 69, 11, 11, 11, 0, 79, 80, 11, 0, 73, 0, 83, 75, 82, 110, 11, 119, 120, 0, 111, 0, 109, 11, 11, 131, 132, 158, 154, 153, 155, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 130, 139, 138, 137, 133, 0, 134, 129, 10, 11, 11, 0, 22, 0, 13, 0, 0, 103, 0, 0, 0, 0, 0, 11, 0, 0, 0, 25, 24, 42, 43, 11, 8, 0, 57, 58, 59, 68, 76, 0, 78, 74, 115, 113, 11, 112, 11, 114, 0, 157, 127, 126, 125, 124, 0, 31, 27, 0, 0, 11, 0, 0, 0, 13, 36, 37, 38, 35, 40, 39, 162, 165, 107, 106, 104, 105, 0, 89, 11, 0, 95, 96, 97, 98, 99, 90, 94, 11, 44, 0, 77, 117, 116, 127, 11, 30, 29, 0, 0, 161, 0, 0, 0, 0, 41, 34, 108, 92, 11, 0, 11, 0, 0, 46, 11, 118, 156, 32, 11, 54, 53, 0, 56, 55, 160, 159, 0, 101, 100, 11, 52, 23, 48, 11, 121, 0, 11, 11, 0, 0, 28, 50, 0, 91, 47, 0, 93, 49, 11, 51 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 5, 43, 6, 7, 8, 235, 21, 9, 10, 32, 44, 96, 172, 256, 173, 221, 189, 269, 270, 222, 303, 271, 223, 224, 119, 89, 45, 46, 47, 48, 49, 50, 51, 52, 53, 184, 54, 245, 287, 55, 15, 58, 59, 60, 273, 90, 169, 91, 92, 93, 94, 226, 227, 131, 99 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -172 static const yytype_int16 yypact[] = { 235, 18, -44, -27, 59, 23, -172, -172, -172, -172, -172, 135, 0, -172, -172, -172, -172, -172, 119, 119, 119, 32, 134, -172, -172, -172, -172, 340, 20, 335, -172, -172, 121, 47, 53, 127, -172, 195, 156, -172, 173, -172, 189, -172, -172, -172, 38, 168, 459, -172, 317, 160, -172, -172, -172, -172, 186, -172, 102, 103, 180, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, 413, 63, -172, -172, -172, -172, -172, 177, -172, -172, 197, -172, -172, -172, 203, 114, -172, -172, 16, -172, 152, 94, 126, -172, -172, -172, -172, -172, -172, -172, 451, -172, -172, 317, 160, 119, 160, -172, 119, -172, -172, -172, -172, 119, 194, -172, 213, -172, -172, -172, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, 277, 119, -172, -172, -172, -172, 378, 32, 193, -172, 133, 219, -172, 181, 192, 196, 206, 383, 127, 173, 241, 37, -172, -172, -172, -172, -172, -172, 383, 119, 119, 119, -172, 119, 160, 119, 119, 119, -172, -172, -172, -172, 119, 335, -172, 74, 119, 119, -172, 157, 107, 32, 222, 276, -172, 278, 279, 281, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, -172, 221, 119, -172, 45, -172, -172, -172, -172, -172, -172, -172, -172, 161, 283, 119, 119, 119, 377, -172, -172, -172, 288, -2, -172, 167, 161, 198, 210, -172, 32, -172, -172, -172, 226, -172, 227, 2, -172, -172, -172, 119, -172, -172, -172, -172, 39, -172, -172, -172, -172, 226, -172, -172, -172, 119, -172, -172, -172, 119, 106, -172, -172, 27, 161, -172, 119, 29, -172, -172, 217, -172, -172, -172, 119 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -172, -172, -172, -172, -172, -172, -1, -78, -172, -172, -172, -31, -172, -172, -172, -172, -172, 31, -172, 44, -172, -172, 7, -172, -172, -172, -172, -171, -172, 105, 199, -93, 297, -32, -37, -172, 146, -172, 99, 64, -172, 304, -172, 293, -172, -172, -66, -172, 184, 272, -172, -172, -172, -172, -3, -172 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -123 static const yytype_int16 yytable[] = { 12, 95, 225, 290, 25, 18, 19, 20, 24, 187, 13, 26, 27, 28, 128, 29, 123, 170, 125, 11, 25, 56, -11, 17, 25, 34, 195, 14, 181, -11, 98, 25, 57, 25, 182, 41, 30, 31, 107, 112, 290, 110, 111, 238, 239, 240, 241, 242, 188, 124, 127, 238, 239, 240, 241, 242, 132, 25, -45, 291, 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, 128, 234, 128, 301, 197, 304, 14, 294, 214, 113, 291, 208, 25, 243, 244, 22, 97, 133, 180, 187, 186, 265, 244, 100, 25, 25, 191, 16, 57, 192, 193, 194, 166, 255, 167, 196, 198, 25, 199, 176, 177, 178, 168, 200, 25, 167, 306, -2, 215, 33, 205, 206, 252, 168, 251, 42, 220, 263, 188, 35, 101, 36, 37, 38, 39, 40, 41, 42, 216, 217, 218, 134, 136, 137, 128, 126, 298, 179, -11, 25, 209, 210, 106, 115, 213, 229, -11, 268, 36, 37, 38, 39, -11, -11, -60, 190, -60, -60, -60, -60, -60, -60, 246, 22, 109, 23, 108, -11, 212, 138, 248, -11, 174, 219, -11, 249, 171, 250, -11, -11, 22, 102, 185, 254, 103, 22, 257, 253, -11, 175, 259, -11, -11, -11, -11, 22, -64, 277, -11, -64, 116, 117, 118, 35, 25, 36, 37, 38, 39, 40, 41, 285, 286, -11, 22, 129, 130, -11, 267, 230, 104, 105, 22, 201, 202, 274, 22, 236, 280, 278, 231, 281, 283, 1, 232, 2, 3, 4, 22, 284, 282, 288, 203, 204, 233, 292, 305, 22, 228, 293, 22, 258, 207, 260, 261, 25, 262, 289, 115, 264, 296, 276, 61, 62, 297, 63, 275, 299, 300, -60, 247, -60, -60, -60, -60, -60, -60, 279, 302, 307, 183, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 237, 86, 36, 37, 38, 39, 87, 266, -65, 88, 25, -65, 116, 117, 118, 25, 122, 61, 62, 295, 63, 114, 135, 35, 211, 36, 37, 38, 39, 40, 41, 42, 165, 0, 0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 25, 86, 61, 62, 0, 63, 87, 0, 35, 88, 36, 37, 38, 39, 40, 41, 0, 0, 0, 272, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 0, 86, -122, -122, 167, 0, 87, 0, 0, 88, 0, 0, 168, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 0, 81, 82, 83, 35, 0, 36, 37, 38, 39, 40, 41, 120, 0, 36, 37, 38, 39, 121 }; static const yytype_int16 yycheck[] = { 1, 32, 173, 1, 4, 6, 7, 8, 11, 11, 54, 11, 13, 14, 51, 16, 48, 95, 50, 1, 4, 1, 4, 0, 4, 26, 119, 54, 12, 11, 33, 4, 12, 4, 18, 19, 4, 5, 39, 1, 1, 42, 43, 6, 7, 8, 9, 10, 50, 50, 51, 6, 7, 8, 9, 10, 57, 4, 56, 57, 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, 123, 180, 125, 62, 122, 62, 54, 54, 172, 57, 57, 163, 4, 62, 63, 54, 55, 1, 105, 11, 109, 62, 63, 56, 4, 4, 113, 54, 12, 116, 117, 118, 55, 12, 57, 122, 123, 4, 125, 11, 12, 13, 65, 130, 4, 57, 303, 0, 1, 1, 137, 138, 64, 65, 206, 20, 173, 221, 50, 12, 19, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 55, 55, 56, 197, 1, 56, 49, 4, 4, 167, 168, 12, 1, 171, 174, 12, 12, 14, 15, 16, 17, 18, 19, 12, 55, 14, 15, 16, 17, 18, 19, 189, 54, 1, 56, 19, 4, 1, 15, 197, 4, 1, 66, 11, 202, 25, 204, 11, 12, 54, 12, 56, 212, 15, 54, 215, 56, 54, 12, 217, 57, 58, 59, 60, 54, 54, 56, 64, 57, 58, 59, 60, 12, 4, 14, 15, 16, 17, 18, 19, 11, 12, 50, 54, 55, 56, 50, 245, 64, 51, 52, 54, 55, 56, 252, 54, 12, 56, 258, 64, 260, 261, 24, 64, 26, 27, 28, 54, 266, 56, 268, 55, 56, 64, 272, 55, 54, 55, 276, 54, 1, 1, 1, 1, 4, 1, 56, 1, 64, 287, 256, 11, 12, 291, 14, 4, 294, 295, 12, 191, 14, 15, 16, 17, 18, 19, 259, 297, 306, 107, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 183, 53, 14, 15, 16, 17, 58, 237, 54, 61, 4, 57, 58, 59, 60, 4, 48, 11, 12, 284, 14, 46, 58, 12, 169, 14, 15, 16, 17, 18, 19, 20, 89, -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 4, 53, 11, 12, -1, 14, 58, -1, 12, 61, 14, 15, 16, 17, 18, 19, -1, -1, -1, 29, -1, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, 53, 55, 56, 57, -1, 58, -1, -1, 61, -1, -1, 65, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, -1, 47, 48, 49, 12, -1, 14, 15, 16, 17, 18, 19, 12, -1, 14, 15, 16, 17, 18 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 24, 26, 27, 28, 68, 70, 71, 72, 75, 76, 1, 73, 54, 54, 108, 54, 0, 73, 73, 73, 74, 54, 56, 121, 4, 11, 73, 73, 73, 4, 5, 77, 1, 73, 12, 14, 15, 16, 17, 18, 19, 20, 69, 78, 94, 95, 96, 97, 98, 99, 100, 101, 102, 104, 107, 1, 12, 109, 110, 111, 11, 12, 14, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 53, 58, 61, 93, 113, 115, 116, 117, 118, 78, 79, 55, 121, 122, 56, 19, 12, 15, 51, 52, 12, 73, 19, 1, 73, 73, 1, 57, 108, 1, 58, 59, 60, 92, 12, 18, 99, 100, 73, 100, 1, 73, 101, 55, 56, 121, 73, 1, 55, 110, 55, 56, 15, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 116, 55, 57, 65, 114, 74, 25, 80, 82, 1, 12, 11, 12, 13, 49, 73, 12, 18, 97, 103, 56, 121, 11, 50, 84, 55, 73, 73, 73, 73, 98, 73, 100, 73, 73, 73, 55, 56, 55, 56, 73, 73, 1, 113, 73, 73, 115, 1, 73, 74, 1, 21, 22, 23, 66, 78, 83, 87, 90, 91, 94, 119, 120, 55, 121, 64, 64, 64, 64, 98, 73, 12, 103, 6, 7, 8, 9, 10, 62, 63, 105, 73, 96, 73, 73, 73, 113, 64, 56, 121, 12, 81, 121, 1, 73, 1, 1, 1, 74, 64, 62, 105, 73, 12, 85, 86, 89, 29, 112, 73, 4, 84, 56, 121, 86, 56, 121, 56, 121, 73, 11, 12, 106, 73, 56, 1, 57, 73, 73, 54, 106, 73, 73, 56, 73, 73, 62, 89, 88, 62, 55, 94, 73 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (&yylval, YYLEX_PARAM) #else # define YYLEX yylex (&yylval) #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) yytype_int16 *bottom; yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); fprintf (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { case 85: /* "maybe_media_list" */ { delete (yyvaluep->mediaList); (yyvaluep->mediaList) = 0; }; break; case 86: /* "media_list" */ { delete (yyvaluep->mediaList); (yyvaluep->mediaList) = 0; }; break; case 88: /* "ruleset_list" */ { delete (yyvaluep->ruleList); (yyvaluep->ruleList) = 0; }; break; case 95: /* "selector_list" */ { if ((yyvaluep->selectorList)) qDeleteAll(*(yyvaluep->selectorList)); delete (yyvaluep->selectorList); (yyvaluep->selectorList) = 0; }; break; case 96: /* "selector" */ { delete (yyvaluep->selector); (yyvaluep->selector) = 0; }; break; case 98: /* "simple_selector" */ { delete (yyvaluep->selector); (yyvaluep->selector) = 0; }; break; case 100: /* "specifier_list" */ { delete (yyvaluep->selector); (yyvaluep->selector) = 0; }; break; case 101: /* "specifier" */ { delete (yyvaluep->selector); (yyvaluep->selector) = 0; }; break; case 102: /* "class" */ { delete (yyvaluep->selector); (yyvaluep->selector) = 0; }; break; case 104: /* "attrib" */ { delete (yyvaluep->selector); (yyvaluep->selector) = 0; }; break; case 107: /* "pseudo" */ { delete (yyvaluep->selector); (yyvaluep->selector) = 0; }; break; case 113: /* "expr" */ { delete (yyvaluep->valueList); (yyvaluep->valueList) = 0; }; break; default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { /* The look-ahead symbol. */ int yychar; /* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; int yystate; int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss = yyssa; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp; #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a look-ahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 8: { CSSParser *p = static_cast(parser); p->rule = (yyvsp[(4) - (6)].rule); ;} break; case 9: { /* can be empty */ ;} break; case 10: { CSSParser *p = static_cast(parser); if ( (yyvsp[(4) - (5)].valueList) ) { p->valueList = (yyvsp[(4) - (5)].valueList); #ifdef CSS_DEBUG kDebug( 6080 ) << " got property for " << p->id << (p->important?" important":""); bool ok = #endif p->parseValue( p->id, p->important ); #ifdef CSS_DEBUG if ( !ok ) kDebug( 6080 ) << " couldn't parse value!"; #endif } #ifdef CSS_DEBUG else kDebug( 6080 ) << " no value found!"; #endif delete p->valueList; p->valueList = 0; ;} break; case 18: { #ifdef CSS_DEBUG kDebug( 6080 ) << "charset rule: " << qString((yyvsp[(3) - (5)].string)); #endif CSSParser* p = static_cast(parser); if ((yyval.rule) && p->styleElement && p->styleElement->isCSSStyleSheet()) { (yyval.rule) = new CSSCharsetRuleImpl(p->styleElement, domString((yyvsp[(3) - (5)].string))); p->styleElement->append((yyval.rule)); } else (yyval.rule) = 0; ;} break; case 19: { (yyval.rule) = 0; ;} break; case 20: { (yyval.rule) = 0; ;} break; case 22: { CSSParser *p = static_cast(parser); if ( (yyvsp[(2) - (3)].rule) && p->styleElement && p->styleElement->isCSSStyleSheet() ) { p->styleElement->append( (yyvsp[(2) - (3)].rule) ); } else { delete (yyvsp[(2) - (3)].rule); } ;} break; case 23: { #ifdef CSS_DEBUG kDebug( 6080 ) << "@import: " << qString((yyvsp[(3) - (6)].string)); #endif CSSParser *p = static_cast(parser); if ( (yyvsp[(5) - (6)].mediaList) && p->styleElement && p->styleElement->isCSSStyleSheet() ) (yyval.rule) = new CSSImportRuleImpl( p->styleElement, domString((yyvsp[(3) - (6)].string)), (yyvsp[(5) - (6)].mediaList) ); else (yyval.rule) = 0; ;} break; case 24: { (yyval.rule) = 0; ;} break; case 25: { (yyval.rule) = 0; ;} break; case 28: { #ifdef CSS_DEBUG kDebug( 6080 ) << "@namespace: " << qString((yyvsp[(4) - (6)].string)); #endif CSSParser *p = static_cast(parser); if (p->styleElement && p->styleElement->isCSSStyleSheet()) static_cast(p->styleElement)->addNamespace(p, domString((yyvsp[(3) - (6)].string)), domString((yyvsp[(4) - (6)].string))); ;} break; case 31: { (yyval.string).string = 0; ;} break; case 32: { (yyval.string) = (yyvsp[(1) - (2)].string); ;} break; case 34: { CSSParser *p = static_cast(parser); if ( (yyvsp[(2) - (3)].rule) && p->styleElement && p->styleElement->isCSSStyleSheet() ) { p->styleElement->append( (yyvsp[(2) - (3)].rule) ); } else { delete (yyvsp[(2) - (3)].rule); } ;} break; case 41: { delete (yyvsp[(1) - (2)].rule); (yyval.rule) = 0; ;} break; case 44: { (yyval.mediaList) = new MediaListImpl(); ;} break; case 46: { (yyval.mediaList) = new MediaListImpl(); (yyval.mediaList)->appendMedium( domString((yyvsp[(1) - (1)].string)).lower() ); ;} break; case 47: { (yyval.mediaList) = (yyvsp[(1) - (4)].mediaList); if ((yyval.mediaList)) (yyval.mediaList)->appendMedium( domString((yyvsp[(4) - (4)].string)).lower() ); ;} break; case 48: { delete (yyvsp[(1) - (2)].mediaList); (yyval.mediaList) = 0; ;} break; case 49: { CSSParser *p = static_cast(parser); if ( (yyvsp[(3) - (7)].mediaList) && (yyvsp[(6) - (7)].ruleList) && p->styleElement && p->styleElement->isCSSStyleSheet() ) { (yyval.rule) = new CSSMediaRuleImpl( static_cast(p->styleElement), (yyvsp[(3) - (7)].mediaList), (yyvsp[(6) - (7)].ruleList) ); } else { (yyval.rule) = 0; delete (yyvsp[(3) - (7)].mediaList); delete (yyvsp[(6) - (7)].ruleList); } ;} break; case 50: { (yyval.ruleList) = 0; ;} break; case 51: { (yyval.ruleList) = (yyvsp[(1) - (3)].ruleList); if ( (yyvsp[(2) - (3)].rule) ) { if ( !(yyval.ruleList) ) (yyval.ruleList) = new CSSRuleListImpl(); (yyval.ruleList)->append( (yyvsp[(2) - (3)].rule) ); } ;} break; case 52: { (yyval.string) = (yyvsp[(1) - (2)].string); ;} break; case 53: { (yyval.rule) = 0; ;} break; case 54: { (yyval.rule) = 0; ;} break; case 55: { (yyval.rule) = 0; ;} break; case 56: { (yyval.rule) = 0; ;} break; case 57: { (yyval.relation) = CSSSelector::DirectAdjacent; ;} break; case 58: { (yyval.relation) = CSSSelector::IndirectAdjacent; ;} break; case 59: { (yyval.relation) = CSSSelector::Child; ;} break; case 60: { (yyval.relation) = CSSSelector::Descendant; ;} break; case 61: { (yyval.val) = -1; ;} break; case 62: { (yyval.val) = 1; ;} break; case 63: { #ifdef CSS_DEBUG kDebug( 6080 ) << "got ruleset" << endl << " selector:"; #endif CSSParser *p = static_cast(parser); if ( (yyvsp[(1) - (2)].selectorList) && (yyvsp[(2) - (2)].ok) && p->numParsedProperties ) { CSSStyleRuleImpl *rule = new CSSStyleRuleImpl( p->styleElement ); CSSStyleDeclarationImpl *decl = p->createStyleDeclaration( rule ); rule->setSelector( (yyvsp[(1) - (2)].selectorList) ); rule->setDeclaration(decl); (yyval.rule) = rule; } else { (yyval.rule) = 0; if ((yyvsp[(1) - (2)].selectorList)) qDeleteAll(*(yyvsp[(1) - (2)].selectorList)); delete (yyvsp[(1) - (2)].selectorList); (yyvsp[(1) - (2)].selectorList) = 0; p->clearProperties(); } ;} break; case 64: { if ( (yyvsp[(1) - (1)].selector) ) { (yyval.selectorList) = new QList; #ifdef CSS_DEBUG kDebug( 6080 ) << " got simple selector:"; (yyvsp[(1) - (1)].selector)->print(); #endif (yyval.selectorList)->append( (yyvsp[(1) - (1)].selector) ); khtml::CSSStyleSelector::precomputeAttributeDependencies(static_cast(parser)->document(), (yyvsp[(1) - (1)].selector)); } else { (yyval.selectorList) = 0; } ;} break; case 65: { if ( (yyvsp[(1) - (4)].selectorList) && (yyvsp[(4) - (4)].selector) ) { (yyval.selectorList) = (yyvsp[(1) - (4)].selectorList); (yyval.selectorList)->append( (yyvsp[(4) - (4)].selector) ); khtml::CSSStyleSelector::precomputeAttributeDependencies(static_cast(parser)->document(), (yyvsp[(4) - (4)].selector)); #ifdef CSS_DEBUG kDebug( 6080 ) << " got simple selector:"; (yyvsp[(4) - (4)].selector)->print(); #endif } else { if ((yyvsp[(1) - (4)].selectorList)) qDeleteAll(*(yyvsp[(1) - (4)].selectorList)); delete (yyvsp[(1) - (4)].selectorList); (yyvsp[(1) - (4)].selectorList)=0; delete (yyvsp[(4) - (4)].selector); (yyval.selectorList) = 0; } ;} break; case 66: { if ((yyvsp[(1) - (2)].selectorList)) qDeleteAll(*(yyvsp[(1) - (2)].selectorList)); delete (yyvsp[(1) - (2)].selectorList); (yyvsp[(1) - (2)].selectorList) = 0; (yyval.selectorList) = 0; ;} break; case 67: { (yyval.selector) = (yyvsp[(1) - (1)].selector); ;} break; case 68: { if ( !(yyvsp[(1) - (3)].selector) || !(yyvsp[(3) - (3)].selector) ) { delete (yyvsp[(1) - (3)].selector); delete (yyvsp[(3) - (3)].selector); (yyval.selector) = 0; } else { (yyval.selector) = (yyvsp[(3) - (3)].selector); CSSSelector *end = (yyvsp[(3) - (3)].selector); while( end->tagHistory ) end = end->tagHistory; end->relation = (yyvsp[(2) - (3)].relation); end->tagHistory = (yyvsp[(1) - (3)].selector); } ;} break; case 69: { delete (yyvsp[(1) - (2)].selector); (yyval.selector) = 0; ;} break; case 70: { (yyval.string).string = 0; (yyval.string).length = 0; ;} break; case 71: { static unsigned short star = '*'; (yyval.string).string = ☆ (yyval.string).length = 1; ;} break; case 72: { (yyval.string) = (yyvsp[(1) - (2)].string); ;} break; case 73: { (yyval.selector) = new CSSSelector(); (yyval.selector)->tag = (yyvsp[(1) - (2)].element); ;} break; case 74: { (yyval.selector) = (yyvsp[(2) - (3)].selector); if ( (yyval.selector) ) (yyval.selector)->tag = (yyvsp[(1) - (3)].element); ;} break; case 75: { (yyval.selector) = (yyvsp[(1) - (2)].selector); if ( (yyval.selector) ) (yyval.selector)->tag = makeId(static_cast(parser)->defaultNamespace(), anyLocalName); ;} break; case 76: { (yyval.selector) = new CSSSelector(); (yyval.selector)->tag = (yyvsp[(2) - (3)].element); CSSParser *p = static_cast(parser); if (p->styleElement && p->styleElement->isCSSStyleSheet()) static_cast(p->styleElement)->determineNamespace((yyval.selector)->tag, domString((yyvsp[(1) - (3)].string))); ;} break; case 77: { (yyval.selector) = (yyvsp[(3) - (4)].selector); if ((yyval.selector)) { (yyval.selector)->tag = (yyvsp[(2) - (4)].element); CSSParser *p = static_cast(parser); if (p->styleElement && p->styleElement->isCSSStyleSheet()) static_cast(p->styleElement)->determineNamespace((yyval.selector)->tag, domString((yyvsp[(1) - (4)].string))); } ;} break; case 78: { (yyval.selector) = (yyvsp[(2) - (3)].selector); if ((yyval.selector)) { (yyval.selector)->tag = makeId(anyNamespace, anyLocalName); CSSParser *p = static_cast(parser); if (p->styleElement && p->styleElement->isCSSStyleSheet()) static_cast(p->styleElement)->determineNamespace((yyval.selector)->tag, domString((yyvsp[(1) - (3)].string))); } ;} break; case 79: { CSSParser *p = static_cast(parser); DOM::DocumentImpl *doc = p->document(); QString tag = qString((yyvsp[(1) - (1)].string)); if ( doc ) { if (doc->isHTMLDocument()) tag = tag.toLower(); const DOMString dtag(tag); (yyval.element) = makeId(p->defaultNamespace(), doc->getId(NodeImpl::ElementId, dtag.implementation(), false, true)); } else { (yyval.element) = makeId(p->defaultNamespace(), khtml::getTagID(tag.toLower().toAscii(), tag.length())); // this case should never happen - only when loading // the default stylesheet - which must not contain unknown tags // assert($$ != 0); } ;} break; case 80: { (yyval.element) = makeId(static_cast(parser)->defaultNamespace(), anyLocalName); ;} break; case 81: { (yyval.selector) = (yyvsp[(1) - (1)].selector); ;} break; case 82: { (yyval.selector) = (yyvsp[(1) - (2)].selector); if ( (yyval.selector) ) { CSSSelector *end = (yyvsp[(1) - (2)].selector); while( end->tagHistory ) end = end->tagHistory; end->relation = CSSSelector::SubSelector; end->tagHistory = (yyvsp[(2) - (2)].selector); } ;} break; case 83: { delete (yyvsp[(1) - (2)].selector); (yyval.selector) = 0; ;} break; case 84: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::Id; (yyval.selector)->attr = ATTR_ID; (yyval.selector)->value = domString((yyvsp[(1) - (1)].string)); ;} break; case 88: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::Class; (yyval.selector)->attr = ATTR_CLASS; (yyval.selector)->value = domString((yyvsp[(2) - (2)].string)); ;} break; case 89: { CSSParser *p = static_cast(parser); DOM::DocumentImpl *doc = p->document(); QString attr = qString((yyvsp[(1) - (2)].string)); if ( doc ) { if (doc->isHTMLDocument()) attr = attr.toLower(); const DOMString dattr(attr); #ifdef APPLE_CHANGES (yyval.attribute) = doc->attrId(0, dattr.implementation(), false); #else (yyval.attribute) = doc->getId(NodeImpl::AttributeId, dattr.implementation(), false, true); #endif } else { (yyval.attribute) = khtml::getAttrID(attr.toLower().toAscii(), attr.length()); // this case should never happen - only when loading // the default stylesheet - which must not contain unknown attributes assert((yyval.attribute) != 0); } ;} break; case 90: { (yyval.selector) = new CSSSelector(); (yyval.selector)->attr = (yyvsp[(3) - (4)].attribute); (yyval.selector)->match = CSSSelector::Set; ;} break; case 91: { (yyval.selector) = new CSSSelector(); (yyval.selector)->attr = (yyvsp[(3) - (8)].attribute); (yyval.selector)->match = (yyvsp[(4) - (8)].match); (yyval.selector)->value = domString((yyvsp[(6) - (8)].string)); ;} break; case 92: { (yyval.selector) = new CSSSelector(); (yyval.selector)->attr = (yyvsp[(4) - (5)].attribute); (yyval.selector)->match = CSSSelector::Set; CSSParser *p = static_cast(parser); if (p->styleElement && p->styleElement->isCSSStyleSheet()) static_cast(p->styleElement)->determineNamespace((yyval.selector)->attr, domString((yyvsp[(3) - (5)].string))); ;} break; case 93: { (yyval.selector) = new CSSSelector(); (yyval.selector)->attr = (yyvsp[(4) - (9)].attribute); (yyval.selector)->match = (CSSSelector::Match)(yyvsp[(5) - (9)].match); (yyval.selector)->value = domString((yyvsp[(7) - (9)].string)); CSSParser *p = static_cast(parser); if (p->styleElement && p->styleElement->isCSSStyleSheet()) static_cast(p->styleElement)->determineNamespace((yyval.selector)->attr, domString((yyvsp[(3) - (9)].string))); ;} break; case 94: { (yyval.match) = CSSSelector::Exact; ;} break; case 95: { (yyval.match) = CSSSelector::List; ;} break; case 96: { (yyval.match) = CSSSelector::Hyphen; ;} break; case 97: { (yyval.match) = CSSSelector::Begin; ;} break; case 98: { (yyval.match) = CSSSelector::End; ;} break; case 99: { (yyval.match) = CSSSelector::Contain; ;} break; case 102: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::PseudoClass; (yyval.selector)->value = domString((yyvsp[(2) - (2)].string)); ;} break; case 103: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::PseudoElement; (yyval.selector)->value = domString((yyvsp[(3) - (3)].string)); ;} break; case 104: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::PseudoClass; (yyval.selector)->string_arg = domString((yyvsp[(3) - (4)].string)); (yyval.selector)->value = domString((yyvsp[(2) - (4)].string)); ;} break; case 105: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::PseudoClass; (yyval.selector)->string_arg = QString::number((yyvsp[(3) - (4)].val)); (yyval.selector)->value = domString((yyvsp[(2) - (4)].string)); ;} break; case 106: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::PseudoClass; (yyval.selector)->string_arg = domString((yyvsp[(3) - (4)].string)); (yyval.selector)->value = domString((yyvsp[(2) - (4)].string)); ;} break; case 107: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::PseudoClass; (yyval.selector)->string_arg = domString((yyvsp[(3) - (4)].string)); (yyval.selector)->value = domString((yyvsp[(2) - (4)].string)); ;} break; case 108: { (yyval.selector) = new CSSSelector(); (yyval.selector)->match = CSSSelector::PseudoClass; (yyval.selector)->simpleSelector = (yyvsp[(4) - (5)].selector); (yyval.selector)->value = domString((yyvsp[(2) - (5)].string)); ;} break; case 109: { (yyval.ok) = (yyvsp[(3) - (4)].ok); ;} break; case 110: { (yyval.ok) = false; ;} break; case 111: { (yyval.ok) = (yyvsp[(3) - (4)].ok); ;} break; case 112: { (yyval.ok) = (yyvsp[(3) - (5)].ok); if ( (yyvsp[(4) - (5)].ok) ) (yyval.ok) = (yyvsp[(4) - (5)].ok); ;} break; case 113: { (yyval.ok) = (yyvsp[(3) - (5)].ok); ;} break; case 114: { (yyval.ok) = (yyvsp[(1) - (3)].ok); ;} break; case 115: { (yyval.ok) = false; ;} break; case 116: { (yyval.ok) = (yyvsp[(1) - (4)].ok); if ( (yyvsp[(2) - (4)].ok) ) (yyval.ok) = (yyvsp[(2) - (4)].ok); ;} break; case 117: { (yyval.ok) = (yyvsp[(1) - (4)].ok); ;} break; case 118: { (yyval.ok) = false; CSSParser *p = static_cast(parser); if ( (yyvsp[(1) - (5)].prop_id) && (yyvsp[(4) - (5)].valueList) ) { p->valueList = (yyvsp[(4) - (5)].valueList); #ifdef CSS_DEBUG kDebug( 6080 ) << " got property: " << (yyvsp[(1) - (5)].prop_id) << ((yyvsp[(5) - (5)].b)?" important":""); #endif bool ok = p->parseValue( (yyvsp[(1) - (5)].prop_id), (yyvsp[(5) - (5)].b) ); if ( ok ) (yyval.ok) = ok; #ifdef CSS_DEBUG else kDebug( 6080 ) << " couldn't parse value!"; #endif } else { delete (yyvsp[(4) - (5)].valueList); } delete p->valueList; p->valueList = 0; ;} break; case 119: { (yyval.ok) = false; ;} break; case 120: { QString str = qString((yyvsp[(1) - (2)].string)); (yyval.prop_id) = getPropertyID( str.toLower().toLatin1(), str.length() ); ;} break; case 121: { (yyval.b) = true; ;} break; case 122: { (yyval.b) = false; ;} break; case 123: { (yyval.valueList) = new ValueList; (yyval.valueList)->addValue( (yyvsp[(1) - (1)].value) ); ;} break; case 124: { (yyval.valueList) = (yyvsp[(1) - (3)].valueList); if ( (yyval.valueList) ) { if ( (yyvsp[(2) - (3)].tok) ) { Value v; v.id = 0; v.unit = Value::Operator; v.iValue = (yyvsp[(2) - (3)].tok); (yyval.valueList)->addValue( v ); } (yyval.valueList)->addValue( (yyvsp[(3) - (3)].value) ); } ;} break; case 125: { (yyval.tok) = '/'; ;} break; case 126: { (yyval.tok) = ','; ;} break; case 127: { (yyval.tok) = 0; ;} break; case 128: { (yyval.value) = (yyvsp[(1) - (1)].value); ;} break; case 129: { (yyval.value) = (yyvsp[(2) - (2)].value); (yyval.value).fValue *= (yyvsp[(1) - (2)].val); ;} break; case 130: { (yyval.value).id = 0; (yyval.value).string = (yyvsp[(1) - (2)].string); (yyval.value).unit = CSSPrimitiveValue::CSS_DIMENSION; ;} break; case 131: { (yyval.value).id = 0; (yyval.value).string = (yyvsp[(1) - (2)].string); (yyval.value).unit = CSSPrimitiveValue::CSS_STRING; ;} break; case 132: { QString str = qString( (yyvsp[(1) - (2)].string) ); (yyval.value).id = getValueID( str.toLower().toLatin1(), str.length() ); (yyval.value).unit = CSSPrimitiveValue::CSS_IDENT; (yyval.value).string = (yyvsp[(1) - (2)].string); ;} break; case 133: { (yyval.value).id = 0; (yyval.value).string = (yyvsp[(1) - (2)].string); (yyval.value).unit = CSSPrimitiveValue::CSS_URI; ;} break; case 134: { (yyval.value).id = 0; (yyval.value).iValue = 0; (yyval.value).unit = CSSPrimitiveValue::CSS_UNKNOWN;/* ### */ ;} break; case 135: { (yyval.value).id = 0; (yyval.value).string = (yyvsp[(1) - (1)].string); (yyval.value).unit = CSSPrimitiveValue::CSS_RGBCOLOR; ;} break; case 136: { (yyval.value) = (yyvsp[(1) - (1)].value); ;} break; case 137: { (yyval.value).id = 0; (yyval.value).isInt = true; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_NUMBER; ;} break; case 138: { (yyval.value).id = 0; (yyval.value).isInt = false; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_NUMBER; ;} break; case 139: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_PERCENTAGE; ;} break; case 140: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_PX; ;} break; case 141: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_CM; ;} break; case 142: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_MM; ;} break; case 143: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_IN; ;} break; case 144: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_PT; ;} break; case 145: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_PC; ;} break; case 146: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_DEG; ;} break; case 147: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_RAD; ;} break; case 148: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_GRAD; ;} break; case 149: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_MS; ;} break; case 150: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_S; ;} break; case 151: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_HZ; ;} break; case 152: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_KHZ; ;} break; case 153: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_EMS; ;} break; case 154: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = Value::Q_EMS; ;} break; case 155: { (yyval.value).id = 0; (yyval.value).fValue = (yyvsp[(1) - (2)].val); (yyval.value).unit = CSSPrimitiveValue::CSS_EXS; ;} break; case 156: { Function *f = new Function; f->name = (yyvsp[(1) - (5)].string); f->args = (yyvsp[(3) - (5)].valueList); (yyval.value).id = 0; (yyval.value).unit = Value::Function; (yyval.value).function = f; ;} break; case 157: { Function *f = new Function; f->name = (yyvsp[(1) - (3)].string); f->args = 0; (yyval.value).id = 0; (yyval.value).unit = Value::Function; (yyval.value).function = f; ;} break; case 158: { (yyval.string) = (yyvsp[(1) - (2)].string); ;} break; case 159: { (yyval.rule) = 0; #ifdef CSS_DEBUG kDebug( 6080 ) << "skipped invalid @-rule"; #endif ;} break; case 160: { (yyval.rule) = 0; #ifdef CSS_DEBUG kDebug( 6080 ) << "skipped invalid @-rule"; #endif ;} break; case 161: { (yyval.rule) = 0; #ifdef CSS_DEBUG kDebug( 6080 ) << "skipped invalid rule"; #endif ;} break; /* Line 1267 of yacc.c. */ default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } diff --git a/khtml/css/parser.h b/khtml/css/parser.h index 02a2ed09af..97ba119540 100644 --- a/khtml/css/parser.h +++ b/khtml/css/parser.h @@ -1,174 +1,174 @@ /* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { UNIMPORTANT_TOK = 258, S = 259, SGML_CD = 260, INCLUDES = 261, DASHMATCH = 262, BEGINSWITH = 263, ENDSWITH = 264, CONTAINS = 265, STRING = 266, IDENT = 267, NTH = 268, HASH = 269, IMPORT_SYM = 270, PAGE_SYM = 271, MEDIA_SYM = 272, FONT_FACE_SYM = 273, CHARSET_SYM = 274, NAMESPACE_SYM = 275, KHTML_RULE_SYM = 276, KHTML_DECLS_SYM = 277, KHTML_VALUE_SYM = 278, IMPORTANT_SYM = 279, QEMS = 280, EMS = 281, EXS = 282, PXS = 283, CMS = 284, MMS = 285, INS = 286, PTS = 287, PCS = 288, DEGS = 289, RADS = 290, GRADS = 291, MSECS = 292, SECS = 293, HERZ = 294, KHERZ = 295, DIMEN = 296, PERCENTAGE = 297, FLOAT = 298, INTEGER = 299, URI = 300, FUNCTION = 301, NOTFUNCTION = 302, UNICODERANGE = 303 }; #endif /* Tokens. */ #define UNIMPORTANT_TOK 258 #define S 259 #define SGML_CD 260 #define INCLUDES 261 #define DASHMATCH 262 #define BEGINSWITH 263 #define ENDSWITH 264 #define CONTAINS 265 #define STRING 266 #define IDENT 267 #define NTH 268 #define HASH 269 #define IMPORT_SYM 270 #define PAGE_SYM 271 #define MEDIA_SYM 272 #define FONT_FACE_SYM 273 #define CHARSET_SYM 274 #define NAMESPACE_SYM 275 #define KHTML_RULE_SYM 276 #define KHTML_DECLS_SYM 277 #define KHTML_VALUE_SYM 278 #define IMPORTANT_SYM 279 #define QEMS 280 #define EMS 281 #define EXS 282 #define PXS 283 #define CMS 284 #define MMS 285 #define INS 286 #define PTS 287 #define PCS 288 #define DEGS 289 #define RADS 290 #define GRADS 291 #define MSECS 292 #define SECS 293 #define HERZ 294 #define KHERZ 295 #define DIMEN 296 #define PERCENTAGE 297 #define FLOAT 298 #define INTEGER 299 #define URI 300 #define FUNCTION 301 #define NOTFUNCTION 302 #define UNICODERANGE 303 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { CSSRuleImpl *rule; CSSSelector *selector; QList *selectorList; bool ok; MediaListImpl *mediaList; CSSMediaRuleImpl *mediaRule; CSSRuleListImpl *ruleList; ParseString string; float val; int prop_id; unsigned int attribute; unsigned int element; unsigned int ns; CSSSelector::Relation relation; CSSSelector::Match match; bool b; char tok; Value value; ValueList *valueList; } -/* Line 1529 of yacc.c. */ +/* Line 1489 of yacc.c. */ YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif diff --git a/khtml/khtmlview.cpp b/khtml/khtmlview.cpp index 5977681b49..8dea439694 100644 --- a/khtml/khtmlview.cpp +++ b/khtml/khtmlview.cpp @@ -1,4869 +1,4892 @@ /* This file is part of the KDE project * * Copyright (C) 1998, 1999 Torben Weis * 1999 Lars Knoll * 1999 Antti Koivisto * 2000-2004 Dirk Mueller * 2003 Leo Savernik * 2003-2004 Apple Computer, Inc. * 2006 Germain Garand * * 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. */ #include "khtmlview.h" #include "khtmlview.moc" #include "khtml_part.h" #include "khtml_events.h" #ifdef Q_WS_X11 #include #endif #include "html/html_documentimpl.h" #include "html/html_inlineimpl.h" #include "html/html_formimpl.h" #include "rendering/render_arena.h" #include "rendering/render_canvas.h" #include "rendering/render_frames.h" #include "rendering/render_replaced.h" #include "rendering/render_form.h" #include "rendering/render_layer.h" #include "rendering/render_line.h" #include "rendering/render_table.h" // removeme #define protected public #include "rendering/render_text.h" #undef protected #include "xml/dom2_eventsimpl.h" #include "css/cssstyleselector.h" #include "css/csshelper.h" #include "misc/htmlhashes.h" #include "misc/helper.h" #include "misc/loader.h" #include "khtml_settings.h" #include "khtml_printsettings.h" #include "khtmlpart_p.h" #ifndef KHTML_NO_CARET #include "khtml_caret_p.h" #include "xml/dom2_rangeimpl.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#define DEBUG_FLICKER //#define DEBUG_PIXEL #include #ifdef Q_WS_X11 #include #include #elif defined(Q_WS_WIN) #include #endif #if 0 namespace khtml { void dumpLineBoxes(RenderFlow *flow); } #endif using namespace DOM; using namespace khtml; class KHTMLViewPrivate { friend class KHTMLView; public: enum PseudoFocusNodes { PFNone, PFTop, PFBottom }; enum CompletedState { CSNone = 0, CSFull, CSActionPending }; KHTMLViewPrivate() : underMouse( 0 ), underMouseNonShared( 0 ), oldUnderMouse( 0 ) { #ifndef KHTML_NO_CARET m_caretViewContext = 0; m_editorContext = 0; #endif // KHTML_NO_CARET postponed_autorepeat = NULL; scrollingFromWheelTimerId = 0; reset(); vpolicy = Qt::ScrollBarAsNeeded; hpolicy = Qt::ScrollBarAsNeeded; formCompletions=0; prevScrollbarVisible = true; possibleTripleClick = false; emitCompletedAfterRepaint = CSNone; cursor_icon_widget = NULL; m_mouseScrollTimer = 0; m_mouseScrollIndicator = 0; } ~KHTMLViewPrivate() { delete formCompletions; delete postponed_autorepeat; if (underMouse) underMouse->deref(); if (underMouseNonShared) underMouseNonShared->deref(); if (oldUnderMouse) oldUnderMouse->deref(); #ifndef KHTML_NO_CARET delete m_caretViewContext; delete m_editorContext; #endif // KHTML_NO_CARET delete cursor_icon_widget; delete m_mouseScrollTimer; delete m_mouseScrollIndicator; } void reset() { if (underMouse) underMouse->deref(); underMouse = 0; if (underMouseNonShared) underMouseNonShared->deref(); underMouseNonShared = 0; if (oldUnderMouse) oldUnderMouse->deref(); oldUnderMouse = 0; linkPressed = false; staticWidget = false; tabMovePending = false; lastTabbingDirection = true; pseudoFocusNode = PFNone; zoomLevel = 100; #ifndef KHTML_NO_SCROLLBARS //We don't turn off the toolbars here //since if the user turns them //off, then chances are they want them turned //off always - even after a reset. #else vpolicy = ScrollBarAlwaysOff; hpolicy = ScrollBarAlwaysOff; #endif #ifdef DEBUG_PIXEL timer.start(); pixelbooth = 0; repaintbooth = 0; #endif scrollBarMoved = false; contentsMoving = false; ignoreWheelEvents = false; scrollingFromWheel = QPoint(-1,-1); borderX = 30; borderY = 30; paged = false; clickX = -1; clickY = -1; contentsX = 0; contentsY = 0; clickCount = 0; isDoubleClick = false; scrollingSelf = false; delete postponed_autorepeat; postponed_autorepeat = NULL; layoutTimerId = 0; repaintTimerId = 0; scrollTimerId = 0; scrollSuspended = false; scrollSuspendPreActivate = false; complete = false; firstRelayout = true; needsFullRepaint = true; dirtyLayout = false; layoutSchedulingEnabled = true; painting = false; updateRegion = QRegion(); m_dialogsAllowed = true; #ifndef KHTML_NO_CARET if (m_caretViewContext) { m_caretViewContext->caretMoved = false; m_caretViewContext->keyReleasePending = false; }/*end if*/ #endif // KHTML_NO_CARET #ifndef KHTML_NO_TYPE_AHEAD_FIND typeAheadActivated = false; #endif // KHTML_NO_TYPE_AHEAD_FIND accessKeysActivated = false; accessKeysPreActivate = false; // the view might have been built before the part it will be assigned to, // so exceptionally, we need to directly ref/deref KHTMLGlobal to // account for this transitory case. KHTMLGlobal::ref(); accessKeysEnabled = KHTMLGlobal::defaultHTMLSettings()->accessKeysEnabled(); KHTMLGlobal::deref(); emitCompletedAfterRepaint = CSNone; m_mouseEventsTarget = 0; m_clipHolder = 0; } void newScrollTimer(QWidget *view, int tid) { //kDebug(6000) << "newScrollTimer timer " << tid; view->killTimer(scrollTimerId); scrollTimerId = tid; scrollSuspended = false; } enum ScrollDirection { ScrollLeft, ScrollRight, ScrollUp, ScrollDown }; void adjustScroller(QWidget *view, ScrollDirection direction, ScrollDirection oppositedir) { static const struct { int msec, pixels; } timings [] = { {320,1}, {224,1}, {160,1}, {112,1}, {80,1}, {56,1}, {40,1}, {28,1}, {20,1}, {20,2}, {20,3}, {20,4}, {20,6}, {20,8}, {0,0} }; if (!scrollTimerId || (static_cast(scrollDirection) != direction && (static_cast(scrollDirection) != oppositedir || scrollSuspended))) { scrollTiming = 6; scrollBy = timings[scrollTiming].pixels; scrollDirection = direction; newScrollTimer(view, view->startTimer(timings[scrollTiming].msec)); } else if (scrollDirection == direction && timings[scrollTiming+1].msec && !scrollSuspended) { scrollBy = timings[++scrollTiming].pixels; newScrollTimer(view, view->startTimer(timings[scrollTiming].msec)); } else if (scrollDirection == oppositedir) { if (scrollTiming) { scrollBy = timings[--scrollTiming].pixels; newScrollTimer(view, view->startTimer(timings[scrollTiming].msec)); } } scrollSuspended = false; } bool haveZoom() const { return zoomLevel != 100; } #ifndef KHTML_NO_CARET /** this function returns an instance of the caret view context. If none * exists, it will be instantiated. */ CaretViewContext *caretViewContext() { if (!m_caretViewContext) m_caretViewContext = new CaretViewContext(); return m_caretViewContext; } /** this function returns an instance of the editor context. If none * exists, it will be instantiated. */ EditorContext *editorContext() { if (!m_editorContext) m_editorContext = new EditorContext(); return m_editorContext; } #endif // KHTML_NO_CARET #ifdef DEBUG_PIXEL QTime timer; unsigned int pixelbooth; unsigned int repaintbooth; #endif NodeImpl *underMouse; NodeImpl *underMouseNonShared; NodeImpl *oldUnderMouse; bool tabMovePending:1; bool lastTabbingDirection:1; PseudoFocusNodes pseudoFocusNode:2; bool scrollBarMoved:1; bool contentsMoving:1; Qt::ScrollBarPolicy vpolicy; Qt::ScrollBarPolicy hpolicy; bool prevScrollbarVisible:1; bool linkPressed:1; bool staticWidget:1; bool ignoreWheelEvents:1; int zoomLevel; int borderX, borderY; KConfig *formCompletions; int clickX, clickY, clickCount; bool isDoubleClick; bool paged; bool scrollingSelf; int contentsX, contentsY; int layoutTimerId; QKeyEvent* postponed_autorepeat; int repaintTimerId; int scrollTimerId; int scrollTiming; int scrollBy; ScrollDirection scrollDirection :2; bool scrollSuspended :1; bool scrollSuspendPreActivate :1; bool complete :1; bool firstRelayout :1; bool layoutSchedulingEnabled :1; bool needsFullRepaint :1; bool painting :1; bool possibleTripleClick :1; bool dirtyLayout :1; bool m_dialogsAllowed :1; QRegion updateRegion; QHash visibleWidgets; #ifndef KHTML_NO_CARET CaretViewContext *m_caretViewContext; EditorContext *m_editorContext; #endif // KHTML_NO_CARET #ifndef KHTML_NO_TYPE_AHEAD_FIND QString findString; QTimer timer; bool findLinksOnly; bool typeAheadActivated; #endif // KHTML_NO_TYPE_AHEAD_FIND bool accessKeysEnabled; bool accessKeysActivated; bool accessKeysPreActivate; CompletedState emitCompletedAfterRepaint; QWidget* cursor_icon_widget; // scrolling activated by MMB short m_mouseScroll_byX; short m_mouseScroll_byY; QPoint scrollingFromWheel; int scrollingFromWheelTimerId; QTimer *m_mouseScrollTimer; QWidget *m_mouseScrollIndicator; QPointer m_mouseEventsTarget; QStack* m_clipHolder; }; #ifndef QT_NO_TOOLTIP /** calculates the client-side image map rectangle for the given image element * @param img image element * @param scrollOfs scroll offset of viewport in content coordinates * @param p position to be probed in viewport coordinates * @param r returns the bounding rectangle in content coordinates * @param s returns the title string * @return true if an appropriate area was found -- only in this case r and * s are valid, false otherwise */ static bool findImageMapRect(HTMLImageElementImpl *img, const QPoint &scrollOfs, const QPoint &p, QRect &r, QString &s) { HTMLMapElementImpl* map; if (img && img->getDocument()->isHTMLDocument() && (map = static_cast(img->getDocument())->getMap(img->imageMap()))) { RenderObject::NodeInfo info(true, false); RenderObject *rend = img->renderer(); int ax, ay; if (!rend || !rend->absolutePosition(ax, ay)) return false; // we're a client side image map bool inside = map->mapMouseEvent(p.x() - ax + scrollOfs.x(), p.y() - ay + scrollOfs.y(), rend->contentWidth(), rend->contentHeight(), info); if (inside && info.URLElement()) { HTMLAreaElementImpl *area = static_cast(info.URLElement()); Q_ASSERT(area->id() == ID_AREA); s = area->getAttribute(ATTR_TITLE).string(); QRegion reg = area->cachedRegion(); if (!s.isEmpty() && !reg.isEmpty()) { r = reg.boundingRect(); r.translate(ax, ay); return true; } } } return false; } bool KHTMLView::event( QEvent* e ) { switch ( e->type() ) { case QEvent::ToolTip: { QHelpEvent *he = static_cast(e); QPoint p = he->pos(); DOM::NodeImpl *node = d->underMouseNonShared; QRect region; while ( node ) { if ( node->isElementNode() ) { DOM::ElementImpl *e = static_cast( node ); QRect r; QString s; bool found = false; // for images, check if it is part of a client-side image map, // and query the s' title attributes, too if (e->id() == ID_IMG && !e->getAttribute( ATTR_USEMAP ).isEmpty()) { found = findImageMapRect(static_cast(e), viewportToContents(QPoint(0, 0)), p, r, s); } if (!found) { s = e->getAttribute( ATTR_TITLE ).string(); r = node->getRect(); } region |= QRect( contentsToViewport( r.topLeft() ), r.size() ); if ( !s.isEmpty() ) { QToolTip::showText( viewport()->mapToGlobal(region.bottomLeft()), Qt::convertFromPlainText( s, Qt::WhiteSpaceNormal ) ); break; } } node = node->parentNode(); } return true; } case QEvent::DragEnter: case QEvent::DragMove: case QEvent::DragLeave: case QEvent::Drop: // In Qt4, one needs to both call accept() on the DND event and return // true on ::event for the candidate widget for the drop to be possible. // Apps hosting us, such as konq, can do the former but not the later. // We will do the second bit, as it's a no-op unless someone else explicitly // accepts the event. We need to skip the scrollarea to do that, // since it will just skip the events, both killing the drop, and // not permitting us to forward it up the part hiearchy in our dragEnterEvent, // etc. handlers return QWidget::event(e); default: return QScrollArea::event(e); } } #endif KHTMLView::KHTMLView( KHTMLPart *part, QWidget *parent ) : QScrollArea( parent ), d( new KHTMLViewPrivate ) { m_medium = "screen"; m_part = part; QScrollArea::setVerticalScrollBarPolicy(d->vpolicy); QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy); connect(KGlobalSettings::self(), SIGNAL(kdisplayPaletteChanged()), this, SLOT(slotPaletteChanged())); #ifndef KHTML_NO_TYPE_AHEAD_FIND connect(&d->timer, SIGNAL(timeout()), this, SLOT(findTimeout())); #endif // KHTML_NO_TYPE_AHEAD_FIND init(); widget()->setMouseTracking(true); QTimer::singleShot(0, this, SLOT(delayedInit())); } KHTMLView::~KHTMLView() { closeChildDialogs(); if (m_part) { DOM::DocumentImpl *doc = m_part->xmlDocImpl(); if (doc) doc->detach(); } delete d; } void KHTMLView::setPart(KHTMLPart *part) { assert(part && !m_part); m_part = part; } void KHTMLView::init() { // Do not access the part here. It might not be fully constructed. setFrameStyle(QFrame::NoFrame); setFocusPolicy(Qt::StrongFocus); viewport()->setFocusProxy(this); _marginWidth = -1; // undefined _marginHeight = -1; _width = 0; _height = 0; installEventFilter(this); setAcceptDrops(true); if (!widget()) setWidget( new QWidget(this) ); widget()->setAttribute( Qt::WA_NoSystemBackground ); } void KHTMLView::delayedInit() { QSize s = viewport()->size(); resizeContents(s.width(), s.height()); } // called by KHTMLPart::clear() void KHTMLView::clear() { #ifndef KHTML_NO_CARET if (!m_part->isCaretMode() && !m_part->isEditable()) caretOff(); #endif #ifndef KHTML_NO_TYPE_AHEAD_FIND if( d->typeAheadActivated ) findTimeout(); #endif if (d->accessKeysEnabled && d->accessKeysActivated) accessKeysTimeout(); viewport()->unsetCursor(); if ( d->cursor_icon_widget ) d->cursor_icon_widget->hide(); d->reset(); QAbstractEventDispatcher::instance()->unregisterTimers(this); emit cleared(); QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy); QScrollArea::setVerticalScrollBarPolicy(d->vpolicy); verticalScrollBar()->setEnabled( false ); horizontalScrollBar()->setEnabled( false ); if (m_kwp->isRedirected()) setHasStaticBackground(); } void KHTMLView::hideEvent(QHideEvent* e) { QScrollArea::hideEvent(e); if ( m_part && m_part->xmlDocImpl() ) m_part->xmlDocImpl()->docLoader()->pauseAnimations(); } void KHTMLView::showEvent(QShowEvent* e) { QScrollArea::showEvent(e); if ( m_part && m_part->xmlDocImpl() ) m_part->xmlDocImpl()->docLoader()->resumeAnimations(); } void KHTMLView::setMouseEventsTarget( QWidget* w ) { d->m_mouseEventsTarget = w; } QWidget* KHTMLView::mouseEventsTarget() const { return d->m_mouseEventsTarget; } void KHTMLView::setClipHolder( QStack* ch ) { d->m_clipHolder = ch; } QStack* KHTMLView::clipHolder() const { return d->m_clipHolder; } int KHTMLView::contentsWidth() const { return widget() ? widget()->width() : 0; } int KHTMLView::contentsHeight() const { return widget() ? widget()->height() : 0; } void KHTMLView::resizeContents(int w, int h) { if (!widget()) return; widget()->resize(w, h); } int KHTMLView::contentsX() const { return d->contentsX; } int KHTMLView::contentsY() const { return d->contentsY; } int KHTMLView::visibleWidth() const { if (m_kwp->isRedirected()) { // our RenderWidget knows better if (RenderWidget* rw = m_kwp->renderWidget()) { int ret = rw->width()-rw->paddingLeft()-rw->paddingRight()-rw->borderLeft()-rw->borderRight(); if (verticalScrollBar()->isVisible()) { ret -= style()->pixelMetric(QStyle::PM_ScrollBarExtent); int lhs = style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); if (lhs > 0) ret -= lhs; ret = qMax(0, ret); } return ret; } } return viewport()->width(); } int KHTMLView::visibleHeight() const { if (m_kwp->isRedirected()) { // our RenderWidget knows better if (RenderWidget* rw = m_kwp->renderWidget()) { int ret = rw->height()-rw->paddingBottom()-rw->paddingTop()-rw->borderTop()-rw->borderBottom(); if (horizontalScrollBar()->isVisible()) { ret -= style()->pixelMetric(QStyle::PM_ScrollBarExtent); int lvs = style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing); if (lvs > 0) ret -= lvs; ret = qMax(0, ret); } return ret; } } return viewport()->height(); } void KHTMLView::setContentsPos( int x, int y) { horizontalScrollBar()->setValue( x ); verticalScrollBar()->setValue( y ); } void KHTMLView::scrollBy(int x, int y) { horizontalScrollBar()->setValue( horizontalScrollBar()->value()+x ); verticalScrollBar()->setValue( verticalScrollBar()->value()+y ); } QPoint KHTMLView::contentsToViewport(const QPoint& p) const { return QPoint(p.x()-contentsX(), p.y()-contentsY()); } void KHTMLView::contentsToViewport(int x, int y, int& cx, int& cy) const { QPoint p(x,y); p = contentsToViewport(p); cx = p.x(); cy = p.y(); } QPoint KHTMLView::viewportToContents(const QPoint& p) const { return QPoint(p.x()+contentsX(), p.y()+contentsY()); } void KHTMLView::viewportToContents(int x, int y, int& cx, int& cy) const { QPoint p(x,y); p = viewportToContents(p); cx = p.x(); cy = p.y(); } void KHTMLView::updateContents(int x, int y, int w, int h) { applyTransforms(x, y, w, h); if (m_kwp->isRedirected()) { QPoint off = m_kwp->absolutePos(); KHTMLView* pview = m_part->parentPart()->view(); pview->updateContents(x+off.x(), y+off.y(), w, h); } else widget()->update(x, y, w, h); } void KHTMLView::updateContents( const QRect& r ) { updateContents( r.x(), r.y(), r.width(), r.height() ); } void KHTMLView::repaintContents(int x, int y, int w, int h) { applyTransforms(x, y, w, h); if (m_kwp->isRedirected()) { QPoint off = m_kwp->absolutePos(); KHTMLView* pview = m_part->parentPart()->view(); pview->repaintContents(x+off.x(), y+off.y(), w, h); } else widget()->repaint(x, y, w, h); } void KHTMLView::repaintContents( const QRect& r ) { repaintContents( r.x(), r.y(), r.width(), r.height() ); } void KHTMLView::applyTransforms( int& x, int& y, int& w, int& h) const { if (d->staticWidget) { x -= contentsX(); y -= contentsY(); } if (d->haveZoom()) { const int z = d->zoomLevel; x = x*z/100; y = y*z/100; w = w*z/100; h = h*z/100; } } void KHTMLView::revertTransforms( int& x, int& y, int& w, int& h) const { if (d->staticWidget) { x += contentsX(); y += contentsY(); } if (d->haveZoom()) { const int z = d->zoomLevel; x = x*100/z; y = y*100/z; w = w*100/z; h = h*100/z; } } void KHTMLView::revertTransforms( int& x, int& y ) const { int dummy = 0; revertTransforms(x, y, dummy, dummy); } void KHTMLView::resizeEvent (QResizeEvent* e) { QScrollArea::resizeEvent( e ); if (d->layoutSchedulingEnabled) layout(); #ifndef KHTML_NO_CARET else { hideCaret(); recalcAndStoreCaretPos(); showCaret(); }/*end if*/ #endif if (d->staticWidget && widget()->pos() != QPoint(0,0)) widget()->move(0,0); QApplication::sendPostedEvents(viewport(), QEvent::Paint); if ( m_part && m_part->xmlDocImpl() ) m_part->xmlDocImpl()->dispatchWindowEvent( EventImpl::RESIZE_EVENT, false, false ); } void KHTMLView::paintEvent( QPaintEvent *e ) { QPainter p(widget()); QRect r = e->rect(); QRect v(contentsX(), contentsY(), visibleWidth(), visibleHeight()); if (d->staticWidget) { QPoint off(contentsX(),contentsY()); p.translate(-off); r.translate(off); } r = r.intersect(v); if (!r.isValid() || r.isEmpty()) return; if (d->haveZoom()) { p.scale( d->zoomLevel/100., d->zoomLevel/100.); r.setX(r.x()*100/d->zoomLevel); r.setY(r.y()*100/d->zoomLevel); r.setWidth(r.width()*100/d->zoomLevel); r.setHeight(r.height()*100/d->zoomLevel); r.adjust(-1,-1,1,1); } p.setClipRect(r); int ex = r.x(); int ey = r.y(); int ew = r.width(); int eh = r.height(); if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) { p.fillRect(ex, ey, ew, eh, palette().brush(QPalette::Active, QPalette::Base)); return; } else if ( d->complete && static_cast(m_part->xmlDocImpl()->renderer())->needsLayout() ) { // an external update request happens while we have a layout scheduled unscheduleRelayout(); layout(); } if (d->painting) { kDebug( 6000 ) << "WARNING: paintEvent reentered! "; kDebug( 6000 ) << kBacktrace(); return; } d->painting = true; m_part->xmlDocImpl()->renderer()->layer()->paint(&p, r); #ifndef KHTML_NO_CARET if (d->m_caretViewContext && d->m_caretViewContext->visible) { QRect pos(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); if (pos.intersects(QRect(ex, ey, ew, eh))) { p.setCompositionMode(QPainter::CompositionMode_Xor); p.setPen(Qt::white); if (pos.width() == 1) p.drawLine(pos.topLeft(), pos.bottomRight()); else { p.fillRect(pos, Qt::white); } } } #endif // KHTML_NO_CARET khtml::DrawContentsEvent event( &p, ex, ey, ew, eh ); QApplication::sendEvent( m_part, &event ); if (d->contentsMoving && widget()->underMouse()) { QMouseEvent *tempEvent = new QMouseEvent( QEvent::MouseMove, widget()->mapFromGlobal( QCursor::pos() ), Qt::NoButton, Qt::NoButton, Qt::NoModifier ); QApplication::postEvent(widget(), tempEvent); } d->painting = false; } void KHTMLView::setMarginWidth(int w) { // make it update the rendering area when set _marginWidth = w; } void KHTMLView::setMarginHeight(int h) { // make it update the rendering area when set _marginHeight = h; } void KHTMLView::layout() { if( m_part && m_part->xmlDocImpl() ) { DOM::DocumentImpl *document = m_part->xmlDocImpl(); khtml::RenderCanvas* canvas = static_cast(document->renderer()); if ( !canvas ) return; d->layoutSchedulingEnabled=false; // the reference object for the overflow property on canvas RenderObject * ref = 0; RenderObject* root = document->documentElement() ? document->documentElement()->renderer() : 0; if (document->isHTMLDocument()) { NodeImpl *body = static_cast(document)->body(); if(body && body->renderer() && body->id() == ID_FRAMESET) { QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); body->renderer()->setNeedsLayout(true); } else if (root) // only apply body's overflow to canvas if root has a visible overflow ref = (!body || root->style()->hidesOverflow()) ? root : body->renderer(); } else { ref = root; } if (ref) { if( ref->style()->overflowX() == OHIDDEN ) { if (d->hpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } else if (ref->style()->overflowX() == OSCROLL ) { if (d->hpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); } else if (horizontalScrollBarPolicy() != d->hpolicy) { QScrollArea::setHorizontalScrollBarPolicy(d->hpolicy); } if ( ref->style()->overflowY() == OHIDDEN ) { if (d->vpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } else if (ref->style()->overflowY() == OSCROLL ) { if (d->vpolicy == Qt::ScrollBarAsNeeded) QScrollArea::setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); } else if (verticalScrollBarPolicy() != d->vpolicy) { QScrollArea::setVerticalScrollBarPolicy(d->vpolicy); } } d->needsFullRepaint = d->firstRelayout; if (_height != visibleHeight() || _width != visibleWidth()) {; d->needsFullRepaint = true; _height = visibleHeight(); _width = visibleWidth(); } canvas->layout(); emit finishedLayout(); if (d->firstRelayout) { // make sure firstRelayout is set to false now in case this layout // wasn't scheduled d->firstRelayout = false; verticalScrollBar()->setEnabled( true ); horizontalScrollBar()->setEnabled( true ); } #ifndef KHTML_NO_CARET hideCaret(); if ((m_part->isCaretMode() || m_part->isEditable()) && !d->complete && d->m_caretViewContext && !d->m_caretViewContext->caretMoved) { initCaret(); } else { recalcAndStoreCaretPos(); showCaret(); }/*end if*/ #endif if (d->accessKeysEnabled && d->accessKeysActivated) { emit hideAccessKeys(); displayAccessKeys(); } } else _width = visibleWidth(); if (d->layoutTimerId) killTimer(d->layoutTimerId); d->layoutTimerId = 0; d->layoutSchedulingEnabled=true; } void KHTMLView::closeChildDialogs() { QList dlgs = findChildren(); foreach (QDialog *dlg, dlgs) { KDialog* dlgbase = dynamic_cast( dlg ); if ( dlgbase ) { if ( dlgbase->testAttribute( Qt::WA_ShowModal ) ) { kDebug(6000) << "closeChildDialogs: closing dialog " << dlgbase; // close() ends up calling QButton::animateClick, which isn't immediate // we need something the exits the event loop immediately (#49068) dlgbase->reject(); } } else { kWarning() << "closeChildDialogs: not a KDialog! Don't use QDialogs in KDE! " << static_cast(dlg); static_cast(dlg)->hide(); } } d->m_dialogsAllowed = false; } bool KHTMLView::dialogsAllowed() { bool allowed = d->m_dialogsAllowed; KHTMLPart* p = m_part->parentPart(); if (p && p->view()) allowed &= p->view()->dialogsAllowed(); return allowed; } void KHTMLView::closeEvent( QCloseEvent* ev ) { closeChildDialogs(); QScrollArea::closeEvent( ev ); } void KHTMLView::setZoomLevel(int percent) { percent = percent < 20 ? 20 : (percent > 800 ? 800 : percent); int oldpercent = d->zoomLevel; d->zoomLevel = percent; if (percent != oldpercent) { if (d->layoutSchedulingEnabled) layout(); widget()->update(); } } int KHTMLView::zoomLevel() const { return d->zoomLevel; } // // Event Handling // ///////////////// void KHTMLView::mousePressEvent( QMouseEvent *_mouse ) { if (!m_part->xmlDocImpl()) return; if (d->possibleTripleClick && ( _mouse->button() & Qt::MouseButtonMask ) == Qt::LeftButton) { mouseDoubleClickEvent( _mouse ); // it handles triple clicks too return; } int xm = _mouse->x(); int ym = _mouse->y(); revertTransforms(xm, ym); // kDebug( 6000 ) << "mousePressEvent: viewport=("<<_mouse->x()-contentsX()<<"/"<<_mouse->y()-contentsY()<<"), contents=(" << xm << "/" << ym << ")\n"; d->isDoubleClick = false; DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MousePress ); m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev ); //kDebug(6000) << "innerNode="<button() == Qt::MidButton) && !m_part->d->m_bOpenMiddleClick && !d->m_mouseScrollTimer && mev.url.isNull() && (mev.innerNode.elementId() != ID_INPUT) ) { QPoint point = mapFromGlobal( _mouse->globalPos() ); d->m_mouseScroll_byX = 0; d->m_mouseScroll_byY = 0; d->m_mouseScrollTimer = new QTimer( this ); connect( d->m_mouseScrollTimer, SIGNAL(timeout()), this, SLOT(slotMouseScrollTimer()) ); if ( !d->m_mouseScrollIndicator ) { QPixmap pixmap( 48, 48 ), icon; pixmap.fill( QColor( qRgba( 127, 127, 127, 127 ) ) ); QPainter p( &pixmap ); QStyleOption option; option.rect.setRect( 16, 0, 16, 16 ); QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowUp, &option, &p ); option.rect.setRect( 0, 16, 16, 16 ); QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowLeft, &option, &p ); option.rect.setRect( 16, 32, 16, 16 ); QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowDown, &option, &p ); option.rect.setRect( 32, 16, 16, 16 ); QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowRight, &option, &p ); p.drawEllipse( 23, 23, 2, 2 ); d->m_mouseScrollIndicator = new QWidget( this ); d->m_mouseScrollIndicator->setFixedSize( 48, 48 ); QPalette palette; palette.setBrush( d->m_mouseScrollIndicator->backgroundRole(), QBrush( pixmap ) ); d->m_mouseScrollIndicator->setPalette( palette ); } d->m_mouseScrollIndicator->move( point.x()-24, point.y()-24 ); bool hasHorBar = visibleWidth() < contentsWidth(); bool hasVerBar = visibleHeight() < contentsHeight(); KConfigGroup cg( KGlobal::config(), "HTML Settings" ); if ( cg.readEntry( "ShowMouseScrollIndicator", true ) ) { d->m_mouseScrollIndicator->show(); d->m_mouseScrollIndicator->unsetCursor(); QBitmap mask = d->m_mouseScrollIndicator->palette().brush(d->m_mouseScrollIndicator->backgroundRole()).texture().createHeuristicMask( true ); if ( hasHorBar && !hasVerBar ) { QBitmap bm( 16, 16 ); bm.clear(); QPainter painter( &mask ); painter.drawPixmap( QRectF( 16, 0, bm.width(), bm.height() ), bm, bm.rect() ); painter.drawPixmap( QRectF( 16, 32, bm.width(), bm.height() ), bm, bm.rect() ); d->m_mouseScrollIndicator->setCursor( Qt::SizeHorCursor ); } else if ( !hasHorBar && hasVerBar ) { QBitmap bm( 16, 16 ); bm.clear(); QPainter painter( &mask ); painter.drawPixmap( QRectF( 0, 16, bm.width(), bm.height() ), bm, bm.rect() ); painter.drawPixmap( QRectF( 32, 16, bm.width(), bm.height() ), bm, bm.rect() ); d->m_mouseScrollIndicator->setCursor( Qt::SizeVerCursor ); } else d->m_mouseScrollIndicator->setCursor( Qt::SizeAllCursor ); d->m_mouseScrollIndicator->setMask( mask ); } else { if ( hasHorBar && !hasVerBar ) viewport()->setCursor( Qt::SizeHorCursor ); else if ( !hasHorBar && hasVerBar ) viewport()->setCursor( Qt::SizeVerCursor ); else viewport()->setCursor( Qt::SizeAllCursor ); } return; } else if ( d->m_mouseScrollTimer ) { delete d->m_mouseScrollTimer; d->m_mouseScrollTimer = 0; if ( d->m_mouseScrollIndicator ) d->m_mouseScrollIndicator->hide(); } d->clickCount = 1; d->clickX = xm; d->clickY = ym; bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true, d->clickCount,_mouse,true,DOM::NodeImpl::MousePress); if (!swallowEvent) { emit m_part->nodeActivated(mev.innerNode); khtml::MousePressEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); QApplication::sendEvent( m_part, &event ); // we might be deleted after this } } void KHTMLView::mouseDoubleClickEvent( QMouseEvent *_mouse ) { if(!m_part->xmlDocImpl()) return; int xm = _mouse->x(); int ym = _mouse->y(); revertTransforms(xm, ym); // kDebug( 6000 ) << "mouseDblClickEvent: x=" << xm << ", y=" << ym; d->isDoubleClick = true; DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseDblClick ); m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev ); // We do the same thing as mousePressEvent() here, since the DOM does not treat // single and double-click events as separate (only the detail, i.e. number of clicks differs) if (d->clickCount > 0 && QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance()) d->clickCount++; else { // shouldn't happen, if Qt has the same criterias for double clicks. d->clickCount = 1; d->clickX = xm; d->clickY = ym; } bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEDOWN_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true, d->clickCount,_mouse,true,DOM::NodeImpl::MouseDblClick); khtml::RenderObject* r = mev.innerNode.handle() ? mev.innerNode.handle()->renderer() : 0; if (r && r->isWidget()) _mouse->ignore(); if (!swallowEvent) { khtml::MouseDoubleClickEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode, d->clickCount ); QApplication::sendEvent( m_part, &event ); } d->possibleTripleClick=true; QTimer::singleShot(QApplication::doubleClickInterval(),this,SLOT(tripleClickTimeout())); } void KHTMLView::tripleClickTimeout() { d->possibleTripleClick = false; d->clickCount = 0; } static bool targetOpensNewWindow(KHTMLPart *part, QString target) { if (!target.isEmpty() && (target.toLower() != "_top") && (target.toLower() != "_self") && (target.toLower() != "_parent")) { if (target.toLower() == "_blank") return true; else { while (part->parentPart()) part = part->parentPart(); if (!part->frameExists(target)) return true; } } return false; } void KHTMLView::mouseMoveEvent( QMouseEvent * _mouse ) { if ( d->m_mouseScrollTimer ) { QPoint point = mapFromGlobal( _mouse->globalPos() ); int deltaX = point.x() - d->m_mouseScrollIndicator->x() - 24; int deltaY = point.y() - d->m_mouseScrollIndicator->y() - 24; (deltaX > 0) ? d->m_mouseScroll_byX = 1 : d->m_mouseScroll_byX = -1; (deltaY > 0) ? d->m_mouseScroll_byY = 1 : d->m_mouseScroll_byY = -1; double adX = qAbs(deltaX)/30.0; double adY = qAbs(deltaY)/30.0; d->m_mouseScroll_byX = qMax(qMin(d->m_mouseScroll_byX * int(adX*adX), SHRT_MAX), SHRT_MIN); d->m_mouseScroll_byY = qMax(qMin(d->m_mouseScroll_byY * int(adY*adY), SHRT_MAX), SHRT_MIN); if (d->m_mouseScroll_byX == 0 && d->m_mouseScroll_byY == 0) { d->m_mouseScrollTimer->stop(); } else if (!d->m_mouseScrollTimer->isActive()) { d->m_mouseScrollTimer->start( 20 ); } } if(!m_part->xmlDocImpl()) return; int xm = _mouse->x(); int ym = _mouse->y(); revertTransforms(xm, ym); DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseMove ); // Do not modify :hover/:active state while mouse is pressed. m_part->xmlDocImpl()->prepareMouseEvent( _mouse->buttons() /*readonly ?*/, xm, ym, &mev ); // kDebug(6000) << "mouse move: " << _mouse->pos() // << " button " << _mouse->button() // << " state " << _mouse->state() << endl; DOM::NodeImpl* target = mev.innerNode.handle(); DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode(); // a widget may be the real target of this event (e.g. if a scrollbar's slider is being moved) if (d->m_mouseEventsTarget && fn && fn->renderer() && fn->renderer()->isWidget()) target = fn; bool swallowEvent = dispatchMouseEvent(EventImpl::MOUSEMOVE_EVENT,target,mev.innerNonSharedNode.handle(),false, 0,_mouse,true,DOM::NodeImpl::MouseMove); if (d->clickCount > 0 && QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() > QApplication::startDragDistance()) { d->clickCount = 0; // moving the mouse outside the threshold invalidates the click } // execute the scheduled script. This is to make sure the mouseover events come after the mouseout events m_part->executeScheduledScript(); khtml::RenderObject* r = target ? target->renderer() : 0; bool setCursor = true; if (r && r->isWidget()) { RenderWidget* rw = static_cast(r); KHTMLWidget* kw = qobject_cast(rw->widget())? dynamic_cast(rw->widget()) : 0; if (kw && kw->m_kwp->isRedirected()) setCursor = false; } khtml::RenderStyle* style = (r && r->style()) ? r->style() : 0; QCursor c; LinkCursor linkCursor = LINK_NORMAL; switch ( style ? style->cursor() : CURSOR_AUTO) { case CURSOR_AUTO: if ( r && r->isText() ) c = QCursor(Qt::IBeamCursor); if ( mev.url.length() && m_part->settings()->changeCursor() ) { c = m_part->urlCursor(); if (mev.url.string().startsWith("mailto:") && mev.url.string().indexOf('@')>0) linkCursor = LINK_MAILTO; else if ( targetOpensNewWindow( m_part, mev.target.string() ) ) linkCursor = LINK_NEWWINDOW; } if (r && r->isFrameSet() && !static_cast(r)->noResize()) c = QCursor(static_cast(r)->cursorShape()); break; case CURSOR_CROSS: c = QCursor(Qt::CrossCursor); break; case CURSOR_POINTER: c = m_part->urlCursor(); if (mev.url.string().startsWith("mailto:") && mev.url.string().indexOf('@')>0) linkCursor = LINK_MAILTO; else if ( targetOpensNewWindow( m_part, mev.target.string() ) ) linkCursor = LINK_NEWWINDOW; break; case CURSOR_PROGRESS: c = QCursor(Qt::BusyCursor); // working_cursor break; case CURSOR_MOVE: + case CURSOR_ALL_SCROLL: c = QCursor(Qt::SizeAllCursor); break; case CURSOR_E_RESIZE: case CURSOR_W_RESIZE: + case CURSOR_EW_RESIZE: c = QCursor(Qt::SizeHorCursor); break; case CURSOR_N_RESIZE: case CURSOR_S_RESIZE: + case CURSOR_NS_RESIZE: c = QCursor(Qt::SizeVerCursor); break; case CURSOR_NE_RESIZE: case CURSOR_SW_RESIZE: + case CURSOR_NESW_RESIZE: c = QCursor(Qt::SizeBDiagCursor); break; case CURSOR_NW_RESIZE: case CURSOR_SE_RESIZE: + case CURSOR_NWSE_RESIZE: c = QCursor(Qt::SizeFDiagCursor); break; case CURSOR_TEXT: c = QCursor(Qt::IBeamCursor); break; case CURSOR_WAIT: c = QCursor(Qt::WaitCursor); break; case CURSOR_HELP: c = QCursor(Qt::WhatsThisCursor); break; case CURSOR_DEFAULT: break; + case CURSOR_NONE: + case CURSOR_NOT_ALLOWED: + c = QCursor(Qt::ForbiddenCursor); + break; + case CURSOR_ROW_RESIZE: + c = QCursor(Qt::SplitVCursor); + break; + case CURSOR_COL_RESIZE: + c = QCursor(Qt::SplitHCursor); + break; + case CURSOR_VERTICAL_TEXT: + case CURSOR_CONTEXT_MENU: + case CURSOR_NO_DROP: + case CURSOR_CELL: + case CURSOR_COPY: + case CURSOR_ALIAS: + c = QCursor(Qt::ArrowCursor); + break; } if (!setCursor && style && style->cursor() != CURSOR_AUTO) setCursor = true; QWidget* vp = viewport(); for (KHTMLPart* p = m_part; p; p = p->parentPart()) if (!p->parentPart()) vp = p->view()->viewport(); if ( setCursor && vp->cursor().handle() != c.handle() ) { if( c.shape() == Qt::ArrowCursor) { for (KHTMLPart* p = m_part; p; p = p->parentPart()) p->view()->viewport()->unsetCursor(); } else { vp->setCursor( c ); } } if ( linkCursor!=LINK_NORMAL && isVisible() && hasFocus() ) { #ifdef Q_WS_X11 QString cursorIcon; switch (linkCursor) { case LINK_MAILTO: cursorIcon = "mail-message-new"; break; case LINK_NEWWINDOW: cursorIcon = "window-new"; break; default: cursorIcon = "dialog-error"; break; } QPixmap icon_pixmap = KHTMLGlobal::iconLoader()->loadIcon( cursorIcon, KIconLoader::Small, 0, KIconLoader::DefaultState, QStringList(), 0, true ); #if 0 if (d->cursor_icon_widget) { const QPixmap *pm = d->cursor_icon_widget->backgroundPixmap(); if (!pm || pm->serialNumber()!=icon_pixmap.serialNumber()) { delete d->cursor_icon_widget; d->cursor_icon_widget = NULL; } } #endif if( !d->cursor_icon_widget ) { #ifdef Q_WS_X11 d->cursor_icon_widget = new QWidget( 0, Qt::X11BypassWindowManagerHint ); XSetWindowAttributes attr; attr.save_under = True; XChangeWindowAttributes( QX11Info::display(), d->cursor_icon_widget->winId(), CWSaveUnder, &attr ); #else d->cursor_icon_widget = new QWidget( NULL, NULL ); //TODO #endif d->cursor_icon_widget->resize( icon_pixmap.width(), icon_pixmap.height()); if( !icon_pixmap.mask().isNull() ) d->cursor_icon_widget->setMask( icon_pixmap.mask()); else d->cursor_icon_widget->clearMask(); QPalette palette; palette.setBrush( d->cursor_icon_widget->backgroundRole(), QBrush( icon_pixmap ) ); d->cursor_icon_widget->setPalette( palette ); d->cursor_icon_widget->update(); } QPoint c_pos = QCursor::pos(); d->cursor_icon_widget->move( c_pos.x() + 15, c_pos.y() + 15 ); #ifdef Q_WS_X11 XRaiseWindow( QX11Info::display(), d->cursor_icon_widget->winId()); QApplication::flush(); #elif defined(Q_WS_WIN) SetWindowPos( d->cursor_icon_widget->winId(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE ); #else //TODO? #endif d->cursor_icon_widget->show(); #endif } else if ( d->cursor_icon_widget ) d->cursor_icon_widget->hide(); if (r && r->isWidget()) { _mouse->ignore(); } if (!swallowEvent) { khtml::MouseMoveEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); QApplication::sendEvent( m_part, &event ); } } void KHTMLView::mouseReleaseEvent( QMouseEvent * _mouse ) { bool swallowEvent = false; int xm = _mouse->x(); int ym = _mouse->y(); revertTransforms(xm, ym); DOM::NodeImpl::MouseEvent mev( _mouse->buttons(), DOM::NodeImpl::MouseRelease ); if ( m_part->xmlDocImpl() ) { m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev ); DOM::NodeImpl* target = mev.innerNode.handle(); DOM::NodeImpl* fn = m_part->xmlDocImpl()->focusNode(); // a widget may be the real target of this event (e.g. if a scrollbar's slider is being moved) if (d->m_mouseEventsTarget && fn && fn->renderer() && fn->renderer()->isWidget()) target = fn; swallowEvent = dispatchMouseEvent(EventImpl::MOUSEUP_EVENT,target,mev.innerNonSharedNode.handle(),true, d->clickCount,_mouse,false,DOM::NodeImpl::MouseRelease); // clear our sticky event target on any mouseRelease event if (d->m_mouseEventsTarget) d->m_mouseEventsTarget = 0; if (d->clickCount > 0 && QPoint(d->clickX-xm,d->clickY-ym).manhattanLength() <= QApplication::startDragDistance()) { QMouseEvent me(d->isDoubleClick ? QEvent::MouseButtonDblClick : QEvent::MouseButtonRelease, _mouse->pos(), _mouse->button(), _mouse->buttons(), _mouse->modifiers()); dispatchMouseEvent(EventImpl::CLICK_EVENT, mev.innerNode.handle(),mev.innerNonSharedNode.handle(),true, d->clickCount, &me, true, DOM::NodeImpl::MouseRelease); } khtml::RenderObject* r = target ? target->renderer() : 0; if (r && r->isWidget()) _mouse->ignore(); } if (!swallowEvent) { khtml::MouseReleaseEvent event( _mouse, xm, ym, mev.url, mev.target, mev.innerNode ); QApplication::sendEvent( m_part, &event ); } } // returns true if event should be swallowed bool KHTMLView::dispatchKeyEvent( QKeyEvent *_ke ) { if (!m_part->xmlDocImpl()) return false; // Pressing and releasing a key should generate keydown, keypress and keyup events // Holding it down should generated keydown, keypress (repeatedly) and keyup events // The problem here is that Qt generates two autorepeat events (keyrelease+keypress) // for autorepeating, while DOM wants only one autorepeat event (keypress), so one // of the Qt events shouldn't be passed to DOM, but it should be still filtered // out if DOM would filter the autorepeat event. Additional problem is that Qt keyrelease // events don't have text() set (Qt bug?), so DOM often would ignore the keypress event // if it was created using Qt keyrelease, but Qt autorepeat keyrelease comes // before Qt autorepeat keypress (i.e. problem whether to filter it out or not). // The solution is to filter out and postpone the Qt autorepeat keyrelease until // the following Qt keypress event comes. If DOM accepts the DOM keypress event, // the postponed event will be simply discarded. If not, it will be passed to keyPressEvent() // again, and here it will be ignored. // // Qt: Press | Release(autorepeat) Press(autorepeat) etc. | Release // DOM: Down + Press | (nothing) Press | Up // It's also possible to get only Releases. E.g. the release of alt-tab, // or when the keypresses get captured by an accel. if( _ke == d->postponed_autorepeat ) // replayed event { return false; } if( _ke->type() == QEvent::KeyPress ) { if( !_ke->isAutoRepeat()) { bool ret = dispatchKeyEventHelper( _ke, false ); // keydown // don't send keypress even if keydown was blocked, like IE (and unlike Mozilla) if( !ret && dispatchKeyEventHelper( _ke, true )) // keypress ret = true; return ret; } else // autorepeat { bool ret = dispatchKeyEventHelper( _ke, true ); // keypress if( !ret && d->postponed_autorepeat ) keyPressEvent( d->postponed_autorepeat ); delete d->postponed_autorepeat; d->postponed_autorepeat = NULL; return ret; } } else // QEvent::KeyRelease { // Discard postponed "autorepeat key-release" events that didn't see // a keypress after them (e.g. due to QAccel) if ( d->postponed_autorepeat ) { delete d->postponed_autorepeat; d->postponed_autorepeat = 0; } if( !_ke->isAutoRepeat()) { return dispatchKeyEventHelper( _ke, false ); // keyup } else { d->postponed_autorepeat = new QKeyEvent( _ke->type(), _ke->key(), _ke->modifiers(), _ke->text(), _ke->isAutoRepeat(), _ke->count()); if( _ke->isAccepted()) d->postponed_autorepeat->accept(); else d->postponed_autorepeat->ignore(); return true; } } } // returns true if event should be swallowed bool KHTMLView::dispatchKeyEventHelper( QKeyEvent *_ke, bool keypress ) { DOM::NodeImpl* keyNode = m_part->xmlDocImpl()->focusNode(); if (keyNode) { return keyNode->dispatchKeyEvent(_ke, keypress); } else { // no focused node, send to document return m_part->xmlDocImpl()->dispatchKeyEvent(_ke, keypress); } } void KHTMLView::keyPressEvent( QKeyEvent *_ke ) { #ifndef KHTML_NO_TYPE_AHEAD_FIND if(d->typeAheadActivated) { // type-ahead find aka find-as-you-type if(_ke->key() == Qt::Key_Backspace) { d->findString = d->findString.left(d->findString.length() - 1); if(!d->findString.isEmpty()) { findAhead(false); } else { findTimeout(); } d->timer.setSingleShot(true); d->timer.start(3000); _ke->accept(); return; } else if(_ke->key() == Qt::Key_Escape) { findTimeout(); _ke->accept(); return; } else if(_ke->key() == Qt::Key_Space || !_ke->text().trimmed().isEmpty()) { d->findString += _ke->text(); findAhead(true); d->timer.setSingleShot(true); d->timer.start(3000); _ke->accept(); return; } } #endif // KHTML_NO_TYPE_AHEAD_FIND #ifndef KHTML_NO_CARET if (m_part->isEditable() || m_part->isCaretMode() || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode() && m_part->xmlDocImpl()->focusNode()->contentEditable())) { d->caretViewContext()->keyReleasePending = true; caretKeyPressEvent(_ke); return; } #endif // KHTML_NO_CARET // If CTRL was hit, be prepared for access keys if (d->accessKeysEnabled && _ke->key() == Qt::Key_Control && _ke->modifiers()==0 && !d->accessKeysActivated) { d->accessKeysPreActivate=true; _ke->accept(); return; } if (_ke->key() == Qt::Key_Shift && _ke->modifiers()==0) d->scrollSuspendPreActivate=true; // accesskey handling needs to be done before dispatching, otherwise e.g. lineedits // may eat the event if (d->accessKeysEnabled && d->accessKeysActivated) { int state = ( _ke->modifiers() & ( Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier )); if ( state==0 || state==Qt::ShiftModifier) { if (_ke->key() != Qt::Key_Shift) accessKeysTimeout(); handleAccessKey( _ke ); _ke->accept(); return; } accessKeysTimeout(); } if ( dispatchKeyEvent( _ke )) { // If either keydown or keypress was accepted by a widget, or canceled by JS, stop here. _ke->accept(); return; } int offs = (viewport()->height() < 30) ? viewport()->height() : 30; // ### ?? if (_ke->modifiers() & Qt::ShiftModifier) switch(_ke->key()) { case Qt::Key_Space: verticalScrollBar()->setValue( verticalScrollBar()->value() -viewport()->height() + offs ); if(d->scrollSuspended) d->newScrollTimer(this, 0); break; case Qt::Key_Down: case Qt::Key_J: d->adjustScroller(this, KHTMLViewPrivate::ScrollDown, KHTMLViewPrivate::ScrollUp); break; case Qt::Key_Up: case Qt::Key_K: d->adjustScroller(this, KHTMLViewPrivate::ScrollUp, KHTMLViewPrivate::ScrollDown); break; case Qt::Key_Left: case Qt::Key_H: d->adjustScroller(this, KHTMLViewPrivate::ScrollLeft, KHTMLViewPrivate::ScrollRight); break; case Qt::Key_Right: case Qt::Key_L: d->adjustScroller(this, KHTMLViewPrivate::ScrollRight, KHTMLViewPrivate::ScrollLeft); break; } else switch ( _ke->key() ) { case Qt::Key_Down: case Qt::Key_J: if (!d->scrollTimerId || d->scrollSuspended) verticalScrollBar()->setValue( verticalScrollBar()->value()+10 ); if (d->scrollTimerId) d->newScrollTimer(this, 0); break; case Qt::Key_Space: case Qt::Key_PageDown: verticalScrollBar()->setValue( verticalScrollBar()->value() +viewport()->height() - offs ); if(d->scrollSuspended) d->newScrollTimer(this, 0); break; case Qt::Key_Up: case Qt::Key_K: if (!d->scrollTimerId || d->scrollSuspended) verticalScrollBar()->setValue( verticalScrollBar()->value()-10 ); if (d->scrollTimerId) d->newScrollTimer(this, 0); break; case Qt::Key_PageUp: verticalScrollBar()->setValue( verticalScrollBar()->value() -viewport()->height() + offs ); if(d->scrollSuspended) d->newScrollTimer(this, 0); break; case Qt::Key_Right: case Qt::Key_L: if (!d->scrollTimerId || d->scrollSuspended) horizontalScrollBar()->setValue( horizontalScrollBar()->value()+10 ); if (d->scrollTimerId) d->newScrollTimer(this, 0); break; case Qt::Key_Left: case Qt::Key_H: if (!d->scrollTimerId || d->scrollSuspended) horizontalScrollBar()->setValue( horizontalScrollBar()->value()-10 ); if (d->scrollTimerId) d->newScrollTimer(this, 0); break; case Qt::Key_Enter: case Qt::Key_Return: // ### FIXME: // or even better to HTMLAnchorElementImpl::event() if (m_part->xmlDocImpl()) { NodeImpl *n = m_part->xmlDocImpl()->focusNode(); if (n) n->setActive(); } break; case Qt::Key_Home: verticalScrollBar()->setValue( 0 ); horizontalScrollBar()->setValue( 0 ); if(d->scrollSuspended) d->newScrollTimer(this, 0); break; case Qt::Key_End: verticalScrollBar()->setValue( contentsHeight() - visibleHeight() ); if(d->scrollSuspended) d->newScrollTimer(this, 0); break; case Qt::Key_Shift: // what are you doing here? _ke->ignore(); return; default: if (d->scrollTimerId) d->newScrollTimer(this, 0); _ke->ignore(); return; } _ke->accept(); } void KHTMLView::findTimeout() { #ifndef KHTML_NO_TYPE_AHEAD_FIND d->typeAheadActivated = false; d->findString = ""; m_part->setStatusBarText(i18n("Find stopped."), KHTMLPart::BarDefaultText); m_part->enableFindAheadActions( true ); #endif // KHTML_NO_TYPE_AHEAD_FIND } #ifndef KHTML_NO_TYPE_AHEAD_FIND void KHTMLView::startFindAhead( bool linksOnly ) { if( linksOnly ) { d->findLinksOnly = true; m_part->setStatusBarText(i18n("Starting -- find links as you type"), KHTMLPart::BarDefaultText); } else { d->findLinksOnly = false; m_part->setStatusBarText(i18n("Starting -- find text as you type"), KHTMLPart::BarDefaultText); } m_part->findTextBegin(); d->typeAheadActivated = true; // disable, so that the shortcut ( / or ' by default ) doesn't interfere m_part->enableFindAheadActions( false ); d->timer.setSingleShot(true); d->timer.start(3000); } void KHTMLView::findAhead(bool increase) { QString status; QString text = d->findString.toLower(); if(d->findLinksOnly) { m_part->findText(d->findString, KHTMLPart::FindNoPopups | KHTMLPart::FindLinksOnly, this); if(m_part->findTextNext()) { status = i18n("Link found: \"%1\".", text); } else { if(increase) KNotification::beep(); status = i18n("Link not found: \"%1\".", text); } } else { m_part->findText(d->findString, KHTMLPart::FindNoPopups, this); if(m_part->findTextNext()) { status = i18n("Text found: \"%1\".", text); } else { if(increase) KNotification::beep(); status = i18n("Text not found: \"%1\".", text); } } m_part->setStatusBarText(status, KHTMLPart::BarDefaultText); } void KHTMLView::updateFindAheadTimeout() { if( d->typeAheadActivated ) { d->timer.setSingleShot( true ); d->timer.start( 3000 ); } } #endif // KHTML_NO_TYPE_AHEAD_FIND void KHTMLView::keyReleaseEvent(QKeyEvent *_ke) { #ifndef KHTML_NO_TYPE_AHEAD_FIND if(d->typeAheadActivated) { _ke->accept(); return; } #endif if (d->m_caretViewContext && d->m_caretViewContext->keyReleasePending) { //caretKeyReleaseEvent(_ke); d->m_caretViewContext->keyReleasePending = false; return; } if( d->scrollSuspendPreActivate && _ke->key() != Qt::Key_Shift ) d->scrollSuspendPreActivate = false; if( _ke->key() == Qt::Key_Shift && d->scrollSuspendPreActivate && _ke->modifiers() == Qt::ShiftModifier && !(QApplication::keyboardModifiers() & Qt::ShiftModifier)) if (d->scrollTimerId) d->scrollSuspended = !d->scrollSuspended; if (d->accessKeysEnabled) { if (d->accessKeysPreActivate && _ke->key() != Qt::Key_Control) d->accessKeysPreActivate=false; if (d->accessKeysPreActivate && _ke->modifiers() == Qt::ControlModifier && !(QApplication::keyboardModifiers() & Qt::ControlModifier)) { displayAccessKeys(); m_part->setStatusBarText(i18n("Access Keys activated"),KHTMLPart::BarOverrideText); d->accessKeysActivated = true; d->accessKeysPreActivate = false; _ke->accept(); return; } else if (d->accessKeysActivated) { accessKeysTimeout(); _ke->accept(); return; } } // Send keyup event if ( dispatchKeyEvent( _ke ) ) { _ke->accept(); return; } QScrollArea::keyReleaseEvent(_ke); } bool KHTMLView::focusNextPrevChild( bool next ) { // Now try to find the next child if (m_part->xmlDocImpl() && focusNextPrevNode(next)) { if (m_part->xmlDocImpl()->focusNode()) kDebug() << "focusNode.name: " << m_part->xmlDocImpl()->focusNode()->nodeName().string() << endl; return true; // focus node found } // If we get here, pass tabbing control up to the next/previous child in our parent d->pseudoFocusNode = KHTMLViewPrivate::PFNone; if (m_part->parentPart() && m_part->parentPart()->view()) return m_part->parentPart()->view()->focusNextPrevChild(next); return QWidget::focusNextPrevChild(next); } void KHTMLView::doAutoScroll() { QPoint pos = QCursor::pos(); pos = viewport()->mapFromGlobal( pos ); int xm, ym; viewportToContents(pos.x(), pos.y(), xm, ym); pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y()); if ( (pos.y() < 0) || (pos.y() > visibleHeight()) || (pos.x() < 0) || (pos.x() > visibleWidth()) ) { ensureVisible( xm, ym, 0, 5 ); #ifndef KHTML_NO_SELECTION // extend the selection while scrolling DOM::Node innerNode; if (m_part->isExtendingSelection()) { RenderObject::NodeInfo renderInfo(true/*readonly*/, false/*active*/); m_part->xmlDocImpl()->renderer()->layer() ->nodeAtPoint(renderInfo, xm, ym); innerNode = renderInfo.innerNode(); }/*end if*/ if (innerNode.handle() && innerNode.handle()->renderer()) { int absX, absY; innerNode.handle()->renderer()->absolutePosition(absX, absY); m_part->extendSelectionTo(xm, ym, absX, absY, innerNode); }/*end if*/ #endif // KHTML_NO_SELECTION } } // KHTML defines its own stacking order for any object and thus takes // control of widget painting whenever it can. This is called "redirection". // // Redirected widgets are placed off screen. When they are declared as a child of our view (ChildPolished event), // an event filter is installed, so as to catch any paint event and translate them as update() of the view's main widget. // // Painting also happens spontaneously within widgets. In this case, the widget would update() parts of itself. // While this ordinarily results in a paintEvent being schedduled, it is not the case with off screen widgets. // Thus update() is monitored by using the mechanism that deffers any update call happening during a paint event, // transforming it into a posted UpdateLater event. Hence the need to set Qt::WA_WState_InPaintEvent on redirected widgets. // // Once the UpdateLater event has been received, Qt::WA_WState_InPaintEvent is removed and the process continues // with the update of the corresponding rect on the view. That in turn will make our painting subsystem render() // the widget at the correct stacking position. // // For non-redirected (e.g. external) widgets, z-order is honoured through masking. cf.RenderLayer::updateWidgetMasks static void handleWidget(QWidget* w, KHTMLView* view, bool recurse=true) { if (w->isWindow()) return; if (!qobject_cast(w)) w->setAttribute( Qt::WA_NoSystemBackground ); w->setAttribute(Qt::WA_WState_InPaintEvent); w->setAttribute(Qt::WA_OpaquePaintEvent); w->installEventFilter(view); if (!recurse) return; if (qobject_cast(w)) { handleWidget(static_cast(w)->widget(), view, false); handleWidget(static_cast(w)->horizontalScrollBar(), view, false); handleWidget(static_cast(w)->verticalScrollBar(), view, false); return; } QObjectList children = w->children(); foreach (QObject* object, children) { QWidget *widget = qobject_cast(object); if (widget) handleWidget(widget, view); } } class KHTMLBackingStoreHackWidget : public QWidget { public: void publicEvent(QEvent *e) { QWidget::event(e); } }; bool KHTMLView::viewportEvent ( QEvent * e ) { switch (e->type()) { // those must not be dispatched to the specialized handlers // as widgetEvent() already took care of that case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: #endif case QEvent::ContextMenu: case QEvent::DragEnter: case QEvent::DragMove: case QEvent::DragLeave: case QEvent::Drop: return false; case QEvent::Paint: { QRect r = static_cast(e)->rect(); r.setX(r.x() +contentsX()); r.setY(r.y() +contentsY()); QPaintEvent pe(r); paintEvent(&pe); return true; } default: break; } return QScrollArea::viewportEvent(e); } static void setInPaintEventFlag(QWidget* w, bool b = true, bool recurse=true) { w->setAttribute(Qt::WA_WState_InPaintEvent, b); if (!recurse) return; if (qobject_cast(w)) { setInPaintEventFlag(static_cast(w)->widget(), b, false); setInPaintEventFlag(static_cast(w)->horizontalScrollBar(), b, false); setInPaintEventFlag(static_cast(w)->verticalScrollBar(), b, false); return; } foreach(QObject* cw, w->children()) { if (cw->isWidgetType() && ! static_cast(cw)->isWindow() && !(static_cast(cw)->windowModality() & Qt::ApplicationModal)) { setInPaintEventFlag(static_cast(cw), b); } } } bool KHTMLView::eventFilter(QObject *o, QEvent *e) { if ( e->type() == QEvent::ShortcutOverride ) { QKeyEvent* ke = (QKeyEvent*) e; if (m_part->isEditable() || m_part->isCaretMode() || (m_part->xmlDocImpl() && m_part->xmlDocImpl()->focusNode() && m_part->xmlDocImpl()->focusNode()->contentEditable())) { if ( (ke->modifiers() & Qt::ControlModifier) || (ke->modifiers() & Qt::ShiftModifier) ) { switch ( ke->key() ) { case Qt::Key_Left: case Qt::Key_Right: case Qt::Key_Up: case Qt::Key_Down: case Qt::Key_Home: case Qt::Key_End: ke->accept(); return true; default: break; } } } } if ( e->type() == QEvent::Leave ) { if ( d->cursor_icon_widget ) d->cursor_icon_widget->hide(); m_part->resetHoverText(); } QWidget *view = widget(); if (o == view) { if (widgetEvent(e)) return true; } else if (o->isWidgetType()) { QWidget *v = static_cast(o); QWidget *c = v; while (v && v != view) { c = v; v = v->parentWidget(); } KHTMLWidget* k = dynamic_cast(c); if (v && k && k->m_kwp->isRedirected()) { bool block = false; bool isUpdate = false; QWidget *w = static_cast(o); switch(e->type()) { case QEvent::UpdateRequest: { // implicitly call qt_syncBackingStore(w) static_cast(w)->publicEvent(e); block = true; break; } case QEvent::UpdateLater: isUpdate = true; // no break; case QEvent::Paint: if (!allowWidgetPaintEvents) { // eat the event. Like this we can control exactly when the widget // gets repainted. block = true; int x = 0, y = 0; QWidget *v = w; while (v && v->parentWidget() != view) { x += v->x(); y += v->y(); v = v->parentWidget(); } QPoint ap = k->m_kwp->absolutePos(); x += ap.x(); y += ap.y(); QRect pr = isUpdate ? static_cast(e)->region().boundingRect() : static_cast(e)->rect(); bool asap = !isUpdate && !d->contentsMoving && qobject_cast(c); if (isUpdate) { setInPaintEventFlag(w, false); w->update(static_cast(e)->region()); setInPaintEventFlag(w); // implicitly call qt_syncBackingStore(w) QEvent fakeEvent(QEvent::UpdateRequest); static_cast(w)->publicEvent(&fakeEvent); } // QScrollView needs fast repaints if ( asap && !d->painting && m_part->xmlDocImpl() && m_part->xmlDocImpl()->renderer() && !static_cast(m_part->xmlDocImpl()->renderer())->needsLayout() ) { repaintContents(x + pr.x(), y + pr.y(), pr.width(), pr.height()+1); // ### investigate that +1 (shows up when // updating e.g a textarea's blinking cursor) } else if (!d->painting) { scheduleRepaint(x + pr.x(), y + pr.y(), pr.width(), pr.height()+1, asap); } } break; case QEvent::MouseMove: case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: { if (0 && w->parentWidget() == view && !qobject_cast(w) && !::qobject_cast(w)) { QMouseEvent *me = static_cast(e); QPoint pt = w->mapTo( view, me->pos()); QMouseEvent me2(me->type(), pt, me->button(), me->buttons(), me->modifiers()); if (e->type() == QEvent::MouseMove) mouseMoveEvent(&me2); else if(e->type() == QEvent::MouseButtonPress) mousePressEvent(&me2); else if(e->type() == QEvent::MouseButtonRelease) mouseReleaseEvent(&me2); else mouseDoubleClickEvent(&me2); block = true; } break; } case QEvent::KeyPress: case QEvent::KeyRelease: if (w->parentWidget() == view && !qobject_cast(w)) { QKeyEvent *ke = static_cast(e); if (e->type() == QEvent::KeyPress) keyPressEvent(ke); else keyReleaseEvent(ke); block = true; } break; case QEvent::FocusIn: case QEvent::FocusOut: block = true; break; default: break; } if (block) { //qDebug("eating event"); return true; } } } // kDebug(6000) <<"passing event on to sv event filter object=" << o->className() << " event=" << e->type(); return QScrollArea::eventFilter(o, e); } bool KHTMLView::widgetEvent(QEvent* e) { switch (e->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: case QEvent::Paint: #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: #endif case QEvent::ContextMenu: case QEvent::DragEnter: case QEvent::DragMove: case QEvent::DragLeave: case QEvent::Drop: return QFrame::event(e); case QEvent::ChildPolished: { // we need to install an event filter on all children of the widget() to // be able to get correct stacking of children within the document. QObject *c = static_cast(e)->child(); if (c->isWidgetType()) { QWidget *w = static_cast(c); // don't install the event filter on toplevels if (!(w->windowFlags() & Qt::Window) && !(w->windowModality() & Qt::ApplicationModal)) { KHTMLWidget* k = dynamic_cast(w); if (k && k->m_kwp->isRedirected()) { w->unsetCursor(); handleWidget(w, this); } } } } default: break; } return false; } DOM::NodeImpl *KHTMLView::nodeUnderMouse() const { return d->underMouse; } DOM::NodeImpl *KHTMLView::nonSharedNodeUnderMouse() const { return d->underMouseNonShared; } bool KHTMLView::scrollTo(const QRect &bounds) { d->scrollingSelf = true; // so scroll events get ignored int x, y, xe, ye; x = bounds.left(); y = bounds.top(); xe = bounds.right(); ye = bounds.bottom(); //kDebug(6000)<<"scrolling coords: x="<pseudoFocusNode == KHTMLViewPrivate::PFTop ) newFocusNode = doc->nextFocusNode(oldFocusNode); } else { if (oldFocusNode || d->pseudoFocusNode == KHTMLViewPrivate::PFBottom ) newFocusNode = doc->previousFocusNode(oldFocusNode); } bool targetVisible = false; if (!newFocusNode) { if ( next ) { targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,contentsHeight()-d->borderY,0,0)); } else { targetVisible = scrollTo(QRect(contentsX()+visibleWidth()/2,d->borderY,0,0)); } } else { #ifndef KHTML_NO_CARET // if it's an editable element, activate the caret if (!m_part->isCaretMode() && !m_part->isEditable() && newFocusNode->contentEditable()) { d->caretViewContext(); moveCaretTo(newFocusNode, 0L, true); } else { caretOff(); } #endif // KHTML_NO_CARET targetVisible = scrollTo(newFocusNode->getRect()); } if (targetVisible) { //kDebug ( 6000 ) << " target reached.\n"; d->tabMovePending = false; m_part->xmlDocImpl()->setFocusNode(newFocusNode); if (newFocusNode) { Node guard(newFocusNode); if (!newFocusNode->hasOneRef() ) { emit m_part->nodeActivated(Node(newFocusNode)); } return true; } else { d->pseudoFocusNode = next?KHTMLViewPrivate::PFBottom:KHTMLViewPrivate::PFTop; return false; } } else { if (!d->tabMovePending) d->lastTabbingDirection = next; d->tabMovePending = true; return true; } } void KHTMLView::displayAccessKeys() { QVector< QChar > taken; displayAccessKeys( NULL, this, taken, false ); displayAccessKeys( NULL, this, taken, true ); } void KHTMLView::displayAccessKeys( KHTMLView* caller, KHTMLView* origview, QVector< QChar >& taken, bool use_fallbacks ) { QMap< ElementImpl*, QChar > fallbacks; if( use_fallbacks ) fallbacks = buildFallbackAccessKeys(); for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) { if( n->isElementNode()) { ElementImpl* en = static_cast< ElementImpl* >( n ); DOMString s = en->getAttribute( ATTR_ACCESSKEY ); QString accesskey; if( s.length() == 1 ) { QChar a = s.string()[ 0 ].toUpper(); if( qFind( taken.begin(), taken.end(), a ) == taken.end()) // !contains accesskey = a; } if( accesskey.isNull() && fallbacks.contains( en )) { QChar a = fallbacks[ en ].toUpper(); if( qFind( taken.begin(), taken.end(), a ) == taken.end()) // !contains accesskey = QString( "" ) + a + ""; } if( !accesskey.isNull()) { QRect rec=en->getRect(); QLabel *lab=new QLabel(accesskey,viewport()); lab->setAttribute(Qt::WA_DeleteOnClose); connect( origview, SIGNAL(hideAccessKeys()), lab, SLOT(close()) ); connect( this, SIGNAL(repaintAccessKeys()), lab, SLOT(repaint())); lab->setPalette(QToolTip::palette()); lab->setLineWidth(2); lab->setFrameStyle(QFrame::Box | QFrame::Plain); lab->setMargin(3); lab->adjustSize(); lab->setParent( widget() ); lab->move( qMin(rec.left()+rec.width()/2, contentsWidth() - lab->width()), qMin(rec.top()+rec.height()/2, contentsHeight() - lab->height())); lab->show(); taken.append( accesskey[ 0 ] ); } } } if( use_fallbacks ) return; QList frames = m_part->frames(); foreach( KParts::ReadOnlyPart* cur, frames ) { if( !qobject_cast(cur) ) continue; KHTMLPart* part = static_cast< KHTMLPart* >( cur ); if( part->view() && part->view() != caller ) part->view()->displayAccessKeys( this, origview, taken, use_fallbacks ); } // pass up to the parent if (m_part->parentPart() && m_part->parentPart()->view() && m_part->parentPart()->view() != caller) m_part->parentPart()->view()->displayAccessKeys( this, origview, taken, use_fallbacks ); } bool KHTMLView::isScrollingFromMouseWheel() const { return d->scrollingFromWheel != QPoint(-1,-1); } void KHTMLView::accessKeysTimeout() { d->accessKeysActivated=false; d->accessKeysPreActivate = false; m_part->setStatusBarText(QString(), KHTMLPart::BarOverrideText); emit hideAccessKeys(); } // Handling of the HTML accesskey attribute. bool KHTMLView::handleAccessKey( const QKeyEvent* ev ) { // Qt interprets the keyevent also with the modifiers, and ev->text() matches that, // but this code must act as if the modifiers weren't pressed QChar c; if( ev->key() >= Qt::Key_A && ev->key() <= Qt::Key_Z ) c = 'A' + ev->key() - Qt::Key_A; else if( ev->key() >= Qt::Key_0 && ev->key() <= Qt::Key_9 ) c = '0' + ev->key() - Qt::Key_0; else { // TODO fake XKeyEvent and XLookupString ? // This below seems to work e.g. for eacute though. if( ev->text().length() == 1 ) c = ev->text()[ 0 ]; } if( c.isNull()) return false; return focusNodeWithAccessKey( c ); } bool KHTMLView::focusNodeWithAccessKey( QChar c, KHTMLView* caller ) { DocumentImpl *doc = m_part->xmlDocImpl(); if( !doc ) return false; ElementImpl* node = doc->findAccessKeyElement( c ); if( !node ) { QList frames = m_part->frames(); foreach( KParts::ReadOnlyPart* cur, frames ) { if( !qobject_cast(cur) ) continue; KHTMLPart* part = static_cast< KHTMLPart* >( cur ); if( part->view() && part->view() != caller && part->view()->focusNodeWithAccessKey( c, this )) return true; } // pass up to the parent if (m_part->parentPart() && m_part->parentPart()->view() && m_part->parentPart()->view() != caller && m_part->parentPart()->view()->focusNodeWithAccessKey( c, this )) return true; if( caller == NULL ) { // the active frame (where the accesskey was pressed) QMap< ElementImpl*, QChar > fallbacks = buildFallbackAccessKeys(); for( QMap< ElementImpl*, QChar >::ConstIterator it = fallbacks.begin(); it != fallbacks.end(); ++it ) if( *it == c ) { node = it.key(); break; } } if( node == NULL ) return false; } // Scroll the view as necessary to ensure that the new focus node is visible #ifndef KHTML_NO_CARET // if it's an editable element, activate the caret if (!m_part->isCaretMode() && !m_part->isEditable() && node->contentEditable()) { d->caretViewContext(); moveCaretTo(node, 0L, true); } else { caretOff(); } #endif // KHTML_NO_CARET QRect r = node->getRect(); ensureVisible( r.right(), r.bottom()); ensureVisible( r.left(), r.top()); Node guard( node ); if( node->isFocusable()) { if (node->id()==ID_LABEL) { // if Accesskey is a label, give focus to the label's referrer. node=static_cast(static_cast< HTMLLabelElementImpl* >( node )->getFormElement()); if (!node) return true; guard = node; } // Set focus node on the document #ifdef __GNUC__ #warning "port QFocusEvent::setReason( QFocusEvent::Shortcut ); to qt4" #endif //QFocusEvent::setReason( QFocusEvent::Shortcut ); m_part->xmlDocImpl()->setFocusNode(node); #ifdef __GNUC__ #warning "port QFocusEvent::resetReason(); to qt4" #endif //QFocusEvent::resetReason(); if( node != NULL && node->hasOneRef()) // deleted, only held by guard return true; emit m_part->nodeActivated(Node(node)); if( node != NULL && node->hasOneRef()) return true; } switch( node->id()) { case ID_A: static_cast< HTMLAnchorElementImpl* >( node )->click(); break; case ID_INPUT: static_cast< HTMLInputElementImpl* >( node )->click(); break; case ID_BUTTON: static_cast< HTMLButtonElementImpl* >( node )->click(); break; case ID_AREA: static_cast< HTMLAreaElementImpl* >( node )->click(); break; case ID_TEXTAREA: break; // just focusing it is enough case ID_LEGEND: // TODO break; } return true; } static QString getElementText( NodeImpl* start, bool after ) { QString ret; // nextSibling(), to go after e.g. for( NodeImpl* n = after ? start->nextSibling() : start->traversePreviousNode(); n != NULL; n = after ? n->traverseNextNode() : n->traversePreviousNode()) { if( n->isTextNode()) { if( after ) ret += static_cast< TextImpl* >( n )->toString().string(); else ret.prepend( static_cast< TextImpl* >( n )->toString().string()); } else { switch( n->id()) { case ID_A: case ID_FONT: case ID_TT: case ID_U: case ID_B: case ID_I: case ID_S: case ID_STRIKE: case ID_BIG: case ID_SMALL: case ID_EM: case ID_STRONG: case ID_DFN: case ID_CODE: case ID_SAMP: case ID_KBD: case ID_VAR: case ID_CITE: case ID_ABBR: case ID_ACRONYM: case ID_SUB: case ID_SUP: case ID_SPAN: case ID_NOBR: case ID_WBR: break; case ID_TD: if( ret.trimmed().isEmpty()) break; // fall through default: return ret.simplified(); } } } return ret.simplified(); } static QMap< NodeImpl*, QString > buildLabels( NodeImpl* start ) { QMap< NodeImpl*, QString > ret; for( NodeImpl* n = start; n != NULL; n = n->traverseNextNode()) { if( n->id() == ID_LABEL ) { HTMLLabelElementImpl* label = static_cast< HTMLLabelElementImpl* >( n ); NodeImpl* labelfor = label->getFormElement(); if( labelfor ) ret[ labelfor ] = label->innerText().string().simplified(); } } return ret; } namespace khtml { struct AccessKeyData { ElementImpl* element; QString text; QString url; int priority; // 10(highest) - 0(lowest) }; } QMap< ElementImpl*, QChar > KHTMLView::buildFallbackAccessKeys() const { // build a list of all possible candidate elements that could use an accesskey QList< AccessKeyData > data; QMap< NodeImpl*, QString > labels = buildLabels( m_part->xmlDocImpl()); for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) { if( n->isElementNode()) { ElementImpl* element = static_cast< ElementImpl* >( n ); if( element->getAttribute( ATTR_ACCESSKEY ).length() == 1 ) continue; // has accesskey set, ignore if( element->renderer() == NULL ) continue; // not visible QString text; QString url; int priority = 0; bool ignore = false; bool text_after = false; bool text_before = false; switch( element->id()) { case ID_A: url = khtml::parseURL(element->getAttribute(ATTR_HREF)).string(); if( url.isEmpty()) // doesn't have href, it's only an anchor continue; text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplified(); priority = 2; break; case ID_INPUT: { HTMLInputElementImpl* in = static_cast< HTMLInputElementImpl* >( element ); switch( in->inputType()) { case HTMLInputElementImpl::SUBMIT: text = in->value().string(); if( text.isEmpty()) text = i18n( "Submit" ); priority = 7; break; case HTMLInputElementImpl::IMAGE: text = in->altText().string(); priority = 7; break; case HTMLInputElementImpl::BUTTON: text = in->value().string(); priority = 5; break; case HTMLInputElementImpl::RESET: text = in->value().string(); if( text.isEmpty()) text = i18n( "Reset" ); priority = 5; break; case HTMLInputElementImpl::HIDDEN: ignore = true; break; case HTMLInputElementImpl::CHECKBOX: case HTMLInputElementImpl::RADIO: text_after = true; priority = 5; break; case HTMLInputElementImpl::TEXT: case HTMLInputElementImpl::PASSWORD: case HTMLInputElementImpl::FILE: text_before = true; priority = 5; break; default: priority = 5; break; } break; } case ID_BUTTON: text = static_cast< HTMLElementImpl* >( element )->innerText().string().simplified(); switch( static_cast< HTMLButtonElementImpl* >( element )->buttonType()) { case HTMLButtonElementImpl::SUBMIT: if( text.isEmpty()) text = i18n( "Submit" ); priority = 7; break; case HTMLButtonElementImpl::RESET: if( text.isEmpty()) text = i18n( "Reset" ); priority = 5; break; default: priority = 5; break; break; } case ID_SELECT: // these don't have accesskey attribute, but quick access may be handy text_before = true; text_after = true; priority = 5; break; case ID_FRAME: ignore = true; break; default: ignore = !element->isFocusable(); priority = 2; break; } if( ignore ) continue; if( text.isNull() && labels.contains( element )) text = labels[ element ]; if( text.isNull() && text_before ) text = getElementText( element, false ); if( text.isNull() && text_after ) text = getElementText( element, true ); text = text.trimmed(); // increase priority of items which have explicitly specified accesskeys in the config QList< QPair< QString, QChar > > priorities = m_part->settings()->fallbackAccessKeysAssignments(); for( QList< QPair< QString, QChar > >::ConstIterator it = priorities.begin(); it != priorities.end(); ++it ) { if( text == (*it).first ) priority = 10; } AccessKeyData tmp = { element, text, url, priority }; data.append( tmp ); } } QList< QChar > keys; for( char c = 'A'; c <= 'Z'; ++c ) keys << c; for( char c = '0'; c <= '9'; ++c ) keys << c; for( NodeImpl* n = m_part->xmlDocImpl(); n != NULL; n = n->traverseNextNode()) { if( n->isElementNode()) { ElementImpl* en = static_cast< ElementImpl* >( n ); DOMString s = en->getAttribute( ATTR_ACCESSKEY ); if( s.length() == 1 ) { QChar c = s.string()[ 0 ].toUpper(); keys.removeAll( c ); // remove manually assigned accesskeys } } } QMap< ElementImpl*, QChar > ret; for( int priority = 10; priority >= 0; --priority ) { for( QList< AccessKeyData >::Iterator it = data.begin(); it != data.end(); ) { if( (*it).priority != priority ) { ++it; continue; } if( keys.isEmpty()) break; QString text = (*it).text; QChar key; if( key.isNull() && !text.isEmpty()) { QList< QPair< QString, QChar > > priorities = m_part->settings()->fallbackAccessKeysAssignments(); for( QList< QPair< QString, QChar > >::ConstIterator it = priorities.begin(); it != priorities.end(); ++it ) if( text == (*it).first && keys.contains( (*it).second )) { key = (*it).second; break; } } // try first to select the first character as the accesskey, // then first character of the following words, // and then simply the first free character if( key.isNull() && !text.isEmpty()) { QStringList words = text.split( ' ' ); for( QStringList::ConstIterator it = words.begin(); it != words.end(); ++it ) { if( keys.contains( (*it)[ 0 ].toUpper())) { key = (*it)[ 0 ].toUpper(); break; } } } if( key.isNull() && !text.isEmpty()) { for( int i = 0; i < text.length(); ++i ) { if( keys.contains( text[ i ].toUpper())) { key = text[ i ].toUpper(); break; } } } if( key.isNull()) key = keys.front(); ret[ (*it).element ] = key; keys.removeAll( key ); QString url = (*it).url; it = data.erase( it ); // assign the same accesskey also to other elements pointing to the same url if( !url.isEmpty() && !url.startsWith( "javascript:", Qt::CaseInsensitive )) { for( QList< AccessKeyData >::Iterator it2 = data.begin(); it2 != data.end(); ) { if( (*it2).url == url ) { ret[ (*it2).element ] = key; if( it == it2 ) ++it; it2 = data.erase( it2 ); } else ++it2; } } } } return ret; } void KHTMLView::setMediaType( const QString &medium ) { m_medium = medium; } QString KHTMLView::mediaType() const { return m_medium; } bool KHTMLView::pagedMode() const { return d->paged; } void KHTMLView::setWidgetVisible(RenderWidget* w, bool vis) { if (vis) { d->visibleWidgets.insert(w, w->widget()); } else d->visibleWidgets.remove(w); } bool KHTMLView::needsFullRepaint() const { return d->needsFullRepaint; } void KHTMLView::print(bool quick) { if(!m_part->xmlDocImpl()) return; khtml::RenderCanvas *root = static_cast(m_part->xmlDocImpl()->renderer()); if(!root) return; KHTMLPrintSettings printSettings; //XXX: doesn't save settings between prints like this QPrinter printer; QPrintDialog *dialog = KdePrint::createPrintDialog(&printer, QList() << &printSettings, this); QString docname = m_part->xmlDocImpl()->URL().prettyUrl(); if ( !docname.isEmpty() ) docname = KStringHandler::csqueeze(docname, 80); if(quick || dialog->exec()) { viewport()->setCursor( Qt::WaitCursor ); // only viewport(), no QApplication::, otherwise we get the busy cursor in kdeprint's dialogs // set up KPrinter printer.setFullPage(false); printer.setCreator(QString("KDE %1.%2.%3 HTML Library").arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(KDE_VERSION_RELEASE)); printer.setDocName(docname); QPainter *p = new QPainter; p->begin( &printer ); khtml::setPrintPainter( p ); m_part->xmlDocImpl()->setPaintDevice( &printer ); QString oldMediaType = mediaType(); setMediaType( "print" ); // We ignore margin settings for html and body when printing // and use the default margins from the print-system // (In Qt 3.0.x the default margins are hardcoded in Qt) m_part->xmlDocImpl()->setPrintStyleSheet( printSettings.printFriendly() ? "* { background-image: none !important;" " background-color: white !important;" " color: black !important; }" "body { margin: 0px !important; }" "html { margin: 0px !important; }" : "body { margin: 0px !important; }" "html { margin: 0px !important; }" ); kDebug(6000) << "printing: physical page width = " << printer.width() << " height = " << printer.height() << endl; root->setStaticMode(true); root->setPagedMode(true); root->setWidth(printer.width()); // root->setHeight(printer.height()); root->setPageTop(0); root->setPageBottom(0); d->paged = true; m_part->xmlDocImpl()->styleSelector()->computeFontSizes(printer.logicalDpiY(), 100); m_part->xmlDocImpl()->updateStyleSelector(); root->setPrintImages(printSettings.printImages()); root->makePageBreakAvoidBlocks(); root->setNeedsLayoutAndMinMaxRecalc(); root->layout(); khtml::RenderWidget::flushWidgetResizes(); // make sure widgets have their final size // check sizes ask for action.. (scale or clip) bool printHeader = printSettings.printHeader(); int headerHeight = 0; QFont headerFont("Sans Serif", 8); QString headerLeft = KGlobal::locale()->formatDate(QDate::currentDate(),KLocale::ShortDate); QString headerMid = docname; QString headerRight; if (printHeader) { p->setFont(headerFont); headerHeight = (p->fontMetrics().lineSpacing() * 3) / 2; } // ok. now print the pages. kDebug(6000) << "printing: html page width = " << root->docWidth() << " height = " << root->docHeight() << endl; kDebug(6000) << "printing: margins left = " << printer.pageRect().left() - printer.paperRect().left() << " top = " << printer.pageRect().top() - printer.paperRect().top() << endl; kDebug(6000) << "printing: paper width = " << printer.width() << " height = " << printer.height() << endl; // if the width is too large to fit on the paper we just scale // the whole thing. int pageWidth = printer.width(); int pageHeight = printer.height(); p->setClipRect(0,0, pageWidth, pageHeight); pageHeight -= headerHeight; bool scalePage = false; double scale = 0.0; #ifndef QT_NO_TRANSFORMATIONS if(root->docWidth() > printer.width()) { scalePage = true; scale = ((double) printer.width())/((double) root->docWidth()); pageHeight = (int) (pageHeight/scale); pageWidth = (int) (pageWidth/scale); headerHeight = (int) (headerHeight/scale); } #endif kDebug(6000) << "printing: scaled html width = " << pageWidth << " height = " << pageHeight << endl; root->setHeight(pageHeight); root->setPageBottom(pageHeight); root->setNeedsLayout(true); root->layoutIfNeeded(); // m_part->slotDebugRenderTree(); // Squeeze header to make it it on the page. if (printHeader) { int available_width = printer.width() - 10 - 2 * qMax(p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerLeft).width(), p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerRight).width()); if (available_width < 150) available_width = 150; int mid_width; int squeeze = 120; do { headerMid = KStringHandler::csqueeze(docname, squeeze); mid_width = p->boundingRect(0, 0, printer.width(), p->fontMetrics().lineSpacing(), Qt::AlignLeft, headerMid).width(); squeeze -= 10; } while (mid_width > available_width); } int top = 0; int bottom = 0; int page = 1; while(top < root->docHeight()) { if(top > 0) printer.newPage(); p->save(); p->setClipRect(0, 0, pageWidth, headerHeight); if (printHeader) { int dy = p->fontMetrics().lineSpacing(); p->setPen(Qt::black); p->setFont(headerFont); headerRight = QString("#%1").arg(page); p->drawText(0, 0, printer.width(), dy, Qt::AlignLeft, headerLeft); p->drawText(0, 0, printer.width(), dy, Qt::AlignHCenter, headerMid); p->drawText(0, 0, printer.width(), dy, Qt::AlignRight, headerRight); } #ifndef QT_NO_TRANSFORMATIONS if (scalePage) p->scale(scale, scale); #endif p->restore(); p->translate(0, headerHeight-top); bottom = top+pageHeight; root->setPageTop(top); root->setPageBottom(bottom); root->setPageNumber(page); root->layer()->paint(p, QRect(0, top, pageWidth, pageHeight)); kDebug(6000) << "printed: page " << page <<" bottom At = " << bottom; top = bottom; p->resetTransform(); page++; } p->end(); delete p; // and now reset the layout to the usual one... root->setPagedMode(false); root->setStaticMode(false); d->paged = false; khtml::setPrintPainter( 0 ); setMediaType( oldMediaType ); m_part->xmlDocImpl()->setPaintDevice( this ); m_part->xmlDocImpl()->styleSelector()->computeFontSizes(m_part->xmlDocImpl()->logicalDpiY(), m_part->fontScaleFactor()); m_part->xmlDocImpl()->updateStyleSelector(); viewport()->unsetCursor(); } } void KHTMLView::slotPaletteChanged() { if(!m_part->xmlDocImpl()) return; DOM::DocumentImpl *document = m_part->xmlDocImpl(); if (!document->isHTMLDocument()) return; khtml::RenderCanvas *root = static_cast(document->renderer()); if(!root) return; root->style()->resetPalette(); NodeImpl *body = static_cast(document)->body(); if(!body) return; body->setChanged(true); body->recalcStyle( NodeImpl::Force ); } void KHTMLView::paint(QPainter *p, const QRect &rc, int yOff, bool *more) { if(!m_part->xmlDocImpl()) return; khtml::RenderCanvas *root = static_cast(m_part->xmlDocImpl()->renderer()); if(!root) return; QPaintDevice* opd = m_part->xmlDocImpl()->paintDevice(); m_part->xmlDocImpl()->setPaintDevice(p->device()); root->setPagedMode(true); root->setStaticMode(true); root->setWidth(rc.width()); // save() QRegion creg = p->clipRegion(); QTransform t = p->worldTransform(); QRect w = p->window(); QRect v = p->viewport(); bool vte = p->viewTransformEnabled(); bool wme = p->worldMatrixEnabled(); p->setClipRect(rc); p->translate(rc.left(), rc.top()); double scale = ((double) rc.width()/(double) root->docWidth()); int height = (int) ((double) rc.height() / scale); #ifndef QT_NO_TRANSFORMATIONS p->scale(scale, scale); #endif root->setPageTop(yOff); root->setPageBottom(yOff+height); root->layer()->paint(p, QRect(0, yOff, root->docWidth(), height)); if (more) *more = yOff + height < root->docHeight(); // restore() p->setWorldTransform(t); p->setWindow(w); p->setViewport(v); p->setViewTransformEnabled( vte ); p->setWorldMatrixEnabled( wme ); if (!creg.isEmpty()) p->setClipRegion( creg ); else p->setClipRegion(QRegion(), Qt::NoClip); root->setPagedMode(false); root->setStaticMode(false); m_part->xmlDocImpl()->setPaintDevice( opd ); } void KHTMLView::render(QPainter* p, const QRect& r, const QPoint& off) { QRect clip(off.x()+r.x(), off.y()+r.y(),r.width(),r.height()); if(!m_part || !m_part->xmlDocImpl() || !m_part->xmlDocImpl()->renderer()) { p->fillRect(clip, palette().brush(QPalette::Active, QPalette::Base)); return; } QPaintDevice* opd = m_part->xmlDocImpl()->paintDevice(); m_part->xmlDocImpl()->setPaintDevice(p->device()); // save() QRegion creg = p->clipRegion(); QTransform t = p->worldTransform(); QRect w = p->window(); QRect v = p->viewport(); bool vte = p->viewTransformEnabled(); bool wme = p->worldMatrixEnabled(); p->setClipRect(clip); QRect rect = r.translated(contentsX(),contentsY()); p->translate(off.x()-contentsX(), off.y()-contentsY()); m_part->xmlDocImpl()->renderer()->layer()->paint(p, rect); // restore() p->setWorldTransform(t); p->setWindow(w); p->setViewport(v); p->setViewTransformEnabled( vte ); p->setWorldMatrixEnabled( wme ); if (!creg.isEmpty()) p->setClipRegion( creg ); else p->setClipRegion(QRegion(), Qt::NoClip); m_part->xmlDocImpl()->setPaintDevice( opd ); } void KHTMLView::setHasStaticBackground() { if (!d->staticWidget) widget()->move(0,0); d->staticWidget = true; } void KHTMLView::setVerticalScrollBarPolicy( Qt::ScrollBarPolicy policy ) { #ifndef KHTML_NO_SCROLLBARS d->vpolicy = policy; QScrollArea::setVerticalScrollBarPolicy(policy); #else Q_UNUSED( policy ); #endif } void KHTMLView::setHorizontalScrollBarPolicy( Qt::ScrollBarPolicy policy ) { #ifndef KHTML_NO_SCROLLBARS d->hpolicy = policy; QScrollArea::setHorizontalScrollBarPolicy(policy); #else Q_UNUSED( policy ); #endif } void KHTMLView::restoreScrollBar() { int ow = visibleWidth(); QScrollArea::setVerticalScrollBarPolicy(d->vpolicy); if (visibleWidth() != ow) layout(); d->prevScrollbarVisible = verticalScrollBar()->isVisible(); } QStringList KHTMLView::formCompletionItems(const QString &name) const { if (!m_part->settings()->isFormCompletionEnabled()) return QStringList(); if (!d->formCompletions) d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions")); return d->formCompletions->group("").readEntry(name, QStringList()); } void KHTMLView::clearCompletionHistory(const QString& name) { if (!d->formCompletions) { d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions")); } d->formCompletions->group("").writeEntry(name, ""); d->formCompletions->sync(); } void KHTMLView::addFormCompletionItem(const QString &name, const QString &value) { if (!m_part->settings()->isFormCompletionEnabled()) return; // don't store values that are all numbers or just numbers with // dashes or spaces as those are likely credit card numbers or // something similar bool cc_number(true); for ( int i = 0; i < value.length(); ++i) { QChar c(value[i]); if (!c.isNumber() && c != '-' && !c.isSpace()) { cc_number = false; break; } } if (cc_number) return; QStringList items = formCompletionItems(name); if (!items.contains(value)) items.prepend(value); while ((int)items.count() > m_part->settings()->maxFormCompletionItems()) items.erase(items.isEmpty() ? items.end() : --items.end()); d->formCompletions->group("").writeEntry(name, items); } void KHTMLView::addNonPasswordStorableSite(const QString& host) { if (!d->formCompletions) { d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions")); } KConfigGroup cg( d->formCompletions, "NonPasswordStorableSites"); QStringList sites = cg.readEntry("Sites", QStringList()); sites.append(host); cg.writeEntry("Sites", sites); cg.sync(); } bool KHTMLView::nonPasswordStorableSite(const QString& host) const { if (!d->formCompletions) { d->formCompletions = new KConfig(KStandardDirs::locateLocal("data", "khtml/formcompletions")); } QStringList sites = d->formCompletions->group( "NonPasswordStorableSites" ).readEntry("Sites", QStringList()); return (sites.indexOf(host) != -1); } // returns true if event should be swallowed bool KHTMLView::dispatchMouseEvent(int eventId, DOM::NodeImpl *targetNode, DOM::NodeImpl *targetNodeNonShared, bool cancelable, int detail,QMouseEvent *_mouse, bool setUnder, int mouseEventType, int orient) { // if the target node is a text node, dispatch on the parent node - rdar://4196646 (and #76948) if (targetNode && targetNode->isTextNode()) targetNode = targetNode->parentNode(); if (d->underMouse) d->underMouse->deref(); d->underMouse = targetNode; if (d->underMouse) d->underMouse->ref(); if (d->underMouseNonShared) d->underMouseNonShared->deref(); d->underMouseNonShared = targetNodeNonShared; if (d->underMouseNonShared) d->underMouseNonShared->ref(); bool isWheelEvent = (mouseEventType == DOM::NodeImpl::MouseWheel); int exceptioncode = 0; int pageX = _mouse->x(); int pageY = _mouse->y(); revertTransforms(pageX, pageY); int clientX = pageX - contentsX(); int clientY = pageY - contentsY(); int screenX = _mouse->globalX(); int screenY = _mouse->globalY(); int button = -1; switch (_mouse->button()) { case Qt::LeftButton: button = 0; break; case Qt::MidButton: button = 1; break; case Qt::RightButton: button = 2; break; default: break; } if (d->accessKeysEnabled && d->accessKeysPreActivate && button!=-1) d->accessKeysPreActivate=false; bool ctrlKey = (_mouse->modifiers() & Qt::ControlModifier); bool altKey = (_mouse->modifiers() & Qt::AltModifier); bool shiftKey = (_mouse->modifiers() & Qt::ShiftModifier); bool metaKey = (_mouse->modifiers() & Qt::MetaModifier); // mouseout/mouseover if (setUnder && d->oldUnderMouse != targetNode) { if (d->oldUnderMouse && d->oldUnderMouse->getDocument() != m_part->xmlDocImpl()) { d->oldUnderMouse->deref(); d->oldUnderMouse = 0; } // send mouseout event to the old node if (d->oldUnderMouse) { // send mouseout event to the old node MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOUT_EVENT, true,true,m_part->xmlDocImpl()->defaultView(), 0,screenX,screenY,clientX,clientY,pageX, pageY, ctrlKey,altKey,shiftKey,metaKey, button,targetNode); me->ref(); d->oldUnderMouse->dispatchEvent(me,exceptioncode,true); me->deref(); } // send mouseover event to the new node if (targetNode) { MouseEventImpl *me = new MouseEventImpl(EventImpl::MOUSEOVER_EVENT, true,true,m_part->xmlDocImpl()->defaultView(), 0,screenX,screenY,clientX,clientY,pageX, pageY, ctrlKey,altKey,shiftKey,metaKey, button,d->oldUnderMouse); me->ref(); targetNode->dispatchEvent(me,exceptioncode,true); me->deref(); } if (d->oldUnderMouse) d->oldUnderMouse->deref(); d->oldUnderMouse = targetNode; if (d->oldUnderMouse) d->oldUnderMouse->ref(); } bool swallowEvent = false; if (targetNode) { // send the actual event bool dblclick = ( eventId == EventImpl::CLICK_EVENT && _mouse->type() == QEvent::MouseButtonDblClick ); MouseEventImpl *me = new MouseEventImpl(static_cast(eventId), true,cancelable,m_part->xmlDocImpl()->defaultView(), detail,screenX,screenY,clientX,clientY,pageX, pageY, ctrlKey,altKey,shiftKey,metaKey, button,0, isWheelEvent ? 0 : _mouse, dblclick, isWheelEvent ? static_cast(orient) : MouseEventImpl::ONone ); me->ref(); if ( !d->m_mouseEventsTarget && RenderLayer::gScrollBar && eventId == EventImpl::MOUSEDOWN_EVENT ) // button is pressed inside a layer scrollbar, so make it the target for future mousemove events until released d->m_mouseEventsTarget = RenderLayer::gScrollBar; if ( d->m_mouseEventsTarget && qobject_cast(d->m_mouseEventsTarget) && dynamic_cast(static_cast(d->m_mouseEventsTarget)) ) { // we have a sticky mouse event target and it is a layer's scrollbar. Forward events manually. // ### should use the dom KHTMLWidget*w = dynamic_cast(static_cast(d->m_mouseEventsTarget)); QPoint p = w->m_kwp->absolutePos(); QMouseEvent fw(_mouse->type(), _mouse->pos()-p, _mouse->button(), _mouse->buttons(), _mouse->modifiers()); static_cast(static_cast(d->m_mouseEventsTarget))->sendEvent(&fw); if (_mouse->type() == QMouseEvent::MouseButtonPress && _mouse->button() == Qt::RightButton) { QContextMenuEvent cme(QContextMenuEvent::Mouse, p); static_cast(static_cast(d->m_mouseEventsTarget))->sendEvent(&cme); } swallowEvent = true; } else { targetNode->dispatchEvent(me,exceptioncode,true); bool defaultHandled = me->defaultHandled(); if (defaultHandled || me->defaultPrevented()) swallowEvent = true; } me->deref(); if (eventId == EventImpl::MOUSEDOWN_EVENT) { // Focus should be shifted on mouse down, not on a click. -dwh // Blur current focus node when a link/button is clicked; this // is expected by some sites that rely on onChange handlers running // from form fields before the button click is processed. DOM::NodeImpl* nodeImpl = targetNode; for ( ; nodeImpl && !nodeImpl->isFocusable(); nodeImpl = nodeImpl->parentNode()); if (nodeImpl && nodeImpl->isMouseFocusable()) m_part->xmlDocImpl()->setFocusNode(nodeImpl); else if (!nodeImpl || !nodeImpl->focused()) m_part->xmlDocImpl()->setFocusNode(0); } } return swallowEvent; } void KHTMLView::setIgnoreWheelEvents( bool e ) { d->ignoreWheelEvents = e; } #ifndef QT_NO_WHEELEVENT void KHTMLView::wheelEvent(QWheelEvent* e) { // check if we should reset the state of the indicator describing if // we are currently scrolling the view as a result of wheel events if (d->scrollingFromWheel != QPoint(-1,-1) && d->scrollingFromWheel != QCursor::pos()) d->scrollingFromWheel = d->scrollingFromWheelTimerId ? QCursor::pos() : QPoint(-1,-1); if (d->accessKeysEnabled && d->accessKeysPreActivate) d->accessKeysPreActivate=false; if ( ( e->modifiers() & Qt::ControlModifier) == Qt::ControlModifier ) { emit zoomView( - e->delta() ); e->accept(); } else if (d->firstRelayout) { e->accept(); } else if( !m_kwp->isRedirected() && ( (e->orientation() == Qt::Vertical && ((d->ignoreWheelEvents && !verticalScrollBar()->isVisible()) || e->delta() > 0 && contentsY() <= 0 || e->delta() < 0 && contentsY() >= contentsHeight() - visibleHeight())) || (e->orientation() == Qt::Horizontal && ((d->ignoreWheelEvents && !horizontalScrollBar()->isVisible()) || e->delta() > 0 && contentsX() <=0 || e->delta() < 0 && contentsX() >= contentsWidth() - visibleWidth()))) && m_part->parentPart()) { if ( m_part->parentPart()->view() ) m_part->parentPart()->view()->wheelEvent( e ); e->ignore(); } else { int xm = e->x(); int ym = e->y(); revertTransforms(xm, ym); DOM::NodeImpl::MouseEvent mev( e->buttons(), DOM::NodeImpl::MouseWheel ); m_part->xmlDocImpl()->prepareMouseEvent( false, xm, ym, &mev ); MouseEventImpl::Orientation o = MouseEventImpl::OVertical; if (e->orientation() == Qt::Horizontal) o = MouseEventImpl::OHorizontal; QMouseEvent _mouse(QEvent::MouseMove, QPoint(xm,ym), Qt::NoButton, e->buttons(), e->modifiers()); bool swallow = dispatchMouseEvent(EventImpl::KHTML_MOUSEWHEEL_EVENT,mev.innerNode.handle(),mev.innerNonSharedNode.handle(), true,-e->delta()/40,&_mouse,true,DOM::NodeImpl::MouseWheel,o); if (swallow) return; d->scrollBarMoved = true; d->scrollingFromWheel = QCursor::pos(); if (d->scrollingFromWheelTimerId) killTimer(d->scrollingFromWheelTimerId); d->scrollingFromWheelTimerId = startTimer(400); if (m_part->parentPart()) { // don't propagate if we are a sub-frame and our scrollbars are already at end of range bool h = (static_cast(e)->orientation() == Qt::Horizontal); bool d = (static_cast(e)->delta() < 0); QScrollBar* hsb = horizontalScrollBar(); QScrollBar* vsb = verticalScrollBar(); if ( h && (d && hsb->value() == hsb->maximum() || !d && hsb->value() == hsb->minimum()) || !h && (d && vsb->value() == vsb->maximum() || !d && vsb->value() == vsb->minimum()) ) { e->accept(); return; } } QScrollArea::wheelEvent( e ); } } #endif void KHTMLView::dragEnterEvent( QDragEnterEvent* ev ) { // Still overriden for BC reasons only... QScrollArea::dragEnterEvent( ev ); } void KHTMLView::dropEvent( QDropEvent *ev ) { // Still overriden for BC reasons only... QScrollArea::dropEvent( ev ); } void KHTMLView::focusInEvent( QFocusEvent *e ) { #ifndef KHTML_NO_TYPE_AHEAD_FIND m_part->enableFindAheadActions( true ); #endif DOM::NodeImpl* fn = m_part->xmlDocImpl() ? m_part->xmlDocImpl()->focusNode() : 0; if (fn && fn->renderer() && fn->renderer()->isWidget() && (e->reason() != Qt::MouseFocusReason) && static_cast(fn->renderer())->widget()) static_cast(fn->renderer())->widget()->setFocus(); #ifndef KHTML_NO_CARET // Restart blink frequency timer if it has been killed, but only on // editable nodes if (d->m_caretViewContext && d->m_caretViewContext->freqTimerId == -1 && fn) { if (m_part->isCaretMode() || m_part->isEditable() || (fn && fn->renderer() && fn->renderer()->style()->userInput() == UI_ENABLED)) { d->m_caretViewContext->freqTimerId = startTimer(500); d->m_caretViewContext->visible = true; }/*end if*/ }/*end if*/ showCaret(); #endif // KHTML_NO_CARET QScrollArea::focusInEvent( e ); } void KHTMLView::focusOutEvent( QFocusEvent *e ) { m_part->stopAutoScroll(); #ifndef KHTML_NO_TYPE_AHEAD_FIND if(d->typeAheadActivated) { findTimeout(); } m_part->enableFindAheadActions( false ); #endif // KHTML_NO_TYPE_AHEAD_FIND #ifndef KHTML_NO_CARET if (d->m_caretViewContext) { switch (d->m_caretViewContext->displayNonFocused) { case KHTMLPart::CaretInvisible: hideCaret(); break; case KHTMLPart::CaretVisible: { if (d->m_caretViewContext->freqTimerId != -1) killTimer(d->m_caretViewContext->freqTimerId); d->m_caretViewContext->freqTimerId = -1; NodeImpl *caretNode = m_part->xmlDocImpl()->focusNode(); if (!d->m_caretViewContext->visible && (m_part->isCaretMode() || m_part->isEditable() || (caretNode && caretNode->renderer() && caretNode->renderer()->style()->userInput() == UI_ENABLED))) { d->m_caretViewContext->visible = true; showCaret(true); }/*end if*/ break; } case KHTMLPart::CaretBlink: // simply leave as is break; }/*end switch*/ }/*end if*/ #endif // KHTML_NO_CARET if ( d->cursor_icon_widget ) d->cursor_icon_widget->hide(); QScrollArea::focusOutEvent( e ); } void KHTMLView::scrollContentsBy( int dx, int dy ) { if ( !d->firstRelayout && !d->complete && m_part->xmlDocImpl() && d->layoutSchedulingEnabled) { // contents scroll while we are not complete: we need to check our layout *now* khtml::RenderCanvas* root = static_cast( m_part->xmlDocImpl()->renderer() ); if (root && root->needsLayout()) { unscheduleRelayout(); layout(); } } if (!d->scrollingSelf) { d->scrollBarMoved = true; d->contentsMoving = true; // ensure quick reset of contentsMoving flag scheduleRepaint(0, 0, 0, 0); } if ((dx || dy) && m_part->xmlDocImpl() && m_part->xmlDocImpl()->documentElement()) m_part->xmlDocImpl()->documentElement()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false); d->contentsX = QApplication::isRightToLeft() ? horizontalScrollBar()->maximum()-horizontalScrollBar()->value() : horizontalScrollBar()->value(); d->contentsY = verticalScrollBar()->value(); if ( d->staticWidget ) { if (widget()->pos() != QPoint(0,0)) widget()->move(0,0); widget()->update(); return; } QScrollArea::scrollContentsBy(dx, dy); } void KHTMLView::addChild(QWidget * child, int x, int y) { if (!child) return; if (child->parent() != widget()) child->setParent( widget() ); // ### handle pseudo-zooming of non-redirected widgets (e.g. just resize'em) if (!d->staticWidget) child->move(x, y); else child->move(x-contentsX(), y-contentsY()); } void KHTMLView::timerEvent ( QTimerEvent *e ) { // kDebug() << "timer event " << e->timerId(); if ( e->timerId() == d->scrollTimerId ) { if( d->scrollSuspended ) return; switch (d->scrollDirection) { case KHTMLViewPrivate::ScrollDown: if (contentsY() + visibleHeight () >= contentsHeight()) d->newScrollTimer(this, 0); else verticalScrollBar()->setValue( verticalScrollBar()->value() +d->scrollBy ); break; case KHTMLViewPrivate::ScrollUp: if (contentsY() <= 0) d->newScrollTimer(this, 0); else verticalScrollBar()->setValue( verticalScrollBar()->value() -d->scrollBy ); break; case KHTMLViewPrivate::ScrollRight: if (contentsX() + visibleWidth () >= contentsWidth()) d->newScrollTimer(this, 0); else horizontalScrollBar()->setValue( horizontalScrollBar()->value() +d->scrollBy ); break; case KHTMLViewPrivate::ScrollLeft: if (contentsX() <= 0) d->newScrollTimer(this, 0); else horizontalScrollBar()->setValue( horizontalScrollBar()->value() -d->scrollBy ); break; } return; } else if ( e->timerId() == d->scrollingFromWheelTimerId ) { killTimer( d->scrollingFromWheelTimerId ); d->scrollingFromWheelTimerId = 0; } else if ( e->timerId() == d->layoutTimerId ) { d->dirtyLayout = true; layout(); if (d->firstRelayout) { d->firstRelayout = false; verticalScrollBar()->setEnabled( true ); horizontalScrollBar()->setEnabled( true ); } } #ifndef KHTML_NO_CARET else if (d->m_caretViewContext && e->timerId() == d->m_caretViewContext->freqTimerId) { d->m_caretViewContext->visible = !d->m_caretViewContext->visible; if (d->m_caretViewContext->displayed) { updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); }/*end if*/ // if (d->m_caretViewContext->visible) cout << "|" << flush; // else cout << "" << flush; return; } #endif d->contentsMoving = false; if( m_part->xmlDocImpl() ) { DOM::DocumentImpl *document = m_part->xmlDocImpl(); khtml::RenderCanvas* root = static_cast(document->renderer()); if ( root && root->needsLayout() ) { if (d->repaintTimerId) killTimer(d->repaintTimerId); d->repaintTimerId = 0; scheduleRelayout(); return; } } if (d->repaintTimerId) killTimer(d->repaintTimerId); d->repaintTimerId = 0; QRect updateRegion; QVector rects = d->updateRegion.rects(); d->updateRegion = QRegion(); if ( rects.size() ) updateRegion = rects[0]; for ( int i = 1; i < rects.size(); ++i ) { QRect newRegion = updateRegion.unite(rects[i]); if (2*newRegion.height() > 3*updateRegion.height() ) { repaintContents( updateRegion ); updateRegion = rects[i]; } else updateRegion = newRegion; } if ( !updateRegion.isNull() ) repaintContents( updateRegion ); // As widgets can only be accurately positioned during painting, every layout might // dissociate a widget from its RenderWidget. E.g: if a RenderWidget was visible before layout, but the layout // pushed it out of the viewport, it will not be repainted, and consequently it's associated widget won't be repositioned. // Thus we need to check each supposedly 'visible' widget at the end of layout, and remove it in case it's no more in sight. if (d->dirtyLayout && !d->visibleWidgets.isEmpty()) { QWidget* w; d->dirtyLayout = false; QRect visibleRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()); QList toRemove; QHashIterator it(d->visibleWidgets); while (it.hasNext()) { int xp = 0, yp = 0; it.next(); RenderWidget* rw = static_cast( it.key() ); if (!rw->absolutePosition(xp, yp) || !visibleRect.intersects(QRect(xp, yp, it.value()->width(), it.value()->height()))) toRemove.append(rw); } foreach (RenderWidget* r, toRemove) if ( (w = d->visibleWidgets.take(r) ) ) w->move( 0, -500000); } emit repaintAccessKeys(); if (d->emitCompletedAfterRepaint) { bool full = d->emitCompletedAfterRepaint == KHTMLViewPrivate::CSFull; d->emitCompletedAfterRepaint = KHTMLViewPrivate::CSNone; if ( full ) emit m_part->completed(); else emit m_part->completed(true); } } void KHTMLView::scheduleRelayout(khtml::RenderObject * /*clippedObj*/) { if (!d->layoutSchedulingEnabled || d->layoutTimerId) return; d->layoutTimerId = startTimer( m_part->xmlDocImpl() && m_part->xmlDocImpl()->parsing() ? 1000 : 0 ); } void KHTMLView::unscheduleRelayout() { if (!d->layoutTimerId) return; killTimer(d->layoutTimerId); d->layoutTimerId = 0; } void KHTMLView::unscheduleRepaint() { if (!d->repaintTimerId) return; killTimer(d->repaintTimerId); d->repaintTimerId = 0; } void KHTMLView::scheduleRepaint(int x, int y, int w, int h, bool asap) { bool parsing = !m_part->xmlDocImpl() || m_part->xmlDocImpl()->parsing(); // kDebug() << "parsing " << parsing; // kDebug() << "complete " << d->complete; int time = parsing ? 300 : (!asap ? ( !d->complete ? 100 : 20 ) : 0); #ifdef DEBUG_FLICKER QPainter p; p.begin( viewport() ); int vx, vy; contentsToViewport( x, y, vx, vy ); p.fillRect( vx, vy, w, h, Qt::red ); p.end(); #endif d->updateRegion = d->updateRegion.unite(QRect(x,y,w,h)); if (asap && !parsing) unscheduleRepaint(); if ( !d->repaintTimerId ) d->repaintTimerId = startTimer( time ); // kDebug() << "starting timer " << time; } void KHTMLView::complete( bool pendingAction ) { // kDebug() << "KHTMLView::complete()"; d->complete = true; // is there a relayout pending? if (d->layoutTimerId) { // kDebug() << "requesting relayout now"; // do it now killTimer(d->layoutTimerId); d->layoutTimerId = startTimer( 0 ); d->emitCompletedAfterRepaint = pendingAction ? KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull; } // is there a repaint pending? if (d->repaintTimerId) { // kDebug() << "requesting repaint now"; // do it now killTimer(d->repaintTimerId); d->repaintTimerId = startTimer( 20 ); d->emitCompletedAfterRepaint = pendingAction ? KHTMLViewPrivate::CSActionPending : KHTMLViewPrivate::CSFull; } if (!d->emitCompletedAfterRepaint) { if (!pendingAction) emit m_part->completed(); else emit m_part->completed(true); } } void KHTMLView::slotMouseScrollTimer() { horizontalScrollBar()->setValue( horizontalScrollBar()->value() +d->m_mouseScroll_byX ); verticalScrollBar()->setValue( verticalScrollBar()->value() +d->m_mouseScroll_byY); } #ifndef KHTML_NO_CARET // ### the dependencies on static functions are a nightmare. just be // hacky and include the implementation here. Clean me up, please. #include "khtml_caret.cpp" void KHTMLView::initCaret(bool keepSelection) { #if DEBUG_CARETMODE > 0 kDebug(6200) << "begin initCaret"; #endif // save caretMoved state as moveCaretTo changes it if (m_part->xmlDocImpl()) { #if 0 ElementImpl *listitem = m_part->xmlDocImpl()->getElementById("__test_element__"); if (listitem) dumpLineBoxes(static_cast(listitem->renderer())); #endif d->caretViewContext(); bool cmoved = d->m_caretViewContext->caretMoved; if (m_part->d->caretNode().isNull()) { // set to document, position will be sanitized anyway m_part->d->caretNode() = m_part->document(); m_part->d->caretOffset() = 0L; // This sanity check is necessary for the not so unlikely case that // setEditable or setCaretMode is called before any render objects have // been created. if (!m_part->d->caretNode().handle()->renderer()) return; }/*end if*/ // kDebug(6200) << "d->m_selectionStart " << m_part->d->m_selectionStart.handle() // << " d->m_selectionEnd " << m_part->d->m_selectionEnd.handle() << endl; // ### does not repaint the selection on keepSelection!=false moveCaretTo(m_part->d->caretNode().handle(), m_part->d->caretOffset(), !keepSelection); // kDebug(6200) << "d->m_selectionStart " << m_part->d->m_selectionStart.handle() // << " d->m_selectionEnd " << m_part->d->m_selectionEnd.handle() << endl; d->m_caretViewContext->caretMoved = cmoved; }/*end if*/ #if DEBUG_CARETMODE > 0 kDebug(6200) << "end initCaret"; #endif } bool KHTMLView::caretOverrides() const { bool cm = m_part->isCaretMode(); bool dm = m_part->isEditable(); return cm && !dm ? false : (dm || m_part->d->caretNode().handle()->contentEditable()) && d->editorContext()->override; } void KHTMLView::ensureNodeHasFocus(NodeImpl *node) { if (m_part->isCaretMode() || m_part->isEditable()) return; if (node->focused()) return; // Find first ancestor whose "user-input" is "enabled" NodeImpl *firstAncestor = 0; while (node) { if (node->renderer() && node->renderer()->style()->userInput() != UI_ENABLED) break; firstAncestor = node; node = node->parentNode(); }/*wend*/ if (!node) firstAncestor = 0; DocumentImpl *doc = m_part->xmlDocImpl(); // ensure that embedded widgets don't lose their focus if (!firstAncestor && doc->focusNode() && doc->focusNode()->renderer() && doc->focusNode()->renderer()->isWidget()) return; // Set focus node on the document #if DEBUG_CARETMODE > 1 kDebug(6200) << "firstAncestor " << firstAncestor << ": " << (firstAncestor ? firstAncestor->nodeName().string() : QString()) << endl; #endif doc->setFocusNode(firstAncestor); emit m_part->nodeActivated(Node(firstAncestor)); } void KHTMLView::recalcAndStoreCaretPos(CaretBox *hintBox) { if (!m_part || m_part->d->caretNode().isNull()) return; d->caretViewContext(); NodeImpl *caretNode = m_part->d->caretNode().handle(); #if DEBUG_CARETMODE > 0 kDebug(6200) << "recalcAndStoreCaretPos: caretNode=" << caretNode << (caretNode ? " "+caretNode->nodeName().string() : QString()) << " r@" << caretNode->renderer() << (caretNode->renderer() && caretNode->renderer()->isText() ? " \"" + QConstString(static_cast(caretNode->renderer())->str->s, qMin(static_cast(caretNode->renderer())->str->l, 15u)).string() + "\"" : QString()); #endif caretNode->getCaret(m_part->d->caretOffset(), caretOverrides(), d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); if (hintBox && d->m_caretViewContext->x == -1) { #if DEBUG_CARETMODE > 1 kDebug(6200) << "using hint inline box coordinates"; #endif RenderObject *r = caretNode->renderer(); const QFontMetrics &fm = r->style()->fontMetrics(); int absx, absy; r->containingBlock()->absolutePosition(absx, absy, false); // ### what about fixed? d->m_caretViewContext->x = absx + hintBox->xPos(); d->m_caretViewContext->y = absy + hintBox->yPos(); // + hintBox->baseline() - fm.ascent(); d->m_caretViewContext->width = 1; // ### firstline not regarded. But I think it can be safely neglected // as hint boxes are only used for empty lines. d->m_caretViewContext->height = fm.height(); }/*end if*/ #if DEBUG_CARETMODE > 4 // kDebug(6200) << "freqTimerId: "<m_caretViewContext->freqTimerId; #endif #if DEBUG_CARETMODE > 0 kDebug(6200) << "caret: ofs="<d->caretOffset()<<" " <<" x="<m_caretViewContext->x<<" y="<m_caretViewContext->y <<" h="<m_caretViewContext->height<m_caretViewContext) { if (d->m_caretViewContext->freqTimerId != -1) killTimer(d->m_caretViewContext->freqTimerId); if (hasFocus() || d->m_caretViewContext->displayNonFocused == KHTMLPart::CaretBlink) { d->m_caretViewContext->freqTimerId = startTimer(500); } else { d->m_caretViewContext->freqTimerId = -1; }/*end if*/ d->m_caretViewContext->visible = true; if ((d->m_caretViewContext->displayed = (hasFocus() || d->m_caretViewContext->displayNonFocused != KHTMLPart::CaretInvisible))) { updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); }/*end if*/ // kDebug(6200) << "caret on"; }/*end if*/ } void KHTMLView::caretOff() { if (d->m_caretViewContext) { if (d->m_caretViewContext->freqTimerId != -1) killTimer(d->m_caretViewContext->freqTimerId); d->m_caretViewContext->freqTimerId = -1; d->m_caretViewContext->displayed = false; if (d->m_caretViewContext->visible) { d->m_caretViewContext->visible = false; updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); }/*end if*/ // kDebug(6200) << "caret off"; }/*end if*/ } void KHTMLView::showCaret(bool forceRepaint) { if (d->m_caretViewContext) { d->m_caretViewContext->displayed = true; if (d->m_caretViewContext->visible) { if (!forceRepaint) { updateContents(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); } else { repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); }/*end if*/ }/*end if*/ // kDebug(6200) << "caret shown"; }/*end if*/ } bool KHTMLView::foldSelectionToCaret(NodeImpl *startNode, long startOffset, NodeImpl *endNode, long endOffset) { m_part->d->m_selectionStart = m_part->d->m_selectionEnd = m_part->d->caretNode(); m_part->d->m_startOffset = m_part->d->m_endOffset = m_part->d->caretOffset(); m_part->d->m_extendAtEnd = true; bool folded = startNode != endNode || startOffset != endOffset; // Only clear the selection if there has been one. if (folded) { m_part->xmlDocImpl()->clearSelection(); }/*end if*/ return folded; } void KHTMLView::hideCaret() { if (d->m_caretViewContext) { if (d->m_caretViewContext->visible) { // kDebug(6200) << "redraw caret hidden"; d->m_caretViewContext->visible = false; // force repaint, otherwise the event won't be handled // before the focus leaves the window repaintContents(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); d->m_caretViewContext->visible = true; }/*end if*/ d->m_caretViewContext->displayed = false; // kDebug(6200) << "caret hidden"; }/*end if*/ } int KHTMLView::caretDisplayPolicyNonFocused() const { if (d->m_caretViewContext) return d->m_caretViewContext->displayNonFocused; else return KHTMLPart::CaretInvisible; } void KHTMLView::setCaretDisplayPolicyNonFocused(int policy) { d->caretViewContext(); // int old = d->m_caretViewContext->displayNonFocused; d->m_caretViewContext->displayNonFocused = (KHTMLPart::CaretDisplayPolicy)policy; // make change immediately take effect if not focused if (!hasFocus()) { switch (d->m_caretViewContext->displayNonFocused) { case KHTMLPart::CaretInvisible: hideCaret(); break; case KHTMLPart::CaretBlink: if (d->m_caretViewContext->freqTimerId != -1) break; d->m_caretViewContext->freqTimerId = startTimer(500); // fall through case KHTMLPart::CaretVisible: d->m_caretViewContext->displayed = true; showCaret(); break; }/*end switch*/ }/*end if*/ } bool KHTMLView::placeCaret(CaretBox *hintBox) { CaretViewContext *cv = d->caretViewContext(); caretOff(); NodeImpl *caretNode = m_part->d->caretNode().handle(); // ### why is it sometimes null? if (!caretNode || !caretNode->renderer()) return false; ensureNodeHasFocus(caretNode); if (m_part->isCaretMode() || m_part->isEditable() || caretNode->renderer()->style()->userInput() == UI_ENABLED) { recalcAndStoreCaretPos(hintBox); cv->origX = cv->x; caretOn(); return true; }/*end if*/ return false; } void KHTMLView::ensureCaretVisible() { CaretViewContext *cv = d->m_caretViewContext; if (!cv) return; ensureVisible(cv->x, cv->y, cv->width, cv->height); d->scrollBarMoved = false; } bool KHTMLView::extendSelection(NodeImpl *oldStartSel, long oldStartOfs, NodeImpl *oldEndSel, long oldEndOfs) { bool changed = false; if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd && m_part->d->m_startOffset == m_part->d->m_endOffset) { changed = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs); m_part->d->m_extendAtEnd = true; } else do { changed = m_part->d->m_selectionStart.handle() != oldStartSel || m_part->d->m_startOffset != oldStartOfs || m_part->d->m_selectionEnd.handle() != oldEndSel || m_part->d->m_endOffset != oldEndOfs; if (!changed) break; // determine start position -- caret position is always at end. NodeImpl *startNode; long startOffset; if (m_part->d->m_extendAtEnd) { startNode = m_part->d->m_selectionStart.handle(); startOffset = m_part->d->m_startOffset; } else { startNode = m_part->d->m_selectionEnd.handle(); startOffset = m_part->d->m_endOffset; m_part->d->m_selectionEnd = m_part->d->m_selectionStart; m_part->d->m_endOffset = m_part->d->m_startOffset; m_part->d->m_extendAtEnd = true; }/*end if*/ bool swapNeeded = false; if (!m_part->d->m_selectionEnd.isNull() && startNode) { swapNeeded = RangeImpl::compareBoundaryPoints(startNode, startOffset, m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset) >= 0; }/*end if*/ m_part->d->m_selectionStart = startNode; m_part->d->m_startOffset = startOffset; if (swapNeeded) { m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset, m_part->d->m_selectionStart.handle(), m_part->d->m_startOffset); } else { m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(), m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset); }/*end if*/ } while(false);/*end if*/ return changed; } void KHTMLView::updateSelection(NodeImpl *oldStartSel, long oldStartOfs, NodeImpl *oldEndSel, long oldEndOfs) { if (m_part->d->m_selectionStart == m_part->d->m_selectionEnd && m_part->d->m_startOffset == m_part->d->m_endOffset) { if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) { m_part->emitSelectionChanged(); }/*end if*/ m_part->d->m_extendAtEnd = true; } else { // check if the extending end has passed the immobile end if (!m_part->d->m_selectionEnd.isNull() && !m_part->d->m_selectionEnd.isNull()) { bool swapNeeded = RangeImpl::compareBoundaryPoints( m_part->d->m_selectionStart.handle(), m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset) >= 0; if (swapNeeded) { DOM::Node tmpNode = m_part->d->m_selectionStart; long tmpOffset = m_part->d->m_startOffset; m_part->d->m_selectionStart = m_part->d->m_selectionEnd; m_part->d->m_startOffset = m_part->d->m_endOffset; m_part->d->m_selectionEnd = tmpNode; m_part->d->m_endOffset = tmpOffset; m_part->d->m_startBeforeEnd = true; m_part->d->m_extendAtEnd = !m_part->d->m_extendAtEnd; }/*end if*/ }/*end if*/ m_part->xmlDocImpl()->setSelection(m_part->d->m_selectionStart.handle(), m_part->d->m_startOffset, m_part->d->m_selectionEnd.handle(), m_part->d->m_endOffset); m_part->emitSelectionChanged(); }/*end if*/ } void KHTMLView::caretKeyPressEvent(QKeyEvent *_ke) { NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle(); long oldStartOfs = m_part->d->m_startOffset; NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle(); long oldEndOfs = m_part->d->m_endOffset; NodeImpl *oldCaretNode = m_part->d->caretNode().handle(); long oldOffset = m_part->d->caretOffset(); bool ctrl = _ke->modifiers() & Qt::ControlModifier; // FIXME: this is that widely indented because I will write ifs around it. switch(_ke->key()) { case Qt::Key_Space: break; case Qt::Key_Down: moveCaretNextLine(1); break; case Qt::Key_Up: moveCaretPrevLine(1); break; case Qt::Key_Left: moveCaretBy(false, ctrl ? CaretByWord : CaretByCharacter, 1); break; case Qt::Key_Right: moveCaretBy(true, ctrl ? CaretByWord : CaretByCharacter, 1); break; case Qt::Key_PageDown: moveCaretNextPage(); break; case Qt::Key_PageUp: moveCaretPrevPage(); break; case Qt::Key_Home: if (ctrl) moveCaretToDocumentBoundary(false); else moveCaretToLineBegin(); break; case Qt::Key_End: if (ctrl) moveCaretToDocumentBoundary(true); else moveCaretToLineEnd(); break; }/*end switch*/ if ((m_part->d->caretNode().handle() != oldCaretNode || m_part->d->caretOffset() != oldOffset) // node should never be null, but faulty conditions may cause it to be && !m_part->d->caretNode().isNull()) { d->m_caretViewContext->caretMoved = true; if (_ke->modifiers() & Qt::ShiftModifier) { // extend selection updateSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs); } else { // clear any selection if (foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs)) m_part->emitSelectionChanged(); }/*end if*/ m_part->emitCaretPositionChanged(m_part->d->caretNode(), m_part->d->caretOffset()); }/*end if*/ _ke->accept(); } bool KHTMLView::moveCaretTo(NodeImpl *node, long offset, bool clearSel) { if (!node) return false; ElementImpl *baseElem = determineBaseElement(node); RenderFlow *base = static_cast(baseElem ? baseElem->renderer() : 0); if (!node) return false; // need to find out the node's inline box. If there is none, this function // will snap to the next node that has one. This is necessary to make the // caret visible in any case. CaretBoxLineDeleter cblDeleter; // RenderBlock *cb; long r_ofs; CaretBoxIterator cbit; CaretBoxLine *cbl = findCaretBoxLine(node, offset, &cblDeleter, base, r_ofs, cbit); if(!cbl) { kWarning() << "KHTMLView::moveCaretTo - findCaretBoxLine() returns NULL"; return false; } #if DEBUG_CARETMODE > 3 if (cbl) kDebug(6200) << cbl->information(); #endif CaretBox *box = *cbit; if (cbit != cbl->end() && box->object() != node->renderer()) { if (box->object()->element()) { mapRenderPosToDOMPos(box->object(), r_ofs, box->isOutside(), box->isOutsideEnd(), node, offset); //if (!outside) offset = node->minOffset(); #if DEBUG_CARETMODE > 1 kDebug(6200) << "set new node " << node->nodeName().string() << "@" << node; #endif } else { // box has no associated element -> do not use // this case should actually never happen. box = 0; kError(6200) << "Box contains no node! Crash imminent" << endl; }/*end if*/ } NodeImpl *oldStartSel = m_part->d->m_selectionStart.handle(); long oldStartOfs = m_part->d->m_startOffset; NodeImpl *oldEndSel = m_part->d->m_selectionEnd.handle(); long oldEndOfs = m_part->d->m_endOffset; // test for position change bool posChanged = m_part->d->caretNode().handle() != node || m_part->d->caretOffset() != offset; bool selChanged = false; m_part->d->caretNode() = node; m_part->d->caretOffset() = offset; if (clearSel || !oldStartSel || !oldEndSel) { selChanged = foldSelectionToCaret(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs); } else { //kDebug(6200) << "moveToCaret: extendSelection: m_extendAtEnd " << m_part->d->m_extendAtEnd; //kDebug(6200) << "selection: start(" << m_part->d->m_selectionStart.handle() << "," << m_part->d->m_startOffset << "), end(" << m_part->d->m_selectionEnd.handle() << "," << m_part->d->m_endOffset << "), caret(" << m_part->d->caretNode().handle() << "," << m_part->d->caretOffset() << ")"; selChanged = extendSelection(oldStartSel, oldStartOfs, oldEndSel, oldEndOfs); //kDebug(6200) << "after extendSelection: m_extendAtEnd " << m_part->d->m_extendAtEnd; //kDebug(6200) << "selection: start(" << m_part->d->m_selectionStart.handle() << "," << m_part->d->m_startOffset << "), end(" << m_part->d->m_selectionEnd.handle() << "," << m_part->d->m_endOffset << "), caret(" << m_part->d->caretNode().handle() << "," << m_part->d->caretOffset() << ")"; }/*end if*/ d->caretViewContext()->caretMoved = true; bool visible_caret = placeCaret(box); // FIXME: if the old position was !visible_caret, and the new position is // also, then two caretPositionChanged signals with a null Node are // emitted in series. if (posChanged) { m_part->emitCaretPositionChanged(visible_caret ? node : 0, offset); }/*end if*/ return selChanged; } void KHTMLView::moveCaretByLine(bool next, int count) { Node &caretNodeRef = m_part->d->caretNode(); if (caretNodeRef.isNull()) return; NodeImpl *caretNode = caretNodeRef.handle(); // kDebug(6200) << ": caretNode=" << caretNode; long offset = m_part->d->caretOffset(); CaretViewContext *cv = d->caretViewContext(); ElementImpl *baseElem = determineBaseElement(caretNode); LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem); ErgonomicEditableLineIterator it(ld.current(), cv->origX); // move count lines vertically while (count > 0 && it != ld.end() && it != ld.preBegin()) { count--; if (next) ++it; else --it; }/*wend*/ // Nothing? Then leave everything as is. if (it == ld.end() || it == ld.preBegin()) return; int x, absx, absy; CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy); placeCaretOnLine(caretBox, x, absx, absy); } void KHTMLView::placeCaretOnLine(CaretBox *caretBox, int x, int absx, int absy) { // paranoia sanity check if (!caretBox) return; RenderObject *caretRender = caretBox->object(); #if DEBUG_CARETMODE > 0 kDebug(6200) << "got valid caretBox " << caretBox; kDebug(6200) << "xPos: " << caretBox->xPos() << " yPos: " << caretBox->yPos() << " width: " << caretBox->width() << " height: " << caretBox->height() << endl; InlineTextBox *tb = static_cast(caretBox->inlineBox()); if (caretBox->isInlineTextBox()) { kDebug(6200) << "contains \"" << QString(static_cast(tb->object())->str->s + tb->m_start, tb->m_len) << "\"";} #endif // inquire height of caret int caretHeight = caretBox->height(); bool isText = caretBox->isInlineTextBox(); int yOfs = 0; // y-offset for text nodes if (isText) { // text boxes need extrawurst RenderText *t = static_cast(caretRender); const QFontMetrics &fm = t->metrics(caretBox->inlineBox()->m_firstLine); caretHeight = fm.height(); yOfs = caretBox->inlineBox()->baseline() - fm.ascent(); }/*end if*/ caretOff(); // set new caret node NodeImpl *caretNode; long &offset = m_part->d->caretOffset(); mapRenderPosToDOMPos(caretRender, offset, caretBox->isOutside(), caretBox->isOutsideEnd(), caretNode, offset); // set all variables not needing special treatment d->m_caretViewContext->y = caretBox->yPos() + yOfs; d->m_caretViewContext->height = caretHeight; d->m_caretViewContext->width = 1; // FIXME: regard override int xPos = caretBox->xPos(); int caretBoxWidth = caretBox->width(); d->m_caretViewContext->x = xPos; if (!caretBox->isOutside()) { // before or at beginning of inline box -> place at beginning long r_ofs = 0; if (x <= xPos) { r_ofs = caretBox->minOffset(); // somewhere within this block } else if (x > xPos && x <= xPos + caretBoxWidth) { if (isText) { // find out where exactly r_ofs = static_cast(caretBox->inlineBox()) ->offsetForPoint(x, d->m_caretViewContext->x); #if DEBUG_CARETMODE > 2 kDebug(6200) << "deviation from origX " << d->m_caretViewContext->x - x; #endif #if 0 } else { // snap to nearest end if (xPos + caretBoxWidth - x < x - xPos) { d->m_caretViewContext->x = xPos + caretBoxWidth; r_ofs = caretNode ? caretNode->maxOffset() : 1; } else { d->m_caretViewContext->x = xPos; r_ofs = caretNode ? caretNode->minOffset() : 0; }/*end if*/ #endif }/*end if*/ } else { // after the inline box -> place at end d->m_caretViewContext->x = xPos + caretBoxWidth; r_ofs = caretBox->maxOffset(); }/*end if*/ offset = r_ofs; }/*end if*/ #if DEBUG_CARETMODE > 0 kDebug(6200) << "new offset: " << offset; #endif m_part->d->caretNode() = caretNode; m_part->d->caretOffset() = offset; d->m_caretViewContext->x += absx; d->m_caretViewContext->y += absy; #if DEBUG_CARETMODE > 1 kDebug(6200) << "new caret position: x " << d->m_caretViewContext->x << " y " << d->m_caretViewContext->y << " w " << d->m_caretViewContext->width << " h " << d->m_caretViewContext->height << " absx " << absx << " absy " << absy; #endif ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); d->scrollBarMoved = false; ensureNodeHasFocus(caretNode); caretOn(); } void KHTMLView::moveCaretToLineBoundary(bool end) { Node &caretNodeRef = m_part->d->caretNode(); if (caretNodeRef.isNull()) return; NodeImpl *caretNode = caretNodeRef.handle(); // kDebug(6200) << ": caretNode=" << caretNode; long offset = m_part->d->caretOffset(); ElementImpl *baseElem = determineBaseElement(caretNode); LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem); EditableLineIterator it = ld.current(); if (it == ld.end()) return; // should not happen, but who knows EditableCaretBoxIterator fbit(it, end); Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin()); CaretBox *b = *fbit; RenderObject *cb = b->containingBlock(); int absx, absy; if (cb) cb->absolutePosition(absx,absy); else absx = absy = 0; int x = b->xPos() + (end && !b->isOutside() ? b->width() : 0); d->m_caretViewContext->origX = absx + x; placeCaretOnLine(b, x, absx, absy); } void KHTMLView::moveCaretToDocumentBoundary(bool end) { Node &caretNodeRef = m_part->d->caretNode(); if (caretNodeRef.isNull()) return; NodeImpl *caretNode = caretNodeRef.handle(); // kDebug(6200) << ": caretNode=" << caretNode; long offset = m_part->d->caretOffset(); ElementImpl *baseElem = determineBaseElement(caretNode); LinearDocument ld(m_part, caretNode, offset, IndicatedFlows, baseElem); EditableLineIterator it(end ? ld.preEnd() : ld.begin(), end); if (it == ld.end() || it == ld.preBegin()) return; // should not happen, but who knows EditableCaretBoxIterator fbit = it; Q_ASSERT(fbit != (*it)->end() && fbit != (*it)->preBegin()); CaretBox *b = *fbit; RenderObject *cb = (*it)->containingBlock(); int absx, absy; if (cb) cb->absolutePosition(absx, absy); else absx = absy = 0; int x = b->xPos()/* + (end ? b->width() : 0) reactivate for rtl*/; d->m_caretViewContext->origX = absx + x; placeCaretOnLine(b, x, absx, absy); } void KHTMLView::moveCaretBy(bool next, CaretMovement cmv, int count) { if (!m_part) return; Node &caretNodeRef = m_part->d->caretNode(); if (caretNodeRef.isNull()) return; NodeImpl *caretNode = caretNodeRef.handle(); // kDebug(6200) << ": caretNode=" << caretNode; long &offset = m_part->d->caretOffset(); ElementImpl *baseElem = determineBaseElement(caretNode); CaretAdvancePolicy advpol = cmv != CaretByWord ? IndicatedFlows : LeafsOnly; LinearDocument ld(m_part, caretNode, offset, advpol, baseElem); EditableCharacterIterator it(&ld); while (!it.isEnd() && count > 0) { count--; if (cmv == CaretByCharacter) { if (next) ++it; else --it; } else if (cmv == CaretByWord) { if (next) moveItToNextWord(it); else moveItToPrevWord(it); }/*end if*/ //kDebug(6200) << "movecaret"; }/*wend*/ CaretBox *hintBox = 0; // make gcc uninit warning disappear if (!it.isEnd()) { NodeImpl *node = caretNodeRef.handle(); hintBox = it.caretBox(); //kDebug(6200) << "hintBox = " << hintBox; //kDebug(6200) << " outside " << hintBox->isOutside() << " outsideEnd " << hintBox->isOutsideEnd() << " r " << it.renderer() << " ofs " << it.offset() << " cb " << hintBox->containingBlock(); mapRenderPosToDOMPos(it.renderer(), it.offset(), hintBox->isOutside(), hintBox->isOutsideEnd(), node, offset); //kDebug(6200) << "mapRTD"; caretNodeRef = node; #if DEBUG_CARETMODE > 2 kDebug(6200) << "set by valid node " << node << " " << (node?node->nodeName().string():QString()) << " offset: " << offset; #endif } else { offset = next ? caretNode->maxOffset() : caretNode->minOffset(); #if DEBUG_CARETMODE > 0 kDebug(6200) << "set by INvalid node. offset: " << offset; #endif }/*end if*/ placeCaretOnChar(hintBox); } void KHTMLView::placeCaretOnChar(CaretBox *hintBox) { caretOff(); recalcAndStoreCaretPos(hintBox); ensureVisible(d->m_caretViewContext->x, d->m_caretViewContext->y, d->m_caretViewContext->width, d->m_caretViewContext->height); d->m_caretViewContext->origX = d->m_caretViewContext->x; d->scrollBarMoved = false; #if DEBUG_CARETMODE > 3 //if (caretNode->isTextNode()) kDebug(6200) << "text[0] = " << (int)*((TextImpl *)caretNode)->data().unicode() << " text :\"" << ((TextImpl *)caretNode)->data().string() << "\""; #endif ensureNodeHasFocus(m_part->d->caretNode().handle()); caretOn(); } void KHTMLView::moveCaretByPage(bool next) { Node &caretNodeRef = m_part->d->caretNode(); if (caretNodeRef.isNull()) return; NodeImpl *caretNode = caretNodeRef.handle(); // kDebug(6200) << ": caretNode=" << caretNode; long offset = m_part->d->caretOffset(); int offs = (viewport()->height() < 30) ? viewport()->height() : 30; // Minimum distance the caret must be moved int mindist = viewport()->height() - offs; CaretViewContext *cv = d->caretViewContext(); // int y = cv->y; // we always measure the top border ElementImpl *baseElem = determineBaseElement(caretNode); LinearDocument ld(m_part, caretNode, offset, LeafsOnly, baseElem); ErgonomicEditableLineIterator it(ld.current(), cv->origX); moveIteratorByPage(ld, it, mindist, next); int x, absx, absy; CaretBox *caretBox = nearestCaretBox(it, d->m_caretViewContext, x, absx, absy); placeCaretOnLine(caretBox, x, absx, absy); } void KHTMLView::moveCaretPrevWord() { moveCaretBy(false, CaretByWord, 1); } void KHTMLView::moveCaretNextWord() { moveCaretBy(true, CaretByWord, 1); } void KHTMLView::moveCaretPrevLine(int n) { moveCaretByLine(false, n); } void KHTMLView::moveCaretNextLine(int n) { moveCaretByLine(true, n); } void KHTMLView::moveCaretPrevPage() { moveCaretByPage(false); } void KHTMLView::moveCaretNextPage() { moveCaretByPage(true); } void KHTMLView::moveCaretToLineBegin() { moveCaretToLineBoundary(false); } void KHTMLView::moveCaretToLineEnd() { moveCaretToLineBoundary(true); } #endif // KHTML_NO_CARET #undef DEBUG_CARETMODE diff --git a/khtml/rendering/render_style.h b/khtml/rendering/render_style.h index 2b903c57c1..d77ca3929a 100644 --- a/khtml/rendering/render_style.h +++ b/khtml/rendering/render_style.h @@ -1,1519 +1,1522 @@ /* * This file is part of the DOM implementation for KDE. * * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org) * (C) 2000 Antti Koivisto (koivisto@kde.org) * (C) 2000-2003 Dirk Mueller (mueller@kde.org) * (C) 2003-2005 Apple Computer, Inc. * (C) 2004-2006 Allan Sandfeld Jensen (kde@carewolf.com) * * 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 RENDERSTYLE_H #define RENDERSTYLE_H /* * WARNING: * -------- * * The order of the values in the enums have to agree with the order specified * in cssvalues.in, otherwise some optimizations in the parser will fail, * and produce invaliud results. */ #include #include #include #include #include #include "dom/dom_misc.h" #include "dom/dom_string.h" #include "misc/khtmllayout.h" #include "misc/shared.h" #include "rendering/font.h" #include #define SET_VAR(group,variable,value) \ if (!(group->variable == value)) \ group.access()->variable = value; #ifndef ENABLE_DUMP #ifndef NDEBUG #define ENABLE_DUMP 1 #endif #endif namespace DOM { class DOMStringImpl; class QuotesValueImpl; class CounterImpl; class CSSValueListImpl; } namespace khtml { class CachedImage; class CachedObject; template class DataRef { public: DataRef() { data=0; } DataRef( const DataRef &d ) { data = d.data; data->ref(); } ~DataRef() { if(data) data->deref(); } const DATA* operator->() const { return data; } const DATA* get() const { return data; } DATA* access() { if (!data->hasOneRef()) { data->deref(); data = new DATA(*data); data->ref(); } return data; } void init() { data = new DATA; data->ref(); } DataRef& operator=(const DataRef& d) { if (data==d.data) return *this; if (data) data->deref(); data = d.data; data->ref(); return *this; } bool operator == ( const DataRef &o ) const { return (*data == *(o.data) ); } bool operator != ( const DataRef &o ) const { return (*data != *(o.data) ); } private: DATA* data; }; //------------------------------------------------ //------------------------------------------------ // Box model attributes. Not inherited. struct LengthBox { LengthBox() { } LengthBox( LengthType t ) : left( t ), right ( t ), top( t ), bottom( t ) {} Length left; Length right; Length top; Length bottom; Length& operator=(Length& len) { left=len; right=len; top=len; bottom=len; return len; } bool operator==(const LengthBox& o) const { return left==o.left && right==o.right && top==o.top && bottom==o.bottom; } bool nonZero() const { return left.value() || right.value() || top.value() || bottom.value(); } }; enum EPosition { STATIC, RELATIVE, ABSOLUTE, FIXED }; enum EFloat { FNONE = 0, FLEFT = 0x01, FRIGHT = 0x02, FLEFT_ALIGN = 0x05, FRIGHT_ALIGN = 0x06 }; //------------------------------------------------ // Border attributes. Not inherited. // These have been defined in the order of their precedence for border-collapsing. Do // not change this order! enum EBorderStyle { BNATIVE, BNONE, BHIDDEN, INSET, GROOVE, RIDGE, OUTSET, DOTTED, DASHED, SOLID, DOUBLE }; class BorderValue { public: BorderValue() : width( 3 ), style( BNONE ) {} QColor color; unsigned short width : 12; EBorderStyle style : 6; bool nonZero(bool checkStyle = true) const { return width != 0 && !(checkStyle && style == BNONE); } bool isTransparent() const { return color.isValid() && color.alpha() == 0; } bool operator==(const BorderValue& o) const { return width==o.width && style==o.style && color==o.color; } bool operator!=(const BorderValue& o) const { return !(*this == o); } }; class OutlineValue : public BorderValue { public: OutlineValue() { _offset = 0; _auto = false; } bool operator==(const OutlineValue& o) const { return width==o.width && style==o.style && color==o.color && _offset == o._offset && _auto == o._auto; } bool operator!=(const OutlineValue& o) const { return !(*this == o); } int _offset; bool _auto; }; enum EBorderPrecedence { BOFF, BTABLE, BCOLGROUP, BCOL, BROWGROUP, BROW, BCELL }; struct CollapsedBorderValue { CollapsedBorderValue() :border(0), precedence(BOFF) {} CollapsedBorderValue(const BorderValue* b, EBorderPrecedence p) :border(b), precedence(p) {} int width() const { return border && border->nonZero() ? border->width : 0; } EBorderStyle style() const { return border ? border->style : BHIDDEN; } bool exists() const { return border; } QColor color() const { return border ? border->color : QColor(); } bool isTransparent() const { return border ? border->isTransparent() : true; } bool operator==(const CollapsedBorderValue& o) const { if (!border) return !o.border; if (!o.border) return false; return *border == *o.border && precedence == o.precedence; } const BorderValue* border; EBorderPrecedence precedence; }; class BorderData : public Shared { public: BorderValue left; BorderValue right; BorderValue top; BorderValue bottom; bool hasBorder() const { return left.nonZero() || right.nonZero() || top.nonZero() || bottom.nonZero(); } unsigned short borderLeftWidth() const { if (left.style == BNONE || left.style == BHIDDEN || left.style == BNATIVE) return 0; return left.width; } unsigned short borderRightWidth() const { if (right.style == BNONE || right.style == BHIDDEN || right.style == BNATIVE) return 0; return right.width; } unsigned short borderTopWidth() const { if (top.style == BNONE || top.style == BHIDDEN || top.style == BNATIVE) return 0; return top.width; } unsigned short borderBottomWidth() const { if (bottom.style == BNONE || bottom.style == BHIDDEN || bottom.style == BNATIVE) return 0; return bottom.width; } bool operator==(const BorderData& o) const { return left==o.left && right==o.right && top==o.top && bottom==o.bottom; } }; class StyleSurroundData : public Shared { public: StyleSurroundData(); StyleSurroundData(const StyleSurroundData& o ); bool operator==(const StyleSurroundData& o) const; bool operator!=(const StyleSurroundData& o) const { return !(*this == o); } bool hasSamePBMData(const StyleSurroundData& o) const { return (margin == o.margin) && (padding == o.padding) && (border == o.border); } LengthBox offset; LengthBox margin; LengthBox padding; BorderData border; }; //------------------------------------------------ // Box attributes. Not inherited. enum EBoxSizing { BORDER_BOX, CONTENT_BOX }; class StyleBoxData : public Shared { public: StyleBoxData(); StyleBoxData(const StyleBoxData& o ); // copy and assignment // StyleBoxData(const StyleBoxData &other); // const StyleBoxData &operator = (const StyleBoxData &other); bool operator==(const StyleBoxData& o) const; bool operator!=(const StyleBoxData& o) const { return !(*this == o); } Length width; Length height; Length min_width; Length max_width; Length min_height; Length max_height; Length vertical_align; EBoxSizing box_sizing; signed int z_index :31; bool z_auto : 1; }; //------------------------------------------------ // Random visual rendering model attributes. Not inherited. enum EOverflow { OVISIBLE, OHIDDEN, OSCROLL, OAUTO, OMARQUEE }; enum EVerticalAlign { BASELINE, MIDDLE, SUB, SUPER, TEXT_TOP, TEXT_BOTTOM, TOP, BOTTOM, BASELINE_MIDDLE, LENGTH }; enum EClear{ CNONE = 0, CLEFT = 1, CRIGHT = 2, CBOTH = 3 }; enum ETableLayout { TAUTO, TFIXED }; enum EUnicodeBidi { UBNormal, Embed, Override }; class StyleVisualData : public Shared { public: StyleVisualData(); ~StyleVisualData(); StyleVisualData(const StyleVisualData& o ); bool operator==( const StyleVisualData &o ) const { return ( clip == o.clip && palette == o.palette ); } bool operator!=( const StyleVisualData &o ) const { return !(*this == o); } LengthBox clip; unsigned textDecoration : 4; // Text decorations defined *only* by this element. QPalette palette; //widget styling with IE attributes }; //------------------------------------------------ enum EBackgroundBox { BGBORDER, BGPADDING, BGCONTENT }; enum EBackgroundRepeat { REPEAT, REPEAT_X, REPEAT_Y, NO_REPEAT }; struct LengthSize { Length width; Length height; }; struct BackgroundLayer { public: BackgroundLayer(); ~BackgroundLayer(); CachedImage* backgroundImage() const { return m_image; } Length backgroundXPosition() const { return m_xPosition; } Length backgroundYPosition() const { return m_yPosition; } bool backgroundAttachment() const { return m_bgAttachment; } EBackgroundBox backgroundClip() const { return m_bgClip; } EBackgroundBox backgroundOrigin() const { return m_bgOrigin; } EBackgroundRepeat backgroundRepeat() const { return m_bgRepeat; } LengthSize backgroundSize() const { return m_backgroundSize; } BackgroundLayer* next() const { return m_next; } BackgroundLayer* next() { return m_next; } bool isBackgroundImageSet() const { return m_imageSet; } bool isBackgroundXPositionSet() const { return m_xPosSet; } bool isBackgroundYPositionSet() const { return m_yPosSet; } bool isBackgroundAttachmentSet() const { return m_attachmentSet; } bool isBackgroundClipSet() const { return m_clipSet; } bool isBackgroundOriginSet() const { return m_originSet; } bool isBackgroundRepeatSet() const { return m_repeatSet; } bool isBackgroundSizeSet() const { return m_backgroundSizeSet; } void setBackgroundImage(CachedImage* i) { m_image = i; m_imageSet = true; } void setBackgroundXPosition(const Length& l) { m_xPosition = l; m_xPosSet = true; } void setBackgroundYPosition(const Length& l) { m_yPosition = l; m_yPosSet = true; } void setBackgroundAttachment(bool b) { m_bgAttachment = b; m_attachmentSet = true; } void setBackgroundClip(EBackgroundBox b) { m_bgClip = b; m_clipSet = true; } void setBackgroundOrigin(EBackgroundBox b) { m_bgOrigin = b; m_originSet = true; } void setBackgroundRepeat(EBackgroundRepeat r) { m_bgRepeat = r; m_repeatSet = true; } void setBackgroundSize(const LengthSize& b) { m_backgroundSize = b; m_backgroundSizeSet = true; } void clearBackgroundImage() { m_imageSet = false; } void clearBackgroundXPosition() { m_xPosSet = false; } void clearBackgroundYPosition() { m_yPosSet = false; } void clearBackgroundAttachment() { m_attachmentSet = false; } void clearBackgroundClip() { m_clipSet = false; } void clearBackgroundOrigin() { m_originSet = false; } void clearBackgroundRepeat() { m_repeatSet = false; } void clearBackgroundSize() { m_backgroundSizeSet = false; } void setNext(BackgroundLayer* n) { if (m_next != n) { delete m_next; m_next = n; } } BackgroundLayer& operator=(const BackgroundLayer& o); BackgroundLayer(const BackgroundLayer& o); bool operator==(const BackgroundLayer& o) const; bool operator!=(const BackgroundLayer& o) const { return !(*this == o); } bool containsImage(CachedImage* c) const { if (c == m_image) return true; if (m_next) return m_next->containsImage(c); return false; } bool hasImage() const { if (m_image) return true; return m_next ? m_next->hasImage() : false; } bool hasFixedImage() const { if (m_image && !m_bgAttachment) return true; return m_next ? m_next->hasFixedImage() : false; } void fillUnsetProperties(); void cullEmptyLayers(); CachedImage* m_image; Length m_xPosition; Length m_yPosition; bool m_bgAttachment : 1; EBackgroundBox m_bgClip : 2; EBackgroundBox m_bgOrigin : 2; EBackgroundRepeat m_bgRepeat : 2; LengthSize m_backgroundSize; bool m_imageSet : 1; bool m_attachmentSet : 1; bool m_clipSet : 1; bool m_originSet : 1; bool m_repeatSet : 1; bool m_xPosSet : 1; bool m_yPosSet : 1; bool m_backgroundSizeSet : 1; BackgroundLayer* m_next; }; class StyleBackgroundData : public Shared { public: StyleBackgroundData(); ~StyleBackgroundData() {} StyleBackgroundData(const StyleBackgroundData& o ); bool operator==(const StyleBackgroundData& o) const; bool operator!=(const StyleBackgroundData &o) const { return !(*this == o); } BackgroundLayer m_background; QColor m_color; OutlineValue m_outline; }; enum EQuoteContent { NO_QUOTE = 0, OPEN_QUOTE, CLOSE_QUOTE, NO_OPEN_QUOTE, NO_CLOSE_QUOTE }; enum ContentType { CONTENT_NONE = 0, CONTENT_NORMAL, CONTENT_OBJECT, CONTENT_TEXT, CONTENT_COUNTER, CONTENT_QUOTE }; struct ContentData { ContentData() : _contentType( CONTENT_NONE ), _nextContent(0) {} ContentData(const ContentData& o); ~ContentData(); void clearContent(); DOM::DOMStringImpl* contentText() { if (_contentType == CONTENT_TEXT) return _content.text; return 0; } CachedObject* contentObject() { if (_contentType == CONTENT_OBJECT) return _content.object; return 0; } DOM::CounterImpl* contentCounter() { if (_contentType == CONTENT_COUNTER) return _content.counter; return 0; } EQuoteContent contentQuote() { if (_contentType == CONTENT_QUOTE) return _content.quote; return NO_QUOTE; } ContentType _contentType; union { CachedObject* object; DOM::DOMStringImpl* text; DOM::CounterImpl* counter; EQuoteContent quote; } _content ; ContentData* _nextContent; }; class StyleGeneratedData : public Shared { public: StyleGeneratedData(); ~StyleGeneratedData(); StyleGeneratedData(const StyleGeneratedData& o ); bool operator==(const StyleGeneratedData& o) const; bool operator!=(const StyleGeneratedData &o) const { return !(*this == o); } bool contentDataEquivalent(const StyleGeneratedData* otherStyle) const; bool counterDataEquivalent(const StyleGeneratedData* otherStyle) const; ContentData *content; DOM::CSSValueListImpl *counter_reset; DOM::CSSValueListImpl *counter_increment; }; //------------------------------------------------ // CSS3 Marquee Properties enum EMarqueeBehavior { MNONE, MSCROLL, MSLIDE, MALTERNATE, MUNFURL }; enum EMarqueeDirection { MAUTO = 0, MLEFT = 1, MRIGHT = -1, MUP = 2, MDOWN = -2, MFORWARD = 3, MBACKWARD = -3 }; class StyleMarqueeData : public Shared { public: StyleMarqueeData(); StyleMarqueeData(const StyleMarqueeData& o); bool operator==(const StyleMarqueeData& o) const; bool operator!=(const StyleMarqueeData& o) const { return !(*this == o); } Length increment; int speed; int loops; // -1 means infinite. EMarqueeBehavior behavior : 3; EMarqueeDirection direction : 3; }; // This struct holds information about shadows for the text-shadow and box-shadow properties. struct ShadowData { ShadowData(int _x, int _y, int _blur, const QColor& _color) :x(_x), y(_y), blur(_blur), color(_color), next(0) {} ShadowData(const ShadowData& o); ~ShadowData() { delete next; } bool operator==(const ShadowData& o) const; bool operator!=(const ShadowData &o) const { return !(*this == o); } int x; int y; int blur; QColor color; ShadowData* next; }; // This struct is for rarely used non-inherited CSS3 properties. By grouping them together, // we save space, and only allocate this object when someone actually uses // a non-inherited CSS3 property. class StyleCSS3NonInheritedData : public Shared { public: StyleCSS3NonInheritedData(); ~StyleCSS3NonInheritedData() {} StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o); bool operator==(const StyleCSS3NonInheritedData& o) const; bool operator!=(const StyleCSS3NonInheritedData &o) const { return !(*this == o); } float opacity; // Whether or not we're transparent. #ifdef APPLE_CHANGES // ### we don't have those (yet) DataRef flexibleBox; // Flexible box properties #endif DataRef marquee; // Marquee properties }; // This struct is for rarely used inherited CSS3 properties. By grouping them together, // we save space, and only allocate this object when someone actually uses // an inherited CSS3 property. class StyleCSS3InheritedData : public Shared { public: StyleCSS3InheritedData(); ~StyleCSS3InheritedData(); StyleCSS3InheritedData(const StyleCSS3InheritedData& o); bool operator==(const StyleCSS3InheritedData& o) const; bool operator!=(const StyleCSS3InheritedData &o) const { return !(*this == o); } bool shadowDataEquivalent(const StyleCSS3InheritedData& o) const; ShadowData* textShadow; // Our text shadow information for shadowed text drawing. #ifdef APPLE_CHANGES EUserModify userModify : 2; // Flag used for editing state bool textSizeAdjust : 1; // An Apple extension. Not really CSS3 but not worth making a new struct over. #endif private: StyleCSS3InheritedData &operator=(const StyleCSS3InheritedData &); }; //------------------------------------------------ // Inherited attributes. // // the inherited-decoration and inherited-shadow attributes // are inherited from the // first parent which is block level // enum EWhiteSpace { NORMAL, PRE, NOWRAP, PRE_WRAP, PRE_LINE, KHTML_NOWRAP }; enum ETextAlign { TAAUTO, LEFT, RIGHT, CENTER, JUSTIFY, KHTML_LEFT, KHTML_RIGHT, KHTML_CENTER }; enum ETextTransform { CAPITALIZE, UPPERCASE, LOWERCASE, TTNONE }; enum EDirection { LTR, RTL }; enum ETextDecoration { TDNONE = 0x0 , UNDERLINE = 0x1, OVERLINE = 0x2, LINE_THROUGH= 0x4, BLINK = 0x8 }; enum EPageBreak { PBAUTO, PBALWAYS, PBAVOID, /* reserved for later use: */ PBLEFT, PBRIGHT }; class StyleInheritedData : public Shared { StyleInheritedData& operator=(const StyleInheritedData&); public: StyleInheritedData(); ~StyleInheritedData(); StyleInheritedData(const StyleInheritedData& o ); bool operator==(const StyleInheritedData& o) const; bool operator != ( const StyleInheritedData &o ) const { return !(*this == o); } Length indent; // could be packed in a short but doesn't // make a difference currently because of padding Length line_height; CachedImage *style_image; khtml::Font font; QColor color; short border_hspacing; short border_vspacing; // Paged media properties. short widows; short orphans; DOM::QuotesValueImpl* quotes; }; enum EEmptyCell { SHOW, HIDE }; enum ECaptionSide { CAPTOP, CAPBOTTOM, CAPLEFT, CAPRIGHT }; enum EListStyleType { // Symbols: LDISC, LCIRCLE, LSQUARE, LBOX, LDIAMOND, // Numeric: LDECIMAL, DECIMAL_LEADING_ZERO, ARABIC_INDIC, LAO, PERSIAN, URDU, THAI, TIBETAN, // Algorithmic: LOWER_ROMAN, UPPER_ROMAN, HEBREW, ARMENIAN, GEORGIAN, // Ideographic: CJK_IDEOGRAPHIC, JAPANESE_FORMAL, JAPANESE_INFORMAL, SIMP_CHINESE_FORMAL, SIMP_CHINESE_INFORMAL, TRAD_CHINESE_FORMAL, TRAD_CHINESE_INFORMAL, // Alphabetic: LOWER_GREEK, UPPER_GREEK, LOWER_ALPHA, LOWER_LATIN, UPPER_ALPHA, UPPER_LATIN, HIRAGANA, KATAKANA, HIRAGANA_IROHA, KATAKANA_IROHA, // Special: LNONE }; inline bool isListStyleCounted(EListStyleType type) { switch(type) { case LDISC: case LCIRCLE: case LSQUARE: case LBOX: case LDIAMOND: case LNONE: return false; default: return true; } } enum EListStylePosition { OUTSIDE, INSIDE }; enum EVisibility { VISIBLE, HIDDEN, COLLAPSE }; enum ECursor { - CURSOR_AUTO, CURSOR_CROSS, CURSOR_DEFAULT, CURSOR_POINTER, CURSOR_PROGRESS, CURSOR_MOVE, - CURSOR_E_RESIZE, CURSOR_NE_RESIZE, CURSOR_NW_RESIZE, CURSOR_N_RESIZE, CURSOR_SE_RESIZE, CURSOR_SW_RESIZE, - CURSOR_S_RESIZE, CURSOR_W_RESIZE, CURSOR_TEXT, CURSOR_WAIT, CURSOR_HELP + CURSOR_AUTO, CURSOR_DEFAULT, CURSOR_CONTEXT_MENU, CURSOR_HELP, CURSOR_POINTER, + CURSOR_PROGRESS, CURSOR_WAIT, CURSOR_CELL, CURSOR_CROSS, CURSOR_TEXT, CURSOR_VERTICAL_TEXT, + CURSOR_ALIAS, CURSOR_COPY, CURSOR_MOVE, CURSOR_NO_DROP, CURSOR_NOT_ALLOWED, + CURSOR_E_RESIZE, CURSOR_N_RESIZE, CURSOR_NE_RESIZE, CURSOR_NW_RESIZE, CURSOR_S_RESIZE, CURSOR_SE_RESIZE, + CURSOR_SW_RESIZE, CURSOR_W_RESIZE, CURSOR_EW_RESIZE, CURSOR_NS_RESIZE, CURSOR_NESW_RESIZE, CURSOR_NWSE_RESIZE, + CURSOR_COL_RESIZE, CURSOR_ROW_RESIZE, CURSOR_ALL_SCROLL, CURSOR_NONE }; enum EUserInput { UI_ENABLED, UI_DISABLED, UI_NONE }; //------------------------------------------------ enum EDisplay { INLINE, BLOCK, LIST_ITEM, RUN_IN, COMPACT, INLINE_BLOCK, TABLE, INLINE_TABLE, TABLE_ROW_GROUP, TABLE_HEADER_GROUP, TABLE_FOOTER_GROUP, TABLE_ROW, TABLE_COLUMN_GROUP, TABLE_COLUMN, TABLE_CELL, TABLE_CAPTION, NONE }; class RenderStyle : public Shared { friend class CSSStyleSelector; public: KHTML_EXPORT static void cleanup(); // pseudo elements enum PseudoId { NOPSEUDO, FIRST_LINE, FIRST_LETTER, SELECTION, BEFORE, AFTER, REPLACED, MARKER }; protected: // !START SYNC!: Keep this in sync with the copy constructor in render_style.cpp // inherit struct InheritedFlags { // 64 bit inherited, update unused when adding to the struct, or the operator will break. bool operator==( const InheritedFlags &other ) const { return _iflags ==other._iflags; } bool operator!=( const InheritedFlags &other ) const { return _iflags != other._iflags; } union { struct { KDE_BF_ENUM(EEmptyCell) _empty_cells : 1 ; KDE_BF_ENUM(ECaptionSide) _caption_side : 2; KDE_BF_ENUM(EListStyleType) _list_style_type : 6; KDE_BF_ENUM(EListStylePosition) _list_style_position : 1; KDE_BF_ENUM(EVisibility) _visibility : 2; KDE_BF_ENUM(ETextAlign) _text_align : 4; KDE_BF_ENUM(ETextTransform) _text_transform : 2; unsigned _text_decorations : 4; KDE_BF_ENUM(ECursor) _cursor_style : 5; KDE_BF_ENUM(EDirection) _direction : 1; unsigned _border_collapse : 1 ; KDE_BF_ENUM(EWhiteSpace) _white_space : 3; // non CSS2 inherited unsigned _visuallyOrdered : 1; unsigned _htmlHacks : 1; KDE_BF_ENUM(EUserInput) _user_input : 2; unsigned _page_break_inside : 1; // AUTO/AVOID unsigned int unused : 27; } f; quint64 _iflags; }; } inherited_flags; // don't inherit struct NonInheritedFlags { // 64 bit non-inherited, update unused when adding to the struct, or the operator will break. bool operator==( const NonInheritedFlags &other ) const { return _niflags == other._niflags; } bool operator!=( const NonInheritedFlags &other ) const { return _niflags != other._niflags; } union { struct { KDE_BF_ENUM(EDisplay) _display : 5; KDE_BF_ENUM(EDisplay) _originalDisplay : 5; KDE_BF_ENUM(EOverflow) _overflowX : 4 ; KDE_BF_ENUM(EOverflow) _overflowY : 4 ; KDE_BF_ENUM(EVerticalAlign) _vertical_align : 4; KDE_BF_ENUM(EClear) _clear : 2; KDE_BF_ENUM(EPosition) _position : 2; KDE_BF_ENUM(EFloat) _floating : 3; KDE_BF_ENUM(ETableLayout) _table_layout : 1; unsigned _flowAroundFloats : 1; KDE_BF_ENUM(EPageBreak) _page_break_before : 3; KDE_BF_ENUM(EPageBreak) _page_break_after : 3; KDE_BF_ENUM(PseudoId) _styleType : 4; unsigned _hasClip : 1; unsigned _pseudoBits : 8; KDE_BF_ENUM(EUnicodeBidi) _unicodeBidi : 2; // non CSS2 non-inherited unsigned _textOverflow : 1; // Whether or not lines that spill out should be truncated with "..." unsigned _inherited_noninherited : 1; unsigned int unused : 10; } f; quint64 _niflags; }; } noninherited_flags; // non-inherited attributes DataRef box; DataRef visual; DataRef background; DataRef surround; DataRef generated; DataRef css3NonInheritedData; // inherited attributes DataRef css3InheritedData; DataRef inherited; // list of associated pseudo styles RenderStyle* pseudoStyle; // !END SYNC! // static default style static RenderStyle* _default; private: RenderStyle(const RenderStyle*) {} protected: void setBitDefaults() { inherited_flags.f._empty_cells = initialEmptyCells(); inherited_flags.f._caption_side = initialCaptionSide(); inherited_flags.f._list_style_type = initialListStyleType(); inherited_flags.f._list_style_position = initialListStylePosition(); inherited_flags.f._visibility = initialVisibility(); inherited_flags.f._text_align = initialTextAlign(); inherited_flags.f._text_transform = initialTextTransform(); inherited_flags.f._text_decorations = initialTextDecoration(); inherited_flags.f._cursor_style = initialCursor(); inherited_flags.f._direction = initialDirection(); inherited_flags.f._border_collapse = initialBorderCollapse(); inherited_flags.f._white_space = initialWhiteSpace(); inherited_flags.f._visuallyOrdered = false; inherited_flags.f._htmlHacks=false; inherited_flags.f._user_input = UI_NONE; inherited_flags.f._page_break_inside = true; inherited_flags.f.unused = 0; noninherited_flags._niflags = 0L; // for safety: without this, the equality method sometimes // makes use of uninitialised bits according to valgrind noninherited_flags.f._display = noninherited_flags.f._originalDisplay = initialDisplay(); noninherited_flags.f._overflowX = initialOverflowX(); noninherited_flags.f._overflowY = initialOverflowY(); noninherited_flags.f._vertical_align = initialVerticalAlign(); noninherited_flags.f._clear = initialClear(); noninherited_flags.f._position = initialPosition(); noninherited_flags.f._floating = initialFloating(); noninherited_flags.f._table_layout = initialTableLayout(); noninherited_flags.f._flowAroundFloats= initialFlowAroundFloats(); noninherited_flags.f._page_break_before = initialPageBreak(); noninherited_flags.f._page_break_after = initialPageBreak(); noninherited_flags.f._styleType = NOPSEUDO; noninherited_flags.f._hasClip = false; noninherited_flags.f._pseudoBits = 0; noninherited_flags.f._unicodeBidi = initialUnicodeBidi(); noninherited_flags.f._textOverflow = initialTextOverflow(); noninherited_flags.f._inherited_noninherited = false; noninherited_flags.f.unused = 0; } public: RenderStyle(); // used to create the default style. RenderStyle(bool); RenderStyle(const RenderStyle&); ~RenderStyle(); void inheritFrom(const RenderStyle* inheritParent); PseudoId styleType() const { return KDE_CAST_BF_ENUM(PseudoId, noninherited_flags.f._styleType); } void setStyleType(PseudoId pi) { noninherited_flags.f._styleType = pi; } bool isGenerated() const { if (styleType() == AFTER || styleType() == BEFORE || styleType() == MARKER || styleType() == REPLACED) return true; else return false; } bool hasPseudoStyle(PseudoId pi) const; void setHasPseudoStyle(PseudoId pi, bool b=true); RenderStyle* getPseudoStyle(PseudoId pi) const; RenderStyle* addPseudoStyle(PseudoId pi); void removePseudoStyle(PseudoId pi); bool operator==(const RenderStyle& other) const; bool isFloating() const { return !(noninherited_flags.f._floating == FNONE); } bool hasMargin() const { return surround->margin.nonZero(); } bool hasBorder() const { return surround->border.hasBorder(); } bool hasPadding() const { return surround->padding.nonZero(); } bool hasOffset() const { return surround->offset.nonZero(); } bool hasBackground() const { if (backgroundColor().isValid() && backgroundColor().alpha() > 0) return true; else return background->m_background.hasImage(); } bool hasFixedBackgroundImage() const { return background->m_background.hasFixedImage(); } bool visuallyOrdered() const { return inherited_flags.f._visuallyOrdered; } void setVisuallyOrdered(bool b) { inherited_flags.f._visuallyOrdered = b; } // attribute getter methods EDisplay display() const { return KDE_CAST_BF_ENUM(EDisplay, noninherited_flags.f._display); } EDisplay originalDisplay() const { return KDE_CAST_BF_ENUM(EDisplay, noninherited_flags.f._originalDisplay); } Length left() const { return surround->offset.left; } Length right() const { return surround->offset.right; } Length top() const { return surround->offset.top; } Length bottom() const { return surround->offset.bottom; } EPosition position() const { return KDE_CAST_BF_ENUM(EPosition, noninherited_flags.f._position); } EFloat floating() const { return KDE_CAST_BF_ENUM(EFloat, noninherited_flags.f._floating); } Length width() const { return box->width; } Length height() const { return box->height; } Length minWidth() const { return box->min_width; } Length maxWidth() const { return box->max_width; } Length minHeight() const { return box->min_height; } Length maxHeight() const { return box->max_height; } const BorderData& border() const { return surround->border; } const BorderValue& borderLeft() const { return surround->border.left; } const BorderValue& borderRight() const { return surround->border.right; } const BorderValue& borderTop() const { return surround->border.top; } const BorderValue& borderBottom() const { return surround->border.bottom; } unsigned short borderLeftWidth() const { return surround->border.borderLeftWidth(); } EBorderStyle borderLeftStyle() const { return surround->border.left.style; } const QColor& borderLeftColor() const { return surround->border.left.color; } bool borderLeftIsTransparent() const { return surround->border.left.isTransparent(); } unsigned short borderRightWidth() const { return surround->border.borderRightWidth(); } EBorderStyle borderRightStyle() const { return surround->border.right.style; } const QColor& borderRightColor() const { return surround->border.right.color; } bool borderRightIsTransparent() const { return surround->border.right.isTransparent(); } unsigned short borderTopWidth() const { return surround->border.borderTopWidth(); } EBorderStyle borderTopStyle() const { return surround->border.top.style; } const QColor& borderTopColor() const { return surround->border.top.color; } bool borderTopIsTransparent() const { return surround->border.top.isTransparent(); } unsigned short borderBottomWidth() const { return surround->border.borderBottomWidth(); } EBorderStyle borderBottomStyle() const { return surround->border.bottom.style; } const QColor& borderBottomColor() const { return surround->border.bottom.color; } bool borderBottomIsTransparent() const { return surround->border.bottom.isTransparent(); } unsigned short outlineSize() const { return outlineWidth() + outlineOffset(); } unsigned short outlineWidth() const { if(background->m_outline.style == BNONE || background->m_outline.style == BHIDDEN) return 0; else return background->m_outline.width; } EBorderStyle outlineStyle() const { return background->m_outline.style; } bool outlineStyleIsAuto() const { return background->m_outline._auto; } const QColor & outlineColor() const { return background->m_outline.color; } EOverflow overflowX() const { return KDE_CAST_BF_ENUM(EOverflow, noninherited_flags.f._overflowX); } EOverflow overflowY() const { return KDE_CAST_BF_ENUM(EOverflow, noninherited_flags.f._overflowY); } bool hidesOverflow() const { // either both overflow are visible or none are return overflowX() != OVISIBLE; } EVisibility visibility() const { return KDE_CAST_BF_ENUM(EVisibility, inherited_flags.f._visibility); } EVerticalAlign verticalAlign() const { return KDE_CAST_BF_ENUM(EVerticalAlign, noninherited_flags.f._vertical_align); } Length verticalAlignLength() const { return box->vertical_align; } Length clipLeft() const { return visual->clip.left; } Length clipRight() const { return visual->clip.right; } Length clipTop() const { return visual->clip.top; } Length clipBottom() const { return visual->clip.bottom; } LengthBox clip() const { return visual->clip; } bool hasClip() const { return noninherited_flags.f._hasClip; } EUnicodeBidi unicodeBidi() const { return KDE_CAST_BF_ENUM(EUnicodeBidi, noninherited_flags.f._unicodeBidi); } EClear clear() const { return KDE_CAST_BF_ENUM(EClear, noninherited_flags.f._clear); } ETableLayout tableLayout() const { return KDE_CAST_BF_ENUM(ETableLayout, noninherited_flags.f._table_layout); } const QFont & font() const { return inherited->font.f; } // use with care. call font->update() after modifications const Font &htmlFont() { return inherited->font; } const QFontMetrics & fontMetrics() const { return inherited->font.fm; } const QColor & color() const { return inherited->color; } Length textIndent() const { return inherited->indent; } ETextAlign textAlign() const { return KDE_CAST_BF_ENUM(ETextAlign, inherited_flags.f._text_align); } ETextTransform textTransform() const { return KDE_CAST_BF_ENUM(ETextTransform, inherited_flags.f._text_transform); } int textDecorationsInEffect() const { return inherited_flags.f._text_decorations; } int textDecoration() const { return visual->textDecoration; } int wordSpacing() const { return inherited->font.wordSpacing; } int letterSpacing() const { return inherited->font.letterSpacing; } EDirection direction() const { return KDE_CAST_BF_ENUM(EDirection, inherited_flags.f._direction); } Length lineHeight() const { return inherited->line_height; } EWhiteSpace whiteSpace() const { return KDE_CAST_BF_ENUM(EWhiteSpace, inherited_flags.f._white_space); } bool autoWrap() const { if (whiteSpace() == NORMAL || whiteSpace() == PRE_WRAP || whiteSpace() == PRE_LINE) return true; // nowrap | pre return false; } bool preserveLF() const { if (whiteSpace() == PRE || whiteSpace() == PRE_WRAP || whiteSpace() == PRE_LINE) return true; // normal | nowrap return false; } bool preserveWS() const { if (whiteSpace() == PRE || whiteSpace() == PRE_WRAP) return true; // normal | nowrap | pre-line return false; } const QColor & backgroundColor() const { return background->m_color; } CachedImage *backgroundImage() const { return background->m_background.m_image; } EBackgroundRepeat backgroundRepeat() const { return background->m_background.m_bgRepeat; } bool backgroundAttachment() const { return background->m_background.m_bgAttachment; } Length backgroundXPosition() const { return background->m_background.m_xPosition; } Length backgroundYPosition() const { return background->m_background.m_yPosition; } BackgroundLayer* accessBackgroundLayers() { return &(background.access()->m_background); } const BackgroundLayer* backgroundLayers() const { return &(background->m_background); } // returns true for collapsing borders, false for separate borders bool borderCollapse() const { return inherited_flags.f._border_collapse; } short borderHorizontalSpacing() const { return inherited->border_hspacing; } short borderVerticalSpacing() const { return inherited->border_vspacing; } EEmptyCell emptyCells() const { return KDE_CAST_BF_ENUM(EEmptyCell, inherited_flags.f._empty_cells); } ECaptionSide captionSide() const { return KDE_CAST_BF_ENUM(ECaptionSide, inherited_flags.f._caption_side); } EListStyleType listStyleType() const { return KDE_CAST_BF_ENUM(EListStyleType, inherited_flags.f._list_style_type); } CachedImage *listStyleImage() const { return inherited->style_image; } EListStylePosition listStylePosition() const { return KDE_CAST_BF_ENUM(EListStylePosition, inherited_flags.f._list_style_position); } Length marginTop() const { return surround->margin.top; } Length marginBottom() const { return surround->margin.bottom; } Length marginLeft() const { return surround->margin.left; } Length marginRight() const { return surround->margin.right; } Length paddingTop() const { return surround->padding.top; } Length paddingBottom() const { return surround->padding.bottom; } Length paddingLeft() const { return surround->padding.left; } Length paddingRight() const { return surround->padding.right; } ECursor cursor() const { return KDE_CAST_BF_ENUM(ECursor, inherited_flags.f._cursor_style); } short widows() const { return inherited->widows; } short orphans() const { return inherited->orphans; } bool pageBreakInside() const { return inherited_flags.f._page_break_inside; } EPageBreak pageBreakBefore() const { return KDE_CAST_BF_ENUM(EPageBreak, noninherited_flags.f._page_break_before); } EPageBreak pageBreakAfter() const { return KDE_CAST_BF_ENUM(EPageBreak, noninherited_flags.f._page_break_after); } DOM::QuotesValueImpl* quotes() const { return inherited->quotes; } QString openQuote(int level) const; QString closeQuote(int level) const; // CSS3 Getter Methods EBoxSizing boxSizing() const { return box->box_sizing; } int outlineOffset() const { if (background->m_outline.style == BNONE || background->m_outline.style == BHIDDEN) return 0; return background->m_outline._offset; } ShadowData* textShadow() const { return css3InheritedData->textShadow; } float opacity() const { return css3NonInheritedData->opacity; } EUserInput userInput() const { return KDE_CAST_BF_ENUM(EUserInput, inherited_flags.f._user_input); } Length marqueeIncrement() const { return css3NonInheritedData->marquee->increment; } int marqueeSpeed() const { return css3NonInheritedData->marquee->speed; } int marqueeLoopCount() const { return css3NonInheritedData->marquee->loops; } EMarqueeBehavior marqueeBehavior() const { return css3NonInheritedData->marquee->behavior; } EMarqueeDirection marqueeDirection() const { return css3NonInheritedData->marquee->direction; } bool textOverflow() const { return noninherited_flags.f._textOverflow; } // End CSS3 Getters // attribute setter methods void setDisplay(EDisplay v) { noninherited_flags.f._display = v; } void setOriginalDisplay(EDisplay v) { noninherited_flags.f._originalDisplay = v; } void setPosition(EPosition v) { noninherited_flags.f._position = v; } void setFloating(EFloat v) { noninherited_flags.f._floating = v; } void setLeft(Length v) { SET_VAR(surround,offset.left,v) } void setRight(Length v) { SET_VAR(surround,offset.right,v) } void setTop(Length v) { SET_VAR(surround,offset.top,v) } void setBottom(Length v){ SET_VAR(surround,offset.bottom,v) } void setWidth(Length v) { SET_VAR(box,width,v) } void setHeight(Length v) { SET_VAR(box,height,v) } void setMinWidth(Length v) { SET_VAR(box,min_width,v) } void setMaxWidth(Length v) { SET_VAR(box,max_width,v) } void setMinHeight(Length v) { SET_VAR(box,min_height,v) } void setMaxHeight(Length v) { SET_VAR(box,max_height,v) } void resetBorderTop() { SET_VAR(surround, border.top, BorderValue()) } void resetBorderRight() { SET_VAR(surround, border.right, BorderValue()) } void resetBorderBottom() { SET_VAR(surround, border.bottom, BorderValue()) } void resetBorderLeft() { SET_VAR(surround, border.left, BorderValue()) } void resetOutline() { SET_VAR(background, m_outline, OutlineValue()) } void setBackgroundColor(const QColor& v) { SET_VAR(background, m_color, v) } void setBorderLeftWidth(unsigned short v) { SET_VAR(surround,border.left.width,v) } void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround,border.left.style,v) } void setBorderLeftColor(const QColor & v) { SET_VAR(surround,border.left.color,v) } void setBorderRightWidth(unsigned short v) { SET_VAR(surround,border.right.width,v) } void setBorderRightStyle(EBorderStyle v) { SET_VAR(surround,border.right.style,v) } void setBorderRightColor(const QColor & v) { SET_VAR(surround,border.right.color,v) } void setBorderTopWidth(unsigned short v) { SET_VAR(surround,border.top.width,v) } void setBorderTopStyle(EBorderStyle v) { SET_VAR(surround,border.top.style,v) } void setBorderTopColor(const QColor & v) { SET_VAR(surround,border.top.color,v) } void setBorderBottomWidth(unsigned short v) { SET_VAR(surround,border.bottom.width,v) } void setBorderBottomStyle(EBorderStyle v) { SET_VAR(surround,border.bottom.style,v) } void setBorderBottomColor(const QColor & v) { SET_VAR(surround,border.bottom.color,v) } void setOutlineWidth(unsigned short v) { SET_VAR(background,m_outline.width,v) } void setOutlineStyle(EBorderStyle v, bool isAuto = false) { SET_VAR(background,m_outline.style,v) SET_VAR(background,m_outline._auto, isAuto) } void setOutlineColor(const QColor & v) { SET_VAR(background,m_outline.color,v) } void setOverflowX(EOverflow v) { noninherited_flags.f._overflowX = v; } void setOverflowY(EOverflow v) { noninherited_flags.f._overflowY = v; } void setVisibility(EVisibility v) { inherited_flags.f._visibility = v; } void setVerticalAlign(EVerticalAlign v) { noninherited_flags.f._vertical_align = v; } void setVerticalAlignLength(Length l) { SET_VAR(box, vertical_align, l ) } void setClipLeft(Length v) { SET_VAR(visual,clip.left,v) } void setClipRight(Length v) { SET_VAR(visual,clip.right,v) } void setClipTop(Length v) { SET_VAR(visual,clip.top,v) } void setClipBottom(Length v) { SET_VAR(visual,clip.bottom,v) } void setClip( Length top, Length right, Length bottom, Length left ); void setHasClip( bool b ) { noninherited_flags.f._hasClip = b; } void setUnicodeBidi( EUnicodeBidi b ) { noninherited_flags.f._unicodeBidi = b; } void setClear(EClear v) { noninherited_flags.f._clear = v; } void setTableLayout(ETableLayout v) { noninherited_flags.f._table_layout = v; } bool setFontDef(const khtml::FontDef & v) { // bah, this doesn't compare pointers. broken! (Dirk) if (!(inherited->font.fontDef == v)) { inherited.access()->font = Font( v ); return true; } return false; } void setColor(const QColor & v) { SET_VAR(inherited,color,v) } void setTextIndent(Length v) { SET_VAR(inherited,indent,v) } void setTextAlign(ETextAlign v) { inherited_flags.f._text_align = v; } void setTextTransform(ETextTransform v) { inherited_flags.f._text_transform = v; } void addToTextDecorationsInEffect(int v) { inherited_flags.f._text_decorations |= v; } void setTextDecorationsInEffect(int v) { inherited_flags.f._text_decorations = v; } void setTextDecoration(unsigned v) { SET_VAR(visual, textDecoration, v); } void setDirection(EDirection v) { inherited_flags.f._direction = v; } void setLineHeight(Length v) { SET_VAR(inherited,line_height,v) } void setWhiteSpace(EWhiteSpace v) { inherited_flags.f._white_space = v; } void setWordSpacing(int v) { SET_VAR(inherited,font.wordSpacing,v) } void setLetterSpacing(int v) { SET_VAR(inherited,font.letterSpacing,v) } void clearBackgroundLayers() { background.access()->m_background = BackgroundLayer(); } void inheritBackgroundLayers(const BackgroundLayer& parent) { background.access()->m_background = parent; } void adjustBackgroundLayers(); void setBorderCollapse(bool collapse) { inherited_flags.f._border_collapse = collapse; } void setBorderHorizontalSpacing(short v) { SET_VAR(inherited,border_hspacing,v) } void setBorderVerticalSpacing(short v) { SET_VAR(inherited,border_vspacing,v) } void setEmptyCells(EEmptyCell v) { inherited_flags.f._empty_cells = v; } void setCaptionSide(ECaptionSide v) { inherited_flags.f._caption_side = v; } void setListStyleType(EListStyleType v) { inherited_flags.f._list_style_type = v; } void setListStyleImage(CachedImage *v) { SET_VAR(inherited,style_image,v)} void setListStylePosition(EListStylePosition v) { inherited_flags.f._list_style_position = v; } void resetMargin() { SET_VAR(surround, margin, LengthBox(Fixed)) } void setMarginTop(Length v) { SET_VAR(surround,margin.top,v) } void setMarginBottom(Length v) { SET_VAR(surround,margin.bottom,v) } void setMarginLeft(Length v) { SET_VAR(surround,margin.left,v) } void setMarginRight(Length v) { SET_VAR(surround,margin.right,v) } void resetPadding() { SET_VAR(surround, padding, LengthBox(Variable)) } void setPaddingTop(Length v) { SET_VAR(surround,padding.top,v) } void setPaddingBottom(Length v) { SET_VAR(surround,padding.bottom,v) } void setPaddingLeft(Length v) { SET_VAR(surround,padding.left,v) } void setPaddingRight(Length v) { SET_VAR(surround,padding.right,v) } void setCursor( ECursor c ) { inherited_flags.f._cursor_style = c; } bool htmlHacks() const { return inherited_flags.f._htmlHacks; } void setHtmlHacks(bool b=true) { inherited_flags.f._htmlHacks = b; } bool flowAroundFloats() const { return noninherited_flags.f._flowAroundFloats; } void setFlowAroundFloats(bool b=true) { noninherited_flags.f._flowAroundFloats = b; } int zIndex() const { return box->z_auto? 0 : box->z_index; } void setZIndex(int v) { SET_VAR(box,z_auto,false ); SET_VAR(box, z_index, v); } bool hasAutoZIndex() const { return box->z_auto; } void setHasAutoZIndex() { SET_VAR(box, z_auto, true ); } void setWidows(short w) { SET_VAR(inherited, widows, w); } void setOrphans(short o) { SET_VAR(inherited, orphans, o); } void setPageBreakInside(bool b) { inherited_flags.f._page_break_inside = b; } void setPageBreakBefore(EPageBreak b) { noninherited_flags.f._page_break_before = b; } void setPageBreakAfter(EPageBreak b) { noninherited_flags.f._page_break_after = b; } void setQuotes(DOM::QuotesValueImpl* q); // CSS3 Setters void setBoxSizing( EBoxSizing b ) { SET_VAR(box,box_sizing,b); } void setOutlineOffset(unsigned short v) { SET_VAR(background,m_outline._offset,v) } void setTextShadow(ShadowData* val, bool add=false); void setOpacity(float f) { SET_VAR(css3NonInheritedData, opacity, f); } void setUserInput(EUserInput ui) { inherited_flags.f._user_input = ui; } void setMarqueeIncrement(const Length& f) { SET_VAR(css3NonInheritedData.access()->marquee, increment, f); } void setMarqueeSpeed(int f) { SET_VAR(css3NonInheritedData.access()->marquee, speed, f); } void setMarqueeDirection(EMarqueeDirection d) { SET_VAR(css3NonInheritedData.access()->marquee, direction, d); } void setMarqueeBehavior(EMarqueeBehavior b) { SET_VAR(css3NonInheritedData.access()->marquee, behavior, b); } void setMarqueeLoopCount(int i) { SET_VAR(css3NonInheritedData.access()->marquee, loops, i); } void setTextOverflow(bool b) { noninherited_flags.f._textOverflow = b; } // End CSS3 Setters QPalette palette() const { return visual->palette; } void setPaletteColor(QPalette::ColorGroup g, QPalette::ColorRole r, const QColor& c); void resetPalette() // Called when the desktop color scheme changes. { const_cast(visual.get())->palette = QApplication::palette(); } bool useNormalContent() const { return generated->content == 0; } ContentData* contentData() const { return generated->content; } bool contentDataEquivalent(const RenderStyle* otherStyle) const { return generated->contentDataEquivalent(otherStyle->generated.get()); } void addContent(DOM::DOMStringImpl* s); void addContent(CachedObject* o); void addContent(DOM::CounterImpl* c); void addContent(EQuoteContent q); void setContentNone(); void setContentNormal(); void setContentData(ContentData* content); DOM::CSSValueListImpl* counterReset() const { return generated->counter_reset; } DOM::CSSValueListImpl* counterIncrement() const { return generated->counter_increment; } void setCounterReset(DOM::CSSValueListImpl* v); void setCounterIncrement(DOM::CSSValueListImpl* v); bool hasCounterReset(const DOM::DOMString& c) const; bool hasCounterIncrement(const DOM::DOMString& c) const; short counterReset(const DOM::DOMString& c) const; short counterIncrement(const DOM::DOMString& c) const; bool inheritedNotEqual( RenderStyle *other ) const; enum Diff { Equal, NonVisible = Equal, Visible, Position, Layout, CbLayout }; Diff diff( const RenderStyle *other ) const; bool isDisplayReplacedType() { return display() == INLINE_BLOCK ||/* display() == INLINE_BOX ||*/ display() == INLINE_TABLE; } bool isDisplayInlineType() { return display() == INLINE || isDisplayReplacedType(); } bool isOriginalDisplayInlineType() { return originalDisplay() == INLINE || originalDisplay() == INLINE_BLOCK || /*originalDisplay() == INLINE_BOX ||*/ originalDisplay() == INLINE_TABLE; } bool inheritedNoninherited() const { return noninherited_flags.f._inherited_noninherited; } void setInheritedNoninherited(bool b) { noninherited_flags.f._inherited_noninherited = b; } #ifdef ENABLE_DUMP QString createDiff( const RenderStyle &parent ) const; #endif // Initial values for all the properties static bool initialBackgroundAttachment() { return true; } static EBackgroundBox initialBackgroundClip() { return BGBORDER; } static EBackgroundBox initialBackgroundOrigin() { return BGPADDING; } static EBackgroundRepeat initialBackgroundRepeat() { return REPEAT; } static LengthSize initialBackgroundSize() { return LengthSize(); } static bool initialBorderCollapse() { return false; } static EBorderStyle initialBorderStyle() { return BNONE; } static ECaptionSide initialCaptionSide() { return CAPTOP; } static EClear initialClear() { return CNONE; } static EDirection initialDirection() { return LTR; } static EDisplay initialDisplay() { return INLINE; } static EEmptyCell initialEmptyCells() { return SHOW; } static EFloat initialFloating() { return FNONE; } static EListStylePosition initialListStylePosition() { return OUTSIDE; } static EListStyleType initialListStyleType() { return LDISC; } static EOverflow initialOverflowX() { return OVISIBLE; } static EOverflow initialOverflowY() { return OVISIBLE; } static EPageBreak initialPageBreak() { return PBAUTO; } static bool initialPageBreakInside() { return true; } static EPosition initialPosition() { return STATIC; } static ETableLayout initialTableLayout() { return TAUTO; } static EUnicodeBidi initialUnicodeBidi() { return UBNormal; } static DOM::QuotesValueImpl* initialQuotes() { return 0; } static EBoxSizing initialBoxSizing() { return CONTENT_BOX; } static ETextTransform initialTextTransform() { return TTNONE; } static EVisibility initialVisibility() { return VISIBLE; } static EWhiteSpace initialWhiteSpace() { return NORMAL; } static Length initialBackgroundXPosition() { return Length(); } static Length initialBackgroundYPosition() { return Length(); } static short initialBorderHorizontalSpacing() { return 0; } static short initialBorderVerticalSpacing() { return 0; } static ECursor initialCursor() { return CURSOR_AUTO; } static QColor initialColor() { return Qt::black; } static CachedImage* initialBackgroundImage() { return 0; } static CachedImage* initialListStyleImage() { return 0; } static unsigned short initialBorderWidth() { return 3; } static int initialLetterWordSpacing() { return 0; } static Length initialSize() { return Length(); } static Length initialMinSize() { return Length(0, Fixed); } static Length initialMaxSize() { return Length(UNDEFINED, Fixed); } static Length initialOffset() { return Length(); } static Length initialMargin() { return Length(Fixed); } static Length initialPadding() { return Length(Variable); } static Length initialTextIndent() { return Length(Fixed); } static EVerticalAlign initialVerticalAlign() { return BASELINE; } static int initialWidows() { return 2; } static int initialOrphans() { return 2; } static Length initialLineHeight() { return Length(-100, Percent); } static ETextAlign initialTextAlign() { return TAAUTO; } static ETextDecoration initialTextDecoration() { return TDNONE; } static bool initialFlowAroundFloats() { return false; } static int initialOutlineOffset() { return 0; } static float initialOpacity() { return 1.0f; } static int initialMarqueeLoopCount() { return -1; } static int initialMarqueeSpeed() { return 85; } static Length initialMarqueeIncrement() { return Length(6, Fixed); } static EMarqueeBehavior initialMarqueeBehavior() { return MSCROLL; } static EMarqueeDirection initialMarqueeDirection() { return MAUTO; } static bool initialTextOverflow() { return false; } }; class RenderPageStyle { friend class CSSStyleSelector; public: enum PageType { NO_PAGE = 0, ANY_PAGE, FIRST_PAGE, LEFT_PAGES, RIGHT_PAGES }; RenderPageStyle(); ~RenderPageStyle(); PageType pageType() { return m_pageType; } RenderPageStyle* getPageStyle(PageType type); RenderPageStyle* addPageStyle(PageType type); void removePageStyle(PageType type); Length marginTop() const { return margin.top; } Length marginBottom() const { return margin.bottom; } Length marginLeft() const { return margin.left; } Length marginRight() const { return margin.right; } Length pageWidth() const { return m_pageWidth; } Length pageHeight() const { return m_pageHeight; } void setMarginTop(Length v) { margin.top = v; } void setMarginBottom(Length v) { margin.bottom = v; } void setMarginLeft(Length v) { margin.left = v; } void setMarginRight(Length v) { margin.right = v; } void setPageWidth(Length v) { m_pageWidth = v; } void setPageHeight(Length v) { m_pageHeight = v; } protected: RenderPageStyle *next; PageType m_pageType; LengthBox margin; Length m_pageWidth; Length m_pageHeight; }; } // namespace #endif