15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Dominik Röttsches <dominik.roettsches@access-company.com>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    notice, this list of conditions and the following disclaimer in the
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *    documentation and/or other materials provided with the distribution.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/TextBoundaries.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/TextBreakIterator.h"
317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/text/StringImpl.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace WTF;
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace Unicode;
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int endOfFirstWordBoundaryContext(const UChar* characters, int length)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = 0; i < length; ) {
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int first = i;
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar32 ch;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        U16_NEXT(characters, i, length, ch);
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!requiresContextForWordBoundary(ch))
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return first;
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return length;
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int startOfLastWordBoundaryContext(const UChar* characters, int length)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = length; i > 0; ) {
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int last = i;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        UChar32 ch;
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        U16_PREV(characters, 0, i, ch);
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!requiresContextForWordBoundary(ch))
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return last;
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int findNextWordFromIndex(const UChar* chars, int len, int position, bool forward)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TextBreakIterator* it = wordBreakIterator(chars, len);
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (forward) {
671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        position = it->following(position);
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (position != TextBreakDone) {
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We stop searching when the character preceeding the break
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // is alphanumeric.
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (position < len && isAlphanumeric(chars[position - 1]))
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return position;
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            position = it->following(position);
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return len;
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        position = it->preceding(position);
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (position != TextBreakDone) {
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // We stop searching when the character following the break
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // is alphanumeric.
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (position > 0 && isAlphanumeric(chars[position]))
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return position;
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            position = it->preceding(position);
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return 0;
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void findWordBoundary(const UChar* chars, int len, int position, int* start, int* end)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TextBreakIterator* it = wordBreakIterator(chars, len);
961e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    *end = it->following(position);
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (*end < 0)
981e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        *end = it->last();
991e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    *start = it->previous();
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
102c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)int findWordEndBoundary(const UChar* chars, int len, int position)
103c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
104c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    TextBreakIterator* it = wordBreakIterator(chars, len);
105c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    int end = it->following(position);
106c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    return end < 0 ? it->last() : end;
107c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
109c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
110