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 <inputsequencechecker_th.hxx> 28 #include <wtt.h> 29 30 using namespace rtl; 31 32 namespace com { namespace sun { namespace star { namespace i18n { 33 34 InputSequenceChecker_th::InputSequenceChecker_th() 35 { 36 serviceName = "com.sun.star.i18n.InputSequenceChecker_th"; 37 } 38 39 InputSequenceChecker_th::~InputSequenceChecker_th() 40 { 41 } 42 43 /* Table for Thai Cell Manipulation */ 44 sal_Char _TAC_celltype_inputcheck[17][17] = { 45 /* Cn */ /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F */ 46 /* Cn-1 00 */{ 'X', 'A', 'A', 'A', 'A', 'A', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 47 /* 10 */{ 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 48 /* 20 */{ 'X', 'A', 'A', 'A', 'A', 'S', 'A', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C' }, 49 /* 30 */{ 'X', 'S', 'A', 'S', 'S', 'S', 'S', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 50 /* 40 */{ 'X', 'A', 'A', 'A', 'A', 'S', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 51 /* 50 */{ 'X', 'A', 'A', 'A', 'A', 'S', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 52 /* 60 */{ 'X', 'A', 'A', 'A', 'S', 'A', 'S', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 53 /* 70 */{ 'X', 'A', 'A', 'A', 'A', 'S', 'A', 'R', 'R', 'R', 'C', 'C', 'R', 'R', 'R', 'R', 'R' }, 54 /* 80 */{ 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'C', 'R', 'R', 'R', 'R', 'R', 'R' }, 55 /* 90 */{ 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 56 /* A0 */{ 'X', 'A', 'A', 'A', 'A', 'A', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 57 /* B0 */{ 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 58 /* C0 */{ 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 59 /* D0 */{ 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R', 'R' }, 60 /* E0 */{ 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'C', 'C', 'R', 'R', 'R', 'R', 'R' }, 61 /* F0 */{ 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'C', 'R', 'R', 'R', 'R', 'R', 'R' }, 62 { 'X', 'A', 'A', 'A', 'S', 'S', 'A', 'R', 'R', 'R', 'C', 'R', 'C', 'R', 'R', 'R', 'R' } 63 }; 64 65 sal_Bool _TAC_Composible[3][5] = { 66 /* 'A', 'C', 'S', 'R', 'X' */ 67 /* Mode 0 */ {sal_True, sal_True, sal_True, sal_True, sal_True}, // PASSTHROUGH = 0 68 /* Mode 1 */ {sal_True, sal_True, sal_True, sal_False, sal_True}, // BASIC = 1 69 /* Mode 2 */ {sal_True, sal_True, sal_False, sal_False, sal_True} // STRICT = 2 70 }; 71 72 static sal_Bool SAL_CALL check(sal_Unicode ch1, sal_Unicode ch2, sal_Int16 inputCheckMode) 73 { 74 sal_Int16 composible_class; 75 switch (_TAC_celltype_inputcheck[getCharType(ch1)][getCharType(ch2)]) { 76 case 'A': composible_class = 0; break; 77 case 'C': composible_class = 1; break; 78 case 'S': composible_class = 2; break; 79 case 'R': composible_class = 3; break; 80 case 'X': composible_class = 4; break; 81 default: composible_class = 0; 82 } 83 return (_TAC_Composible[inputCheckMode][composible_class]); 84 } 85 86 sal_Bool SAL_CALL 87 InputSequenceChecker_th::checkInputSequence(const OUString& Text, sal_Int32 nStartPos, 88 sal_Unicode inputChar, sal_Int16 inputCheckMode) throw(com::sun::star::uno::RuntimeException) 89 { 90 return check(Text[nStartPos], inputChar, inputCheckMode); 91 } 92 93 sal_Int32 SAL_CALL 94 InputSequenceChecker_th::correctInputSequence(OUString& Text, 95 sal_Int32 nStartPos, 96 sal_Unicode inputChar, 97 sal_Int16 inputCheckMode) 98 throw(com::sun::star::uno::RuntimeException) 99 { 100 /* 9 rules for input sequence correction, see issue i42661 for detail, 101 102 http://www.openoffice.org/issues/show_bug.cgi?id=42661 103 104 <abv> = <av1>|<av2>|<av3>|<bv1>|<bv2> 105 <abv1> = <av1>|<bv1> 106 <thanthakhat> = 0E4C (karan) 107 108 1. <cons> <abv>_x + <abv>_y => <cons> <abv>_y (replace) 109 2. <cons> <tone>_x + <tone>_y => <cons> <tone>_y (replace) 110 3. <cons> <abv> <tone>_x + <tone>_y => <cons> <abv> <tone>_y (replace) 111 4. <cons> <abv>_x <tone> + <abv>_y => <cons> <abv>_y <tone> (replace, reorder) 112 5. <cons> <tone> + <abv> => <cons> <abv> <tone> (reorder) 113 6. <cons> <fv1> + <tone> => <cons> <tone> <fv1> (reorder) 114 7. <cons> <tone>_x <fv1> + <tone>_y => <cons> <tone>_y <fv1> (replace, reorder) 115 8. <cons> <thanthakhat> + <abv1> => <cons> <abv1> <thanthakhat> (reorder) 116 9. <cons> <abv1>_x <thanthakhat> + <abv1>_y => <cons> <abv1>_y <thanthakhat>(reorder, replace) 117 */ 118 #define CT_ABV(t) ( (t>=CT_AV1 && t<=CT_AV3) || t==CT_BV1 || t==CT_BV2) 119 #define CT_ABV1(t) (t==CT_AV1 || t==CT_BV1) 120 121 if (check(Text[nStartPos], inputChar, inputCheckMode)) 122 Text = Text.replaceAt(++nStartPos, 0, OUString(inputChar)); 123 else if (nStartPos > 0 && getCharType(Text[nStartPos-1]) == CT_CONS) { 124 sal_uInt16 t1=getCharType(Text[nStartPos]), t2=getCharType(inputChar); 125 if ( (CT_ABV(t1) && CT_ABV(t2)) || // 1. 126 (t1==CT_TONE && t2==CT_TONE) )// 2. 127 Text = Text.replaceAt(nStartPos, 1, OUString(inputChar)); 128 else if ( (t1==CT_TONE && CT_ABV(t2)) || // 5. 129 (t1==CT_FV1 && t2==CT_TONE) || // 6. 130 (Text[nStartPos]==0x0E4C && CT_ABV1(t2)) ) // 8. 131 Text = Text.replaceAt(nStartPos++, 0, OUString(inputChar)); 132 else 133 nStartPos=Text.getLength(); 134 } else if (nStartPos > 1 && getCharType(Text[nStartPos-2]) == CT_CONS) { 135 sal_uInt16 t1=getCharType(Text[nStartPos-1]), t2=getCharType(Text[nStartPos]), t3=getCharType(inputChar); 136 if (CT_ABV(t1) && t2==CT_TONE && t3==CT_TONE) // 3. 137 Text = Text.replaceAt(nStartPos, 1, OUString(inputChar)); 138 else if ( (CT_ABV(t1) && t2==CT_TONE && CT_ABV(t3)) || // 4. 139 (t1==CT_TONE && t2==CT_FV1 && t3==CT_TONE) || // 7. 140 (CT_ABV1(t1) && Text[nStartPos]==0x0E4C && CT_ABV1(t3)) ) // 9. 141 Text = Text.replaceAt(nStartPos-1, 1, OUString(inputChar)); 142 else 143 nStartPos=Text.getLength(); 144 } else 145 nStartPos=Text.getLength(); 146 147 return nStartPos; 148 } 149 150 } } } } 151