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

📄 htmlediting_impl.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    ASSERT(startNode);    ASSERT(endNode);    ASSERT(element);        NodeImpl *node = startNode;    while (1) {        NodeImpl *next = node->traverseNextNode();        if (node->childNodeCount() == 0 && node->renderer() && node->renderer()->isInline()) {            removeNode(node);            appendNode(element, node);        }        if (node == endNode)            break;        node = next;    }}void ApplyStyleCommandImpl::applyStyleIfNeeded(DOM::NodeImpl *startNode, DOM::NodeImpl *endNode){    StyleChange styleChange = computeStyleChange(Position(startNode, 0), style());    int exceptionCode = 0;        if (styleChange.cssStyle.length() > 0) {        ElementImpl *styleElement = document()->createHTMLElement("SPAN", exceptionCode);        ASSERT(exceptionCode == 0);        styleElement->setAttribute(ATTR_STYLE, styleChange.cssStyle);        styleElement->setAttribute(ATTR_CLASS, styleSpanClassString());        insertNodeBefore(styleElement, startNode);        surroundNodeRangeWithElement(startNode, endNode, styleElement);    }    if (styleChange.applyBold) {        ElementImpl *boldElement = document()->createHTMLElement("B", exceptionCode);        ASSERT(exceptionCode == 0);        insertNodeBefore(boldElement, startNode);        surroundNodeRangeWithElement(startNode, endNode, boldElement);    }    if (styleChange.applyItalic) {        ElementImpl *italicElement = document()->createHTMLElement("I", exceptionCode);        ASSERT(exceptionCode == 0);        insertNodeBefore(italicElement, startNode);        surroundNodeRangeWithElement(startNode, endNode, italicElement);    }}bool ApplyStyleCommandImpl::currentlyHasStyle(const Position &pos, const CSSProperty *property) const{    ASSERT(pos.notEmpty());    CSSStyleDeclarationImpl *decl = document()->defaultView()->getComputedStyle(pos.element(), 0);    ASSERT(decl);    CSSValueImpl *value = decl->getPropertyCSSValue(property->id());    return strcasecmp(value->cssText(), property->value()->cssText()) == 0;}ApplyStyleCommandImpl::StyleChange ApplyStyleCommandImpl::computeStyleChange(const Position &insertionPoint, CSSStyleDeclarationImpl *style){    ASSERT(insertionPoint.notEmpty());    ASSERT(style);    StyleChange styleChange;    for (QPtrListIterator<CSSProperty> it(*(style->values())); it.current(); ++it) {        CSSProperty *property = it.current();        if (!currentlyHasStyle(insertionPoint, property)) {            switch (property->id()) {                case CSS_PROP_FONT_WEIGHT:                    if (strcasecmp(property->value()->cssText(), "bold") == 0)                        styleChange.applyBold = true;                    else                        styleChange.cssStyle += property->cssText();                    break;                case CSS_PROP_FONT_STYLE: {                        DOMString cssText(property->value()->cssText());                        if (strcasecmp(cssText, "italic") == 0 || strcasecmp(cssText, "oblique") == 0)                            styleChange.applyItalic = true;                        else                            styleChange.cssStyle += property->cssText();                    }                    break;                default:                    styleChange.cssStyle += property->cssText();                    break;            }        }    }    return styleChange;}Position ApplyStyleCommandImpl::positionInsertionPoint(Position pos){    if (pos.node()->isTextNode() && (pos.offset() > 0 && pos.offset() < pos.node()->maxOffset())) {        SplitTextNodeCommand split(document(), static_cast<TextImpl *>(pos.node()), pos.offset());        split.apply();        pos = Position(split.node(), 0);    }#if 0    // EDIT FIXME: If modified to work with the internals of applying style,    // this code can work to optimize cases where a style change is taking place on    // a boundary between nodes where one of the nodes has the desired style. In other    // words, it is possible for content to be merged into existing nodes rather than adding    // additional markup.    if (currentlyHasStyle(pos))        return pos;            // try next node    if (pos.offset() >= pos.node()->caretMaxOffset()) {        NodeImpl *nextNode = pos.node()->traverseNextNode();        if (nextNode) {            Position next = Position(nextNode, 0);            if (currentlyHasStyle(next))                return next;        }    }    // try previous node    if (pos.offset() <= pos.node()->caretMinOffset()) {        NodeImpl *prevNode = pos.node()->traversePreviousNode();        if (prevNode) {            Position prev = Position(prevNode, prevNode->maxOffset());            if (currentlyHasStyle(prev))                return prev;        }    }#endif        return pos;}//------------------------------------------------------------------------------------------// DeleteCollapsibleWhitespaceCommandImplDeleteCollapsibleWhitespaceCommandImpl::DeleteCollapsibleWhitespaceCommandImpl(DocumentImpl *document)    : CompositeEditCommandImpl(document), m_charactersDeleted(0), m_hasSelectionToCollapse(false){}DeleteCollapsibleWhitespaceCommandImpl::DeleteCollapsibleWhitespaceCommandImpl(DocumentImpl *document, const Selection &selection)    : CompositeEditCommandImpl(document), m_charactersDeleted(0), m_selectionToCollapse(selection), m_hasSelectionToCollapse(true){}DeleteCollapsibleWhitespaceCommandImpl::~DeleteCollapsibleWhitespaceCommandImpl(){}int DeleteCollapsibleWhitespaceCommandImpl::commandID() const{    return DeleteCollapsibleWhitespaceCommandID;}static bool shouldDeleteUpstreamPosition(const Position &pos){    if (!pos.node()->isTextNode())        return false;            RenderObject *renderer = pos.node()->renderer();    if (!renderer)        return true;            TextImpl *textNode = static_cast<TextImpl *>(pos.node());    if (pos.offset() >= (long)textNode->length())        return false;    if (pos.isLastRenderedPositionInEditableBlock())        return false;    if (pos.isFirstRenderedPositionOnLine() || pos.isLastRenderedPositionOnLine())        return false;    RenderText *textRenderer = static_cast<RenderText *>(renderer);    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {        if (pos.offset() < box->m_start) {            return true;        }        if (pos.offset() >= box->m_start && pos.offset() < box->m_start + box->m_len)            return false;    }        return true;}Position DeleteCollapsibleWhitespaceCommandImpl::deleteWhitespace(const Position &pos){    Position upstream = pos.equivalentUpstreamPosition();    Position downstream = pos.equivalentDownstreamPosition();        bool del = shouldDeleteUpstreamPosition(upstream);    LOG(Editing, "pos:        %s [%p:%d]\n", getTagName(pos.node()->id()).string().latin1(), pos.node(), pos.offset());    if (upstream == downstream) {        LOG(Editing, "same:       %s [%p:%d]\n", getTagName(upstream.node()->id()).string().latin1(), upstream.node(), upstream.offset());    }    else {        LOG(Editing, "upstream:   %s %s [%p:%d]\n", del ? "DELETE" : "SKIP", getTagName(upstream.node()->id()).string().latin1(), upstream.node(), upstream.offset());        PositionIterator it(upstream);        for (it.next(); it.current() != downstream; it.next()) {            if (it.current().node()->isTextNode() && (long)static_cast<TextImpl *>(it.current().node())->length() == it.current().offset())                LOG(Editing, "   node:    AT END %s [%p:%d]\n", getTagName(it.current().node()->id()).string().latin1(), it.current().node(), it.current().offset());            else                LOG(Editing, "   node:    DELETE %s [%p:%d]\n", getTagName(it.current().node()->id()).string().latin1(), it.current().node(), it.current().offset());        }        LOG(Editing, "downstream: %s [%p:%d]\n", getTagName(downstream.node()->id()).string().latin1(), downstream.node(), downstream.offset());    }    if (upstream == downstream)        return upstream;            PositionIterator it(upstream);    Position deleteStart = upstream;    if (!del) {        deleteStart = it.peekNext();        if (deleteStart == downstream)            return upstream;    }        Position endingPosition = upstream;        while (it.current() != downstream) {        Position next = it.peekNext();        if (next.node() != deleteStart.node()) {            ASSERT(deleteStart.node()->isTextNode());            TextImpl *textNode = static_cast<TextImpl *>(deleteStart.node());            unsigned long count = it.current().offset() - deleteStart.offset();            if (count == textNode->length()) {                LOG(Editing, "   removeNodeAndPrune 1: [%p]\n", textNode);                if (textNode == endingPosition.node())                    endingPosition = Position(next.node(), next.node()->caretMinOffset());                removeNodeAndPrune(textNode);            }            else {                LOG(Editing, "   deleteText 1: [%p:%d:%d:%d]\n", textNode, textNode->length(), deleteStart.offset(), it.current().offset() - deleteStart.offset());                deleteText(textNode, deleteStart.offset(), count);            }            deleteStart = next;        }        else if (next == downstream) {            ASSERT(deleteStart.node() == downstream.node());            ASSERT(downstream.node()->isTextNode());            TextImpl *textNode = static_cast<TextImpl *>(deleteStart.node());            unsigned long count = downstream.offset() - deleteStart.offset();            ASSERT(count <= textNode->length());            if (count == textNode->length()) {                LOG(Editing, "   removeNodeAndPrune 2: [%p]\n", textNode);                removeNodeAndPrune(textNode);            }            else {                LOG(Editing, "   deleteText 2: [%p:%d:%d:%d]\n", textNode, textNode->length(), deleteStart.offset(), count);                deleteText(textNode, deleteStart.offset(), count);                m_charactersDeleted = count;                endingPosition = Position(downstream.node(), downstream.offset() - m_charactersDeleted);            }        }                it.setPosition(next);    }        return endingPosition;}void DeleteCollapsibleWhitespaceCommandImpl::doApply(){    // If selection has not been set to a custom selection when the command was created,    // use the current ending selection.    if (!m_hasSelectionToCollapse)        m_selectionToCollapse = endingSelection();    int state = m_selectionToCollapse.state();    if (state == Selection::CARET) {        Position endPosition = deleteWhitespace(m_selectionToCollapse.start());        setEndingSelection(endPosition);        LOG(Editing, "-----------------------------------------------------\n");    }    else if (state == Selection::RANGE) {        Position startPosition = deleteWhitespace(m_selectionToCollapse.start());        LOG(Editing, "-----------------------------------------------------\n");        Position endPosition = m_selectionToCollapse.end();        if (m_charactersDeleted > 0 && startPosition.node() == endPosition.node()) {            LOG(Editing, "adjust end position by %d\n", m_charactersDeleted);            endPosition = Position(endPosition.node(), endPosition.offset() - m_charactersDeleted);        }        endPosition = deleteWhitespace(endPosition);        setEndingSelection(Selection(startPosition, endPosition));        LOG(Editing, "=====================================================\n");    }}//------------------------------------------------------------------------------------------// DeleteSelectionCommandImplDeleteSelectionCommandImpl::DeleteSelectionCommandImpl(DocumentImpl *document)    : CompositeEditCommandImpl(document), m_hasSelectionToDelete(false){}DeleteSelectionCommandImpl::DeleteSelectionCommandImpl(DocumentImpl *document, const Selection &selection)    : CompositeEditCommandImpl(document), m_selectionToDelete(selection), m_hasSelectionToDelete(true){}DeleteSelectionCommandImpl::~DeleteSelectionCommandImpl(){}	int DeleteSelectionCommandImpl::commandID() const{    return DeleteSelectionCommandID;}void DeleteSelectionCommandImpl::joinTextNodesWithSameStyle(){    Selection selection = endingSelection();    if (selection.state() != Selection::CARET)        return;    Position pos(selection.start());        if (!pos.node()->isTextNode())        return;    TextImpl *textNode = static_cast<TextImpl *>(pos.node());        if (pos.offset() == 0) {        PositionIterator it(pos);        Position prev = it.previous();        if (prev == pos)            return;        if (prev.node()->isTextNode()) {            TextImpl *prevTextNode = static_cast<TextImpl *>(prev.node());            if (textNodesAreJoinable(prevTextNode, textNode)) {                joinTextNodes(prevTextNode, textNode);                setEndingSelection(Position(textNode, prevTextNode->length()));                LOG(Editing, "joinTextNodesWithSameStyle [1]\n");            }        }    }    else if (pos.offset() == (long)textNode->length()) {        PositionIterator it(pos);        Position next = it.next();        if (next == pos)            return;        if (next.node()->isTextNode()) {            TextImpl *nextTextNode = static_cast<TextImpl *>(next.node());            if (textNodesAreJoinable(textNode, nextTextNode)) {                joinTextNodes(textNode, nextTextNode);                setEndingSelection(Position(nextTextNode, pos.offset()));                LOG(Editing, "joinTextNodesWithSameStyle [2]\n");            }        }    }}bool DeleteSelectionCommandImpl::containsOnlyWhitespace(const Position &start, const Position &end){    // Returns whether the range contains only whitespace characters.    // This is inclusive of the start, but not of the end.    PositionIterator it(start);    while (!it.atEnd()) {        if (!it.current().node()->isTextNode())            return false;        const DOMString &text = static_cast<TextImpl *>(it.current().node())->data();        // EDIT FIXME: signed/unsigned mismatch        if (text.length() > INT_MAX)            return false;        if (it.current().offset() < (int)text.length() && !isWS(text[it.current().offset()]))            return false;        it.next();        if (it.current() == end)            break;    }    return true;}void DeleteSelectionCommandImpl::doApply(){    // If selection has not been set to a custom selection when the command was created,    // use the current ending selection.    if (!m_hasSelectionToDelete)        m_selectionToDelete = endingSelection();            if (m_selectionToDelete.state() != Selection::RANGE)        return;    deleteCollapsibleWhitespace(m_selectionToDelete);    Selection selection = endingSelection();    Position upstreamStart(selection.start().equivalentUpstreamPosition());

⌨️ 快捷键说明

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