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