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/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