15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_text_utils.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
85e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)size_t FindAccessibleTextBoundary(const base::string16& text,
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::vector<int>& line_breaks,
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  TextBoundaryType boundary,
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  size_t start_offset,
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  TextBoundaryDirection direction) {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t text_size = text.size();
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(start_offset <= text_size);
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (boundary == CHAR_BOUNDARY) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (direction == FORWARDS_DIRECTION && start_offset < text_size)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return start_offset + 1;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return start_offset;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (boundary == LINE_BOUNDARY) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (direction == FORWARDS_DIRECTION) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t j = 0; j < line_breaks.size(); ++j) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size_t line_break = line_breaks[j] >= 0 ? line_breaks[j] : 0;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (line_break > start_offset)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return line_break;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return text_size;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      for (size_t j = line_breaks.size(); j != 0; --j) {
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        size_t line_break = line_breaks[j - 1] >= 0 ? line_breaks[j - 1] : 0;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (line_break <= start_offset)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return line_break;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t result = start_offset;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t pos;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (direction == FORWARDS_DIRECTION) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result >= text_size)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return text_size;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos = result;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (result == 0)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pos = result - 1;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (boundary) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case CHAR_BOUNDARY:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case LINE_BOUNDARY:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();  // These are handled above.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case WORD_BOUNDARY:
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (IsWhitespace(text[pos]))
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return result;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case PARAGRAPH_BOUNDARY:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (text[pos] == '\n')
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return result;
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case SENTENCE_BOUNDARY:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((text[pos] == '.' || text[pos] == '!' || text[pos] == '?') &&
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (pos == text_size - 1 || IsWhitespace(text[pos + 1]))) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return result;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ALL_BOUNDARY:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (direction == FORWARDS_DIRECTION) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result++;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result--;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // Namespace ui
89