<rdar://problem/
4386640> AX: AXPreviousSentenceStartTextMarkerForTextMarker does not respect paragraph boundary
<rdar://problem/
4414575> AX: Dictionary popup cannot find some words on Dictionary.app
AXPreviousSentenceStartTextMarkerForTextMarker failed to stop at the beginning a block because
SimplifiedBackwardsTextIterator::handleNonTextNode() emitted a space when exiting the block.
Fixed by emitting a newline instead.
Word boundary failed to stop at the beginning of a block because no character at all was emitted
when leaving the block, because the exitNode was checking specific html tags to decide whether the
node is block, but the node was xml. Fixed by using the node's renderer, if present.
(see related changes in WebKit)
Tests added:
* editing/selection/extend-by-sentence-001.html: Added.
* fast/dom/inner-text-001.html: Added.
* bridge/mac/WebCoreFrameBridge.h:
* bridge/mac/WebCoreFrameBridge.mm:
(-[WebCoreFrameBridge alterCurrentSelection:direction:granularity:]):
Add sentence navigation/selection.
* editing/Selection.cpp:
(WebCore::Selection::validate):
Add sentence navigation/selection.
* editing/SelectionController.cpp:
(WebCore::SelectionController::modifyExtendingRightForward):
(WebCore::SelectionController::modifyMovingRightForward):
(WebCore::SelectionController::modifyExtendingLeftBackward):
(WebCore::SelectionController::modifyMovingLeftBackward):
(WebCore::SelectionController::modify):
Add sentence navigation/selection.
* editing/TextGranularity.h:
(WebCore::):
Add SentenceGranularity and SentenceBoundary.
* editing/TextIterator.cpp:
(WebCore::isTableCell):
(WebCore::shouldEmitTabBeforeNode):
(WebCore::shouldEmitNewlineForNode):
(WebCore::shouldEmitNewlinesBeforeAndAfterNode):
(WebCore::shouldEmitExtraNewlineForNode):
New utility functions that prefer renderers over html tag names.
(WebCore::TextIterator::handleNonTextNode):
(WebCore::TextIterator::exitNode):
(WebCore::SimplifiedBackwardsTextIterator::advance):
Use new utility functions.
(WebCore::SimplifiedBackwardsTextIterator::handleNonTextNode):
Use new utility functions. Also emit linefeed instead of space,
so sentence parsing works across block boundaries.
(WebCore::SimplifiedBackwardsTextIterator::exitNode):
Use new utility functions.
(WebCore::SimplifiedBackwardsTextIterator::emitNewline):
Renamed from emitNewlineForBROrText because it is not always for BR or text.
* editing/TextIterator.h:
Renamed emitNewlineForBROrText to emitNewline.
* editing/visible_units.cpp:
* editing/visible_units.h:
(WebCore::previousBoundary):
(WebCore::nextBoundary):
(WebCore::previousSentencePosition):
(WebCore::nextSentencePosition):
Add sentence navigation/selection.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@13849
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2006-04-12 David Harrison <harrison@apple.com>
+
+ Reviewed by Darin.
+
+ <rdar://problem/4386640> AX: AXPreviousSentenceStartTextMarkerForTextMarker does not respect paragraph boundary
+ <rdar://problem/4414575> AX: Dictionary popup cannot find some words on Dictionary.app
+
+ AXPreviousSentenceStartTextMarkerForTextMarker failed to stop at the beginning a block because
+ SimplifiedBackwardsTextIterator::handleNonTextNode() emitted a space when exiting the block.
+ Fixed by emitting a newline instead.
+
+ Word boundary failed to stop at the beginning of a block because no character at all was emitted
+ when leaving the block, because the exitNode was checking specific html tags to decide whether the
+ node is block, but the node was xml. Fixed by using the node's renderer, if present.
+
+ (see related changes in WebKit)
+
+ Tests added:
+ * editing/selection/extend-by-sentence-001.html: Added.
+ * fast/dom/inner-text-001.html: Added.
+
+ * bridge/mac/WebCoreFrameBridge.h:
+ * bridge/mac/WebCoreFrameBridge.mm:
+ (-[WebCoreFrameBridge alterCurrentSelection:direction:granularity:]):
+ Add sentence navigation/selection.
+
+ * editing/Selection.cpp:
+ (WebCore::Selection::validate):
+ Add sentence navigation/selection.
+
+ * editing/SelectionController.cpp:
+ (WebCore::SelectionController::modifyExtendingRightForward):
+ (WebCore::SelectionController::modifyMovingRightForward):
+ (WebCore::SelectionController::modifyExtendingLeftBackward):
+ (WebCore::SelectionController::modifyMovingLeftBackward):
+ (WebCore::SelectionController::modify):
+ Add sentence navigation/selection.
+
+ * editing/TextGranularity.h:
+ (WebCore::):
+ Add SentenceGranularity and SentenceBoundary.
+
+ * editing/TextIterator.cpp:
+ (WebCore::isTableCell):
+ (WebCore::shouldEmitTabBeforeNode):
+ (WebCore::shouldEmitNewlineForNode):
+ (WebCore::shouldEmitNewlinesBeforeAndAfterNode):
+ (WebCore::shouldEmitExtraNewlineForNode):
+ New utility functions that prefer renderers over html tag names.
+
+ (WebCore::TextIterator::handleNonTextNode):
+ (WebCore::TextIterator::exitNode):
+ (WebCore::SimplifiedBackwardsTextIterator::advance):
+ Use new utility functions.
+
+ (WebCore::SimplifiedBackwardsTextIterator::handleNonTextNode):
+ Use new utility functions. Also emit linefeed instead of space,
+ so sentence parsing works across block boundaries.
+
+ (WebCore::SimplifiedBackwardsTextIterator::exitNode):
+ Use new utility functions.
+
+ (WebCore::SimplifiedBackwardsTextIterator::emitNewline):
+ Renamed from emitNewlineForBROrText because it is not always for BR or text.
+
+ * editing/TextIterator.h:
+ Renamed emitNewlineForBROrText to emitNewline.
+
+ * editing/visible_units.cpp:
+ * editing/visible_units.h:
+ (WebCore::previousBoundary):
+ (WebCore::nextBoundary):
+ (WebCore::previousSentencePosition):
+ (WebCore::nextSentencePosition):
+ Add sentence navigation/selection.
+
2006-04-12 Darin Adler <darin@apple.com>
Rubber-stamped by Hyatt.
typedef enum {
WebBridgeSelectByCharacter,
WebBridgeSelectByWord,
+ WebBridgeSelectBySentence,
WebBridgeSelectByLine,
WebBridgeSelectByParagraph,
+ WebBridgeSelectToSentenceBoundary,
WebBridgeSelectToLineBoundary,
WebBridgeSelectToParagraphBoundary,
WebBridgeSelectToDocumentBoundary
break;
case WebBridgeSelectByCharacter:
case WebBridgeSelectByWord:
+ case WebBridgeSelectBySentence:
case WebBridgeSelectToLineBoundary:
case WebBridgeSelectToParagraphBoundary:
+ case WebBridgeSelectToSentenceBoundary:
case WebBridgeSelectToDocumentBoundary:
break;
}
m_end = endOfWord(end, side).deepEquivalent();
break;
}
+ case SentenceGranularity: {
+ m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent();
+ m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent();
+ break;
+ }
case LineGranularity: {
m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent();
VisiblePosition end = endOfLine(VisiblePosition(m_end, m_affinity));
m_start = startOfParagraph(VisiblePosition(m_start, m_affinity)).deepEquivalent();
m_end = endOfParagraph(VisiblePosition(m_end, m_affinity)).deepEquivalent();
break;
+ case SentenceBoundary:
+ m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent();
+ m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent();
+ break;
}
adjustForEditableContent();
else
pos = nextWordPosition(pos);
break;
- case ParagraphGranularity:
- pos = nextParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
+ case SentenceGranularity:
+ pos = nextSentencePosition(pos);
break;
case LineGranularity:
pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
break;
+ case ParagraphGranularity:
+ pos = nextParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
+ break;
+ case SentenceBoundary:
+ pos = endOfSentence(VisiblePosition(m_sel.end(), m_sel.affinity()));
+ break;
case LineBoundary:
pos = endOfLine(VisiblePosition(m_sel.end(), m_sel.affinity()));
break;
case WordGranularity:
pos = nextWordPosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));
break;
- case ParagraphGranularity:
- pos = nextParagraphPosition(VisiblePosition(m_sel.end(), m_sel.affinity()), xPosForVerticalArrowNavigation(END, isRange()));
+ case SentenceGranularity:
+ pos = nextSentencePosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));
break;
case LineGranularity: {
// down-arrowing from a range selection that ends at the start of a line needs
pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(END, isRange()));
break;
}
+ case ParagraphGranularity:
+ pos = nextParagraphPosition(VisiblePosition(m_sel.end(), m_sel.affinity()), xPosForVerticalArrowNavigation(END, isRange()));
+ break;
+ case SentenceBoundary:
+ pos = endOfSentence(VisiblePosition(m_sel.end(), m_sel.affinity()));
+ break;
case LineBoundary:
pos = endOfLine(VisiblePosition(m_sel.end(), m_sel.affinity()));
break;
else
pos = previousWordPosition(pos);
break;
- case ParagraphGranularity:
- pos = previousParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
+ case SentenceGranularity:
+ pos = previousSentencePosition(pos);
break;
case LineGranularity:
pos = previousLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
break;
+ case ParagraphGranularity:
+ pos = previousParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
+ break;
+ case SentenceBoundary:
+ pos = startOfSentence(VisiblePosition(m_sel.start(), m_sel.affinity()));
+ break;
case LineBoundary:
pos = startOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));
break;
case WordGranularity:
pos = previousWordPosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));
break;
- case ParagraphGranularity:
- pos = previousParagraphPosition(VisiblePosition(m_sel.start(), m_sel.affinity()), xPosForVerticalArrowNavigation(START, isRange()));
+ case SentenceGranularity:
+ pos = previousSentencePosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));
break;
case LineGranularity:
pos = previousLinePosition(VisiblePosition(m_sel.start(), m_sel.affinity()), xPosForVerticalArrowNavigation(START, isRange()));
break;
+ case ParagraphGranularity:
+ pos = previousParagraphPosition(VisiblePosition(m_sel.start(), m_sel.affinity()), xPosForVerticalArrowNavigation(START, isRange()));
+ break;
+ case SentenceBoundary:
+ pos = startOfSentence(VisiblePosition(m_sel.start(), m_sel.affinity()));
+ break;
case LineBoundary:
pos = startOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));
break;
granularity = CharacterGranularity;
else if (granularityStringLower == "word")
granularity = WordGranularity;
+ else if (granularityStringLower == "sentence")
+ granularity = SentenceGranularity;
else if (granularityStringLower == "line")
granularity = LineGranularity;
else if (granularityStringLower == "paragraph")
// FIXME: This really should be broken up into more than one concept.
// Frame doesn't neeed the 3 boundaries in this enum.
+// NOTE: This MUST match WebBridgeSelectionGranularity
enum TextGranularity {
CharacterGranularity,
WordGranularity,
+ SentenceGranularity,
LineGranularity,
ParagraphGranularity,
+ SentenceBoundary,
LineBoundary,
ParagraphBoundary,
DocumentBoundary
#include "Document.h"
#include "Element.h"
#include "HTMLNames.h"
-
-// FIXME: These classes should probably use the render tree and not the DOM tree, since elements could
-// be hidden using CSS, or additional generated content could be added. For now, we just make sure
-// text objects walk their renderers' InlineTextBox objects, so that we at least get the whitespace
-// stripped out properly and obey CSS visibility for text runs.
+#include "htmlediting.h"
+#include "InlineTextBox.h"
+#include "Position.h"
+#include "Range.h"
+#include "RenderTableCell.h"
+#include "RenderTableRow.h"
namespace WebCore {
return true;
}
+static bool isTableCell(Node* node)
+{
+ RenderObject* r = node->renderer();
+ if (!r)
+ return node->hasTagName(tdTag) || node->hasTagName(thTag);
+
+ return r->isTableCell();
+}
+
+static bool shouldEmitTabBeforeNode(Node* node)
+{
+ // Table cells are delimited by tabs.
+ if (!isTableCell(node))
+ return false;
+
+ // Want a tab before every cell other than the first one
+ RenderObject* r = node->renderer();
+ RenderTableCell* rc = static_cast<RenderTableCell*>(r);
+ RenderTable* t = rc->table();
+ return t && (t->cellBefore(rc) || t->cellAbove(rc));
+}
+
+static bool shouldEmitNewlineForNode(Node* node)
+{
+ // br elements are represented by a single newline.
+ RenderObject* r = node->renderer();
+ if (!r)
+ return node->hasTagName(brTag);
+
+ return r->isBR();
+}
+
+static bool shouldEmitNewlinesBeforeAndAfterNode(Node* node)
+{
+ // Block flow (versus inline flow) is represented by having
+ // a newline both before and after the element.
+ RenderObject* r = node->renderer();
+ if (!r) {
+ return (node->hasTagName(blockquoteTag)
+ || node->hasTagName(ddTag)
+ || node->hasTagName(divTag)
+ || node->hasTagName(dlTag)
+ || node->hasTagName(dtTag)
+ || node->hasTagName(h1Tag)
+ || node->hasTagName(h2Tag)
+ || node->hasTagName(h3Tag)
+ || node->hasTagName(h4Tag)
+ || node->hasTagName(h5Tag)
+ || node->hasTagName(h6Tag)
+ || node->hasTagName(hrTag)
+ || node->hasTagName(liTag)
+ || node->hasTagName(listingTag)
+ || node->hasTagName(olTag)
+ || node->hasTagName(pTag)
+ || node->hasTagName(preTag)
+ || node->hasTagName(trTag)
+ || node->hasTagName(ulTag));
+ }
+
+ // Need to make an exception for table cells, because they are blocks, but we
+ // want them tab-delimited rather than having newlines before and after.
+ if (isTableCell(node))
+ return false;
+
+ // Need to make an exception for table row elements, because they are neither
+ // "inline" or "RenderBlock", but we want newlines for them.
+ if (r->isTableRow()) {
+ RenderTable* t = static_cast<RenderTableRow*>(r)->table();
+ if (t && !t->isInline())
+ return true;
+ }
+
+ // Check for non-inline block
+ return !r->isInline() && r->isRenderBlock() && !r->isBody();
+}
+
+static bool shouldEmitExtraNewlineForNode(Node* node)
+{
+ // When there is a significant collapsed bottom margin, emit an extra
+ // newline for a more realistic result. We end up getting the right
+ // result even without margin collapsing. For example: <div><p>text</p></div>
+ // will work right even if both the <div> and the <p> have bottom margins.
+ RenderObject* r = node->renderer();
+ if (!r)
+ return false;
+
+ // NOTE: We only do this for a select set of nodes, and fwiw WinIE appears
+ // not to do this at all
+ if (node->hasTagName(h1Tag)
+ || node->hasTagName(h2Tag)
+ || node->hasTagName(h3Tag)
+ || node->hasTagName(h4Tag)
+ || node->hasTagName(h5Tag)
+ || node->hasTagName(h6Tag)
+ || node->hasTagName(pTag)) {
+ RenderStyle* style = r->style();
+ if (style) {
+ int bottomMargin = r->collapsedMarginBottom();
+ int fontSize = style->fontDescription().computedPixelSize();
+ if (bottomMargin * 2 >= fontSize)
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool TextIterator::handleNonTextNode()
{
- if (m_node->hasTagName(brTag)) {
+ if (shouldEmitNewlineForNode(m_node)) {
emitCharacter('\n', m_node->parentNode(), m_node, 0, 1);
- } else if (m_node->hasTagName(tdTag) || m_node->hasTagName(thTag)) {
- if (m_lastCharacter != '\n' && m_lastTextNode)
+ } else if (m_lastCharacter != '\n' && m_lastTextNode) {
+ // only add the tab or newline if not at the start of a line
+ if (shouldEmitTabBeforeNode(m_node))
emitCharacter('\t', m_lastTextNode->parentNode(), m_lastTextNode, 0, 1);
- } else if (m_node->hasTagName(blockquoteTag)
- || m_node->hasTagName(ddTag)
- || m_node->hasTagName(divTag)
- || m_node->hasTagName(dlTag)
- || m_node->hasTagName(dtTag)
- || m_node->hasTagName(h1Tag)
- || m_node->hasTagName(h2Tag)
- || m_node->hasTagName(h3Tag)
- || m_node->hasTagName(h4Tag)
- || m_node->hasTagName(h5Tag)
- || m_node->hasTagName(h6Tag)
- || m_node->hasTagName(hrTag)
- || m_node->hasTagName(liTag)
- || m_node->hasTagName(listingTag)
- || m_node->hasTagName(olTag)
- || m_node->hasTagName(pTag)
- || m_node->hasTagName(preTag)
- || m_node->hasTagName(trTag)
- || m_node->hasTagName(ulTag)) {
- if (m_lastCharacter != '\n' && m_lastTextNode)
+ else if (shouldEmitNewlinesBeforeAndAfterNode(m_node))
emitCharacter('\n', m_lastTextNode->parentNode(), m_lastTextNode, 0, 1);
}
void TextIterator::exitNode()
{
- bool endLine = false;
- bool addNewline = false;
-
- if (m_node->hasTagName(blockquoteTag)
- || m_node->hasTagName(ddTag)
- || m_node->hasTagName(divTag)
- || m_node->hasTagName(dlTag)
- || m_node->hasTagName(dtTag)
- || m_node->hasTagName(hrTag)
- || m_node->hasTagName(liTag)
- || m_node->hasTagName(listingTag)
- || m_node->hasTagName(olTag)
- || m_node->hasTagName(preTag)
- || m_node->hasTagName(trTag)
- || m_node->hasTagName(ulTag))
- endLine = true;
- else if (m_node->hasTagName(h1Tag)
- || m_node->hasTagName(h2Tag)
- || m_node->hasTagName(h3Tag)
- || m_node->hasTagName(h4Tag)
- || m_node->hasTagName(h5Tag)
- || m_node->hasTagName(h6Tag)
- || m_node->hasTagName(pTag)) {
- endLine = true;
-
- // In certain cases, emit a new newline character for this node
- // regardless of whether we emit another one.
- // FIXME: Some day we could do this for other tags.
- // However, doing it just for the tags above makes it more likely
- // we'll end up getting the right result without margin collapsing.
- // For example: <div><p>text</p></div> will work right even if both
- // the <div> and the <p> have bottom margins.
- RenderObject *renderer = m_node->renderer();
- if (renderer) {
- RenderStyle *style = renderer->style();
- if (style) {
- int bottomMargin = renderer->collapsedMarginBottom();
- int fontSize = style->fontDescription().computedPixelSize();
- if (bottomMargin * 2 >= fontSize)
- addNewline = true;
- }
- }
- }
-
- // emit character(s) iff there is an earlier text node and we need at least one newline
- if (m_lastTextNode && endLine) {
+ if (m_lastTextNode && shouldEmitNewlinesBeforeAndAfterNode(m_node)) {
+ // use extra newline to represent margin bottom, as needed
+ bool addNewline = shouldEmitExtraNewlineForNode(m_node);
+
if (m_lastCharacter != '\n') {
// insert a newline with a position following this block
emitCharacter('\n', m_node->parentNode(), m_node, 1, 1);
- //...and, if needed, set flag to later add a newline for the current node
+ // remember whether to later add a newline for the current node
assert(!m_needAnotherNewline);
m_needAnotherNewline = addNewline;
} else if (addNewline) {
if (block) {
Node *nextBlock = next->enclosingBlockFlowElement();
if (nextBlock && nextBlock->isAncestor(block))
- emitNewlineForBROrText();
+ emitNewline();
}
}
}
bool SimplifiedBackwardsTextIterator::handleNonTextNode()
-{
- if (m_node->hasTagName(brTag))
- emitNewlineForBROrText();
- else if (m_node->hasTagName(blockquoteTag)
- || m_node->hasTagName(ddTag)
- || m_node->hasTagName(divTag)
- || m_node->hasTagName(dlTag)
- || m_node->hasTagName(dtTag)
- || m_node->hasTagName(h1Tag)
- || m_node->hasTagName(h2Tag)
- || m_node->hasTagName(h3Tag)
- || m_node->hasTagName(h4Tag)
- || m_node->hasTagName(h5Tag)
- || m_node->hasTagName(h6Tag)
- || m_node->hasTagName(hrTag)
- || m_node->hasTagName(liTag)
- || m_node->hasTagName(listingTag)
- || m_node->hasTagName(olTag)
- || m_node->hasTagName(pTag)
- || m_node->hasTagName(preTag)
- || m_node->hasTagName(tdTag)
- || m_node->hasTagName(thTag)
- || m_node->hasTagName(trTag)
- || m_node->hasTagName(ulTag)) {
- // Emit a space to "break up" content. Any word break
- // character will do.
- emitCharacter(' ', m_node, 0, 0);
- }
-
+{
+ // We can use a linefeed in place of a tab because this simple iterator is only used to
+ // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs.
+ if (shouldEmitNewlineForNode(m_node) ||
+ shouldEmitNewlinesBeforeAndAfterNode(m_node) ||
+ shouldEmitTabBeforeNode(m_node))
+ emitNewline();
+
return true;
}
void SimplifiedBackwardsTextIterator::exitNode()
{
- // Left this function in so that the name and usage patters remain similar to
+ // Left this function in so that the name and usage patterns remain similar to
// TextIterator. However, the needs of this iterator are much simpler, and
// the handleNonTextNode() function does just what we want (i.e. insert a
- // space for certain node types to "break up" text so that it does not seem
+ // BR for certain node types to "break up" text so that it does not seem
// like content is next to other text when it really isn't).
handleNonTextNode();
}
m_lastCharacter = c;
}
-void SimplifiedBackwardsTextIterator::emitNewlineForBROrText()
+void SimplifiedBackwardsTextIterator::emitNewline()
{
int offset;
bool handleReplacedElement();
bool handleNonTextNode();
void emitCharacter(QChar, Node *Node, int startOffset, int endOffset);
- void emitNewlineForBROrText();
+ void emitNewline();
// Current position, not necessarily of the text being returned, but position
// as we walk through the DOM tree.
if (it.atEnd() && next == 0) {
RefPtr<Range> range(it.range());
pos = Position(range->startContainer(exception), range->startOffset(exception));
- }
- else if (!it.atEnd() && it.length() == 0) {
+ } else if (!it.atEnd() && it.length() == 0) {
// Got a zero-length chunk.
// This means we have hit a replaced element.
// Make a check to see if the position should be before or after the replaced element
pos = Position(range->startContainer(exception), range->startOffset(exception));
else
pos = Position(range->endContainer(exception), range->endOffset(exception));
- }
- else if (next != 0) {
+ } else if (next != 0) {
// The simpler iterator used in this function, as compared to the one used in
// nextWordPosition(), gives us results we can use directly without having to
// iterate again to translate the next value into a DOM position.
RefPtr<Range> range(it.range());
int exception = 0;
pos = Position(range->startContainer(exception), range->startOffset(exception));
- }
- else if (!it.atEnd() && it.length() == 0) {
+ } else if (!it.atEnd() && it.length() == 0) {
// Got a zero-length chunk.
// This means we have hit a replaced element.
// Make a check to see if the position should be before or after the replaced element
pos = Position(range->endContainer(exception), range->endOffset(exception));
else
pos = Position(range->startContainer(exception), range->startOffset(exception));
- }
- else if (next != 0) {
+ } else if (next != 0) {
// Use the character iterator to translate the next value into a DOM position.
CharacterIterator charIt(searchRange.get());
charIt.advance(next - 1);
return findNextSentenceFromIndex(characters, length, length, false);
}
-VisiblePosition previousSentencePosition(const VisiblePosition &c, int x)
+VisiblePosition previousSentencePosition(const VisiblePosition &c)
{
return previousBoundary(c, previousSentencePositionBoundary);
}
return findNextSentenceFromIndex(characters, length, 0, true);
}
-VisiblePosition nextSentencePosition(const VisiblePosition &c, int x)
+VisiblePosition nextSentencePosition(const VisiblePosition &c)
{
return nextBoundary(c, nextSentencePositionBoundary);
}
VisiblePosition previousWordPosition(const VisiblePosition &);
VisiblePosition nextWordPosition(const VisiblePosition &);
+// sentences
+VisiblePosition startOfSentence(const VisiblePosition &);
+VisiblePosition endOfSentence(const VisiblePosition &);
+VisiblePosition previousSentencePosition(const VisiblePosition &);
+VisiblePosition nextSentencePosition(const VisiblePosition &);
+
// lines
VisiblePosition startOfLine(const VisiblePosition &);
VisiblePosition endOfLine(const VisiblePosition &);
bool isStartOfLine(const VisiblePosition &);
bool isEndOfLine(const VisiblePosition &);
-// sentences
-VisiblePosition startOfSentence(const VisiblePosition &);
-VisiblePosition endOfSentence(const VisiblePosition &);
-VisiblePosition previousSentencePosition(const VisiblePosition &);
-VisiblePosition nextSentencePosition(const VisiblePosition &);
-
// paragraphs (perhaps a misnomer, can be divided by line break elements)
VisiblePosition startOfParagraph(const VisiblePosition &);
VisiblePosition endOfParagraph(const VisiblePosition &);