Beispiel #1
0
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 &nbsp with a real space since ICU no longer treats &nbsp 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);
}
Beispiel #2
0
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;
    }
}
Beispiel #4
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;
    }
}
Beispiel #6
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);
}
Beispiel #8
0
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;
}
Beispiel #9
0
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);
}
Beispiel #13
0
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);
}
Beispiel #14
0
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();
}
Beispiel #15
0
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);
    }
}
Beispiel #16
0
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;
}
Beispiel #17
0
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;
}
Beispiel #18
0
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;
    }
}
Beispiel #20
0
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;
}
Beispiel #21
0
// 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());
}
Beispiel #23
0
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;
}