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 35namespace blink { 36 37class Document; 38class Element; 39class ExceptionState; 40class HTMLBRElement; 41class HTMLElement; 42class HTMLLIElement; 43class HTMLOListElement; 44class HTMLSpanElement; 45class HTMLUListElement; 46class Node; 47class Position; 48class PositionWithAffinity; 49class Range; 50class VisiblePosition; 51class 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 62ContainerNode* highestEditableRoot(const Position&, EditableType = ContentIsEditable); 63 64Node* highestEnclosingNodeOfType(const Position&, bool (*nodeIsOfType)(const Node*), 65 EditingBoundaryCrossingRule = CannotCrossEditingBoundary, Node* stayWithin = 0); 66Node* highestNodeToRemoveInPruning(Node*, Node* excludeNode = 0); 67Element* lowestEditableAncestor(Node*); 68 69Element* enclosingBlock(Node*, EditingBoundaryCrossingRule = CannotCrossEditingBoundary); 70Element* enclosingBlockFlowElement(Node&); // Deprecated, use enclosingBlock instead. 71bool inSameContainingBlockFlowElement(Node*, Node*); 72Element* enclosingTableCell(const Position&); 73Node* enclosingEmptyListItem(const VisiblePosition&); 74Element* enclosingAnchorElement(const Position&); 75Element* enclosingElementWithTag(const Position&, const QualifiedName&); 76Node* enclosingNodeOfType(const Position&, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule = CannotCrossEditingBoundary); 77 78HTMLSpanElement* tabSpanElement(const Node*); 79Element* isLastPositionBeforeTable(const VisiblePosition&); 80Element* isFirstPositionAfterTable(const VisiblePosition&); 81 82// offset functions on Node 83 84int lastOffsetForEditing(const Node*); 85int caretMinOffset(const Node*); 86int 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. 95inline bool editingIgnoresContent(const Node* node) 96{ 97 return !node->canContainRangeEndPoint(); 98} 99 100inline bool canHaveChildrenForEditing(const Node* node) 101{ 102 return !node->isTextNode() && node->canContainRangeEndPoint(); 103} 104 105bool isAtomicNode(const Node*); 106bool isBlock(const Node*); 107bool isInline(const Node*); 108bool isSpecialHTMLElement(const Node*); 109bool isTabHTMLSpanElement(const Node*); 110bool isTabHTMLSpanElementTextNode(const Node*); 111bool isMailHTMLBlockquoteElement(const Node*); 112bool isRenderedTableElement(const Node*); 113bool isRenderedHTMLTableElement(const Node*); 114bool isTableCell(const Node*); 115bool isEmptyTableCell(const Node*); 116bool isTableStructureNode(const Node*); 117bool isHTMLListElement(Node*); 118bool isListItem(const Node*); 119bool isNodeRendered(const Node*); 120bool isNodeVisiblyContainedWithin(Node&, const Range&); 121bool isRenderedAsNonInlineTableImageOrHR(const Node*); 122bool areIdenticalElements(const Node*, const Node*); 123bool isNonTableCellHTMLBlockElement(const Node*); 124bool isBlockFlowElement(const Node&); 125TextDirection directionOfEnclosingBlock(const Position&); 126 127// ------------------------------------------------------------------------- 128// Position 129// ------------------------------------------------------------------------- 130 131// Functions returning Position 132 133Position nextCandidate(const Position&); 134Position previousCandidate(const Position&); 135 136Position nextVisuallyDistinctCandidate(const Position&); 137Position previousVisuallyDistinctCandidate(const Position&); 138 139Position positionBeforeContainingSpecialElement(const Position&, HTMLElement** containingSpecialElement = 0); 140Position positionAfterContainingSpecialElement(const Position&, HTMLElement** 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 156Position lastEditablePositionBeforePositionInRoot(const Position&, Node*); 157 158// comparision functions on Position 159 160int comparePositions(const Position&, const Position&); 161int comparePositions(const PositionWithAffinity&, const PositionWithAffinity&); 162 163// boolean functions on Position 164 165enum 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. 170bool isEditablePosition(const Position&, EditableType = ContentIsEditable, EUpdateStyle = UpdateStyle); 171bool isRichlyEditablePosition(const Position&, EditableType = ContentIsEditable); 172bool lineBreakExistsAtPosition(const Position&); 173bool isVisiblyAdjacent(const Position& first, const Position& second); 174bool isAtUnsplittableElement(const Position&); 175 176// miscellaneous functions on Position 177 178enum WhitespacePositionOption { NotConsiderNonCollapsibleWhitespace, ConsiderNonCollapsibleWhitespace }; 179Position leadingWhitespacePosition(const Position&, EAffinity, WhitespacePositionOption = NotConsiderNonCollapsibleWhitespace); 180Position trailingWhitespacePosition(const Position&, EAffinity, WhitespacePositionOption = NotConsiderNonCollapsibleWhitespace); 181unsigned numEnclosingMailBlockquotes(const Position&); 182void updatePositionForNodeRemoval(Position&, Node&); 183 184// ------------------------------------------------------------------------- 185// VisiblePosition 186// ------------------------------------------------------------------------- 187 188// Functions returning VisiblePosition 189 190VisiblePosition firstEditableVisiblePositionAfterPositionInRoot(const Position&, ContainerNode*); 191VisiblePosition lastEditableVisiblePositionBeforePositionInRoot(const Position&, ContainerNode*); 192VisiblePosition visiblePositionBeforeNode(Node&); 193VisiblePosition visiblePositionAfterNode(Node&); 194 195bool lineBreakExistsAtVisiblePosition(const VisiblePosition&); 196 197int comparePositions(const VisiblePosition&, const VisiblePosition&); 198 199int indexForVisiblePosition(const VisiblePosition&, RefPtrWillBeRawPtr<ContainerNode>& scope); 200VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope); 201 202// ------------------------------------------------------------------------- 203// Range 204// ------------------------------------------------------------------------- 205 206// Functions returning Range 207 208PassRefPtrWillBeRawPtr<Range> createRange(Document&, const VisiblePosition& start, const VisiblePosition& end, ExceptionState&); 209 210// ------------------------------------------------------------------------- 211// HTMLElement 212// ------------------------------------------------------------------------- 213 214// Functions returning HTMLElement 215 216PassRefPtrWillBeRawPtr<HTMLElement> createDefaultParagraphElement(Document&); 217PassRefPtrWillBeRawPtr<HTMLBRElement> createBreakElement(Document&); 218PassRefPtrWillBeRawPtr<HTMLOListElement> createOrderedListElement(Document&); 219PassRefPtrWillBeRawPtr<HTMLUListElement> createUnorderedListElement(Document&); 220PassRefPtrWillBeRawPtr<HTMLLIElement> createListItemElement(Document&); 221PassRefPtrWillBeRawPtr<HTMLElement> createHTMLElement(Document&, const QualifiedName&); 222PassRefPtrWillBeRawPtr<HTMLElement> createHTMLElement(Document&, const AtomicString&); 223 224HTMLElement* enclosingList(Node*); 225HTMLElement* outermostEnclosingList(Node*, HTMLElement* rootList = 0); 226Node* enclosingListChild(Node*); 227 228// ------------------------------------------------------------------------- 229// Element 230// ------------------------------------------------------------------------- 231 232// Functions returning Element 233 234PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document&); 235PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document&, PassRefPtrWillBeRawPtr<Text> tabTextNode); 236PassRefPtrWillBeRawPtr<HTMLSpanElement> createTabSpanElement(Document&, const String& tabText); 237PassRefPtrWillBeRawPtr<HTMLBRElement> createBlockPlaceholderElement(Document&); 238 239Element* editableRootForPosition(const Position&, EditableType = ContentIsEditable); 240Element* unsplittableElementForPosition(const Position&); 241 242// Boolean functions on Element 243 244bool canMergeLists(Element* firstList, Element* secondList); 245 246// ------------------------------------------------------------------------- 247// VisibleSelection 248// ------------------------------------------------------------------------- 249 250// Functions returning VisibleSelection 251VisibleSelection selectionForParagraphIteration(const VisibleSelection&); 252 253Position adjustedSelectionStartForStyleComputation(const VisibleSelection&); 254 255 256// Miscellaneous functions on Text 257inline 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. 263inline bool isCollapsibleWhitespace(UChar c) 264{ 265 return c == ' ' || c == '\n'; 266} 267 268inline 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 276String stringWithRebalancedWhitespace(const String&, bool startIsStartOfParagraph, bool endIsEndOfParagraph); 277const String& nonBreakingSpaceString(); 278 279} 280 281#endif 282