| Index: ui/base/text/text_elider.cc
|
| diff --git a/ui/base/text/text_elider.cc b/ui/base/text/text_elider.cc
|
| index 1a4b79d5e2e9ebbcbeeffdc6e35e79bff4b2b9cb..8cbfb3c3c8821179983c3b07a2a669999528558a 100644
|
| --- a/ui/base/text/text_elider.cc
|
| +++ b/ui/base/text/text_elider.cc
|
| @@ -10,6 +10,7 @@
|
| #include "base/i18n/break_iterator.h"
|
| #include "base/i18n/char_iterator.h"
|
| #include "base/i18n/rtl.h"
|
| +#include "base/scoped_ptr.h"
|
| #include "base/string_split.h"
|
| #include "base/string_util.h"
|
| #include "base/sys_string_conversions.h"
|
| @@ -19,6 +20,8 @@
|
| #include "net/base/net_util.h"
|
| #include "net/base/registry_controlled_domain.h"
|
| #include "ui/gfx/font.h"
|
| +#include "unicode/rbbi.h"
|
| +#include "unicode/uloc.h"
|
|
|
| namespace ui {
|
|
|
| @@ -673,4 +676,67 @@ bool ElideRectangleString(const string16& input, size_t max_rows,
|
| return rect.Finalize();
|
| }
|
|
|
| +string16 TruncateString(const string16& string, size_t length) {
|
| + if (string.size() <= length)
|
| + // String fits, return it.
|
| + return string;
|
| +
|
| + if (length == 0) {
|
| + // No room for the elide string, return an empty string.
|
| + return string16();
|
| + }
|
| + size_t max = length - 1;
|
| +
|
| + // Added to the end of strings that are too big.
|
| + static const char16 kElideString[] = { 0x2026, 0 };
|
| +
|
| + if (max == 0) {
|
| + // Just enough room for the elide string.
|
| + return kElideString;
|
| + }
|
| +
|
| + // Use a line iterator to find the first boundary.
|
| + UErrorCode status = U_ZERO_ERROR;
|
| + scoped_ptr<icu::RuleBasedBreakIterator> bi(
|
| + static_cast<icu::RuleBasedBreakIterator*>(
|
| + icu::RuleBasedBreakIterator::createLineInstance(
|
| + icu::Locale::getDefault(), status)));
|
| + if (U_FAILURE(status))
|
| + return string.substr(0, max) + kElideString;
|
| + bi->setText(string.c_str());
|
| + int32_t index = bi->preceding(static_cast<int32_t>(max));
|
| + if (index == icu::BreakIterator::DONE) {
|
| + index = static_cast<int32_t>(max);
|
| + } else {
|
| + // Found a valid break (may be the beginning of the string). Now use
|
| + // a character iterator to find the previous non-whitespace character.
|
| + icu::StringCharacterIterator char_iterator(string.c_str());
|
| + if (index == 0) {
|
| + // No valid line breaks. Start at the end again. This ensures we break
|
| + // on a valid character boundary.
|
| + index = static_cast<int32_t>(max);
|
| + }
|
| + char_iterator.setIndex(index);
|
| + while (char_iterator.hasPrevious()) {
|
| + char_iterator.previous();
|
| + if (!(u_isspace(char_iterator.current()) ||
|
| + u_charType(char_iterator.current()) == U_CONTROL_CHAR ||
|
| + u_charType(char_iterator.current()) == U_NON_SPACING_MARK)) {
|
| + // Not a whitespace character. Advance the iterator so that we
|
| + // include the current character in the truncated string.
|
| + char_iterator.next();
|
| + break;
|
| + }
|
| + }
|
| + if (char_iterator.hasPrevious()) {
|
| + // Found a valid break point.
|
| + index = char_iterator.getIndex();
|
| + } else {
|
| + // String has leading whitespace, return the elide string.
|
| + return kElideString;
|
| + }
|
| + }
|
| + return string.substr(0, index) + kElideString;
|
| +}
|
| +
|
| } // namespace ui
|
|
|