1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_i18npool.hxx"
30 
31 #include <inputsequencechecker.hxx>
32 #include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
33 #include <com/sun/star/i18n/UnicodeType.hpp>
34 #include <i18nutil/unicode.hxx>
35 #include <rtl/ustrbuf.hxx>
36 
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::lang;
39 using namespace ::rtl;
40 
41 namespace com { namespace sun { namespace star { namespace i18n {
42 
43 InputSequenceCheckerImpl::InputSequenceCheckerImpl( const Reference < XMultiServiceFactory >& rxMSF ) : xMSF( rxMSF )
44 {
45         serviceName = "com.sun.star.i18n.InputSequenceCheckerImpl";
46         cachedItem = NULL;
47 }
48 
49 InputSequenceCheckerImpl::InputSequenceCheckerImpl()
50 {
51 }
52 
53 InputSequenceCheckerImpl::~InputSequenceCheckerImpl()
54 {
55         // Clear lookuptable
56         for (size_t l = 0; l < lookupTable.size(); l++)
57             delete lookupTable[l];
58 
59         lookupTable.clear();
60 }
61 
62 sal_Bool SAL_CALL
63 InputSequenceCheckerImpl::checkInputSequence(const OUString& Text, sal_Int32 nStartPos,
64         sal_Unicode inputChar, sal_Int16 inputCheckMode) throw(RuntimeException)
65 {
66         if (inputCheckMode == InputSequenceCheckMode::PASSTHROUGH)
67             return sal_True;
68 
69         sal_Char* language = getLanguageByScripType(Text[nStartPos], inputChar);
70 
71         if (language)
72             return getInputSequenceChecker(language)->checkInputSequence(Text, nStartPos, inputChar, inputCheckMode);
73         else
74             return sal_True; // not a checkable languages.
75 }
76 
77 sal_Int32 SAL_CALL
78 InputSequenceCheckerImpl::correctInputSequence(OUString& Text, sal_Int32 nStartPos,
79         sal_Unicode inputChar, sal_Int16 inputCheckMode) throw(RuntimeException)
80 {
81         if (inputCheckMode != InputSequenceCheckMode::PASSTHROUGH) {
82             sal_Char* language = getLanguageByScripType(Text[nStartPos], inputChar);
83 
84             if (language)
85                 return getInputSequenceChecker(language)->correctInputSequence(Text, nStartPos, inputChar, inputCheckMode);
86         }
87         Text = Text.replaceAt(++nStartPos, 0, OUString(inputChar));
88         return nStartPos;
89 }
90 
91 static ScriptTypeList typeList[] = {
92         //{ UnicodeScript_kHebrew,              UnicodeScript_kHebrew },        // 10,
93         //{ UnicodeScript_kArabic,              UnicodeScript_kArabic },        // 11,
94         { UnicodeScript_kDevanagari,UnicodeScript_kDevanagari,          UnicodeScript_kDevanagari },    // 14,
95         { UnicodeScript_kThai,  UnicodeScript_kThai,                  UnicodeScript_kThai },          // 24,
96 
97         { UnicodeScript_kScriptCount,   UnicodeScript_kScriptCount,           UnicodeScript_kScriptCount }    // 88
98 };
99 
100 sal_Char* SAL_CALL
101 InputSequenceCheckerImpl::getLanguageByScripType(sal_Unicode cChar, sal_Unicode nChar)
102 {
103     sal_Int16 type = unicode::getUnicodeScriptType( cChar, typeList, UnicodeScript_kScriptCount );
104 
105     if (type != UnicodeScript_kScriptCount &&
106             type == unicode::getUnicodeScriptType( nChar, typeList, UnicodeScript_kScriptCount )) {
107         switch(type) {
108             case UnicodeScript_kThai:           return (sal_Char*)"th";
109             //case UnicodeScript_kArabic:       return (sal_Char*)"ar";
110             //case UnicodeScript_kHebrew:       return (sal_Char*)"he";
111             case UnicodeScript_kDevanagari:   return (sal_Char*)"hi";
112         }
113     }
114     return NULL;
115 }
116 
117 Reference< XExtendedInputSequenceChecker >& SAL_CALL
118 InputSequenceCheckerImpl::getInputSequenceChecker(sal_Char* rLanguage) throw (RuntimeException)
119 {
120         if (cachedItem && cachedItem->aLanguage == rLanguage) {
121             return cachedItem->xISC;
122         }
123         else if (xMSF.is()) {
124             for (size_t l = 0; l < lookupTable.size(); l++) {
125                 cachedItem = lookupTable[l];
126                 if (cachedItem->aLanguage == rLanguage)
127                     return cachedItem->xISC;
128             }
129 
130             Reference < uno::XInterface > xI = xMSF->createInstance(
131                         OUString::createFromAscii("com.sun.star.i18n.InputSequenceChecker_") +
132                         OUString::createFromAscii(rLanguage));
133 
134             if ( xI.is() ) {
135                 Reference< XExtendedInputSequenceChecker > xISC;
136                 xI->queryInterface( getCppuType((const Reference< XExtendedInputSequenceChecker>*)0) ) >>= xISC;
137                 if (xISC.is()) {
138                     lookupTable.push_back(cachedItem = new lookupTableItem(rLanguage, xISC));
139                     return cachedItem->xISC;
140                 }
141             }
142         }
143         throw RuntimeException();
144 }
145 
146 OUString SAL_CALL
147 InputSequenceCheckerImpl::getImplementationName(void) throw( RuntimeException )
148 {
149         return OUString::createFromAscii(serviceName);
150 }
151 
152 sal_Bool SAL_CALL
153 InputSequenceCheckerImpl::supportsService(const OUString& rServiceName) throw( RuntimeException )
154 {
155         return !rServiceName.compareToAscii(serviceName);
156 }
157 
158 Sequence< OUString > SAL_CALL
159 InputSequenceCheckerImpl::getSupportedServiceNames(void) throw( RuntimeException )
160 {
161         Sequence< OUString > aRet(1);
162         aRet[0] = OUString::createFromAscii(serviceName);
163         return aRet;
164 }
165 
166 } } } }
167