| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
reserved. | 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights
reserved. |
| 5 * | 5 * |
| 6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
| 8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
| 9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
| 10 * | 10 * |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 PassRefPtr<Text> Text::create(Document& document, const String& data) | 41 PassRefPtr<Text> Text::create(Document& document, const String& data) |
| 42 { | 42 { |
| 43 return adoptRef(new Text(document, data, CreateText)); | 43 return adoptRef(new Text(document, data, CreateText)); |
| 44 } | 44 } |
| 45 | 45 |
| 46 PassRefPtr<Text> Text::createEditingText(Document& document, const String& data) | 46 PassRefPtr<Text> Text::createEditingText(Document& document, const String& data) |
| 47 { | 47 { |
| 48 return adoptRef(new Text(document, data, CreateEditingText)); | 48 return adoptRef(new Text(document, data, CreateEditingText)); |
| 49 } | 49 } |
| 50 | 50 |
| 51 PassRefPtr<Node> Text::mergeNextSiblingNodesIfPossible() | |
| 52 { | |
| 53 RefPtr<Node> protect(this); | |
| 54 | |
| 55 // Remove empty text nodes. | |
| 56 if (!length()) { | |
| 57 // Care must be taken to get the next node before removing the current n
ode. | |
| 58 RefPtr<Node> nextNode(NodeTraversal::nextPostOrder(*this)); | |
| 59 remove(IGNORE_EXCEPTION); | |
| 60 return nextNode.release(); | |
| 61 } | |
| 62 | |
| 63 // Merge text nodes. | |
| 64 while (Node* nextSibling = this->nextSibling()) { | |
| 65 if (nextSibling->nodeType() != TEXT_NODE) | |
| 66 break; | |
| 67 | |
| 68 RefPtr<Text> nextText = toText(nextSibling); | |
| 69 | |
| 70 // Remove empty text nodes. | |
| 71 if (!nextText->length()) { | |
| 72 nextText->remove(IGNORE_EXCEPTION); | |
| 73 continue; | |
| 74 } | |
| 75 | |
| 76 // Both non-empty text nodes. Merge them. | |
| 77 unsigned offset = length(); | |
| 78 String nextTextData = nextText->data(); | |
| 79 String oldTextData = data(); | |
| 80 setDataWithoutUpdate(data() + nextTextData); | |
| 81 updateTextRenderer(oldTextData.length(), 0); | |
| 82 | |
| 83 // Empty nextText for layout update. | |
| 84 nextText->setDataWithoutUpdate(emptyString()); | |
| 85 nextText->updateTextRenderer(0, nextTextData.length()); | |
| 86 | |
| 87 document().didMergeTextNodes(*nextText, offset); | |
| 88 | |
| 89 // Restore nextText for mutation event. | |
| 90 nextText->setDataWithoutUpdate(nextTextData); | |
| 91 nextText->updateTextRenderer(0, 0); | |
| 92 | |
| 93 didModifyData(oldTextData); | |
| 94 nextText->remove(IGNORE_EXCEPTION); | |
| 95 } | |
| 96 | |
| 97 return NodeTraversal::nextPostOrder(*this); | |
| 98 } | |
| 99 | |
| 100 PassRefPtr<Text> Text::splitText(unsigned offset, ExceptionState& exceptionState
) | 51 PassRefPtr<Text> Text::splitText(unsigned offset, ExceptionState& exceptionState
) |
| 101 { | 52 { |
| 102 // IndexSizeError: Raised if the specified offset is negative or greater tha
n | 53 // IndexSizeError: Raised if the specified offset is negative or greater tha
n |
| 103 // the number of 16-bit units in data. | 54 // the number of 16-bit units in data. |
| 104 if (offset > length()) { | 55 if (offset > length()) { |
| 105 exceptionState.throwDOMException(IndexSizeError, "The offset " + String:
:number(offset) + " is larger than the Text node's length."); | 56 exceptionState.throwDOMException(IndexSizeError, "The offset " + String:
:number(offset) + " is larger than the Text node's length."); |
| 106 return nullptr; | 57 return nullptr; |
| 107 } | 58 } |
| 108 | 59 |
| 109 EventQueueScope scope; | 60 EventQueueScope scope; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 120 | 71 |
| 121 if (renderer()) | 72 if (renderer()) |
| 122 renderer()->setTextWithOffset(dataImpl(), 0, oldStr.length()); | 73 renderer()->setTextWithOffset(dataImpl(), 0, oldStr.length()); |
| 123 | 74 |
| 124 if (parentNode()) | 75 if (parentNode()) |
| 125 document().didSplitTextNode(*this); | 76 document().didSplitTextNode(*this); |
| 126 | 77 |
| 127 return newText.release(); | 78 return newText.release(); |
| 128 } | 79 } |
| 129 | 80 |
| 130 static const Text* earliestLogicallyAdjacentTextNode(const Text* t) | |
| 131 { | |
| 132 for (const Node* n = t->previousSibling(); n; n = n->previousSibling()) { | |
| 133 Node::NodeType type = n->nodeType(); | |
| 134 if (type == Node::TEXT_NODE) { | |
| 135 t = toText(n); | |
| 136 continue; | |
| 137 } | |
| 138 | |
| 139 break; | |
| 140 } | |
| 141 return t; | |
| 142 } | |
| 143 | |
| 144 static const Text* latestLogicallyAdjacentTextNode(const Text* t) | |
| 145 { | |
| 146 for (const Node* n = t->nextSibling(); n; n = n->nextSibling()) { | |
| 147 Node::NodeType type = n->nodeType(); | |
| 148 if (type == Node::TEXT_NODE) { | |
| 149 t = toText(n); | |
| 150 continue; | |
| 151 } | |
| 152 | |
| 153 break; | |
| 154 } | |
| 155 return t; | |
| 156 } | |
| 157 | |
| 158 String Text::wholeText() const | |
| 159 { | |
| 160 const Text* startText = earliestLogicallyAdjacentTextNode(this); | |
| 161 const Text* endText = latestLogicallyAdjacentTextNode(this); | |
| 162 | |
| 163 Node* onePastEndText = endText->nextSibling(); | |
| 164 unsigned resultLength = 0; | |
| 165 for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) { | |
| 166 if (!n->isTextNode()) | |
| 167 continue; | |
| 168 const String& data = toText(n)->data(); | |
| 169 if (std::numeric_limits<unsigned>::max() - data.length() < resultLength) | |
| 170 CRASH(); | |
| 171 resultLength += data.length(); | |
| 172 } | |
| 173 StringBuilder result; | |
| 174 result.reserveCapacity(resultLength); | |
| 175 for (const Node* n = startText; n != onePastEndText; n = n->nextSibling()) { | |
| 176 if (!n->isTextNode()) | |
| 177 continue; | |
| 178 result.append(toText(n)->data()); | |
| 179 } | |
| 180 ASSERT(result.length() == resultLength); | |
| 181 | |
| 182 return result.toString(); | |
| 183 } | |
| 184 | |
| 185 PassRefPtr<Text> Text::replaceWholeText(const String& newText) | |
| 186 { | |
| 187 // Remove all adjacent text nodes, and replace the contents of this one. | |
| 188 | |
| 189 // Protect startText and endText against mutation event handlers removing th
e last ref | |
| 190 RefPtr<Text> startText = const_cast<Text*>(earliestLogicallyAdjacentTextNode
(this)); | |
| 191 RefPtr<Text> endText = const_cast<Text*>(latestLogicallyAdjacentTextNode(thi
s)); | |
| 192 | |
| 193 RefPtr<Text> protectedThis(this); // Mutation event handlers could cause our
last ref to go away | |
| 194 RefPtr<ContainerNode> parent = parentNode(); // Protect against mutation han
dlers moving this node during traversal | |
| 195 for (RefPtr<Node> n = startText; n && n != this && n->isTextNode() && n->par
entNode() == parent;) { | |
| 196 RefPtr<Node> nodeToRemove(n.release()); | |
| 197 n = nodeToRemove->nextSibling(); | |
| 198 parent->removeChild(nodeToRemove.get(), IGNORE_EXCEPTION); | |
| 199 } | |
| 200 | |
| 201 if (this != endText) { | |
| 202 Node* onePastEndText = endText->nextSibling(); | |
| 203 for (RefPtr<Node> n = nextSibling(); n && n != onePastEndText && n->isTe
xtNode() && n->parentNode() == parent;) { | |
| 204 RefPtr<Node> nodeToRemove(n.release()); | |
| 205 n = nodeToRemove->nextSibling(); | |
| 206 parent->removeChild(nodeToRemove.get(), IGNORE_EXCEPTION); | |
| 207 } | |
| 208 } | |
| 209 | |
| 210 if (newText.isEmpty()) { | |
| 211 if (parent && parentNode() == parent) | |
| 212 parent->removeChild(this, IGNORE_EXCEPTION); | |
| 213 return nullptr; | |
| 214 } | |
| 215 | |
| 216 setData(newText); | |
| 217 return protectedThis.release(); | |
| 218 } | |
| 219 | |
| 220 String Text::nodeName() const | 81 String Text::nodeName() const |
| 221 { | 82 { |
| 222 return "#text"; | 83 return "#text"; |
| 223 } | 84 } |
| 224 | 85 |
| 225 Node::NodeType Text::nodeType() const | 86 Node::NodeType Text::nodeType() const |
| 226 { | 87 { |
| 227 return TEXT_NODE; | 88 return TEXT_NODE; |
| 228 } | 89 } |
| 229 | 90 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 result.appendLiteral("; "); | 208 result.appendLiteral("; "); |
| 348 result.appendLiteral("value="); | 209 result.appendLiteral("value="); |
| 349 result.append(s); | 210 result.append(s); |
| 350 } | 211 } |
| 351 | 212 |
| 352 strncpy(buffer, result.toString().utf8().data(), length - 1); | 213 strncpy(buffer, result.toString().utf8().data(), length - 1); |
| 353 } | 214 } |
| 354 #endif | 215 #endif |
| 355 | 216 |
| 356 } // namespace blink | 217 } // namespace blink |
| OLD | NEW |