PassRefPtr<StringImpl> StringImpl::capitalize(UChar previous) { StringBuffer stringWithPrevious(m_length + 1); stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous; for (unsigned i = 1; i < m_length + 1; i++) { // Replace   with a real space since ICU no longer treats   as a word separator. if (m_data[i - 1] == noBreakSpace) stringWithPrevious[i] = ' '; else stringWithPrevious[i] = m_data[i - 1]; } TextBreakIterator* boundary = wordBreakIterator(stringWithPrevious.characters(), m_length + 1); if (!boundary) return this; StringBuffer data(m_length); int32_t endOfWord; int32_t startOfWord = textBreakFirst(boundary); for (endOfWord = textBreakNext(boundary); endOfWord != TextBreakDone; startOfWord = endOfWord, endOfWord = textBreakNext(boundary)) { if (startOfWord != 0) // Ignore first char of previous string data[startOfWord - 1] = m_data[startOfWord - 1] == noBreakSpace ? noBreakSpace : toTitleCase(stringWithPrevious[startOfWord]); for (int i = startOfWord + 1; i < endOfWord; i++) data[i - 1] = m_data[i - 1]; } return adopt(data); }
static void findMisspellings(TextCheckerClient& client, StringView text, Vector<TextCheckingResult>& results) { TextBreakIterator* iterator = wordBreakIterator(text); if (!iterator) return; for (int wordStart = textBreakCurrent(iterator); wordStart > 0; ) { int wordEnd = textBreakNext(iterator); if (wordEnd < 0) break; int wordLength = wordEnd - wordStart; int misspellingLocation = -1; int misspellingLength = 0; client.checkSpellingOfString(text.substring(wordStart, wordLength), &misspellingLocation, &misspellingLength); if (misspellingLength > 0) { ASSERT(misspellingLocation >= 0); ASSERT(misspellingLocation <= wordLength); ASSERT(misspellingLength > 0); ASSERT(misspellingLocation + misspellingLength <= wordLength); TextCheckingResult misspelling; misspelling.type = TextCheckingTypeSpelling; misspelling.location = wordStart + misspellingLocation; misspelling.length = misspellingLength; misspelling.replacement = client.getAutoCorrectSuggestionForMisspelledWord(text.substring(misspelling.location, misspelling.length).toStringWithoutCopying()); results.append(misspelling); } wordStart = wordEnd; } }
int findNextWordFromIndex(const UChar* chars, int len, int position, bool forward) { UBreakIterator* it = wordBreakIterator(chars, len); if (forward) { position = ubrk_following(it, position); while (position != UBRK_DONE) { // We stop searching when the character preceeding the break // is alphanumeric. if (position < len && u_isalnum(chars[position - 1])) return position; position = ubrk_following(it, position); } return len; } else { position = ubrk_preceding(it, position); while (position != UBRK_DONE) { // We stop searching when the character following the break // is alphanumeric. if (position > 0 && u_isalnum(chars[position])) return position; position = ubrk_preceding(it, position); } return 0; } }
static void findMisspellings(TextCheckerClient* client, const UChar* text, int start, int length, Vector<TextCheckingResult>& results) { TextBreakIterator* iterator = wordBreakIterator(text + start, length); if (!iterator) return; int wordStart = textBreakCurrent(iterator); while (0 <= wordStart) { int wordEnd = textBreakNext(iterator); if (wordEnd < 0) break; int wordLength = wordEnd - wordStart; int misspellingLocation = -1; int misspellingLength = 0; client->checkSpellingOfString(text + start + wordStart, wordLength, &misspellingLocation, &misspellingLength); if (0 < misspellingLength) { ASSERT(0 <= misspellingLocation && misspellingLocation <= wordLength); ASSERT(0 < misspellingLength && misspellingLocation + misspellingLength <= wordLength); TextCheckingResult misspelling; misspelling.type = TextCheckingTypeSpelling; misspelling.location = start + wordStart + misspellingLocation; misspelling.length = misspellingLength; misspelling.replacement = client->getAutoCorrectSuggestionForMisspelledWord(String(text + misspelling.location, misspelling.length)); results.append(misspelling); } wordStart = wordEnd; } }
int findNextWordFromIndex(StringView text, int position, bool forward) { TextBreakIterator* it = wordBreakIterator(text); if (forward) { position = textBreakFollowing(it, position); while (position != TextBreakDone) { // We stop searching when the character preceeding the break is alphanumeric. if (static_cast<unsigned>(position) < text.length() && u_isalnum(text[position - 1])) return position; position = textBreakFollowing(it, position); } return text.length(); } else { position = textBreakPreceding(it, position); while (position != TextBreakDone) { // We stop searching when the character following the break is alphanumeric. if (position && u_isalnum(text[position])) return position; position = textBreakPreceding(it, position); } return 0; } }
static int nextWordOffset(const UChar* text, int length, int currentOffset) { // FIXME: avoid creating textIterator object here, it could be passed as a parameter. // isTextBreak() leaves the iterator pointing to the first boundary position at // or after "offset" (ubrk_isBoundary side effect). // For many word separators, the method doesn't properly determine the boundaries // without resetting the iterator. TextBreakIterator* textIterator = wordBreakIterator(StringView(text, length)); if (!textIterator) return currentOffset; int wordOffset = currentOffset; while (wordOffset < length && isTextBreak(textIterator, wordOffset)) ++wordOffset; // Do not treat the word's boundary as a separator. if (!currentOffset && wordOffset == 1) return currentOffset; // Omit multiple separators. if ((wordOffset - currentOffset) > 1) --wordOffset; return wordOffset; }
void findEndWordBoundary(StringView text, int position, int* end) { TextBreakIterator* it = wordBreakIterator(text); *end = textBreakFollowing(it, position); if (*end < 0) *end = textBreakLast(it); }
static unsigned nextWordOffset(StringView text, unsigned currentOffset) { // FIXME: avoid creating textIterator object here, it could be passed as a parameter. // ubrk_isBoundary() leaves the iterator pointing to the first boundary position at // or after "offset" (ubrk_isBoundary side effect). // For many word separators, the method doesn't properly determine the boundaries // without resetting the iterator. UBreakIterator* textIterator = wordBreakIterator(text); if (!textIterator) return currentOffset; unsigned wordOffset = currentOffset; while (wordOffset < text.length() && ubrk_isBoundary(textIterator, wordOffset)) ++wordOffset; // Do not treat the word's boundary as a separator. if (!currentOffset && wordOffset == 1) return currentOffset; // Omit multiple separators. if ((wordOffset - currentOffset) > 1) --wordOffset; return wordOffset; }
int findNextWordFromIndex(const UChar* chars, int len, int position, bool forward) { TextBreakIterator* it = wordBreakIterator(chars, len); if (forward) { position = it->following(position); while (position != TextBreakDone) { // We stop searching when the character preceeding the break // is alphanumeric. if (position < len && isAlphanumeric(chars[position - 1])) return position; position = it->following(position); } return len; } else { position = it->preceding(position); while (position != TextBreakDone) { // We stop searching when the character following the break // is alphanumeric. if (position > 0 && isAlphanumeric(chars[position])) return position; position = it->preceding(position); } return 0; } }
static void findMisspellings(TextCheckerClient& client, const UChar* text, int start, int length, Vector<TextCheckingResult>& results) { TextBreakIterator* iterator = wordBreakIterator(text + start, length); if (!iterator) return; int wordStart = iterator->current(); while (0 <= wordStart) { int wordEnd = iterator->next(); if (wordEnd < 0) break; int wordLength = wordEnd - wordStart; int misspellingLocation = -1; int misspellingLength = 0; client.checkSpellingOfString(String(text + start + wordStart, wordLength), &misspellingLocation, &misspellingLength); if (0 < misspellingLength) { ASSERT(0 <= misspellingLocation && misspellingLocation <= wordLength); ASSERT(0 < misspellingLength && misspellingLocation + misspellingLength <= wordLength); TextCheckingResult misspelling; misspelling.decoration = TextDecorationTypeSpelling; misspelling.location = start + wordStart + misspellingLocation; misspelling.length = misspellingLength; results.append(misspelling); } wordStart = wordEnd; } }
void findWordBoundary(const UChar* chars, int len, int position, int* start, int* end) { TextBreakIterator* it = wordBreakIterator(chars, len); *end = textBreakFollowing(it, position); if (*end < 0) *end = WebKitApollo::g_HostFunctions->textBreakLast(reinterpret_cast<void*>(it)); *start = WebKitApollo::g_HostFunctions->textBreakPrev(reinterpret_cast<void*>(it)); }
void findWordBoundary(const UChar* chars, int len, int position, int* start, int* end) { TextBreakIterator* it = wordBreakIterator(chars, len); *end = textBreakFollowing(it, position); if (*end < 0) *end = textBreakLast(it); *start = textBreakPrevious(it); }
void findWordBoundary(const UChar* chars, int len, int position, int* start, int* end) { UBreakIterator* it = wordBreakIterator(chars, len); *end = ubrk_following(it, position); if (*end < 0) *end = ubrk_last(it); *start = ubrk_previous(it); }
void findWordBoundary(const UChar* chars, int len, int position, int* start, int* end) { TextBreakIterator* it = wordBreakIterator(chars, len); *end = it->following(position); if (*end < 0) *end = it->last(); *start = it->previous(); }
static inline void appendContextSubtargetsForNode(Node* node, SubtargetGeometryList& subtargets) { // This is a variant of appendBasicSubtargetsForNode that adds special subtargets for // selected or auto-selectable parts of text nodes. ASSERT(node->renderer()); if (!node->isTextNode()) return appendBasicSubtargetsForNode(node, subtargets); Text* textNode = static_cast<WebCore::Text*>(node); RenderText* textRenderer = static_cast<RenderText*>(textNode->renderer()); if (textRenderer->frame()->editor()->behavior().shouldSelectOnContextualMenuClick()) { // Make subtargets out of every word. String textValue = textNode->data(); TextBreakIterator* wordIterator = wordBreakIterator(textValue.characters(), textValue.length()); int lastOffset = textBreakFirst(wordIterator); if (lastOffset == -1) return; int offset; while ((offset = textBreakNext(wordIterator)) != -1) { if (isWordTextBreak(wordIterator)) { Vector<FloatQuad> quads; textRenderer->absoluteQuadsForRange(quads, lastOffset, offset); appendQuadsToSubtargetList(quads, textNode, subtargets); } lastOffset = offset; } } else { if (textRenderer->selectionState() == RenderObject::SelectionNone) return appendBasicSubtargetsForNode(node, subtargets); // If selected, make subtargets out of only the selected part of the text. int startPos, endPos; switch (textRenderer->selectionState()) { case RenderObject::SelectionInside: startPos = 0; endPos = textRenderer->textLength(); break; case RenderObject::SelectionStart: textRenderer->selectionStartEnd(startPos, endPos); endPos = textRenderer->textLength(); break; case RenderObject::SelectionEnd: textRenderer->selectionStartEnd(startPos, endPos); startPos = 0; break; case RenderObject::SelectionBoth: textRenderer->selectionStartEnd(startPos, endPos); break; default: ASSERT_NOT_REACHED(); return; } Vector<FloatQuad> quads; textRenderer->absoluteQuadsForRange(quads, startPos, endPos); appendQuadsToSubtargetList(quads, textNode, subtargets); } }
Vector<TextCheckingResult> TextChecker::checkTextOfParagraph(int64_t spellDocumentTag, StringView text, int32_t insertionPoint, uint64_t checkingTypes, bool) { UNUSED_PARAM(insertionPoint); Vector<TextCheckingResult> paragraphCheckingResult; #if ENABLE(SPELLCHECK) if (checkingTypes & TextCheckingTypeSpelling) { TextBreakIterator* textIterator = wordBreakIterator(text); if (!textIterator) return paragraphCheckingResult; // Omit the word separators at the beginning/end of the text to don't unnecessarily // involve the client to check spelling for them. unsigned offset = nextWordOffset(text, 0); unsigned lengthStrip = text.length(); while (lengthStrip > 0 && isTextBreak(textIterator, lengthStrip - 1)) --lengthStrip; while (offset < lengthStrip) { int32_t misspellingLocation = -1; int32_t misspellingLength = 0; checkSpellingOfString(spellDocumentTag, text.substring(offset, lengthStrip - offset), misspellingLocation, misspellingLength); if (!misspellingLength) break; TextCheckingResult misspellingResult; misspellingResult.type = TextCheckingTypeSpelling; misspellingResult.location = offset + misspellingLocation; misspellingResult.length = misspellingLength; paragraphCheckingResult.append(misspellingResult); offset += misspellingLocation + misspellingLength; // Generally, we end up checking at the word separator, move to the adjacent word. offset = nextWordOffset(text.substring(0, lengthStrip), offset); } } #else UNUSED_PARAM(spellDocumentTag); UNUSED_PARAM(text); UNUSED_PARAM(insertionPoint); UNUSED_PARAM(checkingTypes); #endif return paragraphCheckingResult; }
bool FatFingers::checkForText(Node* curNode, Vector<IntersectingRegion>& intersectingRegions, Platform::IntRectRegion& fingerRegion) { ASSERT(curNode); if (isFieldWithText(curNode)) { // FIXME: Find all text in the field and find the best word. // For now, we will just select the whole field. IntRect boundingRect = curNode->renderer()->absoluteBoundingBoxRect(true /*use transforms*/); Platform::IntRectRegion nodeRegion(boundingRect); return checkFingerIntersection(nodeRegion, fingerRegion, curNode, intersectingRegions); } if (curNode->isTextNode()) { WebCore::Text* curText = static_cast<WebCore::Text*>(curNode); String allText = curText->wholeText(); // Iterate through all words, breaking at whitespace, to find the bounding box of each word. TextBreakIterator* wordIterator = wordBreakIterator(allText.characters(), allText.length()); int lastOffset = textBreakFirst(wordIterator); if (lastOffset == -1) return false; bool foundOne = false; int offset; Document* document = curNode->document(); while ((offset = textBreakNext(wordIterator)) != -1) { RefPtr<Range> range = Range::create(document, curText, lastOffset, curText, offset); if (!range->text().stripWhiteSpace().isEmpty()) { #if DEBUG_FAT_FINGERS log(LogLevelInfo, "Checking word '%s'", range->text().latin1().data()); #endif Platform::IntRectRegion rangeRegion(DOMSupport::transformedBoundingBoxForRange(*range)); foundOne |= checkFingerIntersection(rangeRegion, fingerRegion, curNode, intersectingRegions); } lastOffset = offset; } return foundOne; } return false; }
static unsigned rightClipToWordBuffer(const String& string, unsigned length, unsigned keepCount, UChar* buffer, bool) { ASSERT(keepCount < length); ASSERT(keepCount < STRING_BUFFER_SIZE); TextBreakIterator* it = wordBreakIterator(StringView(string).substring(0, length)); unsigned keepLength = textBreakAtOrPreceding(it, keepCount); StringView(string).substring(0, keepLength).getCharactersWithUpconvert(buffer); #if PLATFORM(IOS) // FIXME: We should guard this code behind an editing behavior. Then we can remove the PLATFORM(IOS)-guard. // Or just turn it on for all platforms. It seems like good behavior everywhere. Might be better to generalize // it to handle all whitespace, not just "space". // Motivated by <rdar://problem/7439327> truncation should not include a trailing space while (keepLength && string[keepLength - 1] == space) --keepLength; #endif return keepLength; }
void AbstractInlineTextBox::wordBoundaries(Vector<WordBoundaries>& words) const { if (!m_inlineTextBox) return; String text = this->text(); int len = text.length(); TextBreakIterator* iterator = wordBreakIterator(text, 0, len); // FIXME: When http://crbug.com/411764 is fixed, replace this with an ASSERT. if (!iterator) return; int pos = iterator->first(); while (pos >= 0 && pos < len) { int next = iterator->next(); if (isWordTextBreak(iterator)) words.append(WordBoundaries(pos, next)); pos = next; } }
Dart_Handle Paragraph::getWordBoundary(unsigned offset) { String text; int start = 0, end = 0; for (RenderObject* object = m_renderView.get(); object; object = object->nextInPreOrder()) { if (!object->isText()) continue; RenderText* renderText = toRenderText(object); text.append(renderText->text()); } TextBreakIterator* it = wordBreakIterator(text, 0, text.length()); if (it) { end = it->following(offset); if (end < 0) end = it->last(); start = it->previous(); } Dart_Handle result = Dart_NewList(2); Dart_ListSetAt(result, 0, ToDart(start)); Dart_ListSetAt(result, 1, ToDart(end)); return result; }
// Helper function to determine whether text is a single word. static bool isASingleWord(const String& text) { TextBreakIterator* it = wordBreakIterator(text.characters(), text.length()); return it && textBreakNext(it) == static_cast<int>(text.length()); }
// Helper function to determine whether text is a single word. static bool isASingleWord(const String& text) { TextBreakIterator* it = wordBreakIterator(text, 0, text.length()); return it && it->next() == static_cast<int>(text.length()); }
int findWordEndBoundary(const UChar* chars, int len, int position) { TextBreakIterator* it = wordBreakIterator(chars, len); int end = it->following(position); return end < 0 ? it->last() : end; }