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 "EditingBoundary.h"
30#include "Position.h"
31#include "TextDirection.h"
32#include <wtf/Forward.h>
33#include <wtf/unicode/CharacterNames.h>
34
35namespace WebCore {
36
37class Document;
38class Element;
39class HTMLElement;
40class HTMLTextFormControlElement;
41class Node;
42class Position;
43class Range;
44class VisiblePosition;
45class VisibleSelection;
46
47
48// This file contains a set of helper functions used by the editing commands
49
50// -------------------------------------------------------------------------
51// Node
52// -------------------------------------------------------------------------
53
54// Functions returning Node
55
56Node* highestAncestor(Node*);
57Node* highestEditableRoot(const Position&, EditableType = ContentIsEditable);
58
59Node* highestEnclosingNodeOfType(const Position&, bool (*nodeIsOfType)(const Node*),
60    EditingBoundaryCrossingRule = CannotCrossEditingBoundary, Node* stayWithin = 0);
61Node* highestNodeToRemoveInPruning(Node*);
62Node* lowestEditableAncestor(Node*);
63
64Element* deprecatedEnclosingBlockFlowElement(Node*); // Use enclosingBlock instead.
65Element* enclosingBlock(Node*, EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
66Node* enclosingTableCell(const Position&);
67Node* enclosingEmptyListItem(const VisiblePosition&);
68Element* enclosingAnchorElement(const Position&);
69Node* enclosingNodeWithTag(const Position&, const QualifiedName&);
70Node* enclosingNodeOfType(const Position&, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule = CannotCrossEditingBoundary);
71
72Node* tabSpanNode(const Node*);
73Node* isLastPositionBeforeTable(const VisiblePosition&);
74Node* isFirstPositionAfterTable(const VisiblePosition&);
75
76// These two deliver leaf nodes as if the whole DOM tree were a linear chain of its leaf nodes.
77Node* nextLeafNode(const Node*);
78Node* previousLeafNode(const Node*);
79
80// offset functions on Node
81
82int lastOffsetForEditing(const Node*);
83int caretMinOffset(const Node*);
84int caretMaxOffset(const Node*);
85
86// boolean functions on Node
87
88// FIXME: editingIgnoresContent, canHaveChildrenForEditing, and isAtomicNode
89// should be renamed to reflect its usage.
90
91// Returns true for nodes that either have no content, or have content that is ignored (skipped over) while editing.
92// There are no VisiblePositions inside these nodes.
93inline bool editingIgnoresContent(const Node* node)
94{
95    return !node->canContainRangeEndPoint();
96}
97
98inline bool canHaveChildrenForEditing(const Node* node)
99{
100    return !node->isTextNode() && node->canContainRangeEndPoint();
101}
102
103bool isAtomicNode(const Node*);
104bool isBlock(const Node*);
105bool isBlockFlowElement(const Node*);
106bool isInline(const Node*);
107bool isSpecialElement(const Node*);
108bool isTabSpanNode(const Node*);
109bool isTabSpanTextNode(const Node*);
110bool isMailBlockquote(const Node*);
111bool isTableElement(Node*);
112bool isTableCell(const Node*);
113bool isEmptyTableCell(const Node*);
114bool isTableStructureNode(const Node*);
115bool isListElement(Node*);
116bool isListItem(const Node*);
117bool isNodeRendered(const Node*);
118bool isNodeVisiblyContainedWithin(Node*, const Range*);
119bool isRenderedAsNonInlineTableImageOrHR(const Node*);
120bool areIdenticalElements(const Node*, const Node*);
121bool isNonTableCellHTMLBlockElement(const Node*);
122
123TextDirection directionOfEnclosingBlock(const Position&);
124
125// -------------------------------------------------------------------------
126// Position
127// -------------------------------------------------------------------------
128
129// Functions returning Position
130
131Position nextCandidate(const Position&);
132Position previousCandidate(const Position&);
133
134Position nextVisuallyDistinctCandidate(const Position&);
135Position previousVisuallyDistinctCandidate(const Position&);
136
137Position positionOutsideTabSpan(const Position&);
138Position positionBeforeContainingSpecialElement(const Position&, Node** containingSpecialElement = 0);
139Position positionAfterContainingSpecialElement(const Position&, Node** containingSpecialElement = 0);
140Position positionOutsideContainingSpecialElement(const Position&, Node** containingSpecialElement = 0);
141
142inline Position firstPositionInOrBeforeNode(Node* node)
143{
144    if (!node)
145        return Position();
146    return editingIgnoresContent(node) ? positionBeforeNode(node) : firstPositionInNode(node);
147}
148
149inline Position lastPositionInOrAfterNode(Node* node)
150{
151    if (!node)
152        return Position();
153    return editingIgnoresContent(node) ? positionAfterNode(node) : lastPositionInNode(node);
154}
155
156// comparision functions on Position
157
158int comparePositions(const Position&, const Position&);
159
160// boolean functions on Position
161
162enum EUpdateStyle { UpdateStyle, DoNotUpdateStyle };
163bool isEditablePosition(const Position&, EditableType = ContentIsEditable, EUpdateStyle = UpdateStyle);
164bool isRichlyEditablePosition(const Position&, EditableType = ContentIsEditable);
165bool isFirstVisiblePositionInSpecialElement(const Position&);
166bool isLastVisiblePositionInSpecialElement(const Position&);
167bool lineBreakExistsAtPosition(const Position&);
168bool isVisiblyAdjacent(const Position& first, const Position& second);
169bool isAtUnsplittableElement(const Position&);
170
171// miscellaneous functions on Position
172
173unsigned numEnclosingMailBlockquotes(const Position&);
174void updatePositionForNodeRemoval(Position&, Node*);
175
176// -------------------------------------------------------------------------
177// VisiblePosition
178// -------------------------------------------------------------------------
179
180// Functions returning VisiblePosition
181
182VisiblePosition firstEditablePositionAfterPositionInRoot(const Position&, Node*);
183VisiblePosition lastEditablePositionBeforePositionInRoot(const Position&, Node*);
184VisiblePosition visiblePositionBeforeNode(Node*);
185VisiblePosition visiblePositionAfterNode(Node*);
186
187bool lineBreakExistsAtVisiblePosition(const VisiblePosition&);
188
189int comparePositions(const VisiblePosition&, const VisiblePosition&);
190
191int indexForVisiblePosition(const VisiblePosition&, RefPtr<ContainerNode>& scope);
192VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope);
193
194// -------------------------------------------------------------------------
195// Range
196// -------------------------------------------------------------------------
197
198// Functions returning Range
199
200PassRefPtr<Range> createRange(PassRefPtr<Document>, const VisiblePosition& start, const VisiblePosition& end, ExceptionCode&);
201PassRefPtr<Range> extendRangeToWrappingNodes(PassRefPtr<Range> rangeToExtend, const Range* maximumRange, const Node* rootNode);
202
203// -------------------------------------------------------------------------
204// HTMLElement
205// -------------------------------------------------------------------------
206
207// Functions returning HTMLElement
208
209PassRefPtr<HTMLElement> createDefaultParagraphElement(Document*);
210PassRefPtr<HTMLElement> createBreakElement(Document*);
211PassRefPtr<HTMLElement> createOrderedListElement(Document*);
212PassRefPtr<HTMLElement> createUnorderedListElement(Document*);
213PassRefPtr<HTMLElement> createListItemElement(Document*);
214PassRefPtr<HTMLElement> createHTMLElement(Document*, const QualifiedName&);
215PassRefPtr<HTMLElement> createHTMLElement(Document*, const AtomicString&);
216
217HTMLElement* enclosingList(Node*);
218HTMLElement* outermostEnclosingList(Node*, Node* rootList = 0);
219Node* enclosingListChild(Node*);
220
221// -------------------------------------------------------------------------
222// Element
223// -------------------------------------------------------------------------
224
225// Functions returning Element
226
227PassRefPtr<Element> createTabSpanElement(Document*);
228PassRefPtr<Element> createTabSpanElement(Document*, PassRefPtr<Node> tabTextNode);
229PassRefPtr<Element> createTabSpanElement(Document*, const String& tabText);
230PassRefPtr<Element> createBlockPlaceholderElement(Document*);
231
232Element* editableRootForPosition(const Position&, EditableType = ContentIsEditable);
233Element* unsplittableElementForPosition(const Position&);
234
235// Boolean functions on Element
236
237bool canMergeLists(Element* firstList, Element* secondList);
238
239// -------------------------------------------------------------------------
240// VisibleSelection
241// -------------------------------------------------------------------------
242
243// Functions returning VisibleSelection
244VisibleSelection selectionForParagraphIteration(const VisibleSelection&);
245
246Position adjustedSelectionStartForStyleComputation(const VisibleSelection&);
247
248
249// Miscellaneous functions on Text
250inline bool isWhitespace(UChar c)
251{
252    return c == noBreakSpace || c == ' ' || c == '\n' || c == '\t';
253}
254
255inline bool isAmbiguousBoundaryCharacter(UChar character)
256{
257    // These are characters that can behave as word boundaries, but can appear within words.
258    // 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.
259    // FIXME: this is required until 6853027 is fixed and text checking can do this for us.
260    return character == '\'' || character == rightSingleQuotationMark || character == hebrewPunctuationGershayim;
261}
262
263String stringWithRebalancedWhitespace(const String&, bool startIsStartOfParagraph, bool endIsEndOfParagraph);
264const String& nonBreakingSpaceString();
265
266}
267
268#endif
269