⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmltableelement.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
字号:
/** * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.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. * */#include "config.h"#if ENABLE(WML)#include "WMLTableElement.h"#include "CharacterNames.h"#include "CSSPropertyNames.h"#include "CSSValueKeywords.h"#include "Document.h"#include "HTMLNames.h"#include "NodeList.h"#include "RenderObject.h"#include "Text.h"#include "WMLErrorHandling.h"#include "WMLNames.h"namespace WebCore {using namespace WMLNames;WMLTableElement::WMLTableElement(const QualifiedName& tagName, Document* doc)    : WMLElement(tagName, doc)    , m_columns(0){}WMLTableElement::~WMLTableElement(){}bool WMLTableElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const{    if (attrName == HTMLNames::alignAttr) {        result = eTable;        return false;    }    return WMLElement::mapToEntry(attrName, result);}void WMLTableElement::parseMappedAttribute(MappedAttribute* attr){    if (attr->name() == columnsAttr) {        bool isNumber = false;        m_columns = attr->value().string().toUIntStrict(&isNumber);        // Spec: This required attribute specifies the number of columns for the table.        // The user agent must create a table with exactly the number of columns specified        // by the attribute value. It is an error to specify a value of zero ("0")        if (!m_columns || !isNumber)            reportWMLError(document(), WMLErrorInvalidColumnsNumberInTable);    } else if (attr->name() == HTMLNames::alignAttr)        m_alignment = parseValueForbiddingVariableReferences(attr->value());    else        WMLElement::parseMappedAttribute(attr);}void WMLTableElement::finishParsingChildren(){    WMLElement::finishParsingChildren();    if (!m_columns) {        reportWMLError(document(), WMLErrorInvalidColumnsNumberInTable);        return;    }    Vector<WMLElement*> rowElements = scanTableChildElements(this, trTag);    if (rowElements.isEmpty())        return;    Vector<WMLElement*>::iterator it = rowElements.begin();    Vector<WMLElement*>::iterator end = rowElements.end();    for (; it != end; ++it) {        WMLElement* rowElement = (*it);        // Squeeze the table to fit in the desired number of columns        Vector<WMLElement*> columnElements = scanTableChildElements(rowElement, tdTag);        unsigned actualNumberOfColumns = columnElements.size();        if (actualNumberOfColumns > m_columns) {            joinSuperflousColumns(columnElements, rowElement);            columnElements = scanTableChildElements(rowElement, tdTag);        } else if (actualNumberOfColumns < m_columns) {            padWithEmptyColumns(columnElements, rowElement);            columnElements = scanTableChildElements(rowElement, tdTag);        }        // Layout cells according to the 'align' attribute        alignCells(columnElements, rowElement);    }}Vector<WMLElement*> WMLTableElement::scanTableChildElements(WMLElement* startElement, const QualifiedName& tagName) const{    Vector<WMLElement*> childElements;    RefPtr<NodeList> children = startElement->childNodes();    if (!children)        return childElements;    unsigned length = children->length();    for (unsigned i = 0; i < length; ++i) {        Node* child = children->item(i);        if (child->hasTagName(tagName))            childElements.append(static_cast<WMLElement*>(child));    }    return childElements;}void WMLTableElement::transferAllChildrenOfElementToTargetElement(WMLElement* sourceElement, WMLElement* targetElement, unsigned startOffset) const{    RefPtr<NodeList> children = sourceElement->childNodes();    if (!children)        return;    ExceptionCode ec = 0;    unsigned length = children->length();    for (unsigned i = startOffset; i < length; ++i) {        RefPtr<Node> clonedNode = children->item(i)->cloneNode(true);        targetElement->appendChild(clonedNode.release(), ec);        ASSERT(ec == 0);    }}bool WMLTableElement::tryMergeAdjacentTextCells(Node* item, Node* nextItem) const{    if (!item || !nextItem)        return false;    if (!item->isTextNode() || !nextItem->isTextNode())        return false;    Text* itemText = static_cast<Text*>(item);    Text* nextItemText = static_cast<Text*>(nextItem);    String newContent = " ";    newContent += nextItemText->data();    ExceptionCode ec = 0;    itemText->appendData(newContent, ec);    ASSERT(ec == 0);    return true;}void WMLTableElement::joinSuperflousColumns(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const{    // Spec: If the actual number of columns in a row is greater than the value specified    // by this attribute, the extra columns of the row must be aggregated into the last    // column such that the row contains exactly the number of columns specified.    WMLElement* lastColumn = columnElements.at(m_columns - 1);    ASSERT(lastColumn);    // Merge superflous columns into a single one    RefPtr<WMLElement> newCell = new WMLElement(tdTag, document());    transferAllChildrenOfElementToTargetElement(lastColumn, newCell.get(), 0);    ExceptionCode ec = 0;    unsigned actualNumberOfColumns = columnElements.size();    for (unsigned i = m_columns; i < actualNumberOfColumns; ++i) {        WMLElement* columnElement = columnElements.at(i);        unsigned startOffset = 0;        // Spec: A single inter-word space must be inserted between two cells that are being aggregated.        if (tryMergeAdjacentTextCells(newCell->lastChild(), columnElement->firstChild()))            ++startOffset;        transferAllChildrenOfElementToTargetElement(columnElement, newCell.get(), startOffset);    }    // Remove the columns, that have just been merged    unsigned i = actualNumberOfColumns;    for (; i > m_columns; --i) {        rowElement->removeChild(columnElements.at(i - 1), ec);        ASSERT(ec == 0);    }    // Replace the last column in the row with the new merged column    rowElement->replaceChild(newCell.release(), lastColumn, ec);    ASSERT(ec == 0);}void WMLTableElement::padWithEmptyColumns(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const{    // Spec: If the actual number of columns in a row is less than the value specified by the columns     // attribute, the row must be padded with empty columns effectively as if the user agent     // appended empty td elements to the row.     ExceptionCode ec = 0;    for (unsigned i = columnElements.size(); i < m_columns; ++i) {        RefPtr<WMLElement> newCell = new WMLElement(tdTag, document());        rowElement->appendChild(newCell.release(), ec);        ASSERT(ec == 0);    }}void WMLTableElement::alignCells(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const{    // Spec: User agents should consider the current language when determining    // the default alignment and the direction of the table.    bool rtl = false;    if (RenderObject* renderer = rowElement->renderer()) {        if (RenderStyle* style = renderer->style())            rtl = style->direction() == RTL;    }    rowElement->setAttribute(HTMLNames::alignAttr, rtl ? "right" : "left");    if (m_alignment.isEmpty())        return;    unsigned alignLength = m_alignment.length();    Vector<WMLElement*>::iterator it = columnElements.begin();    Vector<WMLElement*>::iterator end = columnElements.end();    for (unsigned i = 0; it != end; ++it, ++i) {        if (i == alignLength)            break;        String alignmentValue;        switch (m_alignment[i]) {        case 'C':            alignmentValue = "center";            break;        case 'L':            alignmentValue = "left";            break;        case 'R':            alignmentValue = "right";            break;        default:            break;        }        if (alignmentValue.isEmpty())            continue;        (*it)->setAttribute(HTMLNames::alignAttr, alignmentValue);    }}}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -