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_unotools.hxx"
26 
27 #include <unotools/transliterationwrapper.hxx>
28 #include <tools/debug.hxx>
29 #include <i18npool/mslangid.hxx>
30 #include <comphelper/componentfactory.hxx>
31 
32 #include <com/sun/star/uno/XInterface.hpp>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/i18n/TransliterationModulesExtra.hpp>
36 
37 #define TRANSLIT_LIBRARYNAME "i18n"
38 #define TRANSLIT_SERVICENAME "com.sun.star.i18n.Transliteration"
39 
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star::i18n;
42 using namespace ::com::sun::star::uno;
43 using namespace ::utl;
44 
TransliterationWrapper(const Reference<XMultiServiceFactory> & xSF,sal_uInt32 nTyp)45 TransliterationWrapper::TransliterationWrapper(
46 					const Reference< XMultiServiceFactory > & xSF,
47 					sal_uInt32 nTyp )
48 	: xSMgr( xSF ), nType( nTyp ), nLanguage( 0 ), bFirstCall( sal_True )
49 {
50 	if( xSMgr.is() )
51 	{
52 		try {
53             xTrans = Reference< XExtendedTransliteration > (
54                     xSMgr->createInstance( ::rtl::OUString(
55                             RTL_CONSTASCII_USTRINGPARAM(
56                                 TRANSLIT_SERVICENAME))), UNO_QUERY );
57 		}
58 		catch ( Exception&  )
59 		{
60 			DBG_ERRORFILE( "TransliterationWrapper: Exception caught!" );
61 		}
62 	}
63 	else
64 	{	// try to get an instance somehow
65 		DBG_ERRORFILE( "TransliterationWrapper: no service manager, trying own" );
66 		try
67 		{
68             Reference< XInterface > xI = ::comphelper::getComponentInstance(
69                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( LLCF_LIBNAME(
70                                 TRANSLIT_LIBRARYNAME ))),
71                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
72                             TRANSLIT_SERVICENAME)));
73 			if ( xI.is() )
74 			{
75 				Any x = xI->queryInterface(
76 					::getCppuType((const Reference< XExtendedTransliteration>*)0) );
77 				x >>= xTrans ;
78 			}
79 		}
80 		catch ( Exception&  )
81 		{
82 			DBG_ERRORFILE( "getComponentInstance: Exception caught!" );
83 		}
84 	}
85 	DBG_ASSERT( xTrans.is(), "TransliterationWrapper: no Transliteraion available" );
86 }
87 
88 
~TransliterationWrapper()89 TransliterationWrapper::~TransliterationWrapper()
90 {
91 }
92 
93 
transliterate(const String & rStr,sal_uInt16 nLang,xub_StrLen nStart,xub_StrLen nLen,Sequence<sal_Int32> * pOffset)94 String TransliterationWrapper::transliterate(
95 								const String& rStr, sal_uInt16 nLang,
96 								xub_StrLen nStart, xub_StrLen nLen,
97 								Sequence <sal_Int32>* pOffset )
98 {
99 	String sRet;
100 	if( xTrans.is() )
101 	{
102 		try
103 		{
104             loadModuleIfNeeded( nLang );
105 
106 			if ( pOffset )
107 			    sRet = xTrans->transliterate( rStr, nStart, nLen, *pOffset );
108             else
109 			    sRet = xTrans->transliterateString2String( rStr, nStart, nLen);
110 		}
111 		catch( Exception&  )
112 		{
113 			DBG_ERRORFILE( "transliterate: Exception caught!" );
114 		}
115 	}
116 	return sRet;
117 }
118 
119 
transliterate(const String & rStr,xub_StrLen nStart,xub_StrLen nLen,Sequence<sal_Int32> * pOffset) const120 String TransliterationWrapper::transliterate(
121 								const String& rStr,
122 								xub_StrLen nStart, xub_StrLen nLen,
123 								Sequence <sal_Int32>* pOffset ) const
124 {
125 	String sRet( rStr );
126 	if( xTrans.is() )
127 	{
128 		try
129 		{
130 			if ( pOffset )
131 			    sRet = xTrans->transliterate( rStr, nStart, nLen, *pOffset );
132             else
133 			    sRet = xTrans->transliterateString2String( rStr, nStart, nLen);
134 		}
135 		catch( Exception&  )
136 		{
137 			DBG_ERRORFILE( "transliterate: Exception caught!" );
138 		}
139 	}
140 	return sRet;
141 }
142 
needLanguageForTheMode() const143 sal_Bool TransliterationWrapper::needLanguageForTheMode() const
144 {
145 	return TransliterationModules_UPPERCASE_LOWERCASE == nType ||
146 		   TransliterationModules_LOWERCASE_UPPERCASE == nType ||
147 		   TransliterationModules_IGNORE_CASE == nType ||
148            (sal_uInt32) TransliterationModulesExtra::SENTENCE_CASE == (sal_uInt32) nType ||
149            (sal_uInt32) TransliterationModulesExtra::TITLE_CASE    == (sal_uInt32) nType ||
150            (sal_uInt32) TransliterationModulesExtra::TOGGLE_CASE   == (sal_uInt32) nType;
151 }
152 
153 
setLanguageLocaleImpl(sal_uInt16 nLang)154 void TransliterationWrapper::setLanguageLocaleImpl( sal_uInt16 nLang )
155 {
156     nLanguage = nLang;
157     if( LANGUAGE_NONE == nLanguage )
158         nLanguage = LANGUAGE_SYSTEM;
159     MsLangId::convertLanguageToLocale( nLanguage, aLocale);
160 }
161 
162 
loadModuleIfNeeded(sal_uInt16 nLang)163 void TransliterationWrapper::loadModuleIfNeeded( sal_uInt16 nLang )
164 {
165     sal_Bool bLoad = bFirstCall;
166     bFirstCall = sal_False;
167 
168     if( static_cast< sal_Int32 >(nType) == TransliterationModulesExtra::SENTENCE_CASE )
169     {
170         if( bLoad )
171             loadModuleByImplName(String::CreateFromAscii("SENTENCE_CASE"), nLang);
172     }
173     else if( static_cast< sal_Int32 >(nType) == TransliterationModulesExtra::TITLE_CASE )
174     {
175         if( bLoad )
176             loadModuleByImplName(String::CreateFromAscii("TITLE_CASE"), nLang);
177     }
178     else if( static_cast< sal_Int32 >(nType) == TransliterationModulesExtra::TOGGLE_CASE )
179     {
180         if( bLoad )
181             loadModuleByImplName(String::CreateFromAscii("TOGGLE_CASE"), nLang);
182     }
183     else
184     {
185         if( nLanguage != nLang )
186         {
187             setLanguageLocaleImpl( nLang );
188             if( !bLoad )
189                 bLoad = needLanguageForTheMode();
190         }
191         if( bLoad )
192             loadModuleImpl();
193     }
194 }
195 
196 
loadModuleImpl() const197 void TransliterationWrapper::loadModuleImpl() const
198 {
199     if ( bFirstCall )
200         ((TransliterationWrapper*)this)->setLanguageLocaleImpl( LANGUAGE_SYSTEM );
201 
202     try
203     {
204         if ( xTrans.is() )
205             xTrans->loadModule( (TransliterationModules)nType, aLocale );
206     }
207     catch ( Exception& e )
208     {
209 #ifdef DBG_UTIL
210         ByteString aMsg( "loadModuleImpl: Exception caught\n" );
211         aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
212         DBG_ERRORFILE( aMsg.GetBuffer() );
213 #else
214         (void)e;
215 #endif
216     }
217 
218     bFirstCall = sal_False;
219 }
220 
221 
loadModuleByImplName(const String & rModuleName,sal_uInt16 nLang)222 void TransliterationWrapper::loadModuleByImplName(
223         const String& rModuleName, sal_uInt16 nLang )
224 {
225     try
226     {
227         setLanguageLocaleImpl( nLang );
228         // Reset LanguageType, so the next call to loadModuleIfNeeded() forces
229         // new settings.
230         nLanguage = LANGUAGE_DONTKNOW;
231         if ( xTrans.is() )
232             xTrans->loadModuleByImplName( rModuleName, aLocale );
233     }
234     catch ( Exception& e )
235     {
236 #ifdef DBG_UTIL
237         ByteString aMsg( "loadModuleByImplName: Exception caught\n" );
238         aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
239         DBG_ERRORFILE( aMsg.GetBuffer() );
240 #else
241         (void)e;
242 #endif
243     }
244 
245     bFirstCall = sal_False;
246 }
247 
248 
equals(const String & rStr1,sal_Int32 nPos1,sal_Int32 nCount1,sal_Int32 & nMatch1,const String & rStr2,sal_Int32 nPos2,sal_Int32 nCount2,sal_Int32 & nMatch2) const249 sal_Bool TransliterationWrapper::equals(
250     const String& rStr1, sal_Int32 nPos1, sal_Int32 nCount1, sal_Int32& nMatch1,
251     const String& rStr2, sal_Int32 nPos2, sal_Int32 nCount2, sal_Int32& nMatch2 ) const
252 {
253     try
254     {
255         if( bFirstCall )
256             loadModuleImpl();
257         if ( xTrans.is() )
258             return xTrans->equals( rStr1, nPos1, nCount1, nMatch1, rStr2, nPos2, nCount2, nMatch2 );
259     }
260 	catch ( Exception& e )
261 	{
262 #ifdef DBG_UTIL
263         ByteString aMsg( "equals: Exception caught\n" );
264 		aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
265 		DBG_ERRORFILE( aMsg.GetBuffer() );
266 #else
267         (void)e;
268 #endif
269 	}
270     return sal_False;
271 }
272 
273 
compareSubstring(const String & rStr1,sal_Int32 nOff1,sal_Int32 nLen1,const String & rStr2,sal_Int32 nOff2,sal_Int32 nLen2) const274 sal_Int32 TransliterationWrapper::compareSubstring(
275     const String& rStr1, sal_Int32 nOff1, sal_Int32 nLen1,
276     const String& rStr2, sal_Int32 nOff2, sal_Int32 nLen2 ) const
277 {
278     try
279     {
280         if( bFirstCall )
281             loadModuleImpl();
282         if ( xTrans.is() )
283             return xTrans->compareSubstring( rStr1, nOff1, nLen1, rStr2, nOff2, nLen2 );
284     }
285 	catch ( Exception& e )
286 	{
287 #ifdef DBG_UTIL
288         ByteString aMsg( "compareSubstring: Exception caught\n" );
289 		aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
290 		DBG_ERRORFILE( aMsg.GetBuffer() );
291 #else
292         (void)e;
293 #endif
294 	}
295     return 0;
296 }
297 
298 
compareString(const String & rStr1,const String & rStr2) const299 sal_Int32 TransliterationWrapper::compareString( const String& rStr1, const String& rStr2 ) const
300 {
301     try
302     {
303         if( bFirstCall )
304             loadModuleImpl();
305         if ( xTrans.is() )
306             return xTrans->compareString( rStr1, rStr2 );
307     }
308 	catch ( Exception& e )
309 	{
310 #ifdef DBG_UTIL
311         ByteString aMsg( "compareString: Exception caught\n" );
312 		aMsg += ByteString( String( e.Message ), RTL_TEXTENCODING_UTF8 );
313 		DBG_ERRORFILE( aMsg.GetBuffer() );
314 #else
315         (void)e;
316 #endif
317 	}
318     return 0;
319 }
320 
321 
322 // --- helpers --------------------------------------------------------
323 
isEqual(const String & rStr1,const String & rStr2) const324 sal_Bool TransliterationWrapper::isEqual( const String& rStr1, const String& rStr2 ) const
325 {
326     sal_Int32 nMatch1, nMatch2;
327     sal_Bool bMatch = equals(
328         rStr1, 0, rStr1.Len(), nMatch1,
329         rStr2, 0, rStr2.Len(), nMatch2 );
330     return bMatch;
331 }
332 
333 
isMatch(const String & rStr1,const String & rStr2) const334 sal_Bool TransliterationWrapper::isMatch( const String& rStr1, const String& rStr2 ) const
335 {
336     sal_Int32 nMatch1, nMatch2;
337     equals(
338         rStr1, 0, rStr1.Len(), nMatch1,
339         rStr2, 0, rStr2.Len(), nMatch2 );
340     return (nMatch1 <= nMatch2) && (nMatch1 == rStr1.Len());
341 }
342