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