diff options
Diffstat (limited to 'src/thinp/thinp.c')
-rw-r--r-- | src/thinp/thinp.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/src/thinp/thinp.c b/src/thinp/thinp.c new file mode 100644 index 0000000..3d36150 --- /dev/null +++ b/src/thinp/thinp.c @@ -0,0 +1,194 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libthai - Thai Language Support Library + * Copyright (C) 2001 Theppitak Karoonboonyanan <thep@linux.thai.net> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * thinp.c - Thai string input sequence filtering + * Created: 2001-08-04 + * Author: Theppitak Karoonboonyanan <thep@linux.thai.net> + */ + +#include <string.h> +#include <thai/thinp.h> +#include <thai/thctype.h> +#include <thai/tis.h> +#include <thai/wtt.h> + + +/** + * @brief Check for acceptance of input sequence + * + * @param c1 : previous character + * @param c2 : the newly input character + * @param s : strictness level + * + * @return non-zero if accepted, 0 otherwise + * + * Checks if, according to WTT 2.0 strictness level @a s, @a c2 is allowed + * after @a c1. + */ +int +th_isaccept (thchar_t c1, thchar_t c2, thstrict_t s) +{ + switch (s) { + case ISC_PASSTHROUGH: + return 1; + + case ISC_BASICCHECK: + return TACio_op (c1, c2) != RJ; + + case ISC_STRICT: + { + WTTOp op = TACio_op (c1, c2); + return op != RJ && op != SR; + } + + default: + return 0; + } +} + +static const struct correction_t { + thchar_t c1, c2, to[3]; +} corrections[] = { + { TIS_RU, TIS_SARA_AA, { TIS_RU, TIS_LAKKHANGYAO, 0 } }, + { TIS_LU, TIS_SARA_AA, { TIS_LU, TIS_LAKKHANGYAO, 0 } }, + { TIS_NIKHAHIT, TIS_SARA_AA, { TIS_SARA_AM, 0, 0 } }, + { 0, 0, { 0, 0, 0 } } +}; + +static int +correct_ (thchar_t c_1, thchar_t c, thchar_t conv[3]) +{ + const struct correction_t *p; + for (p = corrections; p->c1; ++p) { + if (c_1 == (thchar_t) p->c1 && c == (thchar_t) p->c2) { + strcpy ((char *) conv, (const char *) p->to); + return 1; + } + } + return 0; +} + +/** + * @brief Check and try to correct input sequence + * + * @param context : previous cell + * @param c : the newly input character + * @param conv : the storage for resulting correction info + * + * @returns 0 if the input is to be rejected + * non-zero otherwise. + * + * Given the previous cell as @a context, edit the input buffer using + * the given input @a c, maintaining WTT canonical order, and do some + * convenient correction in @a conv. + */ +int +th_validate (struct thcell_t context, thchar_t c, struct thinpconv_t *conv) +{ + thchar_t prev_c = context.top ? + context.top : + (context.hilo ? context.hilo : context.base); + int ret; + + /* SARA_AM, if present, is always the last char of the cell */ + if (context.hilo == TIS_SARA_AM) { + prev_c = TIS_SARA_AM; + } + + /* try predefined corrections */ + ret = correct_ (prev_c, c, conv->conv); + if (ret) { + conv->offset = -1; + return 1; + } + + /* normal cases, using Strict level */ + if (th_isaccept (prev_c, c, ISC_STRICT)) { + conv->conv[0] = c; conv->conv[1] = 0; + conv->offset = 0; + return 1; + } + + /* try correction by conversion */ + switch (th_chlevel(c)) { + case 3: + case 2: + if (context.hilo && th_isaccept (context.hilo, c, ISC_STRICT)) { + /* hilo OK, replace top only */ + conv->offset = 0; + conv->conv[0] = c; conv->conv[1] = 0; + if (context.top) { + --conv->offset; + } + return 1; + } + /* hilo not OK with c (hilo == SARA_AM falls here), or no hilo */ + if (th_isaccept (context.base, c, ISC_STRICT) + && (context.hilo != TIS_SARA_AM + || th_isaccept (c, TIS_SARA_AM, ISC_STRICT))) + { + /* replace from hilo on, using new top */ + int i = 0; + conv->offset = 0; + conv->conv[i++] = c; + if (context.hilo) { + --conv->offset; + if (context.hilo == TIS_SARA_AM) { + conv->conv[i++] = TIS_SARA_AM; + } + } + if (context.top) { + --conv->offset; + } + conv->conv[i] = 0; + return 1; + } + if (th_chlevel(c) == 2) + break; + /* fall through for level 3 */ + case -1: + case 1: + if (th_isaccept (context.base, c, ISC_STRICT)) { + /* replace from hilo on; use new hilo + old top if OK */ + int i = 0; + conv->offset = 0; + conv->conv[i++] = c; + if (context.hilo) { + --conv->offset; + } + if (context.top) { + --conv->offset; + if (th_isaccept (c, context.top, ISC_STRICT)) { + conv->conv[i++] = context.top; + } + } + conv->conv[i] = 0; + return 1; + } + break; + } + + return 0; +} + +/* +vi:ts=4:ai:expandtab +*/ |