Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / dom / Text.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@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.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #include "config.h"
23 #include "Text.h"
24
25 #include "Event.h"
26 #include "RenderCombineText.h"
27 #include "RenderSVGInlineText.h"
28 #include "RenderText.h"
29 #include "SVGElement.h"
30 #include "SVGNames.h"
31 #include "ScopedEventQueue.h"
32 #include "ShadowRoot.h"
33 #include "StyleInheritedData.h"
34 #include "StyleResolver.h"
35 #include "TextNodeTraversal.h"
36 #include <wtf/CheckedArithmetic.h>
37 #include <wtf/text/CString.h>
38 #include <wtf/text/StringBuilder.h>
39
40 namespace WebCore {
41
42 Ref<Text> Text::create(Document& document, const String& data)
43 {
44     return adoptRef(*new Text(document, data, CreateText));
45 }
46
47 Ref<Text> Text::createEditingText(Document& document, const String& data)
48 {
49     return adoptRef(*new Text(document, data, CreateEditingText));
50 }
51
52 Text::~Text()
53 {
54     ASSERT(!renderer());
55 }
56
57 RefPtr<Text> Text::splitText(unsigned offset, ExceptionCode& ec)
58 {
59     ec = 0;
60
61     // INDEX_SIZE_ERR: Raised if the specified offset is negative or greater than
62     // the number of 16-bit units in data.
63     if (offset > length()) {
64         ec = INDEX_SIZE_ERR;
65         return 0;
66     }
67
68     EventQueueScope scope;
69     String oldStr = data();
70     Ref<Text> newText = virtualCreate(oldStr.substring(offset));
71     setDataWithoutUpdate(oldStr.substring(0, offset));
72
73     dispatchModifiedEvent(oldStr);
74
75     if (parentNode())
76         parentNode()->insertBefore(newText.copyRef(), nextSibling(), ec);
77     if (ec)
78         return 0;
79
80     if (parentNode())
81         document().textNodeSplit(this);
82
83     if (renderer())
84         renderer()->setTextWithOffset(data(), 0, oldStr.length());
85
86     return WTFMove(newText);
87 }
88
89 static const Text* earliestLogicallyAdjacentTextNode(const Text* text)
90 {
91     const Node* node = text;
92     while ((node = node->previousSibling())) {
93         if (!is<Text>(*node))
94             break;
95         text = downcast<Text>(node);
96     }
97     return text;
98 }
99
100 static const Text* latestLogicallyAdjacentTextNode(const Text* text)
101 {
102     const Node* node = text;
103     while ((node = node->nextSibling())) {
104         if (!is<Text>(*node))
105             break;
106         text = downcast<Text>(node);
107     }
108     return text;
109 }
110
111 String Text::wholeText() const
112 {
113     const Text* startText = earliestLogicallyAdjacentTextNode(this);
114     const Text* endText = latestLogicallyAdjacentTextNode(this);
115     ASSERT(endText);
116     const Node* onePastEndText = TextNodeTraversal::nextSibling(*endText);
117
118     StringBuilder result;
119     for (const Text* text = startText; text != onePastEndText; text = TextNodeTraversal::nextSibling(*text))
120         result.append(text->data());
121     return result.toString();
122 }
123
124 RefPtr<Text> Text::replaceWholeText(const String& newText, ExceptionCode&)
125 {
126     // Remove all adjacent text nodes, and replace the contents of this one.
127
128     // Protect startText and endText against mutation event handlers removing the last ref
129     RefPtr<Text> startText = const_cast<Text*>(earliestLogicallyAdjacentTextNode(this));
130     RefPtr<Text> endText = const_cast<Text*>(latestLogicallyAdjacentTextNode(this));
131
132     RefPtr<Text> protectedThis(this); // Mutation event handlers could cause our last ref to go away
133     RefPtr<ContainerNode> parent = parentNode(); // Protect against mutation handlers moving this node during traversal
134     for (RefPtr<Node> n = startText; n && n != this && n->isTextNode() && n->parentNode() == parent;) {
135         Ref<Node> nodeToRemove(n.releaseNonNull());
136         n = nodeToRemove->nextSibling();
137         parent->removeChild(WTFMove(nodeToRemove), IGNORE_EXCEPTION);
138     }
139
140     if (this != endText) {
141         Node* onePastEndText = endText->nextSibling();
142         for (RefPtr<Node> n = nextSibling(); n && n != onePastEndText && n->isTextNode() && n->parentNode() == parent;) {
143             Ref<Node> nodeToRemove(n.releaseNonNull());
144             n = nodeToRemove->nextSibling();
145             parent->removeChild(WTFMove(nodeToRemove), IGNORE_EXCEPTION);
146         }
147     }
148
149     if (newText.isEmpty()) {
150         if (parent && parentNode() == parent)
151             parent->removeChild(*this, IGNORE_EXCEPTION);
152         return nullptr;
153     }
154
155     setData(newText, IGNORE_EXCEPTION);
156     return protectedThis;
157 }
158
159 String Text::nodeName() const
160 {
161     return textAtom.string();
162 }
163
164 Node::NodeType Text::nodeType() const
165 {
166     return TEXT_NODE;
167 }
168
169 Ref<Node> Text::cloneNodeInternal(Document& targetDocument, CloningOperation)
170 {
171     return create(targetDocument, data());
172 }
173
174 static bool isSVGShadowText(Text* text)
175 {
176     Node* parentNode = text->parentNode();
177     ASSERT(parentNode);
178     return is<ShadowRoot>(*parentNode) && downcast<ShadowRoot>(*parentNode).host()->hasTagName(SVGNames::trefTag);
179 }
180
181 static bool isSVGText(Text* text)
182 {
183     Node* parentOrShadowHostNode = text->parentOrShadowHostNode();
184     return parentOrShadowHostNode->isSVGElement() && !parentOrShadowHostNode->hasTagName(SVGNames::foreignObjectTag);
185 }
186
187 RenderPtr<RenderText> Text::createTextRenderer(const RenderStyle& style)
188 {
189     if (isSVGText(this) || isSVGShadowText(this))
190         return createRenderer<RenderSVGInlineText>(*this, data());
191
192     if (style.hasTextCombine())
193         return createRenderer<RenderCombineText>(*this, data());
194
195     return createRenderer<RenderText>(*this, data());
196 }
197
198 bool Text::childTypeAllowed(NodeType) const
199 {
200     return false;
201 }
202
203 Ref<Text> Text::virtualCreate(const String& data)
204 {
205     return create(document(), data);
206 }
207
208 Ref<Text> Text::createWithLengthLimit(Document& document, const String& data, unsigned start, unsigned lengthLimit)
209 {
210     unsigned dataLength = data.length();
211
212     if (!start && dataLength <= lengthLimit)
213         return create(document, data);
214
215     Ref<Text> result = Text::create(document, String());
216     result->parserAppendData(data, start, lengthLimit);
217     return result;
218 }
219
220 #if ENABLE(TREE_DEBUGGING)
221 void Text::formatForDebugger(char* buffer, unsigned length) const
222 {
223     StringBuilder result;
224     String s;
225
226     result.append(nodeName());
227
228     s = data();
229     if (s.length() > 0) {
230         if (result.length())
231             result.appendLiteral("; ");
232         result.appendLiteral("length=");
233         result.appendNumber(s.length());
234         result.appendLiteral("; value=\"");
235         result.append(s);
236         result.append('"');
237     }
238
239     strncpy(buffer, result.toString().utf8().data(), length - 1);
240     buffer[length - 1] = '\0';
241 }
242 #endif
243
244 } // namespace WebCore