• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/accessibility/ax_text_utils.h"
6 
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 
10 namespace ui {
11 
FindAccessibleTextBoundary(const base::string16 & text,const std::vector<int> & line_breaks,TextBoundaryType boundary,size_t start_offset,TextBoundaryDirection direction)12 size_t FindAccessibleTextBoundary(const base::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       for (size_t j = line_breaks.size(); j != 0; --j) {
35         size_t line_break = line_breaks[j - 1] >= 0 ? line_breaks[j - 1] : 0;
36         if (line_break <= start_offset)
37           return line_break;
38       }
39       return 0;
40     }
41   }
42 
43   size_t result = start_offset;
44   for (;;) {
45     size_t pos;
46     if (direction == FORWARDS_DIRECTION) {
47       if (result >= text_size)
48         return text_size;
49       pos = result;
50     } else {
51       if (result == 0)
52         return 0;
53       pos = result - 1;
54     }
55 
56     switch (boundary) {
57       case CHAR_BOUNDARY:
58       case LINE_BOUNDARY:
59         NOTREACHED();  // These are handled above.
60         break;
61       case WORD_BOUNDARY:
62         if (IsWhitespace(text[pos]))
63           return result;
64         break;
65       case PARAGRAPH_BOUNDARY:
66         if (text[pos] == '\n')
67           return result;
68         break;
69       case SENTENCE_BOUNDARY:
70         if ((text[pos] == '.' || text[pos] == '!' || text[pos] == '?') &&
71             (pos == text_size - 1 || IsWhitespace(text[pos + 1]))) {
72           return result;
73         }
74         break;
75       case ALL_BOUNDARY:
76       default:
77         break;
78     }
79 
80     if (direction == FORWARDS_DIRECTION) {
81       result++;
82     } else {
83       result--;
84     }
85   }
86 }
87 
88 }  // Namespace ui
89