1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/base/accessibility/accessible_text_utils.h" 6 7 #include "base/logging.h" 8 #include "base/strings/string_util.h" 9 10 namespace ui { 11 12 size_t FindAccessibleTextBoundary(const string16& text, 13 const std::vector<int>& line_breaks, 14 TextBoundaryType boundary, 15 size_t start_offset, 16 TextBoundaryDirection direction) { 17 size_t text_size = text.size(); 18 DCHECK(start_offset <= text_size); 19 20 if (boundary == CHAR_BOUNDARY) { 21 if (direction == FORWARDS_DIRECTION && start_offset < text_size) 22 return start_offset + 1; 23 else 24 return start_offset; 25 } else if (boundary == LINE_BOUNDARY) { 26 if (direction == FORWARDS_DIRECTION) { 27 for (size_t j = 0; j < line_breaks.size(); ++j) { 28 size_t line_break = line_breaks[j] >= 0 ? line_breaks[j] : 0; 29 if (line_break > start_offset) 30 return line_break; 31 } 32 return text_size; 33 } else { 34 // Note: j is unsigned, so for loop continues until j wraps around 35 // and becomes greater than the starting value. 36 for (size_t j = line_breaks.size() - 1; 37 j < line_breaks.size(); 38 --j) { 39 size_t line_break = line_breaks[j] >= 0 ? line_breaks[j] : 0; 40 if (line_break <= start_offset) 41 return line_break; 42 } 43 return 0; 44 } 45 } 46 47 size_t result = start_offset; 48 for (;;) { 49 size_t pos; 50 if (direction == FORWARDS_DIRECTION) { 51 if (result >= text_size) 52 return text_size; 53 pos = result; 54 } else { 55 if (result == 0) 56 return 0; 57 pos = result - 1; 58 } 59 60 switch (boundary) { 61 case CHAR_BOUNDARY: 62 case LINE_BOUNDARY: 63 NOTREACHED(); // These are handled above. 64 break; 65 case WORD_BOUNDARY: 66 if (IsWhitespace(text[pos])) 67 return result; 68 break; 69 case PARAGRAPH_BOUNDARY: 70 if (text[pos] == '\n') 71 return result; 72 case SENTENCE_BOUNDARY: 73 if ((text[pos] == '.' || text[pos] == '!' || text[pos] == '?') && 74 (pos == text_size - 1 || IsWhitespace(text[pos + 1]))) { 75 return result; 76 } 77 case ALL_BOUNDARY: 78 default: 79 break; 80 } 81 82 if (direction == FORWARDS_DIRECTION) { 83 result++; 84 } else { 85 result--; 86 } 87 } 88 } 89 90 } // Namespace ui 91