aboutsummaryrefslogtreecommitdiff
path: root/src/share/classes/com/sun/inputmethods/internal/thaiim/ThaiRules.java
blob: 02e4b6ed47969709c02aa5bd6f4434660e17b861 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
/*
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.inputmethods.internal.thaiim;

import java.awt.im.InputMethodRequests;

public class ThaiRules {

    public static final char BASE = 0x0e00;

    public static final byte NON  =  0;
    public static final byte CONS =  1;
    public static final byte LV   =  2;
    public static final byte FV1  =  3;
    public static final byte FV2  =  4;
    public static final byte FV3  =  5;
    public static final byte FV4  =  6;
    /* Note that FV4 is added. It is not in WTT.
     * We need it for SARA AM since it has a
     * weired characteristic to share the same
     * cell with whatever consonant preceeds it.
     */
    public static final byte BV1  =  7;
    public static final byte BV2  =  8;
    public static final byte BD   =  9;
    public static final byte TONE = 10;
    public static final byte AD1  = 11;
    public static final byte AD2  = 12;
    public static final byte AD3  = 13;
    public static final byte AV1  = 14;
    public static final byte AV2  = 15;
    public static final byte AV3  = 16;

    /**
     * Constants for validity checking and auto correction
     */
    public static final byte STRICT    = 0;
    public static final byte LOOSE     = 1;
    public static final byte NOREPLACE = 2;

    public static final byte[] CHARTYPE = {
    /* 0e00 UNUSED                      */      NON,
    /* THAI CHARACTER KO KAI            */      CONS,
    /* THAI CHARACTER KHO KHAI          */      CONS,
    /* THAI CHARACTER KHO KHUAT         */      CONS,
    /* THAI CHARACTER KHO KHWAI         */      CONS,
    /* THAI CHARACTER KHO KHON          */      CONS,
    /* THAI CHARACTER KHO RAKHANG       */      CONS,
    /* THAI CHARACTER NGO NGU           */      CONS,
    /* THAI CHARACTER CHO CHAN          */      CONS,
    /* THAI CHARACTER CHO CHING         */      CONS,
    /* THAI CHARACTER CHO CHANG         */      CONS,
    /* THAI CHARACTER SO SO             */      CONS,
    /* THAI CHARACTER CHO CHOE          */      CONS,
    /* THAI CHARACTER YO YING           */      CONS,
    /* THAI CHARACTER DO CHADA          */      CONS,
    /* THAI CHARACTER TO PATAK          */      CONS,
    /* THAI CHARACTER THO THAN          */      CONS,
    /* THAI CHARACTER THO NANGMONTHO    */      CONS,
    /* THAI CHARACTER THO PHUTHAO       */      CONS,
    /* THAI CHARACTER NO NEN            */      CONS,
    /* THAI CHARACTER DO DEK            */      CONS,
    /* THAI CHARACTER TO TAO            */      CONS,
    /* THAI CHARACTER THO THUNG         */      CONS,
    /* THAI CHARACTER THO THAHAN        */      CONS,
    /* THAI CHARACTER THO THONG         */      CONS,
    /* THAI CHARACTER NO NU             */      CONS,
    /* THAI CHARACTER BO BAIMAI         */      CONS,
    /* THAI CHARACTER PO PLA            */      CONS,
    /* THAI CHARACTER PHO PHUNG         */      CONS,
    /* THAI CHARACTER FO FA             */      CONS,
    /* THAI CHARACTER PHO PHAN          */      CONS,
    /* THAI CHARACTER FO FAN            */      CONS,
    /* THAI CHARACTER PHO SAMPHAO       */      CONS,
    /* THAI CHARACTER MO MA             */      CONS,
    /* THAI CHARACTER YO YAK            */      CONS,
    /* THAI CHARACTER RO RUA            */      CONS,
    /* THAI CHARACTER RU                */      FV3,
    /* THAI CHARACTER LO LING           */      CONS,
    /* THAI CHARACTER LU                */      FV3,
    /* THAI CHARACTER WO WAEN           */      CONS,
    /* THAI CHARACTER SO SALA           */      CONS,
    /* THAI CHARACTER SO RUSI           */      CONS,
    /* THAI CHARACTER SO SUA            */      CONS,
    /* THAI CHARACTER HO HIP            */      CONS,
    /* THAI CHARACTER LO CHULA          */      CONS,
    /* THAI CHARACTER O ANG             */      CONS,
    /* THAI CHARACTER HO NOKHUK         */      CONS,
    /* THAI CHARACTER PAIYANNOI         */      NON,
    /* THAI CHARACTER SARA A            */      FV1,
    /* THAI CHARACTER MAI HAN-AKAT      */      AV2,
    /* THAI CHARACTER SARA AA           */      FV1,
    /* THAI CHARACTER SARA AM           */      FV4,
    /* THAI CHARACTER SARA I            */      AV1,
    /* THAI CHARACTER SARA II           */      AV3,
    /* THAI CHARACTER SARA UE           */      AV2,
    /* THAI CHARACTER SARA UEE          */      AV3,
    /* THAI CHARACTER SARA U            */      BV1,
    /* THAI CHARACTER SARA UU           */      BV2,
    /* THAI CHARACTER PHINTHU           */      BD,
    /* 0e3b UNUSED                      */      NON,
    /* 0e3c UNUSED                      */      NON,
    /* 0e3d UNUSED                      */      NON,
    /* 0e3e UNUSED                      */      NON,
    /* THAI CURRENCY SYMBOL BAHT        */      NON,
    /* THAI CHARACTER SARA E            */      LV,
    /* THAI CHARACTER SARA AE           */      LV,
    /* THAI CHARACTER SARA O            */      LV,
    /* THAI CHARACTER SARA AI MAIMUAN   */      LV,
    /* THAI CHARACTER SARA AI MAIMALAI  */      LV,
    /* THAI CHARACTER LAKKHANGYAO       */      FV2,
    /* THAI CHARACTER MAIYAMOK          */      NON,
    /* THAI CHARACTER MAITAIKHU         */      AD2,
    /* THAI CHARACTER MAI EK            */      TONE,
    /* THAI CHARACTER MAI THO           */      TONE,
    /* THAI CHARACTER MAI TRI           */      TONE,
    /* THAI CHARACTER MAI CHATTAWA      */      TONE,
    /* THAI CHARACTER THANTHAKHAT       */      AD1,
    /* THAI CHARACTER NIKHAHIT          */      AD3,
    /* THAI CHARACTER YAMAKKAN          */      AD3,
    /* THAI CHARACTER FONGMAN           */      NON,
    /* THAI DIGIT ZERO                  */      NON,
    /* THAI DIGIT ONE                   */      NON,
    /* THAI DIGIT TWO                   */      NON,
    /* THAI DIGIT THREE                 */      NON,
    /* THAI DIGIT FOUR                  */      NON,
    /* THAI DIGIT FIVE                  */      NON,
    /* THAI DIGIT SIX                   */      NON,
    /* THAI DIGIT SEVEN                 */      NON,
    /* THAI DIGIT EIGHT                 */      NON,
    /* THAI DIGIT NINE                  */      NON,
    /* THAI CHARACTER ANGKHANKHU        */      NON,
    /* THAI CHARACTER KHOMUT            */      NON
    };

    private InputMethodRequests requests;

    ThaiRules(InputMethodRequests requests) {
        this.requests = requests;
    }

    public static byte getCharType(char c) {
        byte cType;
        int ci = ((int) c) - (int) BASE;
        if (ci < 0 || ci >= CHARTYPE.length)
            cType = NON;
        else
            cType = CHARTYPE[ci];
        return cType;
    }

    private static boolean isValid(char c1, char c2, int[] validityArray) {
        return ((validityArray[getCharType(c1)]
                & (1 << getCharType(c2))) != 0);
    }

    /**
     * VALIDITY is a bit matrix defining whether one
     * character is allowed to be typed in after the
     * previous one (array index). Determining the
     * validity is done by bit-anding the 2nd char
     * type's mask (obtained by 1 << chartype) with
     * the array element indexed by the first char
     * type. If the result is non-zero, the 2nd
     * character is allowed to follow the first.
     */

    /* Please note that the bits in the comment below
     * are displayed least significant bit first.
     * The actual value reflexs this representation
     * when the bits are swapped.
     */

    private static final int[] INPUTVALIDITY = {
    /* NON  1110 010  0 0000 0000 0 */          0x00027,
    /* CONS 1111 111  1 1111 1111 1 */          0x1ffff,
    /* LV   0100 000  0 0000 0000 0 */          0x00002,
    /* FV1  1110 010  0 0000 0000 0 */          0x00027,
    /* FV2  1110 010  0 0000 0000 0 */          0x00027,
    /* FV3  1110 110  0 0000 0000 0 */          0x00037,
    /* FV4  1110 010  0 0000 0000 0 */          0x00027,
    /* BV1  1110 010  0 0011 0000 0 */          0x00c27,
    /* BV2  1110 010  0 0010 0000 0 */          0x00427,
    /* BD   1110 010  0 0000 0000 0 */          0x00027,
    /* TONE 1111 011  0 0000 0000 0 */          0x0006f,
    /* AD1  1110 010  0 0000 0000 0 */          0x00027,
    /* AD2  1110 010  0 0000 0000 0 */          0x00027,
    /* AD3  1110 010  0 0000 0000 0 */          0x00027,
    /* AV1  1110 010  0 0011 0000 0 */          0x00c27,
    /* AV2  1110 010  0 0010 0000 0 */          0x00427,
    /* AV3  1110 010  0 0010 0100 0 */          0x02427
    };

    private static final int[] COMPOSABLE = {
    /* NON  0000 000  0 0000 0000 0 */          0x00000,
    /* CONS 0000 001  1 1111 1111 1 */          0x1ffc0,
    /* LV   0000 000  0 0000 0000 0 */          0x00000,
    /* FV1  0000 000  0 0000 0000 0 */          0x00000,
    /* FV2  0000 000  0 0000 0000 0 */          0x00000,
    /* FV3  0000 000  0 0000 0000 0 */          0x00000,
    /* FV4  0000 000  0 0000 0000 0 */          0x00000,
    /* BV1  0000 000  0 0011 0000 0 */          0x00c00,
    /* BV2  0000 000  0 0010 0000 0 */          0x00400,
    /* BD   0000 000  0 0000 0000 0 */          0x00000,
    /* TONE 0000 001  0 0000 0000 0 */          0x00040,
    /* AD1  0000 000  0 0000 0000 0 */          0x00000,
    /* AD2  0000 000  0 0000 0000 0 */          0x00000,
    /* AD3  0000 000  0 0000 0000 0 */          0x00000,
    /* AV1  0000 000  0 0011 0000 0 */          0x00c00,
    /* AV2  0000 000  0 0010 0000 0 */          0x00400,
    /* AV3  0000 000  0 0010 0100 0 */          0x02400
    };

    private static final int[] REPLACABLE = {
    /* NON  0000 000  0 0000 0000 0 */          0x00000,
    /* CONS 0000 000  0 0000 0000 0 */          0x00000,
    /* LV   0000 000  0 0000 0000 0 */          0x00000,
    /* FV1  0000 000  0 0000 0000 0 */          0x00000,
    /* FV2  0000 000  0 0000 0000 0 */          0x00000,
    /* FV3  0000 000  0 0000 0000 0 */          0x00000,
    /* FV4  0000 001  1 1001 1111 1 */          0x1f9c0,
    /* BV1  0000 001  1 1100 1111 1 */          0x1f3c0,
    /* BV2  0000 001  1 1101 1111 1 */          0x1fbc0,
    /* BD   0000 001  1 1111 1111 1 */          0x1ffc0,
    /* TONE 0000 000  0 0111 1100 0 */          0x03e00,
    /* AD1  0000 001  0 1111 1101 1 */          0x1bf40,
    /* AD2  0000 001  1 1111 1111 1 */          0x1ffc0,
    /* AD3  0000 001  1 1111 1111 0 */          0x0ffc0,
    /* AV1  0000 001  1 1100 1111 1 */          0x1f3c0,
    /* AV2  0000 001  1 1101 1111 1 */          0x1fbc0,
    /* AV3  0000 001  1 1101 1011 1 */          0x1dbc0
    };

    private static final int[] SWAPPABLE = {
    /* NON  0000 000  0 0000 0000 0 */          0x00000,
    /* CONS 0000 000  0 0000 0000 0 */          0x00000,
    /* LV   0000 000  0 0000 0000 0 */          0x00000,
    /* FV1  0000 000  0 0000 0000 0 */          0x00000,
    /* FV2  0000 000  0 0000 0000 0 */          0x00000,
    /* FV3  0000 000  0 0000 0000 0 */          0x00000,
    /* FV4  0000 000  0 0010 0000 0 */          0x00400,
    /* BV1  0000 000  0 0000 0000 0 */          0x00000,
    /* BV2  0000 000  0 0000 0000 0 */          0x00000,
    /* BD   0000 000  0 0000 0000 0 */          0x00000,
    /* TONE 0000 000  1 1000 0011 1 */          0x1c180,
    /* AD1  0000 000  1 0000 0010 0 */          0x04080,
    /* AD2  0000 000  0 0000 0000 0 */          0x00000,
    /* AD3  0000 000  0 0000 0000 1 */          0x10000,
    /* AV1  0000 000  0 0000 0000 0 */          0x00000,
    /* AV2  0000 000  0 0000 0000 0 */          0x00000,
    /* AV3  0000 000  0 0000 0000 0 */          0x00000
    };

    public static boolean isInputValid(char c1, char c2) {
        return isValid(c1, c2, INPUTVALIDITY);
    }

    public static boolean isComposable(char c1, char c2) {
        return isValid(c1, c2, COMPOSABLE);
    }

    public static boolean isSwappable(char c1, char c2) {
        return isValid(c1, c2, SWAPPABLE);
    }

    public static boolean isReplacable(char c1, char c2) {
        return isValid(c1, c2, REPLACABLE);
    }

    public static boolean isForward(char c) {
        return (getCharType(c) < FV4);
    }

    public static boolean isDead(char c) {
        return (getCharType(c) > FV3);
    }

    public boolean isInputValid(char current) {
        int offset = requests.getInsertPositionOffset();
        if (offset == 0) {
            byte charType = getCharType(current);
            return ((charType < FV1) || (charType == FV3));
        }
        else {
            char prev = requests.getCommittedText(offset-1, offset, null).first();

            if(isForward(current)) {
                if (isInputValid(prev, current)) {
                    if (getCharType(prev) == TONE &&
                        getCharType(current) == FV1) {
                        if (offset == 1) {
                            return true;
                        } else {
                            char pprev =
                                requests.getCommittedText(offset-2, offset-1, null).first();
                            return isInputValid(pprev, current);
                        }
                    } else {
                        return true;
                    }
                } else if (prev == '\u0e32' &&       // SARA AA
                           current  == '\u0e30') {   // SARA A
                    return true;
                } else if (prev == '\u0e4d' &&       // NIKAHIT
                           current  == '\u0e32') {   // SARA AA
                                                     // Special compose to SARA AM
                    return true;
                } else {
                    return false;
                }
            } else {
                if(isInputValid(prev, current)) {
                    if (getCharType(prev) == TONE &&
                        getCharType(current) == FV4) {
                        return (offset != 1);
                    } else {
                        return true;
                    }
                } else {
                    return false;
                }
            }
        }
    }
}