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; } }
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 textBreakFollowing(TextBreakIterator* bi, int pos) { if (pos < 0) pos = -1; bi->m_index = pos; return textBreakNext(bi); }
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 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); } }
int textBreakFollowing(TextBreakIterator* iterator, int offset) { if (offset > iterator->m_charIterator.getUTF16Length()) return TextBreakDone; if (offset < 0) return 0; iterator->m_charIterator.setUTF16Index(offset); return textBreakNext(iterator); }
unsigned String::numGraphemeClusters() const { TextBreakIterator* it = characterBreakIterator(characters(), length()); if (!it) return length(); unsigned num = 0; while (textBreakNext(it) != TextBreakDone) ++num; return num; }
unsigned numGraphemeClusters(const String& s) { NonSharedCharacterBreakIterator it(s.characters(), s.length()); if (!it) return s.length(); unsigned num = 0; while (textBreakNext(it) != TextBreakDone) ++num; return num; }
unsigned String::numCharactersInGraphemeClusters(unsigned numGraphemeClusters) const { TextBreakIterator* it = characterBreakIterator(characters(), length()); if (!it) return min(length(), numGraphemeClusters); for (unsigned i = 0; i < numGraphemeClusters; ++i) { if (textBreakNext(it) == TextBreakDone) return length(); } return textBreakCurrent(it); }
unsigned numCharactersInGraphemeClusters(const String& s, unsigned numGraphemeClusters) { NonSharedCharacterBreakIterator it(s.characters(), s.length()); if (!it) return min(s.length(), numGraphemeClusters); for (unsigned i = 0; i < numGraphemeClusters; ++i) { if (textBreakNext(it) == TextBreakDone) return s.length(); } return textBreakCurrent(it); }
bool isTextBreak(TextBreakIterator* iterator, int offset) { if (!offset) return true; if (offset > iterator->m_charIterator.getUTF16Length()) return false; iterator->m_charIterator.setUTF16Index(offset); int index = iterator->m_charIterator.getIndex(); iterator->m_charIterator.previous(); textBreakNext(iterator); return iterator->m_charIterator.getIndex() == index; }
unsigned numGraphemeClusters(const String& s) { unsigned stringLength = s.length(); if (!stringLength) return 0; // The only Latin-1 Extended Grapheme Cluster is CR LF if (s.is8Bit() && !s.contains('\r')) return stringLength; NonSharedCharacterBreakIterator it(s); if (!it) return stringLength; unsigned num = 0; while (textBreakNext(it) != TextBreakDone) ++num; return num; }
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; }
unsigned numCharactersInGraphemeClusters(const StringView& s, unsigned numGraphemeClusters) { unsigned stringLength = s.length(); if (!stringLength) return 0; // The only Latin-1 Extended Grapheme Cluster is CR LF if (s.is8Bit() && !s.contains('\r')) return std::min(stringLength, numGraphemeClusters); NonSharedCharacterBreakIterator it(s); if (!it) return std::min(stringLength, numGraphemeClusters); for (unsigned i = 0; i < numGraphemeClusters; ++i) { if (textBreakNext(it) == TextBreakDone) return stringLength; } return textBreakCurrent(it); }
// 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()); }