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