blob: 08cd562ecd04496d0d577e22512c8e34ed0ba52b [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/accessibility/ax_text_utils.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
namespace ui {
size_t FindAccessibleTextBoundary(const base::string16& text,
const std::vector<int>& line_breaks,
TextBoundaryType boundary,
size_t start_offset,
TextBoundaryDirection direction) {
size_t text_size = text.size();
DCHECK(start_offset <= text_size);
if (boundary == CHAR_BOUNDARY) {
if (direction == FORWARDS_DIRECTION && start_offset < text_size)
return start_offset + 1;
else
return start_offset;
} else if (boundary == LINE_BOUNDARY) {
if (direction == FORWARDS_DIRECTION) {
for (size_t j = 0; j < line_breaks.size(); ++j) {
size_t line_break = line_breaks[j] >= 0 ? line_breaks[j] : 0;
if (line_break > start_offset)
return line_break;
}
return text_size;
} else {
for (size_t j = line_breaks.size(); j != 0; --j) {
size_t line_break = line_breaks[j - 1] >= 0 ? line_breaks[j - 1] : 0;
if (line_break <= start_offset)
return line_break;
}
return 0;
}
}
size_t result = start_offset;
for (;;) {
size_t pos;
if (direction == FORWARDS_DIRECTION) {
if (result >= text_size)
return text_size;
pos = result;
} else {
if (result == 0)
return 0;
pos = result - 1;
}
switch (boundary) {
case CHAR_BOUNDARY:
case LINE_BOUNDARY:
NOTREACHED(); // These are handled above.
break;
case WORD_BOUNDARY:
if (IsWhitespace(text[pos]))
return result;
break;
case PARAGRAPH_BOUNDARY:
if (text[pos] == '\n')
return result;
break;
case SENTENCE_BOUNDARY:
if ((text[pos] == '.' || text[pos] == '!' || text[pos] == '?') &&
(pos == text_size - 1 || IsWhitespace(text[pos + 1]))) {
return result;
}
break;
case ALL_BOUNDARY:
default:
break;
}
if (direction == FORWARDS_DIRECTION) {
result++;
} else {
result--;
}
}
}
} // Namespace ui