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

📄 htmlediting.cpp

📁 最新Nokia手机浏览器全套源代码完美版。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    }

    // Get the adjustment amount out of the style.
    CSSValueImpl *value = style->getPropertyCSSValue(CSS_PROP__KHTML_FONT_SIZE_DELTA);
    if (!value)
        return;
    value->ref();
    float adjustment = NoFontDelta;
    if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {
        CSSPrimitiveValueImpl *primitiveValue = static_cast<CSSPrimitiveValueImpl *>(value);
        if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_PX) {
            // Only PX handled now. If we handle more types in the future, perhaps
            // a switch statement here would be more appropriate.
            adjustment = primitiveValue->getFloatValue(CSSPrimitiveValue::CSS_PX);
        }
    }
    style->removeProperty(CSS_PROP__KHTML_FONT_SIZE_DELTA);
    value->deref();
    if (adjustment == NoFontDelta)
        return;

    // Adjust to the positions we want to use for applying style.
    Selection selection = endingSelection();
    Position start(selection.start().downstream(StayInBlock));
    Position end(selection.end().upstream(StayInBlock));
    if (RangeImpl::compareBoundaryPoints(end, start) < 0) {
        Position swap = start;
        start = end;
        end = swap;
    }

    // Join up any adjacent text nodes.
    if (start.node()->isTextNode()) {
        joinChildTextNodes(start.node()->parentNode(), start, end);
        selection = endingSelection();
        start = selection.start();
        end = selection.end();
    }
    if (end.node()->isTextNode() && start.node()->parentNode() != end.node()->parentNode()) {
        joinChildTextNodes(end.node()->parentNode(), start, end);
        selection = endingSelection();
        start = selection.start();
        end = selection.end();
    }

    // Split the start text nodes if needed to apply style.
    bool splitStart = splitTextAtStartIfNeeded(start, end);
    if (splitStart) {
        start = endingSelection().start();
        end = endingSelection().end();
    }
    bool splitEnd = splitTextAtEndIfNeeded(start, end);
    if (splitEnd) {
        start = endingSelection().start();
        end = endingSelection().end();
    }

    NodeImpl *beyondEnd = end.node()->traverseNextNode(); // Calculate loop end point.
    start = start.upstream(StayInBlock); // Move upstream to ensure we do not add redundant spans.
    NodeImpl *startNode = start.node();
    if (startNode->isTextNode() && start.offset() >= startNode->caretMaxOffset()) // Move out of text node if range does not include its characters.
        startNode = startNode->traverseNextNode();

    // Store away font size before making any changes to the document.
    // This ensures that changes to one node won't effect another.
    QMap<const NodeImpl *,float> startingFontSizes;
    for (const NodeImpl *node = startNode; node != beyondEnd; node = node->traverseNextNode())
        startingFontSizes.insert(node, computedFontSize(node));

    // These spans were added by us. If empty after font size changes, they can be removed.
    QPtrList<NodeImpl> emptySpans;

    NodeImpl *lastStyledNode = 0;
    for (NodeImpl *node = startNode; node != beyondEnd; node = node->traverseNextNode()) {
        HTMLElementImpl *elem = 0;
        if (node->isHTMLElement()) {
            // Only work on fully selected nodes.
            if (!nodeFullySelected(node, start, end))
                continue;
            elem = static_cast<HTMLElementImpl *>(node);
        }
        else if (node->isTextNode() && node->parentNode() != lastStyledNode) {
            // Last styled node was not parent node of this text node, but we wish to style this
            // text node. To make this possible, add a style span to surround this text node.
            elem = static_cast<HTMLElementImpl *>(createStyleSpanElement(document()));
            insertNodeBefore(elem, node);
            surroundNodeRangeWithElement(node, node, elem);
        }
        else {
            // Only handle HTML elements and text nodes.
            continue;
        }
        lastStyledNode = node;

        CSSMutableStyleDeclarationImpl *inlineStyleDecl = elem->getInlineStyleDecl();
        float currentFontSize = computedFontSize(node);
        float desiredFontSize = kMax(MinimumFontSize, startingFontSizes[node] + adjustment);
        if (inlineStyleDecl->getPropertyCSSValue(CSS_PROP_FONT_SIZE)) {
            inlineStyleDecl->removeProperty(CSS_PROP_FONT_SIZE, true);
            currentFontSize = computedFontSize(node);
        }
        if (currentFontSize != desiredFontSize) {
            QString desiredFontSizeString = QString::number(desiredFontSize);
            desiredFontSizeString += "px";
            inlineStyleDecl->setProperty(CSS_PROP_FONT_SIZE, desiredFontSizeString, false, false);
            setNodeAttribute(elem, ATTR_STYLE, inlineStyleDecl->cssText());
        }
        if (inlineStyleDecl->length() == 0) {
            removeNodeAttribute(elem, ATTR_STYLE);
            if (isEmptyStyleSpan(elem))
                emptySpans.append(elem);
        }
    }

    for (QPtrListIterator<NodeImpl> it(emptySpans); it.current(); ++it)
        removeNodePreservingChildren(it.current());
}

#undef NoFontDelta
#undef MinimumFontSize

void ApplyStyleCommand::applyInlineStyle(CSSMutableStyleDeclarationImpl *style)
{
    // adjust to the positions we want to use for applying style
    Position start(endingSelection().start().downstream(StayInBlock).equivalentRangeCompliantPosition());
    Position end(endingSelection().end().upstream(StayInBlock));

    if (RangeImpl::compareBoundaryPoints(end, start) < 0) {
        Position swap = start;
        start = end;
        end = swap;
    }

    // update document layout once before removing styles
    // so that we avoid the expense of updating before each and every call
    // to check a computed style
    document()->updateLayout();

    // split the start node and containing element if the selection starts inside of it
    bool splitStart = splitTextElementAtStartIfNeeded(start, end);
    if (splitStart) {
        start = endingSelection().start();
        end = endingSelection().end();
    }

    // split the end node and containing element if the selection ends inside of it
    bool splitEnd = splitTextElementAtEndIfNeeded(start, end);
    start = endingSelection().start();
    end = endingSelection().end();

    // Remove style from the selection.
    // Use the upstream position of the start for removing style.
    // This will ensure we remove all traces of the relevant styles from the selection
    // and prevent us from adding redundant ones, as described in:
    // <rdar://problem/3724344> Bolding and unbolding creates extraneous tags
    removeInlineStyle(style, start.upstream(StayInBlock), end);
    start = endingSelection().start();
    end = endingSelection().end();

    if (splitStart) {
        bool mergedStart = mergeStartWithPreviousIfIdentical(start, end);
        if (mergedStart) {
            start = endingSelection().start();
            end = endingSelection().end();
        }
    }

    if (splitEnd) {
        mergeEndWithNextIfIdentical(start, end);
        start = endingSelection().start();
        end = endingSelection().end();
    }

    // update document layout once before running the rest of the function
    // so that we avoid the expense of updating before each and every call
    // to check a computed style
    document()->updateLayout();

    if (start.node() == end.node()) {
        // simple case...start and end are the same node
        addInlineStyleIfNeeded(style, start.node(), end.node());
    }
    else {
        NodeImpl *node = start.node();
        if (start.offset() >= start.node()->caretMaxOffset())
            node = node->traverseNextNode();
        while (1) {
            if (node->childNodeCount() == 0 && node->renderer() && node->renderer()->isInline()) {
                NodeImpl *runStart = node;
                while (1) {
                    NodeImpl *next = node->traverseNextNode();
                    // Break if node is the end node, or if the next node does not fit in with
                    // the current group.
                    if (node == end.node() ||
                        runStart->parentNode() != next->parentNode() ||
                        (next->isHTMLElement() && next->id() != ID_BR) ||
                        (next->renderer() && !next->renderer()->isInline()))
                        break;
                    node = next;
                }
                // Now apply style to the run we found.
                addInlineStyleIfNeeded(style, runStart, node);
            }
            if (node == end.node())
                break;
            node = node->traverseNextNode();
        }
    }

    if (splitStart || splitEnd) {
        cleanUpEmptyStyleSpans(start, end);
    }
}

//------------------------------------------------------------------------------------------
// ApplyStyleCommand: style-removal helpers

bool ApplyStyleCommand::isHTMLStyleNode(CSSMutableStyleDeclarationImpl *style, HTMLElementImpl *elem)
{
    QValueListConstIterator<CSSProperty> end;
    for (QValueListConstIterator<CSSProperty> it = style->valuesIterator(); it != end; ++it) {
        switch ((*it).id()) {
            case CSS_PROP_FONT_WEIGHT:
                if (elem->id() == ID_B)
                    return true;
                break;
            case CSS_PROP_FONT_STYLE:
                if (elem->id() == ID_I)
                    return true;
        }
    }

    return false;
}

void ApplyStyleCommand::removeHTMLStyleNode(HTMLElementImpl *elem)
{
    // This node can be removed.
    // EDIT FIXME: This does not handle the case where the node
    // has attributes. But how often do people add attributes to <B> tags?
    // Not so often I think.
    ASSERT(elem);
    removeNodePreservingChildren(elem);
}

void ApplyStyleCommand::removeHTMLFontStyle(CSSMutableStyleDeclarationImpl *style, HTMLElementImpl *elem)
{
    ASSERT(style);
    ASSERT(elem);

    if (elem->id() != ID_FONT)
        return;

    int exceptionCode = 0;
    QValueListConstIterator<CSSProperty> end;
    for (QValueListConstIterator<CSSProperty> it = style->valuesIterator(); it != end; ++it) {
        switch ((*it).id()) {
            case CSS_PROP_COLOR:
                elem->removeAttribute(ATTR_COLOR, exceptionCode);
                ASSERT(exceptionCode == 0);
                break;
            case CSS_PROP_FONT_FAMILY:
                elem->removeAttribute(ATTR_FACE, exceptionCode);
                ASSERT(exceptionCode == 0);
                break;
            case CSS_PROP_FONT_SIZE:
                elem->removeAttribute(ATTR_SIZE, exceptionCode);
                ASSERT(exceptionCode == 0);
                break;
        }
    }

    if (isEmptyFontTag(elem))
        removeNodePreservingChildren(elem);
}

void ApplyStyleCommand::removeCSSStyle(CSSMutableStyleDeclarationImpl *style, HTMLElementImpl *elem)
{
    ASSERT(style);
    ASSERT(elem);

    CSSMutableStyleDeclarationImpl *decl = elem->inlineStyleDecl();
    if (!decl)
        return;

    QValueListConstIterator<CSSProperty> end;
    for (QValueListConstIterator<CSSProperty> it = style->valuesIterator(); it != end; ++it) {
        int propertyID = (*it).id();
        CSSValueImpl *value = decl->getPropertyCSSValue(propertyID);
        if (value) {
            if (propertyID == CSS_PROP_WHITE_SPACE && isTabSpanNode(elem))
                continue;
            value->ref();
            removeCSSProperty(decl, propertyID);
            value->deref();
        }
    }

    if (isEmptyStyleSpan(elem))
        removeNodePreservingChildren(elem);
}

void ApplyStyleCommand::removeBlockStyle(CSSMutableStyleDeclarationImpl *style, const Position &start, const Position &end)
{
    ASSERT(start.isNotNull());
    ASSERT(end.isNotNull());
    ASSERT(start.node()->inDocument());
    ASSERT(end.node()->inDocument());
    ASSERT(RangeImpl::compareBoundaryPoints(start, end) <= 0);

}

static bool hasTextDecorationProperty(NodeImpl *node)
{
    if (!node->isElementNode())
        return false;

    ElementImpl *element = static_cast<ElementImpl *>(node);
    CSSComputedStyleDeclarationImpl style(element);

    CSSValueImpl *value = style.getPropertyCSSValue(CSS_PROP_TEXT_DECORATION, DoNotUpdateLayout);

    if (value) {
        value->ref();
        DOMString valueText(value->cssText());
        value->deref();
        if (strcasecmp(valueText,"none") != 0)
            return true;
    }

    return false;
}

static NodeImpl* highestAncestorWithTextDecoration(NodeImpl *node)
{
    NodeImpl *result = NULL;

    for (NodeImpl *n = node; n; n = n->parentNode()) {
        if (hasTextDecorationProperty(n))
            result = n;
    }

    return result;
}

CSSMutableStyleDeclarationImpl *ApplyStyleCommand::extractTextDecorationStyle(NodeImpl *node)
{
    ASSERT(node);
    ASSERT(node->isElementNode());

    // non-html elements not handled yet
    if (!node->isHTMLElement())
        return 0;

    HTMLElementImpl *element = static_cast<HTMLElementImpl *>(node);
    CSSMutableStyleDeclarationImpl *style = element->inlineStyleDecl();
    if (!style)
        return 0;

    style->ref();
    int properties[1] = { CSS_PROP_TEXT_DECORATION };
    CSSMutableStyleDeclarationImpl *textDecorationStyle = style->copyPropertiesInSet(properties, 1);

    CSSValueImpl *property = style->getPropertyCSSValue(CSS_PROP_TEXT_DECORATION);
    if (property && strcasecmp(property->cssText(), "none") != 0) {
        removeCSSProperty(style, CSS_PROP_TEXT_DECORATION);
    }

    style->deref();

    return textDecorationStyle;
}

CSSMutableStyleDeclarationImpl *ApplyStyleCommand::extractAndNegateTextDecorationStyle(NodeImpl *node)
{
    ASSERT(node);
    ASSERT(node->isElementNode());

    // non-html elements not handled yet
    if (!node->isHTMLElement())
        return 0;

    HTMLElementImpl *element = static_cast<HTMLElementImpl *>(node);
    CSSComputedStyleDeclarationImpl *computedStyle = new CSSComputedStyleDeclarationImpl(element);
    ASSERT(computedStyle);

    computedStyle->ref();

    int properties[1] = { CSS_PROP_TEXT_DECORATION };
    CSSMutableStyleDeclarationImpl *textDecorationStyle = computedStyle->copyPropertiesInSet(properties, 1);


    CSSValueImpl *property = computedStyle->getPropertyCSSValue(CSS_PROP_TEXT_DECORATION);
    if (property && strcasecmp(property->cssText(), "none") != 0) {
        property->ref();
        CSSMutableStyleDeclarationImpl *newStyle = textDecorationStyle->copy();

     

⌨️ 快捷键说明

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