Home | History | Annotate | Download | only in accessibility
      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 
     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