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