1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_i18npool.hxx"
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #define BREAKITERATOR_ALL
28*b1cdbd2cSJim Jagielski #include <breakiterator_cjk.hxx>
29*b1cdbd2cSJim Jagielski #include <localedata.hxx>
30*b1cdbd2cSJim Jagielski #include <i18nutil/unicode.hxx>
31*b1cdbd2cSJim Jagielski 
32*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::uno;
33*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::lang;
34*b1cdbd2cSJim Jagielski using namespace ::rtl;
35*b1cdbd2cSJim Jagielski 
36*b1cdbd2cSJim Jagielski namespace com { namespace sun { namespace star { namespace i18n {
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski //      ----------------------------------------------------
39*b1cdbd2cSJim Jagielski //      class BreakIterator_CJK
40*b1cdbd2cSJim Jagielski //      ----------------------------------------------------;
41*b1cdbd2cSJim Jagielski 
BreakIterator_CJK()42*b1cdbd2cSJim Jagielski BreakIterator_CJK::BreakIterator_CJK() :
43*b1cdbd2cSJim Jagielski     dict( NULL ),
44*b1cdbd2cSJim Jagielski     hangingCharacters()
45*b1cdbd2cSJim Jagielski {
46*b1cdbd2cSJim Jagielski         cBreakIterator = "com.sun.star.i18n.BreakIterator_CJK";
47*b1cdbd2cSJim Jagielski }
48*b1cdbd2cSJim Jagielski 
49*b1cdbd2cSJim Jagielski Boundary SAL_CALL
previousWord(const OUString & text,sal_Int32 anyPos,const lang::Locale & nLocale,sal_Int16 wordType)50*b1cdbd2cSJim Jagielski BreakIterator_CJK::previousWord(const OUString& text, sal_Int32 anyPos,
51*b1cdbd2cSJim Jagielski         const lang::Locale& nLocale, sal_Int16 wordType) throw(RuntimeException)
52*b1cdbd2cSJim Jagielski {
53*b1cdbd2cSJim Jagielski         if (dict) {
54*b1cdbd2cSJim Jagielski             result = dict->previousWord(text, anyPos, wordType);
55*b1cdbd2cSJim Jagielski             // #109813# for non-CJK, single character word, fallback to ICU breakiterator.
56*b1cdbd2cSJim Jagielski             if (result.endPos - result.startPos != 1 ||
57*b1cdbd2cSJim Jagielski                     getScriptType(text, result.startPos) == ScriptType::ASIAN)
58*b1cdbd2cSJim Jagielski                 return result;
59*b1cdbd2cSJim Jagielski             result = BreakIterator_Unicode::getWordBoundary(text, result.startPos, nLocale, wordType, true);
60*b1cdbd2cSJim Jagielski             if (result.endPos < anyPos)
61*b1cdbd2cSJim Jagielski                 return result;
62*b1cdbd2cSJim Jagielski         }
63*b1cdbd2cSJim Jagielski         return BreakIterator_Unicode::previousWord(text, anyPos, nLocale, wordType);
64*b1cdbd2cSJim Jagielski }
65*b1cdbd2cSJim Jagielski 
66*b1cdbd2cSJim Jagielski Boundary SAL_CALL
nextWord(const OUString & text,sal_Int32 anyPos,const lang::Locale & nLocale,sal_Int16 wordType)67*b1cdbd2cSJim Jagielski BreakIterator_CJK::nextWord(const OUString& text, sal_Int32 anyPos,
68*b1cdbd2cSJim Jagielski         const lang::Locale& nLocale, sal_Int16 wordType) throw(RuntimeException)
69*b1cdbd2cSJim Jagielski {
70*b1cdbd2cSJim Jagielski         if (dict) {
71*b1cdbd2cSJim Jagielski             result = dict->nextWord(text, anyPos, wordType);
72*b1cdbd2cSJim Jagielski             // #109813# for non-CJK, single character word, fallback to ICU breakiterator.
73*b1cdbd2cSJim Jagielski             if (result.endPos - result.startPos != 1 ||
74*b1cdbd2cSJim Jagielski                     getScriptType(text, result.startPos) == ScriptType::ASIAN)
75*b1cdbd2cSJim Jagielski                 return result;
76*b1cdbd2cSJim Jagielski             result = BreakIterator_Unicode::getWordBoundary(text, result.startPos, nLocale, wordType, true);
77*b1cdbd2cSJim Jagielski             if (result.startPos > anyPos)
78*b1cdbd2cSJim Jagielski                 return result;
79*b1cdbd2cSJim Jagielski         }
80*b1cdbd2cSJim Jagielski         return BreakIterator_Unicode::nextWord(text, anyPos, nLocale, wordType);
81*b1cdbd2cSJim Jagielski }
82*b1cdbd2cSJim Jagielski 
83*b1cdbd2cSJim Jagielski Boundary SAL_CALL
getWordBoundary(const OUString & text,sal_Int32 anyPos,const lang::Locale & nLocale,sal_Int16 wordType,sal_Bool bDirection)84*b1cdbd2cSJim Jagielski BreakIterator_CJK::getWordBoundary( const OUString& text, sal_Int32 anyPos,
85*b1cdbd2cSJim Jagielski         const lang::Locale& nLocale, sal_Int16 wordType, sal_Bool bDirection )
86*b1cdbd2cSJim Jagielski         throw(RuntimeException)
87*b1cdbd2cSJim Jagielski {
88*b1cdbd2cSJim Jagielski         if (dict) {
89*b1cdbd2cSJim Jagielski             result = dict->getWordBoundary(text, anyPos, wordType, bDirection);
90*b1cdbd2cSJim Jagielski             // #109813# for non-CJK, single character word, fallback to ICU breakiterator.
91*b1cdbd2cSJim Jagielski             if (result.endPos - result.startPos != 1 ||
92*b1cdbd2cSJim Jagielski                     getScriptType(text, result.startPos) == ScriptType::ASIAN)
93*b1cdbd2cSJim Jagielski                 return result;
94*b1cdbd2cSJim Jagielski         }
95*b1cdbd2cSJim Jagielski         return BreakIterator_Unicode::getWordBoundary(text, anyPos, nLocale, wordType, bDirection);
96*b1cdbd2cSJim Jagielski }
97*b1cdbd2cSJim Jagielski 
getLineBreak(const OUString & Text,sal_Int32 nStartPos,const lang::Locale &,sal_Int32,const LineBreakHyphenationOptions &,const LineBreakUserOptions & bOptions)98*b1cdbd2cSJim Jagielski LineBreakResults SAL_CALL BreakIterator_CJK::getLineBreak(
99*b1cdbd2cSJim Jagielski         const OUString& Text, sal_Int32 nStartPos,
100*b1cdbd2cSJim Jagielski         const lang::Locale& /*rLocale*/, sal_Int32 /*nMinBreakPos*/,
101*b1cdbd2cSJim Jagielski         const LineBreakHyphenationOptions& /*hOptions*/,
102*b1cdbd2cSJim Jagielski         const LineBreakUserOptions& bOptions ) throw(RuntimeException)
103*b1cdbd2cSJim Jagielski {
104*b1cdbd2cSJim Jagielski         LineBreakResults lbr;
105*b1cdbd2cSJim Jagielski 
106*b1cdbd2cSJim Jagielski         if (bOptions.allowPunctuationOutsideMargin &&
107*b1cdbd2cSJim Jagielski                 hangingCharacters.indexOf(Text[nStartPos]) != -1 &&
108*b1cdbd2cSJim Jagielski                 (Text.iterateCodePoints( &nStartPos, 1), nStartPos == Text.getLength())) {
109*b1cdbd2cSJim Jagielski             ; // do nothing
110*b1cdbd2cSJim Jagielski         } else if (bOptions.applyForbiddenRules && 0 < nStartPos && nStartPos < Text.getLength()) {
111*b1cdbd2cSJim Jagielski             while (nStartPos > 0 &&
112*b1cdbd2cSJim Jagielski                     (bOptions.forbiddenBeginCharacters.indexOf(Text[nStartPos]) != -1 ||
113*b1cdbd2cSJim Jagielski                     bOptions.forbiddenEndCharacters.indexOf(Text[nStartPos-1]) != -1))
114*b1cdbd2cSJim Jagielski                 Text.iterateCodePoints( &nStartPos, -1);
115*b1cdbd2cSJim Jagielski         }
116*b1cdbd2cSJim Jagielski 
117*b1cdbd2cSJim Jagielski         lbr.breakIndex = nStartPos;
118*b1cdbd2cSJim Jagielski         lbr.breakType = BreakType::WORDBOUNDARY;
119*b1cdbd2cSJim Jagielski         return lbr;
120*b1cdbd2cSJim Jagielski }
121*b1cdbd2cSJim Jagielski 
122*b1cdbd2cSJim Jagielski #define LOCALE(language, country) lang::Locale(OUString::createFromAscii(language), OUString::createFromAscii(country), OUString())
123*b1cdbd2cSJim Jagielski //      ----------------------------------------------------
124*b1cdbd2cSJim Jagielski //      class BreakIterator_zh
125*b1cdbd2cSJim Jagielski //      ----------------------------------------------------;
BreakIterator_zh()126*b1cdbd2cSJim Jagielski BreakIterator_zh::BreakIterator_zh()
127*b1cdbd2cSJim Jagielski {
128*b1cdbd2cSJim Jagielski         dict = new xdictionary("zh");
129*b1cdbd2cSJim Jagielski         hangingCharacters = LocaleData().getHangingCharacters(LOCALE("zh", "CN"));
130*b1cdbd2cSJim Jagielski         cBreakIterator = "com.sun.star.i18n.BreakIterator_zh";
131*b1cdbd2cSJim Jagielski }
132*b1cdbd2cSJim Jagielski 
~BreakIterator_zh()133*b1cdbd2cSJim Jagielski BreakIterator_zh::~BreakIterator_zh()
134*b1cdbd2cSJim Jagielski {
135*b1cdbd2cSJim Jagielski         delete dict;
136*b1cdbd2cSJim Jagielski }
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski //      ----------------------------------------------------
139*b1cdbd2cSJim Jagielski //      class BreakIterator_zh_TW
140*b1cdbd2cSJim Jagielski //      ----------------------------------------------------;
BreakIterator_zh_TW()141*b1cdbd2cSJim Jagielski BreakIterator_zh_TW::BreakIterator_zh_TW()
142*b1cdbd2cSJim Jagielski {
143*b1cdbd2cSJim Jagielski         dict = new xdictionary("zh");
144*b1cdbd2cSJim Jagielski         hangingCharacters = LocaleData().getHangingCharacters(LOCALE("zh", "TW"));
145*b1cdbd2cSJim Jagielski         cBreakIterator = "com.sun.star.i18n.BreakIterator_zh_TW";
146*b1cdbd2cSJim Jagielski }
147*b1cdbd2cSJim Jagielski 
~BreakIterator_zh_TW()148*b1cdbd2cSJim Jagielski BreakIterator_zh_TW::~BreakIterator_zh_TW()
149*b1cdbd2cSJim Jagielski {
150*b1cdbd2cSJim Jagielski         delete dict;
151*b1cdbd2cSJim Jagielski }
152*b1cdbd2cSJim Jagielski 
153*b1cdbd2cSJim Jagielski //      ----------------------------------------------------
154*b1cdbd2cSJim Jagielski //      class BreakIterator_ja
155*b1cdbd2cSJim Jagielski //      ----------------------------------------------------;
BreakIterator_ja()156*b1cdbd2cSJim Jagielski BreakIterator_ja::BreakIterator_ja()
157*b1cdbd2cSJim Jagielski {
158*b1cdbd2cSJim Jagielski         dict = new xdictionary("ja");
159*b1cdbd2cSJim Jagielski         dict->setJapaneseWordBreak();
160*b1cdbd2cSJim Jagielski         hangingCharacters = LocaleData().getHangingCharacters(LOCALE("ja", "JP"));
161*b1cdbd2cSJim Jagielski         cBreakIterator = "com.sun.star.i18n.BreakIterator_ja";
162*b1cdbd2cSJim Jagielski }
163*b1cdbd2cSJim Jagielski 
~BreakIterator_ja()164*b1cdbd2cSJim Jagielski BreakIterator_ja::~BreakIterator_ja()
165*b1cdbd2cSJim Jagielski {
166*b1cdbd2cSJim Jagielski         delete dict;
167*b1cdbd2cSJim Jagielski }
168*b1cdbd2cSJim Jagielski 
169*b1cdbd2cSJim Jagielski //      ----------------------------------------------------
170*b1cdbd2cSJim Jagielski //      class BreakIterator_ko
171*b1cdbd2cSJim Jagielski //      ----------------------------------------------------;
BreakIterator_ko()172*b1cdbd2cSJim Jagielski BreakIterator_ko::BreakIterator_ko()
173*b1cdbd2cSJim Jagielski {
174*b1cdbd2cSJim Jagielski         hangingCharacters = LocaleData().getHangingCharacters(LOCALE("ko", "KR"));
175*b1cdbd2cSJim Jagielski         cBreakIterator = "com.sun.star.i18n.BreakIterator_ko";
176*b1cdbd2cSJim Jagielski }
177*b1cdbd2cSJim Jagielski 
~BreakIterator_ko()178*b1cdbd2cSJim Jagielski BreakIterator_ko::~BreakIterator_ko()
179*b1cdbd2cSJim Jagielski {
180*b1cdbd2cSJim Jagielski }
181*b1cdbd2cSJim Jagielski 
182*b1cdbd2cSJim Jagielski } } } }
183