1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_i18npool.hxx"
26 
27 #include <com/sun/star/i18n/CTLScriptType.hpp>
28 #include <com/sun/star/i18n/ScriptDirection.hpp>
29 #include <com/sun/star/i18n/UnicodeScript.hpp>
30 #include <scripttypedetector.hxx>
31 #include <i18nutil/unicode.hxx>
32 
33 //      ----------------------------------------------------
34 //      class ScriptTypeDetector
35 //      ----------------------------------------------------;
36 
37 using namespace com::sun::star::i18n;
38 
ScriptTypeDetector()39 ScriptTypeDetector::ScriptTypeDetector()
40 {
41 }
42 
~ScriptTypeDetector()43 ScriptTypeDetector::~ScriptTypeDetector()
44 {
45 }
46 
47 static sal_Int16 scriptDirection[] = {
48     ScriptDirection::LEFT_TO_RIGHT,     // DirectionProperty_LEFT_TO_RIGHT = 0,
49     ScriptDirection::RIGHT_TO_LEFT,     // DirectionProperty_RIGHT_TO_LEFT = 1,
50     ScriptDirection::LEFT_TO_RIGHT,     // DirectionProperty_EUROPEAN_NUMBER = 2,
51     ScriptDirection::LEFT_TO_RIGHT,     // DirectionProperty_EUROPEAN_NUMBER_SEPARATOR = 3,
52     ScriptDirection::LEFT_TO_RIGHT,     // DirectionProperty_EUROPEAN_NUMBER_TERMINATOR = 4,
53     ScriptDirection::RIGHT_TO_LEFT,     // DirectionProperty_ARABIC_NUMBER = 5,
54     ScriptDirection::NEUTRAL,           // DirectionProperty_COMMON_NUMBER_SEPARATOR = 6,
55     ScriptDirection::NEUTRAL,           // DirectionProperty_BLOCK_SEPARATOR = 7,
56     ScriptDirection::NEUTRAL,           // DirectionProperty_SEGMENT_SEPARATOR = 8,
57     ScriptDirection::NEUTRAL,           // DirectionProperty_WHITE_SPACE_NEUTRAL = 9,
58     ScriptDirection::NEUTRAL,           // DirectionProperty_OTHER_NEUTRAL = 10,
59     ScriptDirection::LEFT_TO_RIGHT,     // DirectionProperty_LEFT_TO_RIGHT_EMBEDDING = 11,
60     ScriptDirection::LEFT_TO_RIGHT,     // DirectionProperty_LEFT_TO_RIGHT_OVERRIDE = 12,
61     ScriptDirection::RIGHT_TO_LEFT,     // DirectionProperty_RIGHT_TO_LEFT_ARABIC = 13,
62     ScriptDirection::RIGHT_TO_LEFT,     // DirectionProperty_RIGHT_TO_LEFT_EMBEDDING = 14,
63     ScriptDirection::RIGHT_TO_LEFT,     // DirectionProperty_RIGHT_TO_LEFT_OVERRIDE = 15,
64     ScriptDirection::NEUTRAL,           // DirectionProperty_POP_DIRECTIONAL_FORMAT = 16,
65     ScriptDirection::NEUTRAL,           // DirectionProperty_DIR_NON_SPACING_MARK = 17,
66     ScriptDirection::NEUTRAL,           // DirectionProperty_BOUNDARY_NEUTRAL = 18,
67 };
68 
69 sal_Int16 SAL_CALL
getScriptDirection(const::rtl::OUString & Text,sal_Int32 nPos,sal_Int16 defaultScriptDirection)70 ScriptTypeDetector::getScriptDirection( const ::rtl::OUString& Text, sal_Int32 nPos, sal_Int16 defaultScriptDirection ) throw (::com::sun::star::uno::RuntimeException)
71 {
72     sal_Int16 dir = scriptDirection[unicode::getUnicodeDirection(Text[nPos])];
73     return (dir == ScriptDirection::NEUTRAL) ? defaultScriptDirection : dir;
74 }
75 
76 // return value '-1' means either the direction on nPos is not same as scriptDirection or nPos is out of range.
77 sal_Int32 SAL_CALL
beginOfScriptDirection(const::rtl::OUString & Text,sal_Int32 nPos,sal_Int16 direction)78 ScriptTypeDetector::beginOfScriptDirection( const ::rtl::OUString& Text, sal_Int32 nPos, sal_Int16 direction ) throw (::com::sun::star::uno::RuntimeException)
79 {
80         sal_Int32 cPos = nPos;
81 
82         if (cPos < Text.getLength()) {
83             for (; cPos >= 0; cPos--) {
84                 if (direction != getScriptDirection(Text, cPos, direction))
85                     break;
86             }
87         }
88         return cPos == nPos ? -1 : cPos + 1;
89 }
90 
91 sal_Int32 SAL_CALL
endOfScriptDirection(const::rtl::OUString & Text,sal_Int32 nPos,sal_Int16 direction)92 ScriptTypeDetector::endOfScriptDirection( const ::rtl::OUString& Text, sal_Int32 nPos, sal_Int16 direction ) throw (::com::sun::star::uno::RuntimeException)
93 {
94         sal_Int32 cPos = nPos;
95         sal_Int32 len = Text.getLength();
96 
97         if (cPos >=0) {
98             for (; cPos < len; cPos++) {
99                 if (direction != getScriptDirection(Text, cPos, direction))
100                     break;
101             }
102         }
103         return cPos == nPos ? -1 : cPos;
104 }
105 
106 sal_Int16 SAL_CALL
getCTLScriptType(const::rtl::OUString & Text,sal_Int32 nPos)107 ScriptTypeDetector::getCTLScriptType( const ::rtl::OUString& Text, sal_Int32 nPos ) throw (::com::sun::star::uno::RuntimeException)
108 {
109     static ScriptTypeList typeList[] = {
110         { UnicodeScript_kHebrew, UnicodeScript_kHebrew, CTLScriptType::CTL_HEBREW },    // 10
111         { UnicodeScript_kArabic, UnicodeScript_kArabic, CTLScriptType::CTL_ARABIC },    // 11
112         { UnicodeScript_kDevanagari, UnicodeScript_kDevanagari, CTLScriptType::CTL_INDIC },     // 14
113         { UnicodeScript_kThai, UnicodeScript_kThai, CTLScriptType::CTL_THAI },      // 24
114         { UnicodeScript_kScriptCount, UnicodeScript_kScriptCount,   CTLScriptType::CTL_UNKNOWN }    // 88
115     };
116 
117     return unicode::getUnicodeScriptType(Text[nPos], typeList, CTLScriptType::CTL_UNKNOWN);
118 }
119 
120 // Begin of Script Type is inclusive.
121 sal_Int32 SAL_CALL
beginOfCTLScriptType(const::rtl::OUString & Text,sal_Int32 nPos)122 ScriptTypeDetector::beginOfCTLScriptType( const ::rtl::OUString& Text, sal_Int32 nPos ) throw (::com::sun::star::uno::RuntimeException)
123 {
124     if (nPos < 0)
125         return 0;
126     else if (nPos >= Text.getLength())
127         return Text.getLength();
128     else {
129         sal_Int16 cType = getCTLScriptType(Text, nPos);
130         for (nPos--; nPos >= 0; nPos--) {
131             if (cType != getCTLScriptType(Text, nPos))
132                 break;
133         }
134         return nPos + 1;
135     }
136 }
137 
138 // End of the Script Type is exclusive, the return value pointing to the begin of next script type
139 sal_Int32 SAL_CALL
endOfCTLScriptType(const::rtl::OUString & Text,sal_Int32 nPos)140 ScriptTypeDetector::endOfCTLScriptType( const ::rtl::OUString& Text, sal_Int32 nPos ) throw (::com::sun::star::uno::RuntimeException)
141 {
142     if (nPos < 0)
143         return 0;
144     else if (nPos >= Text.getLength())
145         return Text.getLength();
146     else {
147         sal_Int16 cType = getCTLScriptType(Text, nPos);
148         sal_Int32 len = Text.getLength();
149         for (nPos++; nPos < len; nPos++) {
150             if (cType != getCTLScriptType(Text, nPos))
151                 break;
152         }
153         return nPos;
154     }
155 }
156 
157 const sal_Char sDetector[] = "draft.com.sun.star.i18n.ScriptTypeDetector";
158 
159 rtl::OUString SAL_CALL
getImplementationName()160 ScriptTypeDetector::getImplementationName() throw( ::com::sun::star::uno::RuntimeException )
161 {
162     return ::rtl::OUString::createFromAscii(sDetector);
163 }
164 
165 sal_Bool SAL_CALL
supportsService(const rtl::OUString & ServiceName)166 ScriptTypeDetector::supportsService(const rtl::OUString& ServiceName) throw( ::com::sun::star::uno::RuntimeException )
167 {
168     return !ServiceName.compareToAscii(sDetector);
169 }
170 
171 ::com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL
getSupportedServiceNames()172 ScriptTypeDetector::getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException )
173 {
174     ::com::sun::star::uno::Sequence< ::rtl::OUString > aRet(1);
175     aRet[0] = ::rtl::OUString::createFromAscii(sDetector);
176     return aRet;
177 }
178 
179