1 /*
2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifndef htmlediting_h
27 #define htmlediting_h
28
29 #include "core/dom/Position.h"
30 #include "core/editing/EditingBoundary.h"
31 #include "platform/text/TextDirection.h"
32 #include "wtf/Forward.h"
33 #include "wtf/unicode/CharacterNames.h"
34
35 namespace blink {
36
37 class Document;
38 class Element;
39 class ExceptionState;
40 class HTMLBRElement;
41 class HTMLElement;
42 class HTMLLIElement;
43 class HTMLOListElement;
44 class HTMLSpanElement;
45 class HTMLUListElement;
46 class Node;
47 class Position;
48 class PositionWithAffinity;
49 class Range;
50 class VisiblePosition;
51 class VisibleSelection;
52
53
54 // This file contains a set of helper functions used by the editing commands
55
56 // -------------------------------------------------------------------------
57 // Node
58 // -------------------------------------------------------------------------
59
60 // Functions returning Node
61
62 ContainerNode* highestEditableRoot(const Position&, EditableType = ContentIsEditable);
63
64 Node* highestEnclosingNodeOfType(const Position&, bool (*nodeIsOfType)(const Node*),
65 EditingBoundaryCrossingRule = CannotCrossEditingBoundary, Node* stayWithin = 0);
66 Node* highestNodeToRemoveInPruning(Node*, Node* excludeNode = 0);
67 Element* lowestEditableAncestor(Node*);
68
69 Element* enclosingBlock(Node*, EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
70 Element* enclosingBlockFlowElement(Node&); // Deprecated, use enclosingBlock instead.
71 bool inSameContainingBlockFlowElement(Node*, Node*);
72 Element* enclosingTableCell(const Position&);
73 Node* enclosingEmptyListItem(const VisiblePosition&);
74 Element* enclosingAnchorElement(const Position&);
75 Element* enclosingElementWithTag(const Position&, const QualifiedName&);
76 Node* enclosingNodeOfType(const Position&, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
77
78 HTMLSpanElement* tabSpanElement(const Node*);
79 Element* isLastPositionBeforeTable(const VisiblePosition&);
80 Element* isFirstPositionAfterTable(const VisiblePosition&);
81
82 // offset functions on Node
83
84 int lastOffsetForEditing(const Node*);
85 int caretMinOffset(const Node*);
86 int caretMaxOffset(const Node*);
87
88 // boolean functions on Node
89
90 // FIXME: editingIgnoresContent, canHaveChildrenForEditing, and isAtomicNode
91 // should be renamed to reflect its usage.
92
93 // Returns true for nodes that either have no content, or have content that is ignored (skipped over) while editing.
94 // There are no VisiblePositions inside these nodes.
editingIgnoresContent(const Node * node)95 inline bool editingIgnoresContent(const Node* node)
96 {
97 return !node->canContainRangeEndPoint();
98 }
99
canHaveChildrenForEditing(const Node * node)100 inline bool canHaveChildrenForEditing(const Node* node)
101 {
102 return !node->isTextNode() && node->canContainRangeEndPoint();
103 }
104
105 bool isAtomicNode(const Node*);
106 bool isBlock(const Node*);
107 bool isInline(const Node*);
108 bool isSpecialHTMLElement(const Node*);
109 bool isTabHTMLSpanElement(const Node*);
110 bool isTabHTMLSpanElementTextNode(const Node*);
111 bool isMailHTMLBlockquoteElement(const Node*);
112 bool isRenderedTableElement(const Node*);
113 bool isRenderedHTMLTableElement(const Node*);
114 bool isTableCell(const Node*);
115 bool isEmptyTableCell(const Node*);
116 bool isTableStructureNode(const Node*);
117 bool isHTMLListElement(Node*);
118 bool isListItem(const Node*);
119 bool isNodeRendered(const Node*);
120 bool isNodeVisiblyContainedWithin(Node&, const Range&);
121 bool isRenderedAsNonInlineTableImageOrHR(const Node*);
122 bool areIdenticalElements(const Node*, const Node*);
123 bool isNonTableCellHTMLBlockElement(const Node*);
124 bool isBlockFlowElement(const Node&);
125 TextDirection directionOfEnclosingBlock(const Position&);
126
127 // -------------------------------------------------------------------------
128 // Position
129 // -------------------------------------------------------------------------
130
131 // Functions returning Position
132
133 Position nextCandidate(const Position&);
134 Position previousCandidate(const Position&);
135
136 Position nextVisuallyDistinctCandidate(const Position&);
137 Position previousVisuallyDistinctCandidate(const Position&);
138
139 Position positionBeforeContainingSpecialElement(const Position&, HTMLElement** containingSpecialElement = 0);
140 Position positionAfterContainingSpecialElement(const Position&, HTMLElement** containingSpecialElement = 0);
141
firstPositionInOrBeforeNode(Node * node)142 inline Position firstPositionInOrBeforeNode(Node* node)
143 {
144 if (!node)
145 return Position();
146 return editingIgnoresContent(node) ? positionBeforeNode(node) : firstPositionInNode(node);
147 }
148
lastPositionInOrAfterNode(Node * node)149 inline Position lastPositionInOrAfterNode(Node* node)
150 {
151 if (!node)
152 return Position();
153 return editingIgnoresContent(node) ? positionAfterNode(node) : lastPositionInNode(node);
154 }
155
156 Position lastEditablePositionBeforePositionInRoot(const Position&, Node*);
157
158 // comparision functions on Position
159
160 int comparePositions(const Position&, const Position&);
161 int comparePositions(const PositionWithAffinity&, const PositionWithAffinity&);
162
163 // boolean functions on Position
164
165 enum EUpdateStyle { UpdateStyle, DoNotUpdateStyle };
166 // FIXME: Both isEditablePosition and isRichlyEditablePosition rely on up-to-date
167 // style to give proper results. They shouldn't update style by default, but
168 // should make it clear that that is the contract.
169 // FIXME: isRichlyEditablePosition should also take EUpdateStyle.
170 bool isEditablePosition(const Position&, EditableType = ContentIsEditable, EUpdateStyle = UpdateStyle);
171 bool isRichlyEditablePosition(const Position&, EditableType = ContentIsEditable);
172 bool lineBreakExistsAtPosition(const Position&);
173 bool isVisiblyAdjacent(const Position& first, const Position& second);
174 bool isAtUnsplittableElement(const Position&);
175
176 // miscellaneous functions on Position
177
178 enum WhitespacePositionOption { NotConsiderNonCollapsibleWhitespace, ConsiderNonCollapsibleWhitespace };
179 Position leadingWhitespacePosition(const Position&, EAffinity, WhitespacePositionOption = NotConsiderNonCollapsibleWhitespace);
180 Position trailingWhitespacePosition(const Position&, EAffinity, WhitespacePositionOption = NotConsiderNonCollapsibleWhitespace);
181 unsigned numEnclosingMailBlockquotes(const Position&);
182 void updatePositionForNodeRemoval(Position&, Node&);
183
184 // -------------------------------------------------------------------------
185 // VisiblePosition
186 // -------------------------------------------------------------------------
187
188 // Functions returning VisiblePosition
189
190 VisiblePosition firstEditableVisiblePositionAfterPositionInRoot(const Position&, ContainerNode*);
191 VisiblePosition lastEditableVisiblePositionBeforePositionInRoot(const Position&, ContainerNode*);
192 VisiblePosition visiblePositionBeforeNode(Node&);
193 VisiblePosition visiblePositionAfterNode(Node&);
194
195 bool lineBreakExistsAtVisiblePosition(const VisiblePosition&);
196
197 int comparePositions(const VisiblePosition&, const VisiblePosition&);
198
199 int indexForVisiblePosition(const VisiblePosition&, RefPtrWillBeRawPtr<ContainerNode>& scope);
200 VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope);
201
202 // -------------------------------------------------------------------------
203 // Range
204 // -------------------------------------------------------------------------
205
206 // Functions returning Range
207
208 PassRefPtrWillBeRawPtr<Range> createRange(Document&, const VisiblePosition& start, const VisiblePosition& end, ExceptionState&);
209
210 // -------------------------------------------------------------------------
211 // HTMLElement
212 // -------------------------------------------------------------------------
213
214 // Functions returning HTMLElement
215
216 PassRefPtrWillBeRawPtr<HTMLElement> createDefaultParagraphElement(Document&);
217 PassRefPtrWillBeRawPtr<HTMLBRElement> createBreakElement(Document&);
218 PassRefPtrWillBeRawPtr<HTMLOListElement> createOrderedListElement(Document&);
219 PassRefPtrWillBeRawPtr<HTMLUListElement> createUnorderedListElement(Document&);
220 PassRefPtrWillBeRawPtr<HTMLLIElement> createListItemElement(Document&);
221 PassRefPtrWillBeRawPtr<HTMLElement> createHTMLElement(Document&, const QualifiedName&);
222 PassRefPtrWillBeRawPtr<HTMLElement> createHTMLElement(Document&, const AtomicString&);
223
224 HTMLElement* enclosingList(Node*);
225 HTMLElement* outermostEnclosingList(Node*, HTMLElement* rootList = 0);
226 Node* enclosingListChild(Node*);
227
228 // -------------------------------------------------------------------------
229 // Element
230 // -------------------------------------------------------------------------
231
232 // Functions returning Element
233
234 PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document&);
235 PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document&, PassRefPtrWillBeRawPtr<Text> tabTextNode);
236 PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document&, const String& tabText);
237 PassRefPtrWillBeRawPtr<HTMLBRElement> createBlockPlaceholderElement(Document&);
238
239 Element* editableRootForPosition(const Position&, EditableType = ContentIsEditable);
240 Element* unsplittableElementForPosition(const Position&);
241
242 // Boolean functions on Element
243
244 bool canMergeLists(Element* firstList, Element* secondList);
245
246 // -------------------------------------------------------------------------
247 // VisibleSelection
248 // -------------------------------------------------------------------------
249
250 // Functions returning VisibleSelection
251 VisibleSelection selectionForParagraphIteration(const VisibleSelection&);
252
253 Position adjustedSelectionStartForStyleComputation(const VisibleSelection&);
254
255
256 // Miscellaneous functions on Text
isWhitespace(UChar c)257 inline bool isWhitespace(UChar c)
258 {
259 return c == noBreakSpace || c == ' ' || c == '\n' || c == '\t';
260 }
261
262 // FIXME: Can't really answer this question correctly without knowing the white-space mode.
isCollapsibleWhitespace(UChar c)263 inline bool isCollapsibleWhitespace(UChar c)
264 {
265 return c == ' ' || c == '\n';
266 }
267
isAmbiguousBoundaryCharacter(UChar character)268 inline bool isAmbiguousBoundaryCharacter(UChar character)
269 {
270 // These are characters that can behave as word boundaries, but can appear within words.
271 // If they are just typed, i.e. if they are immediately followed by a caret, we want to delay text checking until the next character has been typed.
272 // FIXME: this is required until 6853027 is fixed and text checking can do this for us.
273 return character == '\'' || character == rightSingleQuotationMark || character == hebrewPunctuationGershayim;
274 }
275
276 String stringWithRebalancedWhitespace(const String&, bool startIsStartOfParagraph, bool endIsEndOfParagraph);
277 const String& nonBreakingSpaceString();
278
279 }
280
281 #endif
282