Index: ui/gfx/render_text.cc |
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc |
index 91f9f42bd89ad69dad47646e52c08516e9cad394..a80f0e0e9634d3ebdbf76b835a1ea615f3672202 100644 |
--- a/ui/gfx/render_text.cc |
+++ b/ui/gfx/render_text.cc |
@@ -789,6 +789,49 @@ SelectionModel RenderText::GetAdjacentSelectionModel( |
return AdjacentWordSelectionModel(current, direction); |
} |
+SelectionModel RenderText::AdjacentWordSelectionModel( |
+ const SelectionModel& selection, |
+ VisualCursorDirection direction) { |
+ if (obscured()) |
+ return EdgeSelectionModel(direction); |
+ |
+ base::i18n::BreakIterator iter(text(), base::i18n::BreakIterator::BREAK_WORD); |
+ bool success = iter.Init(); |
+ DCHECK(success); |
+ if (!success) |
+ return selection; |
+ |
+ size_t pos = 0; |
+ // TODO(msw): Cache a list of word breaks or add WordIterator functionality to |
+ // start from supplied indices and to iterate backward for better performance. |
+ if (direction == CURSOR_RIGHT) { |
+ pos = std::min(selection.caret_pos() + 1, text().length()); |
+ while (iter.Advance()) { |
+ pos = iter.pos(); |
+ if (iter.IsWord() && pos > selection.caret_pos()) |
+ break; |
+ } |
+ } else { |
+ pos = std::max<int>(selection.caret_pos() - 1, 0); |
+ while (iter.Advance()) { |
+ if (iter.IsWord()) { |
+ size_t begin = iter.pos() - iter.GetString().length(); |
+ if (begin == selection.caret_pos()) { |
+ // The cursor is at a word beginning; move it to the previous word. |
+ break; |
+ } else if (iter.pos() >= selection.caret_pos()) { |
+ // The cursor is at a word middle or end; move it to its beginning. |
+ pos = begin; |
+ break; |
+ } else { |
+ pos = iter.pos() - iter.GetString().length(); |
+ } |
+ } |
+ } |
+ } |
+ return SelectionModel(pos, CURSOR_FORWARD); |
+} |
+ |
SelectionModel RenderText::EdgeSelectionModel( |
VisualCursorDirection direction) { |
if (direction == GetVisualDirectionOfLogicalEnd()) |