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 textBreakPrevious(TextBreakIterator* bi) { for (int i = bi->m_index - 1; i >= 0; i--) { if ((bi->m_type == UBRK_LINE && bi->m_logAttrs[i].is_line_break) || (bi->m_type == UBRK_WORD && (bi->m_logAttrs[i].is_word_start || bi->m_logAttrs[i].is_word_end)) || (bi->m_type == UBRK_CHARACTER && bi->m_logAttrs[i].is_cursor_position) || (bi->m_type == UBRK_SENTENCE && (bi->m_logAttrs[i].is_sentence_start || bi->m_logAttrs[i].is_sentence_end)) ) { bi->m_index = i; return i; } } return textBreakFirst(bi); }
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; }