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

📄 htmlediting_impl.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    Position downstreamStart(selection.start().equivalentDownstreamPosition());    Position upstreamEnd(selection.end().equivalentUpstreamPosition());    Position downstreamEnd(selection.end().equivalentDownstreamPosition());    if (upstreamStart == downstreamEnd)        // after collapsing whitespace, selection is empty...no work to do        return;    Position endingPosition;    bool adjustEndingPositionDownstream = false;    bool onlyWhitespace = containsOnlyWhitespace(upstreamStart, downstreamEnd);     bool startCompletelySelected = !onlyWhitespace &&        (downstreamStart.offset() <= downstreamStart.node()->caretMinOffset() &&        ((downstreamStart.node() != upstreamEnd.node()) ||         (upstreamEnd.offset() >= upstreamEnd.node()->caretMaxOffset())));    bool endCompletelySelected = !onlyWhitespace &&        (upstreamEnd.offset() >= upstreamEnd.node()->caretMaxOffset() &&        ((downstreamStart.node() != upstreamEnd.node()) ||         (downstreamStart.offset() <= downstreamStart.node()->caretMinOffset())));    unsigned long startRenderedOffset = downstreamStart.renderedOffset();        bool startAtStartOfRootEditableElement = startRenderedOffset == 0 && downstreamStart.inFirstEditableInRootEditableElement();    bool startAtStartOfBlock = startAtStartOfRootEditableElement ||         (startRenderedOffset == 0 && downstreamStart.inFirstEditableInContainingEditableBlock());    bool endAtEndOfBlock = downstreamEnd.isLastRenderedPositionInEditableBlock();    NodeImpl *startBlock = upstreamStart.node()->enclosingBlockFlowElement();    NodeImpl *endBlock = downstreamEnd.node()->enclosingBlockFlowElement();    bool startBlockEndBlockAreSiblings = startBlock->parentNode() == endBlock->parentNode();    debugPosition("upstreamStart:       ", upstreamStart);    debugPosition("downstreamStart:     ", downstreamStart);    debugPosition("upstreamEnd:         ", upstreamEnd);    debugPosition("downstreamEnd:       ", downstreamEnd);    LOG(Editing,  "start selected:      %s", startCompletelySelected ? "YES" : "NO");    LOG(Editing,  "at start block:      %s", startAtStartOfBlock ? "YES" : "NO");    LOG(Editing,  "at start root block: %s", startAtStartOfRootEditableElement ? "YES" : "NO");    LOG(Editing,  "at end block:        %s", endAtEndOfBlock ? "YES" : "NO");    LOG(Editing,  "only whitespace:     %s", onlyWhitespace ? "YES" : "NO");    // Determine where to put the caret after the deletion    if (startAtStartOfBlock) {        LOG(Editing,  "ending position case 1");        endingPosition = Position(startBlock, 0);        adjustEndingPositionDownstream = true;    }    else if (!startCompletelySelected) {        LOG(Editing,  "ending position case 2");        endingPosition = upstreamStart;        if (upstreamStart.node()->id() == ID_BR && upstreamStart.offset() == 1)            adjustEndingPositionDownstream = true;    }    else if (upstreamStart != downstreamStart) {        LOG(Editing,  "ending position case 3");        endingPosition = upstreamStart;        if (upstreamStart.node()->id() == ID_BR && upstreamStart.offset() == 1)            adjustEndingPositionDownstream = true;    }       //    // Figure out the whitespace conversions to do    //    if ((startAtStartOfBlock && !endAtEndOfBlock) || (!startCompletelySelected && adjustEndingPositionDownstream)) {        // convert trailing whitespace        Position trailing = trailingWhitespacePosition(downstreamEnd.equivalentDownstreamPosition());        if (trailing.notEmpty()) {            debugPosition("convertTrailingWhitespace: ", trailing);            Position collapse = trailing.nextCharacterPosition();            if (collapse != trailing)                deleteCollapsibleWhitespace(collapse);            TextImpl *textNode = static_cast<TextImpl *>(trailing.node());            replaceText(textNode, trailing.offset(), 1, nonBreakingSpaceString());        }    }    else if (!startAtStartOfBlock && endAtEndOfBlock) {        // convert leading whitespace        Position leading = leadingWhitespacePosition(upstreamStart.equivalentUpstreamPosition());        if (leading.notEmpty()) {            debugPosition("convertLeadingWhitespace:  ", leading);            TextImpl *textNode = static_cast<TextImpl *>(leading.node());            replaceText(textNode, leading.offset(), 1, nonBreakingSpaceString());        }    }    else if (!startAtStartOfBlock && !endAtEndOfBlock) {        // convert contiguous whitespace        Position leading = leadingWhitespacePosition(upstreamStart.equivalentUpstreamPosition());        Position trailing = trailingWhitespacePosition(downstreamEnd.equivalentDownstreamPosition());        if (leading.notEmpty() && trailing.notEmpty()) {            debugPosition("convertLeadingWhitespace [contiguous]:  ", leading);            TextImpl *textNode = static_cast<TextImpl *>(leading.node());            replaceText(textNode, leading.offset(), 1, nonBreakingSpaceString());        }    }            //    // Do the delete    //    NodeImpl *n = downstreamStart.node()->traverseNextNode();    // work on start node    if (startCompletelySelected) {        LOG(Editing,  "start node delete case 1");        removeNodeAndPrune(downstreamStart.node(), startBlock);    }    else if (onlyWhitespace) {        // Selection only contains whitespace. This is really a special-case to         // handle significant whitespace that is collapsed at the end of a line,        // but also handles deleting a space in mid-line.        LOG(Editing,  "start node delete case 2");        ASSERT(upstreamStart.node()->isTextNode());        TextImpl *text = static_cast<TextImpl *>(upstreamStart.node());        int offset = upstreamStart.offset();        // EDIT FIXME: Signed/unsigned mismatch        int length = text->length();        if (length == upstreamStart.offset())            offset--;        deleteText(text, offset, 1);    }    else if (downstreamStart.node()->isTextNode()) {        LOG(Editing,  "start node delete case 3");        TextImpl *text = static_cast<TextImpl *>(downstreamStart.node());        int endOffset = text == upstreamEnd.node() ? upstreamEnd.offset() : text->length();        if (endOffset > downstreamStart.offset()) {            deleteText(text, downstreamStart.offset(), endOffset - downstreamStart.offset());        }    }    else {        // we have clipped the end of a non-text element        // the offset must be 1 here. if it is, do nothing and move on.        LOG(Editing,  "start node delete case 4");        ASSERT(downstreamStart.offset() == 1);    }    if (!onlyWhitespace && downstreamStart.node() != upstreamEnd.node()) {        // work on intermediate nodes        while (n != upstreamEnd.node()) {            NodeImpl *d = n;            n = n->traverseNextNode();            if (d->renderer() && d->renderer()->isEditable())                removeNodeAndPrune(d, startBlock);        }                // work on end node        ASSERT(n == upstreamEnd.node());        if (endCompletelySelected) {            removeNodeAndPrune(upstreamEnd.node(), startBlock);        }        else if (upstreamEnd.node()->isTextNode()) {            if (upstreamEnd.offset() > 0) {                TextImpl *text = static_cast<TextImpl *>(upstreamEnd.node());                deleteText(text, 0, upstreamEnd.offset());            }        }        else {            // we have clipped the beginning of a non-text element            // the offset must be 0 here. if it is, do nothing and move on.            ASSERT(downstreamStart.offset() == 0);        }    }    // Do block merge if start and end of selection are in different blocks    // and the blocks are siblings. This is a first cut at this rule arrived    // at by doing a bunch of edits and settling on the behavior that made    // the most sense. This could change in the future as we get more    // experience with how this should behave.    if (startBlock != endBlock && startBlockEndBlockAreSiblings) {        LOG(Editing,  "merging content to start block");        NodeImpl *node = endBlock->firstChild();        while (node) {            NodeImpl *moveNode = node;            node = node->nextSibling();            removeNode(moveNode);            appendNode(startBlock, moveNode);        }    }    if (adjustEndingPositionDownstream) {        LOG(Editing,  "adjust ending position downstream");        endingPosition = endingPosition.equivalentDownstreamPosition();    }    debugPosition("ending position:     ", endingPosition);    setEndingSelection(endingPosition);    LOG(Editing, "-----------------------------------------------------\n");}//------------------------------------------------------------------------------------------// DeleteTextCommandImplDeleteTextCommandImpl::DeleteTextCommandImpl(DocumentImpl *document, TextImpl *node, long offset, long count)    : EditCommandImpl(document), m_node(node), m_offset(offset), m_count(count){    ASSERT(m_node);    ASSERT(m_offset >= 0);    ASSERT(m_count >= 0);        m_node->ref();}DeleteTextCommandImpl::~DeleteTextCommandImpl(){    if (m_node)        m_node->deref();}int DeleteTextCommandImpl::commandID() const{    return DeleteTextCommandID;}void DeleteTextCommandImpl::doApply(){    ASSERT(m_node);    int exceptionCode = 0;    m_text = m_node->substringData(m_offset, m_count, exceptionCode);    ASSERT(exceptionCode == 0);        m_node->deleteData(m_offset, m_count, exceptionCode);    ASSERT(exceptionCode == 0);}void DeleteTextCommandImpl::doUnapply(){    ASSERT(m_node);    ASSERT(!m_text.isEmpty());    int exceptionCode = 0;    m_node->insertData(m_offset, m_text, exceptionCode);    ASSERT(exceptionCode == 0);}//------------------------------------------------------------------------------------------// InputNewlineCommandImplInputNewlineCommandImpl::InputNewlineCommandImpl(DocumentImpl *document)     : CompositeEditCommandImpl(document){}InputNewlineCommandImpl::~InputNewlineCommandImpl() {}int InputNewlineCommandImpl::commandID() const{    return InputNewlineCommandID;}void InputNewlineCommandImpl::insertNodeAfterPosition(NodeImpl *node, const Position &pos){    // Insert the BR after the caret position. In the case the    // position is a block, do an append. We don't want to insert    // the BR *after* the block.    Position upstream(pos.equivalentUpstreamPosition());    NodeImpl *cb = pos.node()->enclosingBlockFlowElement();    if (cb == pos.node())        appendNode(cb, node);    else        insertNodeAfter(node, pos.node());}void InputNewlineCommandImpl::insertNodeBeforePosition(NodeImpl *node, const Position &pos){    // Insert the BR after the caret position. In the case the    // position is a block, do an append. We don't want to insert    // the BR *before* the block.    Position upstream(pos.equivalentUpstreamPosition());    NodeImpl *cb = pos.node()->enclosingBlockFlowElement();    if (cb == pos.node())        appendNode(cb, node);    else        insertNodeBefore(node, pos.node());}void InputNewlineCommandImpl::doApply(){    deleteSelection();    Selection selection = endingSelection();    int exceptionCode = 0;    ElementImpl *breakNode = document()->createHTMLElement("BR", exceptionCode);    ASSERT(exceptionCode == 0);    NodeImpl *nodeToInsert = breakNode;        // Handle the case where there is a typing style.    if (document()->part()->typingStyle()) {        int exceptionCode = 0;        ElementImpl *styleElement = createTypingStyleElement();        styleElement->appendChild(breakNode, exceptionCode);        ASSERT(exceptionCode == 0);        nodeToInsert = styleElement;    }        Position pos(selection.start().equivalentDownstreamPosition());    bool atStart = pos.offset() <= pos.node()->caretMinOffset();    bool atEndOfBlock = pos.isLastRenderedPositionInEditableBlock();        if (atEndOfBlock) {        LOG(Editing, "input newline case 1");        // Insert an "extra" BR at the end of the block. This makes the "real" BR we want        // to insert appear in the rendering without any significant side effects (and no        // real worries either since you can't arrow past this extra one.        insertNodeAfterPosition(nodeToInsert, pos);        exceptionCode = 0;        ElementImpl *extraBreakNode = document()->createHTMLElement("BR", exceptionCode);        ASSERT(exceptionCode == 0);        insertNodeAfter(extraBreakNode, nodeToInsert);        setEndingSelection(Position(extraBreakNode, 0));    }    else if (atStart) {        LOG(Editing, "input newline case 2");        // Insert node, but place the caret into index 0 of the downstream        // position. This will make the caret appear after the break, and as we know        // there is content at that location, this is OK.        insertNodeBeforePosition(nodeToInsert, pos);        setEndingSelection(Position(pos.node(), 0));    }    else {        // Split a text node        LOG(Editing, "input newline case 3");        ASSERT(pos.node()->isTextNode());        TextImpl *textNode = static_cast<TextImpl *>(pos.node());        TextImpl *textBeforeNode = document()->createTextNode(textNode->substringData(0, selection.start().offset(), exceptionCode));        deleteText(textNode, 0, selection.start().offset());        insertNodeBefore(textBeforeNode, textNode);        insertNodeBefore(nodeToInsert, textNode);        setEndingSelection(Position(textNode, 0));    }}//------------------------------------------------------------------------------------------// InputTextCommandImplInputTextCommandImpl::InputTextCommandImpl(DocumentImpl *document)     : CompositeEditCommandImpl(document), m_charactersAdded(0){}InputTextCommandImpl::~InputTextCommandImpl() {}int InputTextCommandImpl::commandID() const{    return InputTextCommandID;}void InputTextCommandImpl::doApply(){}void InputTextCommandImpl::input(const DOMString &text){    execute(text);}void InputTextCommandImpl::deleteCharacter(){    ASSERT(state() == Applied);    Selection selection = endingSelection();    if (!selection.start().node()->isTextNode())        return;    int exceptionCode = 0;    int offset = selection.start().offset() - 1;    if (offset >= selection.start().node()->caretMinOffset()) {        TextImpl *textNode = static_cast<TextImpl *>(selection.start().node());        textNode->deleteData(offset, 1, exceptionCode);        ASSERT(exceptionCode == 0);        selection = Selection(Position(textNode, offset));        setEndingSelection(selection);        m_charactersAdded--;    }}Position InputTextCommandImpl::prepareForTextInsertion(bool adjustDownstream){    // Prepare for text input by looking at the current position.    // It may be necessary to insert a text node to receive characters.    Selection selection = endingSelection();    ASSERT(selection.state() == Selection::CARET);

⌨️ 快捷键说明

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