📄 htmlediting_impl.cpp
字号:
Position pos = selection.start(); if (adjustDownstream) pos = pos.equivalentDownstreamPosition(); else pos = pos.equivalentUpstreamPosition(); if (!pos.node()->isTextNode()) { NodeImpl *textNode = document()->createEditingTextNode(""); NodeImpl *nodeToInsert = textNode; if (document()->part()->typingStyle()) { int exceptionCode = 0; ElementImpl *styleElement = createTypingStyleElement(); styleElement->appendChild(textNode, exceptionCode); ASSERT(exceptionCode == 0); nodeToInsert = styleElement; } // Now insert the node in the right place if (pos.node()->isEditableBlock()) { LOG(Editing, "prepareForTextInsertion case 1"); appendNode(pos.node(), nodeToInsert); } else if (pos.node()->id() == ID_BR && pos.offset() == 1) { LOG(Editing, "prepareForTextInsertion case 2"); insertNodeAfter(nodeToInsert, pos.node()); } else if (pos.node()->caretMinOffset() == pos.offset()) { LOG(Editing, "prepareForTextInsertion case 3"); insertNodeBefore(nodeToInsert, pos.node()); } else if (pos.node()->caretMaxOffset() == pos.offset()) { LOG(Editing, "prepareForTextInsertion case 4"); insertNodeAfter(nodeToInsert, pos.node()); } else ASSERT_NOT_REACHED(); pos = Position(textNode, 0); } else { // Handle the case where there is a typing style. if (document()->part()->typingStyle()) { if (pos.node()->isTextNode() && pos.offset() > pos.node()->caretMinOffset() && pos.offset() < pos.node()->caretMaxOffset()) { // Need to split current text node in order to insert a span. TextImpl *text = static_cast<TextImpl *>(pos.node()); SplitTextNodeCommand cmd(document(), text, pos.offset()); applyCommandToComposite(cmd); setEndingSelection(Position(cmd.node(), 0)); } int exceptionCode = 0; TextImpl *editingTextNode = document()->createEditingTextNode(""); ElementImpl *styleElement = createTypingStyleElement(); styleElement->appendChild(editingTextNode, exceptionCode); ASSERT(exceptionCode == 0); NodeImpl *node = endingSelection().start().node(); if (endingSelection().start().isLastRenderedPositionOnLine()) insertNodeAfter(styleElement, node); else insertNodeBefore(styleElement, node); pos = Position(editingTextNode, 0); } } return pos;}void InputTextCommandImpl::execute(const DOMString &text){ Selection selection = endingSelection(); bool adjustDownstream = selection.start().isFirstRenderedPositionOnLine(); // Delete the current selection, or collapse whitespace, as needed if (selection.state() == Selection::RANGE) deleteSelection(); else deleteCollapsibleWhitespace(); // EDIT FIXME: Need to take typing style from upstream text, if any. // Make sure the document is set up to receive text Position pos = prepareForTextInsertion(adjustDownstream); TextImpl *textNode = static_cast<TextImpl *>(pos.node()); long offset = pos.offset(); // This is a temporary implementation for inserting adjoining spaces // into a document. We are working on a CSS-related whitespace solution // that will replace this some day. if (isWS(text)) insertSpace(textNode, offset); else { const DOMString &existingText = textNode->data(); if (textNode->length() >= 2 && offset >= 2 && isNBSP(existingText[offset - 1]) && !isWS(existingText[offset - 2])) { // DOM looks like this: // character nbsp caret // As we are about to insert a non-whitespace character at the caret // convert the nbsp to a regular space. // EDIT FIXME: This needs to be improved some day to convert back only // those nbsp's added by the editor to make rendering come out right. replaceText(textNode, offset - 1, 1, " "); } insertText(textNode, offset, text); } setEndingSelection(Position(textNode, offset + text.length())); m_charactersAdded += text.length();}void InputTextCommandImpl::insertSpace(TextImpl *textNode, unsigned long offset){ ASSERT(textNode); DOMString text(textNode->data()); // count up all spaces and newlines in front of the caret // delete all collapsed ones // this will work out OK since the offset we have been passed has been upstream-ized int count = 0; for (unsigned int i = offset; i < text.length(); i++) { if (isWS(text[i])) count++; else break; } if (count > 0) { // By checking the character at the downstream position, we can // check if there is a rendered WS at the caret Position pos(textNode, offset); Position downstream = pos.equivalentDownstreamPosition(); if (downstream.offset() < (long)text.length() && isWS(text[downstream.offset()])) count--; // leave this WS in if (count > 0) deleteText(textNode, offset, count); } if (offset > 0 && offset <= text.length() - 1 && !isWS(text[offset]) && !isWS(text[offset - 1])) { // insert a "regular" space insertText(textNode, offset, " "); return; } if (text.length() >= 2 && offset >= 2 && isNBSP(text[offset - 2]) && isNBSP(text[offset - 1])) { // DOM looks like this: // nbsp nbsp caret // insert a space between the two nbsps insertText(textNode, offset - 1, " "); return; } // insert an nbsp insertText(textNode, offset, nonBreakingSpaceString());}//------------------------------------------------------------------------------------------// InsertNodeBeforeCommandImplInsertNodeBeforeCommandImpl::InsertNodeBeforeCommandImpl(DocumentImpl *document, NodeImpl *insertChild, NodeImpl *refChild) : EditCommandImpl(document), m_insertChild(insertChild), m_refChild(refChild){ ASSERT(m_insertChild); m_insertChild->ref(); ASSERT(m_refChild); m_refChild->ref();}InsertNodeBeforeCommandImpl::~InsertNodeBeforeCommandImpl(){ if (m_insertChild) m_insertChild->deref(); if (m_refChild) m_refChild->deref();}int InsertNodeBeforeCommandImpl::commandID() const{ return InsertNodeBeforeCommandID;}void InsertNodeBeforeCommandImpl::doApply(){ ASSERT(m_insertChild); ASSERT(m_refChild); ASSERT(m_refChild->parentNode()); int exceptionCode = 0; m_refChild->parentNode()->insertBefore(m_insertChild, m_refChild, exceptionCode); ASSERT(exceptionCode == 0);}void InsertNodeBeforeCommandImpl::doUnapply(){ ASSERT(m_insertChild); ASSERT(m_refChild); ASSERT(m_refChild->parentNode()); int exceptionCode = 0; m_refChild->parentNode()->removeChild(m_insertChild, exceptionCode); ASSERT(exceptionCode == 0);}//------------------------------------------------------------------------------------------// InsertTextCommandImplInsertTextCommandImpl::InsertTextCommandImpl(DocumentImpl *document, TextImpl *node, long offset, const DOMString &text) : EditCommandImpl(document), m_node(node), m_offset(offset){ ASSERT(m_node); ASSERT(m_offset >= 0); ASSERT(text.length() > 0); m_node->ref(); m_text = text.copy(); // make a copy to ensure that the string never changes}InsertTextCommandImpl::~InsertTextCommandImpl(){ if (m_node) m_node->deref();}int InsertTextCommandImpl::commandID() const{ return InsertTextCommandID;}void InsertTextCommandImpl::doApply(){ ASSERT(m_node); ASSERT(!m_text.isEmpty()); int exceptionCode = 0; m_node->insertData(m_offset, m_text, exceptionCode); ASSERT(exceptionCode == 0);}void InsertTextCommandImpl::doUnapply(){ ASSERT(m_node); ASSERT(!m_text.isEmpty()); int exceptionCode = 0; m_node->deleteData(m_offset, m_text.length(), exceptionCode); ASSERT(exceptionCode == 0);}//------------------------------------------------------------------------------------------// JoinTextNodesCommandImplJoinTextNodesCommandImpl::JoinTextNodesCommandImpl(DocumentImpl *document, TextImpl *text1, TextImpl *text2) : EditCommandImpl(document), m_text1(text1), m_text2(text2){ ASSERT(m_text1); ASSERT(m_text2); ASSERT(m_text1->nextSibling() == m_text2); ASSERT(m_text1->length() > 0); ASSERT(m_text2->length() > 0); m_text1->ref(); m_text2->ref();}JoinTextNodesCommandImpl::~JoinTextNodesCommandImpl(){ if (m_text1) m_text1->deref(); if (m_text2) m_text2->deref();}int JoinTextNodesCommandImpl::commandID() const{ return JoinTextNodesCommandID;}void JoinTextNodesCommandImpl::doApply(){ ASSERT(m_text1); ASSERT(m_text2); ASSERT(m_text1->nextSibling() == m_text2); int exceptionCode = 0; m_text2->insertData(0, m_text1->data(), exceptionCode); ASSERT(exceptionCode == 0); m_text2->parentNode()->removeChild(m_text1, exceptionCode); ASSERT(exceptionCode == 0); m_offset = m_text1->length();}void JoinTextNodesCommandImpl::doUnapply(){ ASSERT(m_text2); ASSERT(m_offset > 0); int exceptionCode = 0; m_text2->deleteData(0, m_offset, exceptionCode); ASSERT(exceptionCode == 0); m_text2->parentNode()->insertBefore(m_text1, m_text2, exceptionCode); ASSERT(exceptionCode == 0); ASSERT(m_text2->previousSibling()->isTextNode()); ASSERT(m_text2->previousSibling() == m_text1);}//------------------------------------------------------------------------------------------// ReplaceSelectionCommandImplReplaceSelectionCommandImpl::ReplaceSelectionCommandImpl(DocumentImpl *document, DOM::DocumentFragmentImpl *fragment, bool selectReplacement) : CompositeEditCommandImpl(document), m_fragment(fragment), m_selectReplacement(selectReplacement){}ReplaceSelectionCommandImpl::~ReplaceSelectionCommandImpl(){}int ReplaceSelectionCommandImpl::commandID() const{ return ReplaceSelectionCommandID;}void ReplaceSelectionCommandImpl::doApply(){ NodeImpl *firstChild = m_fragment->firstChild(); NodeImpl *lastChild = m_fragment->lastChild(); Selection selection = endingSelection(); // Delete the current selection, or collapse whitespace, as needed if (selection.state() == Selection::RANGE) deleteSelection(); else deleteCollapsibleWhitespace(); selection = endingSelection(); ASSERT(!selection.isEmpty()); if (!firstChild) { // Pasting something that didn't parse or was empty. ASSERT(!lastChild); } else if (firstChild == lastChild && firstChild->isTextNode()) { // Simple text paste. Treat as if the text were typed. Position base = selection.base(); inputText(static_cast<TextImpl *>(firstChild)->data()); if (m_selectReplacement) { setEndingSelection(Selection(base, endingSelection().extent())); } } else { // HTML fragment paste. NodeImpl *beforeNode = firstChild; NodeImpl *node = firstChild->nextSibling(); insertNodeAt(firstChild, selection.start().node(), selection.start().offset()); // Insert the nodes from the fragment while (node) { NodeImpl *next = node->nextSibling(); insertNodeAfter(node, beforeNode); beforeNode = node; node = next; } ASSERT(beforeNode); // Find the last leaf. NodeImpl *lastLeaf = lastChild; while (1) { NodeImpl *nextChild = lastLeaf->lastChild(); if (!nextChild) break; lastLeaf = nextChild; } if (m_selectReplacement) { // Find the first leaf. NodeImpl *firstLeaf = firstChild; while (1) { NodeImpl *nextChild = firstLeaf->firstChild(); if (!nextChild) break; firstLeaf = nextChild; } // Select what was inserted.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -