From 77ec02adbc8f9657e7749b307d3cc86ccbd163ea Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Sat, 12 Mar 2011 14:57:48 +0000
Subject: libX11 pixman mesa git update 12 Mar 2011

---
 libX11/modules/im/ximcp/imThaiFlt.c | 2835 ++++++++++++++++++-----------------
 1 file changed, 1421 insertions(+), 1414 deletions(-)

(limited to 'libX11/modules/im')

diff --git a/libX11/modules/im/ximcp/imThaiFlt.c b/libX11/modules/im/ximcp/imThaiFlt.c
index e0b3988e3..d22b13038 100644
--- a/libX11/modules/im/ximcp/imThaiFlt.c
+++ b/libX11/modules/im/ximcp/imThaiFlt.c
@@ -1,1414 +1,1421 @@
-/***********************************************************
-
-Copyright 1993, 1998  The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1993 by Digital Equipment Corporation, Maynard, Massachusetts.
-
-                        All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
-**++
-**  FACILITY:
-**
-**      Xlib
-**
-**  ABSTRACT:
-**
-**	Thai specific functions.
-**	Handles character classifications, composibility checking,
-**	Input sequence check and other Thai specific requirements
-**	according to WTT specification and DEC extensions.
-**
-**  MODIFICATION HISTORY:
-**
-**/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <X11/Xlib.h>
-#include <X11/Xmd.h>
-#include <X11/keysym.h>
-#include <X11/Xutil.h>
-#include "Xlibint.h"
-#include "Xlcint.h"
-#include "Ximint.h"
-#include "XimThai.h"
-#include "XlcPubI.h"
-
-
-#define SPACE   32
-
-/* character classification table */
-#define TACTIS_CHARS 256
-Private
-char const tactis_chtype[TACTIS_CHARS] = {
-    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /*  0 -  7 */
-    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /*  8 - 15 */
-    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 16 - 23 */
-    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 24 - 31 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 32 - 39 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 40 - 47 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 48 - 55 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 56 - 63 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 64 - 71 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 72 - 79 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 80 - 87 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 88 - 95 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 96 - 103 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 104 - 111 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 112 - 119 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  CTRL,  /* 120 - 127 */
-    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 128 - 135 */
-    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 136 - 143 */
-    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 144 - 151 */
-    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 152 - 159 */
-    NON,  CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 160 - 167 */
-    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 168 - 175 */
-    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 176 - 183 */
-    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 184 - 191 */
-    CONS, CONS, CONS, CONS,  FV3, CONS,  FV3, CONS,  /* 192 - 199 */
-    CONS, CONS, CONS, CONS, CONS, CONS, CONS, NON,   /* 200 - 207 */
-    FV1,  AV2,  FV1,  FV1,  AV1,  AV3,  AV2,  AV3,   /* 208 - 215 */
-    BV1,  BV2,  BD,   NON,  NON,  NON,  NON,  NON,   /* 216 - 223 */
-    LV,   LV,   LV,   LV,   LV,   FV2,  NON,  AD2,   /* 224 - 231 */
-    TONE, TONE, TONE, TONE, AD1,  AD1,  AD3,  NON,   /* 232 - 239 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 240 - 247 */
-    NON,  NON,  NON,  NON,  NON,  NON,  NON,  CTRL   /* 248 - 255 */
-};
-
-/* Composibility checking tables */
-#define NC  0   /* NOT COMPOSIBLE - following char displays in next cell */
-#define CP  1   /* COMPOSIBLE - following char is displayed in the same cell
-                                as leading char, also implies ACCEPT */
-#define XC  3   /* Non-display */
-#define AC  4   /* ACCEPT - display the following char in the next cell */
-#define RJ  5   /* REJECT - discard that following char, ignore it */
-
-#define CH_CLASSES      17  /* 17 classes of chars */
-
-Private
-char const write_rules_lookup[CH_CLASSES][CH_CLASSES] = {
-        /* Table 0: writing/outputing rules */
-        /* row: leading char,  column: following char */
-/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
-   {XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*CTRL*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*NON*/
-  ,{XC, NC, NC, NC, NC, NC, NC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*LV*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV1*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV2*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV3*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, CP, NC, NC, NC, NC, NC}/*BV1*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, NC, NC, NC, NC, NC}/*BV2*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*BD*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*TONE*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD1*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD2*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD3*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, CP, NC, NC, NC, NC, NC}/*AV1*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, NC, NC, NC, NC, NC}/*AV2*/
-  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, CP, NC, NC, NC, NC}/*AV3*/
-};
-
-Private
-char const wtt_isc1_lookup[CH_CLASSES][CH_CLASSES] = {
-      /* Table 1: WTT default input sequence check rules */
-      /* row: leading char,  column: following char */
-/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
-   {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/
-  ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV3*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*TONE*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD1*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD2*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/
-};
-
-Private
-char const wtt_isc2_lookup[CH_CLASSES][CH_CLASSES] = {
-      /* Table 2: WTT strict input sequence check rules */
-      /* row: leading char,  column: following char */
-/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
-   {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/
-  ,{XC, AC, AC, AC, AC, RJ, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
-  ,{XC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/
-  ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/
-  ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/
-  ,{XC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV3*/
-  ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*TONE*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD1*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD2*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/
-  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/
-};
-
-Private
-char const thaicat_isc_lookup[CH_CLASSES][CH_CLASSES] = {
-      /* Table 3: Thaicat input sequence check rules */
-      /* row: leading char,  column: following char */
-/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
-   {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/
-  ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ} /*FV3*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/
-  ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, RJ, RJ, RJ, RJ, RJ, CP, CP, CP}/*TONE*/
-  ,{XC, AC, AC, AC, AC, AC, AC, CP, RJ, RJ, RJ, RJ, RJ, RJ, CP, RJ, RJ}/*AD1*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, CP}/*AD2*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/
-  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/
-};
-
-
-/* returns classification of a char */
-Private int
-THAI_chtype (unsigned char	ch)
-{
-    return tactis_chtype[ch];
-}
-
-#ifdef UNUSED
-/* returns the display level */
-Private int
-THAI_chlevel (unsigned char	ch)
-{
-    int     chlevel;
-
-    switch (tactis_chtype[ch])
-    {
-        case CTRL:
-            chlevel = NON;
-            break;
-        case BV1:
-        case BV2:
-        case BD:
-            chlevel = BELOW;
-            break;
-        case TONE:
-        case AD1:
-        case AD2:
-            chlevel = TOP;
-            break;
-        case AV1:
-        case AV2:
-        case AV3:
-        case AD3:
-            chlevel = ABOVE;
-            break;
-        case NON:
-        case CONS:
-        case LV:
-        case FV1:
-        case FV2:
-        case FV3:
-        default: /* if tactis_chtype is invalid */
-            chlevel = BASE;
-            break;
-    }
-    return chlevel;
-}
-
-
-/* return True if char is non-spacing */
-Private Bool
-THAI_isdead (unsigned char	ch)
-{
-    return ((tactis_chtype[ch] == CTRL) || (tactis_chtype[ch] == BV1) ||
-            (tactis_chtype[ch] == BV2)  || (tactis_chtype[ch] == BD)  ||
-            (tactis_chtype[ch] == TONE) || (tactis_chtype[ch] == AD1) ||
-            (tactis_chtype[ch] == AD2)  || (tactis_chtype[ch] == AD3) ||
-            (tactis_chtype[ch] == AV1)  || (tactis_chtype[ch] == AV2) ||
-            (tactis_chtype[ch] == AV3));
-}
-
-
-/* return True if char is consonant */
-Private Bool
-THAI_iscons (unsigned char	ch)
-{
-    return (tactis_chtype[ch] == CONS);
-}
-
-
-/* return True if char is vowel */
-Private Bool
-THAI_isvowel (unsigned char	ch)
-{
-    return ((tactis_chtype[ch] == LV)  || (tactis_chtype[ch] == FV1) ||
-            (tactis_chtype[ch] == FV2) || (tactis_chtype[ch] == FV3) ||
-            (tactis_chtype[ch] == BV1) || (tactis_chtype[ch] == BV2) ||
-            (tactis_chtype[ch] == AV1) || (tactis_chtype[ch] == AV2) ||
-            (tactis_chtype[ch] == AV3));
-}
-
-
-/* return True if char is tonemark */
-Private Bool
-THAI_istone (unsigned char	ch)
-{
-    return (tactis_chtype[ch] == TONE);
-}
-#endif
-
-Private Bool
-THAI_iscomposible (
-    unsigned char	follow_ch,
-    unsigned char	lead_ch)
-{/* "Can follow_ch be put in the same display cell as lead_ch?" */
-
-    return (write_rules_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)]
-            == CP);
-}
-
-Private Bool
-THAI_isaccepted (
-    unsigned char	follow_ch,
-    unsigned char	lead_ch,
-    unsigned char	mode)
-{
-    Bool iskeyvalid; /*  means "Can follow_ch be keyed in after lead_ch?" */
-
-    switch (mode)
-    {
-        case WTT_ISC1:
-            iskeyvalid =
-          (wtt_isc1_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ);
-            break;
-        case WTT_ISC2:
-            iskeyvalid =
-          (wtt_isc2_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ);
-            break;
-        case THAICAT_ISC:
-            iskeyvalid =
-       (thaicat_isc_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ);
-            break;
-        default:
-            iskeyvalid = True;
-            break;
-    }
-
-    return iskeyvalid;
-}
-
-#ifdef UNUSED
-Private void
-THAI_apply_write_rules(
-    unsigned char	*instr,
-    unsigned char	*outstr,
-    unsigned char	insert_ch,
-    int 		*num_insert_ch)
-{
-/*
-Input parameters:
-    instr - input string
-    insert_ch specify what char to be added when invalid composition is found
-Output parameters:
-    outstr - output string after input string has been applied the rules
-    num_insert_ch - number of insert_ch added to outstr.
-*/
-    unsigned char   *lead_ch = NULL, *follow_ch = NULL, *out_ch = NULL;
-
-    *num_insert_ch = 0;
-    lead_ch = follow_ch = instr;
-    out_ch = outstr;
-    if ((*lead_ch == '\0') || !(THAI_find_chtype(instr,DEAD)))
-    {   /* Empty string or can't find any non-spacing char*/
-        strcpy((char *)outstr, (char *)instr);
-    } else { /* String of length >= 1, keep looking */
-        follow_ch++;
-        if (THAI_isdead(*lead_ch)) { /* is first char non-spacing? */
-            *out_ch++ = SPACE;
-            (*num_insert_ch)++;
-        }
-        *out_ch++ = *lead_ch;
-        while (*follow_ch != '\0')  /* more char in string to check */
-        {
-            if (THAI_isdead(*follow_ch) &&
-                 !THAI_iscomposible(*follow_ch,*lead_ch))
-            {
-                *out_ch++ = SPACE;
-                (*num_insert_ch)++;
-            }
-            *out_ch++ = *follow_ch;
-            lead_ch = follow_ch;
-            follow_ch++;
-        }
-        *out_ch = '\0';
-    }
-}
-
-Private int
-THAI_find_chtype (
-    unsigned char	*instr,
-    int		chtype)
-{
-/*
-Input parameters:
-    instr - input string
-    chtype - type of character to look for
-Output parameters:
-    function returns first position of character with matched chtype
-    function returns -1 if it does not find.
-*/
-    int i = 0, position = -1;
-
-    switch (chtype)
-    {
-        case DEAD:
-            for (i = 0; *instr != '\0' && THAI_isdead(*instr); i++, instr++)
-		;
-            if (*instr != '\0') position = i;
-            break;
-        default:
-            break;
-    }
-    return position;
-}
-
-
-Private int
-THAI_apply_scm(
-    unsigned char	*instr,
-    unsigned char	*outstr,
-    unsigned char	spec_ch,
-    int		num_sp,
-    unsigned char	insert_ch)
-{
-    unsigned char   *scan, *outch;
-    int             i, dead_count, found_count;
-    Bool            isconsecutive;
-
-    scan = instr;
-    outch = outstr;
-    dead_count = found_count = 0;
-    isconsecutive = False;
-    while (*scan != '\0') {
-        if (THAI_isdead(*scan))
-            dead_count++;       /* count number of non-spacing char */
-        if (*scan == spec_ch)
-            if (!isconsecutive)
-                found_count++;      /* count number consecutive spec char found */
-        *outch++ = *scan++;
-        if (found_count == num_sp) {
-            for (i = 0; i < dead_count; i++)
-                *outch++ = insert_ch;
-            dead_count = found_count = 0;
-        }
-    }
-    /* what to return? */
-    return 0; /* probably not right but better than returning garbage */
-}
-
-
-/* The following functions are copied from XKeyBind.c */
-
-Private void ComputeMaskFromKeytrans();
-Private int IsCancelComposeKey(KeySym *symbol, XKeyEvent *event);
-Private void SetLed(Display *dpy, int num, int state);
-Private CARD8 FindKeyCode();
-
-
-/* The following functions are specific to this module */
-
-Private int XThaiTranslateKey();
-Private int XThaiTranslateKeySym();
-
-
-Private KeySym HexIMNormalKey(
-    XicThaiPart *thai_part,
-    KeySym symbol,
-    XKeyEvent *event);
-Private KeySym HexIMFirstComposeKey(
-    XicThaiPart *thai_part,
-    KeySym symbol,
-    XKeyEvent *event);
-Private KeySym HexIMSecondComposeKey(
-    XicThaiPart *thai_part,
-    KeySym symbol
-    XKeyEvent *event);
-Private KeySym HexIMComposeSequence(KeySym ks1, KeySym ks2);
-Private void InitIscMode(Xic ic);
-Private Bool ThaiComposeConvert(
-    Display *dpy,
-    KeySym insym,
-    KeySym *outsym, KeySym *lower, KeySym *upper);
-#endif
-
-/*
- * Definitions
- */
-
-#define BellVolume 		0
-
-#define ucs2tis(wc)  \
- (unsigned char) ( \
-   (0<=(wc)&&(wc)<=0x7F) ? \
-     (wc) : \
-     ((0x0E01<=(wc)&&(wc)<=0x0E5F) ? ((wc)-0x0E00+0xA0) : 0))
-/* "c" is an unsigned char */
-#define tis2ucs(c)  \
-  ( \
-   ((c)<=0x7F) ? \
-     (wchar_t)(c) : \
-     ((0x0A1<=(c)) ? ((wchar_t)(c)-0xA0+0x0E00) : 0))
-
-/*
- * Macros to save and recall last input character in XIC
- */
-#define IC_SavePreviousChar(ic,ch) \
-                ((ic)->private.local.base.mb[(ic)->private.local.base.tree[(ic)->private.local.context].mb] = (char) (ch))
-#define IC_ClearPreviousChar(ic) \
-                ((ic)->private.local.base.mb[(ic)->private.local.base.tree[(ic)->private.local.context].mb] = 0)
-#define IC_GetPreviousChar(ic) \
-		(IC_RealGetPreviousChar(ic,1))
-#define IC_GetContextChar(ic) \
-		(IC_RealGetPreviousChar(ic,2))
-#define IC_DeletePreviousChar(ic) \
-		(IC_RealDeletePreviousChar(ic))
-
-Private unsigned char
-IC_RealGetPreviousChar(Xic ic, unsigned short pos)
-{
-    XICCallback* cb = &ic->core.string_conversion_callback;
-    DefTreeBase *b = &ic->private.local.base;
-
-    if (cb && cb->callback) {
-        XIMStringConversionCallbackStruct screc;
-        unsigned char c;
-
-        /* Use a safe value of position = 0 and stretch the range to desired
-         * place, as XIM protocol is unclear here whether it could be negative
-         */
-        screc.position = 0;
-        screc.direction = XIMBackwardChar;
-        screc.operation = XIMStringConversionRetrieval;
-        screc.factor = pos;
-        screc.text = 0;
-
-        (cb->callback)((XIC)ic, cb->client_data, (XPointer)&screc);
-        if (!screc.text)
-            return (unsigned char) b->mb[b->tree[(ic)->private.local.context].mb];
-        if ((screc.text->feedback &&
-             *screc.text->feedback == XIMStringConversionLeftEdge) ||
-            screc.text->length < 1)
-        {
-            c = 0;
-        } else {
-            Xim     im;
-            XlcConv conv;
-            int     from_left;
-            int     to_left;
-            char   *from_buf;
-            char   *to_buf;
-
-            im = (Xim) XIMOfIC((XIC)ic);
-            if (screc.text->encoding_is_wchar) {
-                conv = _XlcOpenConverter(im->core.lcd, XlcNWideChar,
-                                         im->core.lcd, XlcNCharSet);
-                from_buf = (char *) screc.text->string.wcs;
-                from_left = screc.text->length * sizeof(wchar_t);
-            } else {
-                conv = _XlcOpenConverter(im->core.lcd, XlcNMultiByte,
-                                         im->core.lcd, XlcNCharSet);
-                from_buf = screc.text->string.mbs;
-                from_left = screc.text->length;
-            }
-            to_buf = (char *)&c;
-            to_left = 1;
-
-            _XlcResetConverter(conv);
-            if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
-                            (XPointer *)&to_buf, &to_left, NULL, 0) < 0)
-            {
-                c = (unsigned char) b->mb[b->tree[(ic)->private.local.context].mb];
-            }
-            _XlcCloseConverter(conv);
-
-            XFree(screc.text->string.mbs);
-        }
-        XFree(screc.text);
-        return c;
-    } else {
-        return (unsigned char) b->mb[b->tree[(ic)->private.local.context].mb];
-    }
-}
-
-Private unsigned char
-IC_RealDeletePreviousChar(Xic ic)
-{
-    XICCallback* cb = &ic->core.string_conversion_callback;
-
-    if (cb && cb->callback) {
-        XIMStringConversionCallbackStruct screc;
-        unsigned char c;
-
-        screc.position = 0;
-        screc.direction = XIMBackwardChar;
-        screc.operation = XIMStringConversionSubstitution;
-        screc.factor = 1;
-        screc.text = 0;
-
-        (cb->callback)((XIC)ic, cb->client_data, (XPointer)&screc);
-        if (!screc.text) { return 0; }
-        if ((screc.text->feedback &&
-             *screc.text->feedback == XIMStringConversionLeftEdge) ||
-            screc.text->length < 1)
-        {
-            c = 0;
-        } else {
-            if (screc.text->encoding_is_wchar) {
-                c = ucs2tis(screc.text->string.wcs[0]);
-                XFree(screc.text->string.wcs);
-            } else {
-                c = screc.text->string.mbs[0];
-                XFree(screc.text->string.mbs);
-            }
-        }
-        XFree(screc.text);
-        return c;
-    } else {
-        return 0;
-    }
-}
-/*
- * Input sequence check mode in XIC
- */
-#define IC_IscMode(ic)		((ic)->private.local.thai.input_mode)
-
-/*
- * Max. size of string handled by the two String Lookup functions.
- */
-#define STR_LKUP_BUF_SIZE	256
-
-/*
- * Size of buffer to contain previous locale name.
- */
-#define SAV_LOCALE_NAME_SIZE	256
-
-/*
- * Size of buffer to contain the IM modifier.
- */
-#define MAXTHAIIMMODLEN 20
-
-#define AllMods (ShiftMask|LockMask|ControlMask| \
-		 Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
-
-
-#define IsISOControlKey(ks) ((ks) >= XK_2 && (ks) <= XK_8)
-
-#define IsValidControlKey(ks)   (((((ks)>=XK_A && (ks)<=XK_asciitilde) || \
-                (ks)==XK_space || (ks)==XK_Delete) && \
-                ((ks)!=0)))
-
-#define COMPOSE_LED 2
-
-#ifdef UNUSED
-typedef KeySym (*StateProc)(
-    XicThaiPart *thai_part,
-    KeySym symbol,
-    XKeyEvent *event);
-
-
-/*
- * macros to classify XKeyEvent state field
- */
-
-#define IsShift(state) (((state) & ShiftMask) != 0)
-#define IsLock(state) (((state) & LockMask) != 0)
-#define IsControl(state) (((state) & ControlMask) != 0)
-#define IsMod1(state) (((state) & Mod1Mask) != 0)
-#define IsMod2(state) (((state) & Mod2Mask) != 0)
-#define IsMod3(state) (((state) & Mod3Mask) != 0)
-#define IsMod4(state) (((state) & Mod4Mask) != 0)
-#define IsMod5(state) (((state) & Mod5Mask) != 0)
-
-/*
- * key starts Thai compose sequence (Hex input method) if :
- */
-
-#define IsComposeKey(ks, event)  \
-	(( ks==XK_Alt_L && 	\
-	   IsControl((event)->state) &&	\
-	   !IsShift((event)->state))	\
-	 ? True : False)
-
-
-/*
- *  State handler to implement the Thai hex input method.
- */
-
-Private int const nstate_handlers = 3;
-Private StateProc state_handler[] = {
-	HexIMNormalKey,
-	HexIMFirstComposeKey,
-	HexIMSecondComposeKey
-};
-
-
-/*
- *  Table for 'Thai Compose' character input.
- *  The current implementation uses latin-1 keysyms.
- */
-struct _XMapThaiKey {
-	KeySym from;
-	KeySym to;
-};
-
-Private struct _XMapThaiKey const ThaiComposeTable[] = {
-	{ /* 0xa4 */ XK_currency,	/* 0xa5 */ XK_yen },
-	{ /* 0xa2 */ XK_cent,		/* 0xa3 */ XK_sterling },
-	{ /* 0xe6 */ XK_ae,		/* 0xef */ XK_idiaeresis },
-	{ /* 0xd3 */ XK_Oacute,		/* 0xee */ XK_icircumflex },
-	{ /* 0xb9 */ XK_onesuperior,	/* 0xfa */ XK_uacute },
-	{ /* 0xd2 */ XK_Ograve,		/* 0xe5 */ XK_aring },
-	{ /* 0xbc */ XK_onequarter,	/* 0xfb */ XK_ucircumflex },
-	{	     XK_VoidSymbol,		   XK_VoidSymbol }
-};
-
-struct _XKeytrans {
-	struct _XKeytrans *next;/* next on list */
-	char *string;		/* string to return when the time comes */
-	int len;		/* length of string (since NULL is legit)*/
-	KeySym key;		/* keysym rebound */
-	unsigned int state;	/* modifier state */
-	KeySym *modifiers;	/* modifier keysyms you want */
-	int mlen;		/* length of modifier list */
-};
-
-
-/* Convert keysym to 'Thai Compose' keysym */
-/* The current implementation use latin-1 keysyms */
-Private Bool
-ThaiComposeConvert(
-    Display *dpy,
-    KeySym insym,
-    KeySym *outsym, KeySym *lower, KeySym *upper)
-{
-    struct _XMapThaiKey const *table_entry = ThaiComposeTable;
-
-    while (table_entry->from != XK_VoidSymbol) {
-	if (table_entry->from == insym) {
-	    *outsym = table_entry->to;
-	    *lower = *outsym;
-	    *upper = *outsym;
-	    return True;
-	}
-	table_entry++;
-    }
-    return False;
-}
-
-Private int
-XThaiTranslateKey(
-    register Display *dpy,
-    KeyCode keycode,
-    register unsigned int modifiers,
-    unsigned int *modifiers_return,
-    KeySym *keysym_return,
-    KeySym *lsym_return,
-    KeySym *usym_return)
-{
-    int per;
-    register KeySym *syms;
-    KeySym sym = 0, lsym = 0, usym = 0;
-
-    if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
-	return 0;
-    *modifiers_return = (ShiftMask|LockMask) | dpy->mode_switch;
-    if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
-    {
-	*keysym_return = NoSymbol;
-	return 1;
-    }
-    per = dpy->keysyms_per_keycode;
-    syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
-    while ((per > 2) && (syms[per - 1] == NoSymbol))
-	per--;
-    if ((per > 2) && (modifiers & dpy->mode_switch)) {
-	syms += 2;
-	per -= 2;
-    }
-    if (!(modifiers & ShiftMask) &&
-	(!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
-	if ((per == 1) || (syms[1] == NoSymbol))
-	    XConvertCase(syms[0], keysym_return, &usym);
-	else {
-	    XConvertCase(syms[0], &lsym, &usym);
-	    *keysym_return = syms[0];
-	}
-    } else if (!(modifiers & LockMask) ||
-	       (dpy->lock_meaning != XK_Caps_Lock)) {
-	if ((per == 1) || ((usym = syms[1]) == NoSymbol))
-	    XConvertCase(syms[0], &lsym, &usym);
-	*keysym_return = usym;
-    } else {
-	if ((per == 1) || ((sym = syms[1]) == NoSymbol))
-	    sym = syms[0];
-	XConvertCase(sym, &lsym, &usym);
-	if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
-	    ((sym != usym) || (lsym == usym)))
-	    XConvertCase(syms[0], &lsym, &usym);
-	*keysym_return = usym;
-    }
-    /*
-     * ThaiCat keyboard support :
-     * When the Shift and Thai keys are hold for some keys a 'Thai Compose'
-     * character code is generated which is different from column 3 and
-     * 4 of the keymap.
-     * Since we don't know whether ThaiCat keyboard or WTT keyboard is
-     * in use, the same mapping is done for all Thai input.
-     * We just arbitary choose to use column 3 keysyms as the indices of
-     * this mapping.
-     * When the control key is also hold, this mapping has no effect.
-     */
-    if ((modifiers & Mod1Mask) &&
-	(modifiers & ShiftMask) &&
-	!(modifiers & ControlMask)) {
-	if (ThaiComposeConvert(dpy, syms[0], &sym, &lsym, &usym))
-	    *keysym_return = sym;
-    }
-
-    if (*keysym_return == XK_VoidSymbol)
-	*keysym_return = NoSymbol;
-    *lsym_return = lsym;
-    *usym_return = usym;
-    return 1;
-}
-
-/*
- * XThaiTranslateKeySym
- *
- * Translate KeySym to TACTIS code output.
- * The current implementation uses ISO latin-1 keysym.
- * Should be changed to TACTIS keysyms when they are defined by the
- * standard.
- */
-Private int
-XThaiTranslateKeySym(
-    Display *dpy,
-    register KeySym symbol,
-    register KeySym lsym,
-    register KeySym usym,
-    unsigned int modifiers,
-    unsigned char *buffer,
-    int nbytes)
-{
-    KeySym ckey = 0;
-    register struct _XKeytrans *p;
-    int length;
-    unsigned long hiBytes;
-    register unsigned char c;
-
-    /*
-     * initialize length = 1 ;
-     */
-    length = 1;
-
-    if (!symbol)
-	return 0;
-    /* see if symbol rebound, if so, return that string. */
-    for (p = dpy->key_bindings; p; p = p->next) {
-	if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
-	    length = p->len;
-	    if (length > nbytes) length = nbytes;
-	    memcpy (buffer, p->string, length);
-	    return length;
-	}
-    }
-    /* try to convert to TACTIS, handling control */
-    hiBytes = symbol >> 8;
-    if (!(nbytes &&
-	  ((hiBytes == 0) ||
-	   ((hiBytes == 0xFF) &&
-	    (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
-	     (symbol == XK_Return) ||
-	     (symbol == XK_Escape) ||
-	     (symbol == XK_KP_Space) ||
-	     (symbol == XK_KP_Tab) ||
-	     (symbol == XK_KP_Enter) ||
-	     ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
-	     (symbol == XK_KP_Equal) ||
-             (symbol == XK_Scroll_Lock) ||
-#ifdef DXK_PRIVATE /* DEC private keysyms */
-             (symbol == DXK_Remove) ||
-#endif
-             (symbol == NoSymbol) ||
-	     (symbol == XK_Delete))))))
-	return 0;
-
-    /* if X keysym, convert to ascii by grabbing low 7 bits */
-    if (symbol == XK_KP_Space)
-	c = XK_space & 0x7F; /* patch encoding botch */
-/* not for Thai
-    else if (symbol == XK_hyphen)
-	c = XK_minus & 0xFF; */ /* map to equiv character */
-    else if (hiBytes == 0xFF)
-	c = symbol & 0x7F;
-    else
-	c = symbol & 0xFF;
-    /* only apply Control key if it makes sense, else ignore it */
-    if (modifiers & ControlMask) {
-    if (!(IsKeypadKey(lsym) || lsym==XK_Return || lsym==XK_Tab)) {
-        if (IsISOControlKey(lsym)) ckey = lsym;
-        else if (IsISOControlKey(usym)) ckey = usym;
-        else if (lsym == XK_question) ckey = lsym;
-        else if (usym == XK_question) ckey = usym;
-        else if (IsValidControlKey(lsym)) ckey = lsym;
-        else if (IsValidControlKey(usym)) ckey = usym;
-        else length = 0;
-
-        if (length != 0) {
-        if (ckey == XK_2) c = '\000';
-        else if (ckey >= XK_3 && ckey <= XK_7)
-            c = (char)(ckey-('3'-'\033'));
-        else if (ckey == XK_8) c = '\177';
-        else if (ckey == XK_Delete) c = '\030';
-        else if (ckey == XK_question) c = '\037';
-        else if (ckey == XK_quoteleft) c = '\036';  /* KLee 1/24/91 */
-        else c = (char)(ckey & 0x1f);
-        }
-    }
-    }
-    /*
-     *  ThaiCat has a key that generates two TACTIS codes D1 & E9.
-     *  It is represented by the latin-1 keysym XK_thorn (0xfe).
-     *  If c is XK_thorn, this key is pressed and it is converted to
-     *  0xd1 0xe9.
-     */
-    if (c == XK_thorn) {
-	buffer[0] = 0xd1;
-	buffer[1] = 0xe9;
-	buffer[2] = '\0';
-	return 2;
-    }
-    else {
-	/* Normal case */
-        buffer[0] = c;
-	buffer[1] = '\0';
-        return 1;
-    }
-}
-
-/*
- * given a KeySym, returns the first keycode containing it, if any.
- */
-Private CARD8
-FindKeyCode(
-    register Display *dpy,
-    register KeySym code)
-{
-
-    register KeySym *kmax = dpy->keysyms +
-	(dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
-    register KeySym *k = dpy->keysyms;
-    while (k < kmax) {
-	if (*k == code)
-	    return (((k - dpy->keysyms) / dpy->keysyms_per_keycode) +
-		    dpy->min_keycode);
-	k += 1;
-	}
-    return 0;
-}
-
-/*
- * given a list of modifiers, computes the mask necessary for later matching.
- * This routine must lookup the key in the Keymap and then search to see
- * what modifier it is bound to, if any.  Sets the AnyModifier bit if it
- * can't map some keysym to a modifier.
- */
-Private void
-ComputeMaskFromKeytrans(
-    Display *dpy,
-    register struct _XKeytrans *p)
-{
-    register int i;
-    register CARD8 code;
-    register XModifierKeymap *m = dpy->modifiermap;
-
-    p->state = AnyModifier;
-    for (i = 0; i < p->mlen; i++) {
-	/* if not found, then not on current keyboard */
-	if ((code = FindKeyCode(dpy, p->modifiers[i])) == 0)
-		return;
-	/* code is now the keycode for the modifier you want */
-	{
-	    register int j = m->max_keypermod<<3;
-
-	    while ((--j >= 0) && (code != m->modifiermap[j]))
-		;
-	    if (j < 0)
-		return;
-	    p->state |= (1<<(j/m->max_keypermod));
-	}
-    }
-    p->state &= AllMods;
-}
-
-/************************************************************************
- *
- *
- * Compose handling routines - compose handlers 0,1,2
- *
- *
- ************************************************************************/
-
-#define NORMAL_KEY_STATE 0
-#define FIRST_COMPOSE_KEY_STATE 1
-#define SECOND_COMPOSE_KEY_STATE 2
-
-Private
-KeySym HexIMNormalKey(
-    XicThaiPart *thai_part,
-    KeySym symbol,
-    XKeyEvent *event)
-{
-    if (IsComposeKey (symbol, event))	/* start compose sequence	*/
-	{
-	SetLed (event->display,COMPOSE_LED, LedModeOn);
-	thai_part->comp_state = FIRST_COMPOSE_KEY_STATE;
-	return NoSymbol;
-	}
-    return symbol;
-}
-
-
-Private
-KeySym HexIMFirstComposeKey(
-    XicThaiPart *thai_part,
-    KeySym symbol,
-    XKeyEvent *event)
-{
-    if (IsModifierKey (symbol)) return symbol; /* ignore shift etc. */
-    if (IsCancelComposeKey (&symbol, event))	/* cancel sequence */
-	{
-	SetLed (event->display,COMPOSE_LED, LedModeOff);
-	thai_part->comp_state = NORMAL_KEY_STATE;
-	return symbol;
-	}
-    if (IsComposeKey (symbol, event))		/* restart sequence ?? */
-	{
-	return NoSymbol;			/* no state change necessary */
-	}
-
-    thai_part->keysym = symbol;		/* save key pressed */
-    thai_part->comp_state = SECOND_COMPOSE_KEY_STATE;
-    return NoSymbol;
-}
-
-Private
-KeySym HexIMSecondComposeKey(
-    XicThaiPart *thai_part,
-    KeySym symbol,
-    XKeyEvent *event)
-{
-    if (IsModifierKey (symbol)) return symbol;	/* ignore shift etc. */
-    if (IsComposeKey (symbol, event))		/* restart sequence ? */
-	{
-	thai_part->comp_state =FIRST_COMPOSE_KEY_STATE;
-	return NoSymbol;
-	}
-    SetLed (event->display,COMPOSE_LED, LedModeOff);
-    if (IsCancelComposeKey (&symbol, event))	/* cancel sequence ? */
-	{
-	thai_part->comp_state = NORMAL_KEY_STATE;
-	return symbol;
-	}
-
-    if ((symbol = HexIMComposeSequence (thai_part->keysym, symbol))
-								==NoSymbol)
-	{ /* invalid compose sequence */
-	XBell(event->display, BellVolume);
-	}
-    thai_part->comp_state = NORMAL_KEY_STATE; /* reset to normal state */
-    return symbol;
-}
-
-
-/*
- * Interprets two keysyms entered as hex digits and return the Thai keysym
- * correspond to the TACTIS code formed.
- * The current implementation of this routine returns ISO Latin Keysyms.
- */
-
-Private
-KeySym HexIMComposeSequence(KeySym ks1, KeySym ks2)
-{
-int	hi_digit;
-int	lo_digit;
-int	tactis_code;
-
-    if ((ks1 >= XK_0) && (ks1 <= XK_9))
-	hi_digit = ks1 - XK_0;
-    else if ((ks1 >= XK_A) && (ks1 <= XK_F))
-	hi_digit = ks1 - XK_A + 10;
-    else if ((ks1 >= XK_a) && (ks1 <= XK_f))
-	hi_digit = ks1 - XK_a + 10;
-    else	/* out of range */
-	return NoSymbol;
-
-    if ((ks2 >= XK_0) && (ks2 <= XK_9))
-	lo_digit = ks2 - XK_0;
-    else if ((ks2 >= XK_A) && (ks2 <= XK_F))
-	lo_digit = ks2 - XK_A + 10;
-    else if ((ks2 >= XK_a) && (ks2 <= XK_f))
-	lo_digit = ks2 - XK_a + 10;
-    else	/* out of range */
-	return NoSymbol;
-
-    tactis_code = hi_digit * 0x10 + lo_digit ;
-
-    return (KeySym)tactis_code;
-
-}
-
-/*
- * routine determines
- *	1) whether key event should cancel a compose sequence
- *	2) whether cancelling key event should be processed or ignored
- */
-
-Private
-int IsCancelComposeKey(
-    KeySym *symbol,
-    XKeyEvent *event)
-{
-    if (*symbol==XK_Delete && !IsControl(event->state) &&
-						!IsMod1(event->state)) {
-	*symbol=NoSymbol;  /* cancel compose sequence, and ignore key */
-	return True;
-    }
-    if (IsComposeKey(*symbol, event)) return False;
-    return (
-	IsControl (event->state) ||
-	IsMod1(event->state) ||
-	IsKeypadKey (*symbol) ||
-	IsFunctionKey (*symbol) ||
-	IsMiscFunctionKey (*symbol) ||
-#ifdef DXK_PRIVATE /* DEC private keysyms */
-	*symbol == DXK_Remove ||
-#endif
-	IsPFKey (*symbol) ||
-	IsCursorKey (*symbol) ||
-	(*symbol >= XK_Tab && *symbol < XK_Multi_key)
-		? True : False);	/* cancel compose sequence and pass */
-					/* cancelling key through	    */
-}
-
-
-/*
- *	set specified keyboard LED on or off
- */
-
-Private
-void SetLed(
-    Display *dpy,
-    int num,
-    int state)
-{
-    XKeyboardControl led_control;
-
-    led_control.led_mode = state;
-    led_control.led = num;
-    XChangeKeyboardControl (dpy, KBLed | KBLedMode,	&led_control);
-}
-#endif
-
-/*
- * Initialize ISC mode from im modifier
- */
-Private void InitIscMode(Xic ic)
-{
-    Xim im;
-    char *im_modifier_name;
-
-    /* If already defined, just return */
-
-    if (IC_IscMode(ic)) return;
-
-    /* Get IM modifier */
-
-    im = (Xim) XIMOfIC((XIC)ic);
-    im_modifier_name = im->core.im_name;
-
-    /* Match with predefined value, default is Basic Check */
-
-    if (!strncmp(im_modifier_name,"BasicCheck",MAXTHAIIMMODLEN+1))
-	IC_IscMode(ic) = WTT_ISC1;
-    else if (!strncmp(im_modifier_name,"Strict",MAXTHAIIMMODLEN+1))
-	IC_IscMode(ic) = WTT_ISC2;
-    else if (!strncmp(im_modifier_name,"Thaicat",MAXTHAIIMMODLEN+1))
-	IC_IscMode(ic) = THAICAT_ISC;
-    else if (!strncmp(im_modifier_name,"Passthrough",MAXTHAIIMMODLEN+1))
-	IC_IscMode(ic) = NOISC;
-    else
-	IC_IscMode(ic) = WTT_ISC1;
-
-    return;
-}
-
-/*
- * Helper functions for _XimThaiFilter()
- */
-Private Bool
-ThaiFltAcceptInput(Xic ic, unsigned char new_char, KeySym symbol)
-{
-    DefTreeBase *b = &ic->private.local.base;
-    b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char);
-    b->wc[b->tree[ic->private.local.composed].wc+1] = '\0';
-
-    if ((new_char <= 0x1f) || (new_char == 0x7f))
-        b->tree[ic->private.local.composed].keysym = symbol;
-    else
-        b->tree[ic->private.local.composed].keysym = NoSymbol;
-
-    return True;
-}
-
-Private Bool
-ThaiFltReorderInput(Xic ic, unsigned char previous_char, unsigned char new_char)
-{
-    DefTreeBase *b = &ic->private.local.base;
-    if (!IC_DeletePreviousChar(ic)) return False;
-    b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char);
-    b->wc[b->tree[ic->private.local.composed].wc+1] = tis2ucs(previous_char);
-    b->wc[b->tree[ic->private.local.composed].wc+2] = '\0';
-
-    b->tree[ic->private.local.composed].keysym = NoSymbol;
-
-    return True;
-}
-
-Private Bool
-ThaiFltReplaceInput(Xic ic, unsigned char new_char, KeySym symbol)
-{
-    DefTreeBase *b = &ic->private.local.base;
-    if (!IC_DeletePreviousChar(ic)) return False;
-    b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char);
-    b->wc[b->tree[ic->private.local.composed].wc+1] = '\0';
-
-    if ((new_char <= 0x1f) || (new_char == 0x7f))
-        b->tree[ic->private.local.composed].keysym = symbol;
-    else
-        b->tree[ic->private.local.composed].keysym = NoSymbol;
-
-    return True;
-}
-
-Private unsigned
-NumLockMask(Display *d)
-{
-    int i;
-    XModifierKeymap *map = XGetModifierMapping (d);
-    KeyCode numlock_keycode = XKeysymToKeycode (d, XK_Num_Lock);
-    if (numlock_keycode == NoSymbol)
-        return 0;
-
-    for (i = 0; i < 8; i++) {
-        if (map->modifiermap[map->max_keypermod * i] == numlock_keycode)
-            return 1 << i;
-    }
-    return 0;
-}
-
-/*
- * Filter function for TACTIS
- */
-Bool
-_XimThaiFilter(Display *d, Window w, XEvent *ev, XPointer client_data)
-{
-    Xic		    ic = (Xic)client_data;
-    KeySym 	    symbol;
-    int 	    isc_mode; /* Thai Input Sequence Check mode */
-    unsigned char   previous_char; /* Last inputted Thai char */
-    unsigned char   new_char;
-#ifdef UNUSED
-    unsigned int    modifiers;
-    KeySym	    lsym,usym;
-    int		    state;
-    XicThaiPart     *thai_part;
-    char	    buf[10];
-#endif
-    wchar_t	    wbuf[10];
-    Bool            isReject;
-    DefTreeBase    *b = &ic->private.local.base;
-
-    if ((ev->type != KeyPress)
-        || (ev->xkey.keycode == 0))
-        return False;
-
-    if (!IC_IscMode(ic)) InitIscMode(ic);
-
-    XwcLookupString((XIC)ic, &ev->xkey, wbuf, sizeof(wbuf) / sizeof(wbuf[0]),
-		    &symbol, NULL);
-
-    if ((ev->xkey.state & (AllMods & ~(ShiftMask|LockMask|NumLockMask(d)))) ||
-         ((symbol >> 8 == 0xFF) &&
-         ((XK_BackSpace <= symbol && symbol <= XK_Clear) ||
-           (symbol == XK_Return) ||
-           (symbol == XK_Pause) ||
-           (symbol == XK_Scroll_Lock) ||
-           (symbol == XK_Sys_Req) ||
-           (symbol == XK_Escape) ||
-           (symbol == XK_Delete) ||
-           IsCursorKey(symbol) ||
-           IsKeypadKey(symbol) ||
-           IsMiscFunctionKey(symbol) ||
-           IsFunctionKey(symbol))))
-        {
-            IC_ClearPreviousChar(ic);
-            return False;
-        }
-    if (((symbol >> 8 == 0xFF) &&
-         IsModifierKey(symbol)) ||
-#ifdef XK_XKB_KEYS
-        ((symbol >> 8 == 0xFE) &&
-         (XK_ISO_Lock <= symbol && symbol <= XK_ISO_Last_Group_Lock)) ||
-#endif
-        (symbol == NoSymbol))
-    {
-        return False;
-    }
-#ifdef UNUSED
-    if (! XThaiTranslateKey(ev->xkey.display, ev->xkey.keycode, ev->xkey.state,
-	 		&modifiers, &symbol, &lsym, &usym))
-	return False;
-
-    /*
-     *  Hex input method processing
-     */
-
-    thai_part = &ic->private.local.thai;
-    state = thai_part->comp_state;
-    if (state >= 0 && state < nstate_handlers) /* call handler for state */
-    {
-        symbol = (* state_handler[state])(thai_part, symbol, (XKeyEvent *)ev);
-    }
-
-    /*
-     *  Translate KeySym into mb.
-     */
-    count = XThaiTranslateKeySym(ev->xkey.display, symbol, lsym,
-				usym, ev->xkey.state, buf, 10);
-
-    if (!symbol && !count)
-	return True;
-
-    /* Return symbol if cannot convert to character */
-    if (!count)
-	return False;
-#endif
-
-    /*
-     *  Thai Input sequence check
-     */
-    isc_mode = IC_IscMode(ic);
-    if (!(previous_char = IC_GetPreviousChar(ic))) previous_char = ' ';
-    new_char = ucs2tis(wbuf[0]);
-    isReject = True;
-    if (THAI_isaccepted(new_char, previous_char, isc_mode)) {
-        ThaiFltAcceptInput(ic, new_char, symbol);
-        isReject = False;
-    } else {
-        unsigned char context_char;
-
-        context_char = IC_GetContextChar(ic);
-        if (context_char) {
-            if (THAI_iscomposible(new_char, context_char)) {
-                if (THAI_iscomposible(previous_char, new_char)) {
-                    isReject = !ThaiFltReorderInput(ic, previous_char, new_char);
-                } else if (THAI_iscomposible(previous_char, context_char)) {
-                    isReject = !ThaiFltReplaceInput(ic, new_char, symbol);
-                } else if (THAI_chtype(previous_char) == FV1
-                           && THAI_chtype(new_char) == TONE) {
-                    isReject = !ThaiFltReorderInput(ic, previous_char, new_char);
-                }
-            } else if (THAI_isaccepted(new_char, context_char, isc_mode)) {
-                isReject = !ThaiFltReplaceInput(ic, new_char, symbol);
-            }
-        }
-    }
-    if (isReject) {
-        /* reject character */
-        XBell(ev->xkey.display, BellVolume);
-        return True;
-    }
-
-    _Xlcwcstombs(ic->core.im->core.lcd, &b->mb[b->tree[ic->private.local.composed].mb],
-		 &b->wc[b->tree[ic->private.local.composed].wc], 10);
-
-    _Xlcmbstoutf8(ic->core.im->core.lcd, &b->utf8[b->tree[ic->private.local.composed].utf8],
-		  &b->mb[b->tree[ic->private.local.composed].mb], 10);
-
-    /* Remember the last character inputted
-     * (as fallback in case StringConversionCallback is not provided)
-     */
-    IC_SavePreviousChar(ic, new_char);
-
-    ev->xkey.keycode = 0;
-    XPutBackEvent(d, ev);
-    return True;
-}
+/***********************************************************
+
+Copyright 1993, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+
+Copyright 1993 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+**++
+**  FACILITY:
+**
+**      Xlib
+**
+**  ABSTRACT:
+**
+**	Thai specific functions.
+**	Handles character classifications, composibility checking,
+**	Input sequence check and other Thai specific requirements
+**	according to WTT specification and DEC extensions.
+**
+**  MODIFICATION HISTORY:
+**
+**/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+#include <X11/keysym.h>
+#include <X11/Xutil.h>
+#include "Xlibint.h"
+#include "Xlcint.h"
+#include "Ximint.h"
+#include "XimThai.h"
+#include "XlcPubI.h"
+
+
+#define SPACE   32
+
+/* character classification table */
+#define TACTIS_CHARS 256
+Private
+char const tactis_chtype[TACTIS_CHARS] = {
+    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /*  0 -  7 */
+    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /*  8 - 15 */
+    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 16 - 23 */
+    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 24 - 31 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 32 - 39 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 40 - 47 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 48 - 55 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 56 - 63 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 64 - 71 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 72 - 79 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 80 - 87 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 88 - 95 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 96 - 103 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 104 - 111 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 112 - 119 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  CTRL,  /* 120 - 127 */
+    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 128 - 135 */
+    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 136 - 143 */
+    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 144 - 151 */
+    CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL,  /* 152 - 159 */
+    NON,  CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 160 - 167 */
+    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 168 - 175 */
+    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 176 - 183 */
+    CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS,  /* 184 - 191 */
+    CONS, CONS, CONS, CONS,  FV3, CONS,  FV3, CONS,  /* 192 - 199 */
+    CONS, CONS, CONS, CONS, CONS, CONS, CONS, NON,   /* 200 - 207 */
+    FV1,  AV2,  FV1,  FV1,  AV1,  AV3,  AV2,  AV3,   /* 208 - 215 */
+    BV1,  BV2,  BD,   NON,  NON,  NON,  NON,  NON,   /* 216 - 223 */
+    LV,   LV,   LV,   LV,   LV,   FV2,  NON,  AD2,   /* 224 - 231 */
+    TONE, TONE, TONE, TONE, AD1,  AD1,  AD3,  NON,   /* 232 - 239 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  NON,   /* 240 - 247 */
+    NON,  NON,  NON,  NON,  NON,  NON,  NON,  CTRL   /* 248 - 255 */
+};
+
+/* Composibility checking tables */
+#define NC  0   /* NOT COMPOSIBLE - following char displays in next cell */
+#define CP  1   /* COMPOSIBLE - following char is displayed in the same cell
+                                as leading char, also implies ACCEPT */
+#define XC  3   /* Non-display */
+#define AC  4   /* ACCEPT - display the following char in the next cell */
+#define RJ  5   /* REJECT - discard that following char, ignore it */
+
+#define CH_CLASSES      17  /* 17 classes of chars */
+
+Private
+char const write_rules_lookup[CH_CLASSES][CH_CLASSES] = {
+        /* Table 0: writing/outputing rules */
+        /* row: leading char,  column: following char */
+/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
+   {XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*CTRL*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*NON*/
+  ,{XC, NC, NC, NC, NC, NC, NC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*LV*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV1*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV2*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV3*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, CP, NC, NC, NC, NC, NC}/*BV1*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, NC, NC, NC, NC, NC}/*BV2*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*BD*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*TONE*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD1*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD2*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD3*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, CP, NC, NC, NC, NC, NC}/*AV1*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, NC, NC, NC, NC, NC}/*AV2*/
+  ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, CP, NC, NC, NC, NC}/*AV3*/
+};
+
+Private
+char const wtt_isc1_lookup[CH_CLASSES][CH_CLASSES] = {
+      /* Table 1: WTT default input sequence check rules */
+      /* row: leading char,  column: following char */
+/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
+   {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/
+  ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV3*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*TONE*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD1*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD2*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/
+};
+
+Private
+char const wtt_isc2_lookup[CH_CLASSES][CH_CLASSES] = {
+      /* Table 2: WTT strict input sequence check rules */
+      /* row: leading char,  column: following char */
+/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
+   {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/
+  ,{XC, AC, AC, AC, AC, RJ, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
+  ,{XC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/
+  ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/
+  ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/
+  ,{XC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV3*/
+  ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*TONE*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD1*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD2*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/
+  ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/
+};
+
+Private
+char const thaicat_isc_lookup[CH_CLASSES][CH_CLASSES] = {
+      /* Table 3: Thaicat input sequence check rules */
+      /* row: leading char,  column: following char */
+/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */
+   {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/
+  ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ} /*FV3*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/
+  ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, RJ, RJ, RJ, RJ, RJ, CP, CP, CP}/*TONE*/
+  ,{XC, AC, AC, AC, AC, AC, AC, CP, RJ, RJ, RJ, RJ, RJ, RJ, CP, RJ, RJ}/*AD1*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, CP}/*AD2*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/
+  ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/
+};
+
+
+/* returns classification of a char */
+Private int
+THAI_chtype (unsigned char	ch)
+{
+    return tactis_chtype[ch];
+}
+
+#ifdef UNUSED
+/* returns the display level */
+Private int
+THAI_chlevel (unsigned char	ch)
+{
+    int     chlevel;
+
+    switch (tactis_chtype[ch])
+    {
+        case CTRL:
+            chlevel = NON;
+            break;
+        case BV1:
+        case BV2:
+        case BD:
+            chlevel = BELOW;
+            break;
+        case TONE:
+        case AD1:
+        case AD2:
+            chlevel = TOP;
+            break;
+        case AV1:
+        case AV2:
+        case AV3:
+        case AD3:
+            chlevel = ABOVE;
+            break;
+        case NON:
+        case CONS:
+        case LV:
+        case FV1:
+        case FV2:
+        case FV3:
+        default: /* if tactis_chtype is invalid */
+            chlevel = BASE;
+            break;
+    }
+    return chlevel;
+}
+
+
+/* return True if char is non-spacing */
+Private Bool
+THAI_isdead (unsigned char	ch)
+{
+    return ((tactis_chtype[ch] == CTRL) || (tactis_chtype[ch] == BV1) ||
+            (tactis_chtype[ch] == BV2)  || (tactis_chtype[ch] == BD)  ||
+            (tactis_chtype[ch] == TONE) || (tactis_chtype[ch] == AD1) ||
+            (tactis_chtype[ch] == AD2)  || (tactis_chtype[ch] == AD3) ||
+            (tactis_chtype[ch] == AV1)  || (tactis_chtype[ch] == AV2) ||
+            (tactis_chtype[ch] == AV3));
+}
+
+
+/* return True if char is consonant */
+Private Bool
+THAI_iscons (unsigned char	ch)
+{
+    return (tactis_chtype[ch] == CONS);
+}
+
+
+/* return True if char is vowel */
+Private Bool
+THAI_isvowel (unsigned char	ch)
+{
+    return ((tactis_chtype[ch] == LV)  || (tactis_chtype[ch] == FV1) ||
+            (tactis_chtype[ch] == FV2) || (tactis_chtype[ch] == FV3) ||
+            (tactis_chtype[ch] == BV1) || (tactis_chtype[ch] == BV2) ||
+            (tactis_chtype[ch] == AV1) || (tactis_chtype[ch] == AV2) ||
+            (tactis_chtype[ch] == AV3));
+}
+
+
+/* return True if char is tonemark */
+Private Bool
+THAI_istone (unsigned char	ch)
+{
+    return (tactis_chtype[ch] == TONE);
+}
+#endif
+
+Private Bool
+THAI_iscomposible (
+    unsigned char	follow_ch,
+    unsigned char	lead_ch)
+{/* "Can follow_ch be put in the same display cell as lead_ch?" */
+
+    return (write_rules_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)]
+            == CP);
+}
+
+Private Bool
+THAI_isaccepted (
+    unsigned char	follow_ch,
+    unsigned char	lead_ch,
+    unsigned char	mode)
+{
+    Bool iskeyvalid; /*  means "Can follow_ch be keyed in after lead_ch?" */
+
+    switch (mode)
+    {
+        case WTT_ISC1:
+            iskeyvalid =
+          (wtt_isc1_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ);
+            break;
+        case WTT_ISC2:
+            iskeyvalid =
+          (wtt_isc2_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ);
+            break;
+        case THAICAT_ISC:
+            iskeyvalid =
+       (thaicat_isc_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ);
+            break;
+        default:
+            iskeyvalid = True;
+            break;
+    }
+
+    return iskeyvalid;
+}
+
+#ifdef UNUSED
+Private void
+THAI_apply_write_rules(
+    unsigned char	*instr,
+    unsigned char	*outstr,
+    unsigned char	insert_ch,
+    int 		*num_insert_ch)
+{
+/*
+Input parameters:
+    instr - input string
+    insert_ch specify what char to be added when invalid composition is found
+Output parameters:
+    outstr - output string after input string has been applied the rules
+    num_insert_ch - number of insert_ch added to outstr.
+*/
+    unsigned char   *lead_ch = NULL, *follow_ch = NULL, *out_ch = NULL;
+
+    *num_insert_ch = 0;
+    lead_ch = follow_ch = instr;
+    out_ch = outstr;
+    if ((*lead_ch == '\0') || !(THAI_find_chtype(instr,DEAD)))
+    {   /* Empty string or can't find any non-spacing char*/
+        strcpy((char *)outstr, (char *)instr);
+    } else { /* String of length >= 1, keep looking */
+        follow_ch++;
+        if (THAI_isdead(*lead_ch)) { /* is first char non-spacing? */
+            *out_ch++ = SPACE;
+            (*num_insert_ch)++;
+        }
+        *out_ch++ = *lead_ch;
+        while (*follow_ch != '\0')  /* more char in string to check */
+        {
+            if (THAI_isdead(*follow_ch) &&
+                 !THAI_iscomposible(*follow_ch,*lead_ch))
+            {
+                *out_ch++ = SPACE;
+                (*num_insert_ch)++;
+            }
+            *out_ch++ = *follow_ch;
+            lead_ch = follow_ch;
+            follow_ch++;
+        }
+        *out_ch = '\0';
+    }
+}
+
+Private int
+THAI_find_chtype (
+    unsigned char	*instr,
+    int		chtype)
+{
+/*
+Input parameters:
+    instr - input string
+    chtype - type of character to look for
+Output parameters:
+    function returns first position of character with matched chtype
+    function returns -1 if it does not find.
+*/
+    int i = 0, position = -1;
+
+    switch (chtype)
+    {
+        case DEAD:
+            for (i = 0; *instr != '\0' && THAI_isdead(*instr); i++, instr++)
+		;
+            if (*instr != '\0') position = i;
+            break;
+        default:
+            break;
+    }
+    return position;
+}
+
+
+Private int
+THAI_apply_scm(
+    unsigned char	*instr,
+    unsigned char	*outstr,
+    unsigned char	spec_ch,
+    int		num_sp,
+    unsigned char	insert_ch)
+{
+    unsigned char   *scan, *outch;
+    int             i, dead_count, found_count;
+    Bool            isconsecutive;
+
+    scan = instr;
+    outch = outstr;
+    dead_count = found_count = 0;
+    isconsecutive = False;
+    while (*scan != '\0') {
+        if (THAI_isdead(*scan))
+            dead_count++;       /* count number of non-spacing char */
+        if (*scan == spec_ch)
+            if (!isconsecutive)
+                found_count++;      /* count number consecutive spec char found */
+        *outch++ = *scan++;
+        if (found_count == num_sp) {
+            for (i = 0; i < dead_count; i++)
+                *outch++ = insert_ch;
+            dead_count = found_count = 0;
+        }
+    }
+    /* what to return? */
+    return 0; /* probably not right but better than returning garbage */
+}
+
+
+/* The following functions are copied from XKeyBind.c */
+
+Private void ComputeMaskFromKeytrans();
+Private int IsCancelComposeKey(KeySym *symbol, XKeyEvent *event);
+Private void SetLed(Display *dpy, int num, int state);
+Private CARD8 FindKeyCode();
+
+
+/* The following functions are specific to this module */
+
+Private int XThaiTranslateKey();
+Private int XThaiTranslateKeySym();
+
+
+Private KeySym HexIMNormalKey(
+    XicThaiPart *thai_part,
+    KeySym symbol,
+    XKeyEvent *event);
+Private KeySym HexIMFirstComposeKey(
+    XicThaiPart *thai_part,
+    KeySym symbol,
+    XKeyEvent *event);
+Private KeySym HexIMSecondComposeKey(
+    XicThaiPart *thai_part,
+    KeySym symbol
+    XKeyEvent *event);
+Private KeySym HexIMComposeSequence(KeySym ks1, KeySym ks2);
+Private void InitIscMode(Xic ic);
+Private Bool ThaiComposeConvert(
+    Display *dpy,
+    KeySym insym,
+    KeySym *outsym, KeySym *lower, KeySym *upper);
+#endif
+
+/*
+ * Definitions
+ */
+
+#define BellVolume 		0
+
+#define ucs2tis(wc)  \
+ (unsigned char) ( \
+   (0<=(wc)&&(wc)<=0x7F) ? \
+     (wc) : \
+     ((0x0E01<=(wc)&&(wc)<=0x0E5F) ? ((wc)-0x0E00+0xA0) : 0))
+/* "c" is an unsigned char */
+#define tis2ucs(c)  \
+  ( \
+   ((c)<=0x7F) ? \
+     (wchar_t)(c) : \
+     ((0x0A1<=(c)) ? ((wchar_t)(c)-0xA0+0x0E00) : 0))
+
+/*
+ * Macros to save and recall last input character in XIC
+ */
+#define IC_SavePreviousChar(ic,ch) \
+                ((ic)->private.local.base.mb[(ic)->private.local.base.tree[(ic)->private.local.context].mb] = (char) (ch))
+#define IC_ClearPreviousChar(ic) \
+                ((ic)->private.local.base.mb[(ic)->private.local.base.tree[(ic)->private.local.context].mb] = 0)
+#define IC_GetPreviousChar(ic) \
+		(IC_RealGetPreviousChar(ic,1))
+#define IC_GetContextChar(ic) \
+		(IC_RealGetPreviousChar(ic,2))
+#define IC_DeletePreviousChar(ic) \
+		(IC_RealDeletePreviousChar(ic))
+
+Private unsigned char
+IC_RealGetPreviousChar(Xic ic, unsigned short pos)
+{
+    XICCallback* cb = &ic->core.string_conversion_callback;
+    DefTreeBase *b = &ic->private.local.base;
+
+    if (cb && cb->callback) {
+        XIMStringConversionCallbackStruct screc;
+        unsigned char c;
+
+        /* Use a safe value of position = 0 and stretch the range to desired
+         * place, as XIM protocol is unclear here whether it could be negative
+         */
+        screc.position = 0;
+        screc.direction = XIMBackwardChar;
+        screc.operation = XIMStringConversionRetrieval;
+        screc.factor = pos;
+        screc.text = 0;
+
+        (cb->callback)((XIC)ic, cb->client_data, (XPointer)&screc);
+        if (!screc.text)
+            return (unsigned char) b->mb[b->tree[(ic)->private.local.context].mb];
+        if ((screc.text->feedback &&
+             *screc.text->feedback == XIMStringConversionLeftEdge) ||
+            screc.text->length < 1)
+        {
+            c = 0;
+        } else {
+            Xim     im;
+            XlcConv conv;
+            int     from_left;
+            int     to_left;
+            char   *from_buf;
+            char   *to_buf;
+
+            im = (Xim) XIMOfIC((XIC)ic);
+            if (screc.text->encoding_is_wchar) {
+                conv = _XlcOpenConverter(im->core.lcd, XlcNWideChar,
+                                         im->core.lcd, XlcNCharSet);
+                from_buf = (char *) screc.text->string.wcs;
+                from_left = screc.text->length * sizeof(wchar_t);
+            } else {
+                conv = _XlcOpenConverter(im->core.lcd, XlcNMultiByte,
+                                         im->core.lcd, XlcNCharSet);
+                from_buf = screc.text->string.mbs;
+                from_left = screc.text->length;
+            }
+            to_buf = (char *)&c;
+            to_left = 1;
+
+            _XlcResetConverter(conv);
+            if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
+                            (XPointer *)&to_buf, &to_left, NULL, 0) < 0)
+            {
+                c = (unsigned char) b->mb[b->tree[(ic)->private.local.context].mb];
+            }
+            _XlcCloseConverter(conv);
+
+            XFree(screc.text->string.mbs);
+        }
+        XFree(screc.text);
+        return c;
+    } else {
+        return (unsigned char) b->mb[b->tree[(ic)->private.local.context].mb];
+    }
+}
+
+Private unsigned char
+IC_RealDeletePreviousChar(Xic ic)
+{
+    XICCallback* cb = &ic->core.string_conversion_callback;
+
+    if (cb && cb->callback) {
+        XIMStringConversionCallbackStruct screc;
+        unsigned char c;
+
+        screc.position = 0;
+        screc.direction = XIMBackwardChar;
+        screc.operation = XIMStringConversionSubstitution;
+        screc.factor = 1;
+        screc.text = 0;
+
+        (cb->callback)((XIC)ic, cb->client_data, (XPointer)&screc);
+        if (!screc.text) { return 0; }
+        if ((screc.text->feedback &&
+             *screc.text->feedback == XIMStringConversionLeftEdge) ||
+            screc.text->length < 1)
+        {
+            c = 0;
+        } else {
+            if (screc.text->encoding_is_wchar) {
+                c = ucs2tis(screc.text->string.wcs[0]);
+                XFree(screc.text->string.wcs);
+            } else {
+                c = screc.text->string.mbs[0];
+                XFree(screc.text->string.mbs);
+            }
+        }
+        XFree(screc.text);
+        return c;
+    } else {
+        return 0;
+    }
+}
+/*
+ * Input sequence check mode in XIC
+ */
+#define IC_IscMode(ic)		((ic)->private.local.thai.input_mode)
+
+/*
+ * Max. size of string handled by the two String Lookup functions.
+ */
+#define STR_LKUP_BUF_SIZE	256
+
+/*
+ * Size of buffer to contain previous locale name.
+ */
+#define SAV_LOCALE_NAME_SIZE	256
+
+/*
+ * Size of buffer to contain the IM modifier.
+ */
+#define MAXTHAIIMMODLEN 20
+
+#define AllMods (ShiftMask|LockMask|ControlMask| \
+		 Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)
+
+
+#define IsISOControlKey(ks) ((ks) >= XK_2 && (ks) <= XK_8)
+
+#define IsValidControlKey(ks)   (((((ks)>=XK_A && (ks)<=XK_asciitilde) || \
+                (ks)==XK_space || (ks)==XK_Delete) && \
+                ((ks)!=0)))
+
+#define COMPOSE_LED 2
+
+#ifdef UNUSED
+typedef KeySym (*StateProc)(
+    XicThaiPart *thai_part,
+    KeySym symbol,
+    XKeyEvent *event);
+
+
+/*
+ * macros to classify XKeyEvent state field
+ */
+
+#define IsShift(state) (((state) & ShiftMask) != 0)
+#define IsLock(state) (((state) & LockMask) != 0)
+#define IsControl(state) (((state) & ControlMask) != 0)
+#define IsMod1(state) (((state) & Mod1Mask) != 0)
+#define IsMod2(state) (((state) & Mod2Mask) != 0)
+#define IsMod3(state) (((state) & Mod3Mask) != 0)
+#define IsMod4(state) (((state) & Mod4Mask) != 0)
+#define IsMod5(state) (((state) & Mod5Mask) != 0)
+
+/*
+ * key starts Thai compose sequence (Hex input method) if :
+ */
+
+#define IsComposeKey(ks, event)  \
+	(( ks==XK_Alt_L && 	\
+	   IsControl((event)->state) &&	\
+	   !IsShift((event)->state))	\
+	 ? True : False)
+
+
+/*
+ *  State handler to implement the Thai hex input method.
+ */
+
+Private int const nstate_handlers = 3;
+Private StateProc state_handler[] = {
+	HexIMNormalKey,
+	HexIMFirstComposeKey,
+	HexIMSecondComposeKey
+};
+
+
+/*
+ *  Table for 'Thai Compose' character input.
+ *  The current implementation uses latin-1 keysyms.
+ */
+struct _XMapThaiKey {
+	KeySym from;
+	KeySym to;
+};
+
+Private struct _XMapThaiKey const ThaiComposeTable[] = {
+	{ /* 0xa4 */ XK_currency,	/* 0xa5 */ XK_yen },
+	{ /* 0xa2 */ XK_cent,		/* 0xa3 */ XK_sterling },
+	{ /* 0xe6 */ XK_ae,		/* 0xef */ XK_idiaeresis },
+	{ /* 0xd3 */ XK_Oacute,		/* 0xee */ XK_icircumflex },
+	{ /* 0xb9 */ XK_onesuperior,	/* 0xfa */ XK_uacute },
+	{ /* 0xd2 */ XK_Ograve,		/* 0xe5 */ XK_aring },
+	{ /* 0xbc */ XK_onequarter,	/* 0xfb */ XK_ucircumflex },
+	{	     XK_VoidSymbol,		   XK_VoidSymbol }
+};
+
+struct _XKeytrans {
+	struct _XKeytrans *next;/* next on list */
+	char *string;		/* string to return when the time comes */
+	int len;		/* length of string (since NULL is legit)*/
+	KeySym key;		/* keysym rebound */
+	unsigned int state;	/* modifier state */
+	KeySym *modifiers;	/* modifier keysyms you want */
+	int mlen;		/* length of modifier list */
+};
+
+
+/* Convert keysym to 'Thai Compose' keysym */
+/* The current implementation use latin-1 keysyms */
+Private Bool
+ThaiComposeConvert(
+    Display *dpy,
+    KeySym insym,
+    KeySym *outsym, KeySym *lower, KeySym *upper)
+{
+    struct _XMapThaiKey const *table_entry = ThaiComposeTable;
+
+    while (table_entry->from != XK_VoidSymbol) {
+	if (table_entry->from == insym) {
+	    *outsym = table_entry->to;
+	    *lower = *outsym;
+	    *upper = *outsym;
+	    return True;
+	}
+	table_entry++;
+    }
+    return False;
+}
+
+Private int
+XThaiTranslateKey(
+    register Display *dpy,
+    KeyCode keycode,
+    register unsigned int modifiers,
+    unsigned int *modifiers_return,
+    KeySym *keysym_return,
+    KeySym *lsym_return,
+    KeySym *usym_return)
+{
+    int per;
+    register KeySym *syms;
+    KeySym sym = 0, lsym = 0, usym = 0;
+
+    if ((! dpy->keysyms) && (! _XKeyInitialize(dpy)))
+	return 0;
+    *modifiers_return = (ShiftMask|LockMask) | dpy->mode_switch;
+    if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
+    {
+	*keysym_return = NoSymbol;
+	return 1;
+    }
+    per = dpy->keysyms_per_keycode;
+    syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
+    while ((per > 2) && (syms[per - 1] == NoSymbol))
+	per--;
+    if ((per > 2) && (modifiers & dpy->mode_switch)) {
+	syms += 2;
+	per -= 2;
+    }
+    if (!(modifiers & ShiftMask) &&
+	(!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
+	if ((per == 1) || (syms[1] == NoSymbol))
+	    XConvertCase(syms[0], keysym_return, &usym);
+	else {
+	    XConvertCase(syms[0], &lsym, &usym);
+	    *keysym_return = syms[0];
+	}
+    } else if (!(modifiers & LockMask) ||
+	       (dpy->lock_meaning != XK_Caps_Lock)) {
+	if ((per == 1) || ((usym = syms[1]) == NoSymbol))
+	    XConvertCase(syms[0], &lsym, &usym);
+	*keysym_return = usym;
+    } else {
+	if ((per == 1) || ((sym = syms[1]) == NoSymbol))
+	    sym = syms[0];
+	XConvertCase(sym, &lsym, &usym);
+	if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
+	    ((sym != usym) || (lsym == usym)))
+	    XConvertCase(syms[0], &lsym, &usym);
+	*keysym_return = usym;
+    }
+    /*
+     * ThaiCat keyboard support :
+     * When the Shift and Thai keys are hold for some keys a 'Thai Compose'
+     * character code is generated which is different from column 3 and
+     * 4 of the keymap.
+     * Since we don't know whether ThaiCat keyboard or WTT keyboard is
+     * in use, the same mapping is done for all Thai input.
+     * We just arbitary choose to use column 3 keysyms as the indices of
+     * this mapping.
+     * When the control key is also hold, this mapping has no effect.
+     */
+    if ((modifiers & Mod1Mask) &&
+	(modifiers & ShiftMask) &&
+	!(modifiers & ControlMask)) {
+	if (ThaiComposeConvert(dpy, syms[0], &sym, &lsym, &usym))
+	    *keysym_return = sym;
+    }
+
+    if (*keysym_return == XK_VoidSymbol)
+	*keysym_return = NoSymbol;
+    *lsym_return = lsym;
+    *usym_return = usym;
+    return 1;
+}
+
+/*
+ * XThaiTranslateKeySym
+ *
+ * Translate KeySym to TACTIS code output.
+ * The current implementation uses ISO latin-1 keysym.
+ * Should be changed to TACTIS keysyms when they are defined by the
+ * standard.
+ */
+Private int
+XThaiTranslateKeySym(
+    Display *dpy,
+    register KeySym symbol,
+    register KeySym lsym,
+    register KeySym usym,
+    unsigned int modifiers,
+    unsigned char *buffer,
+    int nbytes)
+{
+    KeySym ckey = 0;
+    register struct _XKeytrans *p;
+    int length;
+    unsigned long hiBytes;
+    register unsigned char c;
+
+    /*
+     * initialize length = 1 ;
+     */
+    length = 1;
+
+    if (!symbol)
+	return 0;
+    /* see if symbol rebound, if so, return that string. */
+    for (p = dpy->key_bindings; p; p = p->next) {
+	if (((modifiers & AllMods) == p->state) && (symbol == p->key)) {
+	    length = p->len;
+	    if (length > nbytes) length = nbytes;
+	    memcpy (buffer, p->string, length);
+	    return length;
+	}
+    }
+    /* try to convert to TACTIS, handling control */
+    hiBytes = symbol >> 8;
+    if (!(nbytes &&
+	  ((hiBytes == 0) ||
+	   ((hiBytes == 0xFF) &&
+	    (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) ||
+	     (symbol == XK_Return) ||
+	     (symbol == XK_Escape) ||
+	     (symbol == XK_KP_Space) ||
+	     (symbol == XK_KP_Tab) ||
+	     (symbol == XK_KP_Enter) ||
+	     ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) ||
+	     (symbol == XK_KP_Equal) ||
+             (symbol == XK_Scroll_Lock) ||
+#ifdef DXK_PRIVATE /* DEC private keysyms */
+             (symbol == DXK_Remove) ||
+#endif
+             (symbol == NoSymbol) ||
+	     (symbol == XK_Delete))))))
+	return 0;
+
+    /* if X keysym, convert to ascii by grabbing low 7 bits */
+    if (symbol == XK_KP_Space)
+	c = XK_space & 0x7F; /* patch encoding botch */
+/* not for Thai
+    else if (symbol == XK_hyphen)
+	c = XK_minus & 0xFF; */ /* map to equiv character */
+    else if (hiBytes == 0xFF)
+	c = symbol & 0x7F;
+    else
+	c = symbol & 0xFF;
+    /* only apply Control key if it makes sense, else ignore it */
+    if (modifiers & ControlMask) {
+    if (!(IsKeypadKey(lsym) || lsym==XK_Return || lsym==XK_Tab)) {
+        if (IsISOControlKey(lsym)) ckey = lsym;
+        else if (IsISOControlKey(usym)) ckey = usym;
+        else if (lsym == XK_question) ckey = lsym;
+        else if (usym == XK_question) ckey = usym;
+        else if (IsValidControlKey(lsym)) ckey = lsym;
+        else if (IsValidControlKey(usym)) ckey = usym;
+        else length = 0;
+
+        if (length != 0) {
+        if (ckey == XK_2) c = '\000';
+        else if (ckey >= XK_3 && ckey <= XK_7)
+            c = (char)(ckey-('3'-'\033'));
+        else if (ckey == XK_8) c = '\177';
+        else if (ckey == XK_Delete) c = '\030';
+        else if (ckey == XK_question) c = '\037';
+        else if (ckey == XK_quoteleft) c = '\036';  /* KLee 1/24/91 */
+        else c = (char)(ckey & 0x1f);
+        }
+    }
+    }
+    /*
+     *  ThaiCat has a key that generates two TACTIS codes D1 & E9.
+     *  It is represented by the latin-1 keysym XK_thorn (0xfe).
+     *  If c is XK_thorn, this key is pressed and it is converted to
+     *  0xd1 0xe9.
+     */
+    if (c == XK_thorn) {
+	buffer[0] = 0xd1;
+	buffer[1] = 0xe9;
+	buffer[2] = '\0';
+	return 2;
+    }
+    else {
+	/* Normal case */
+        buffer[0] = c;
+	buffer[1] = '\0';
+        return 1;
+    }
+}
+
+/*
+ * given a KeySym, returns the first keycode containing it, if any.
+ */
+Private CARD8
+FindKeyCode(
+    register Display *dpy,
+    register KeySym code)
+{
+
+    register KeySym *kmax = dpy->keysyms +
+	(dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode;
+    register KeySym *k = dpy->keysyms;
+    while (k < kmax) {
+	if (*k == code)
+	    return (((k - dpy->keysyms) / dpy->keysyms_per_keycode) +
+		    dpy->min_keycode);
+	k += 1;
+	}
+    return 0;
+}
+
+/*
+ * given a list of modifiers, computes the mask necessary for later matching.
+ * This routine must lookup the key in the Keymap and then search to see
+ * what modifier it is bound to, if any.  Sets the AnyModifier bit if it
+ * can't map some keysym to a modifier.
+ */
+Private void
+ComputeMaskFromKeytrans(
+    Display *dpy,
+    register struct _XKeytrans *p)
+{
+    register int i;
+    register CARD8 code;
+    register XModifierKeymap *m = dpy->modifiermap;
+
+    p->state = AnyModifier;
+    for (i = 0; i < p->mlen; i++) {
+	/* if not found, then not on current keyboard */
+	if ((code = FindKeyCode(dpy, p->modifiers[i])) == 0)
+		return;
+	/* code is now the keycode for the modifier you want */
+	{
+	    register int j = m->max_keypermod<<3;
+
+	    while ((--j >= 0) && (code != m->modifiermap[j]))
+		;
+	    if (j < 0)
+		return;
+	    p->state |= (1<<(j/m->max_keypermod));
+	}
+    }
+    p->state &= AllMods;
+}
+
+/************************************************************************
+ *
+ *
+ * Compose handling routines - compose handlers 0,1,2
+ *
+ *
+ ************************************************************************/
+
+#define NORMAL_KEY_STATE 0
+#define FIRST_COMPOSE_KEY_STATE 1
+#define SECOND_COMPOSE_KEY_STATE 2
+
+Private
+KeySym HexIMNormalKey(
+    XicThaiPart *thai_part,
+    KeySym symbol,
+    XKeyEvent *event)
+{
+    if (IsComposeKey (symbol, event))	/* start compose sequence	*/
+	{
+	SetLed (event->display,COMPOSE_LED, LedModeOn);
+	thai_part->comp_state = FIRST_COMPOSE_KEY_STATE;
+	return NoSymbol;
+	}
+    return symbol;
+}
+
+
+Private
+KeySym HexIMFirstComposeKey(
+    XicThaiPart *thai_part,
+    KeySym symbol,
+    XKeyEvent *event)
+{
+    if (IsModifierKey (symbol)) return symbol; /* ignore shift etc. */
+    if (IsCancelComposeKey (&symbol, event))	/* cancel sequence */
+	{
+	SetLed (event->display,COMPOSE_LED, LedModeOff);
+	thai_part->comp_state = NORMAL_KEY_STATE;
+	return symbol;
+	}
+    if (IsComposeKey (symbol, event))		/* restart sequence ?? */
+	{
+	return NoSymbol;			/* no state change necessary */
+	}
+
+    thai_part->keysym = symbol;		/* save key pressed */
+    thai_part->comp_state = SECOND_COMPOSE_KEY_STATE;
+    return NoSymbol;
+}
+
+Private
+KeySym HexIMSecondComposeKey(
+    XicThaiPart *thai_part,
+    KeySym symbol,
+    XKeyEvent *event)
+{
+    if (IsModifierKey (symbol)) return symbol;	/* ignore shift etc. */
+    if (IsComposeKey (symbol, event))		/* restart sequence ? */
+	{
+	thai_part->comp_state =FIRST_COMPOSE_KEY_STATE;
+	return NoSymbol;
+	}
+    SetLed (event->display,COMPOSE_LED, LedModeOff);
+    if (IsCancelComposeKey (&symbol, event))	/* cancel sequence ? */
+	{
+	thai_part->comp_state = NORMAL_KEY_STATE;
+	return symbol;
+	}
+
+    if ((symbol = HexIMComposeSequence (thai_part->keysym, symbol))
+								==NoSymbol)
+	{ /* invalid compose sequence */
+	XBell(event->display, BellVolume);
+	}
+    thai_part->comp_state = NORMAL_KEY_STATE; /* reset to normal state */
+    return symbol;
+}
+
+
+/*
+ * Interprets two keysyms entered as hex digits and return the Thai keysym
+ * correspond to the TACTIS code formed.
+ * The current implementation of this routine returns ISO Latin Keysyms.
+ */
+
+Private
+KeySym HexIMComposeSequence(KeySym ks1, KeySym ks2)
+{
+int	hi_digit;
+int	lo_digit;
+int	tactis_code;
+
+    if ((ks1 >= XK_0) && (ks1 <= XK_9))
+	hi_digit = ks1 - XK_0;
+    else if ((ks1 >= XK_A) && (ks1 <= XK_F))
+	hi_digit = ks1 - XK_A + 10;
+    else if ((ks1 >= XK_a) && (ks1 <= XK_f))
+	hi_digit = ks1 - XK_a + 10;
+    else	/* out of range */
+	return NoSymbol;
+
+    if ((ks2 >= XK_0) && (ks2 <= XK_9))
+	lo_digit = ks2 - XK_0;
+    else if ((ks2 >= XK_A) && (ks2 <= XK_F))
+	lo_digit = ks2 - XK_A + 10;
+    else if ((ks2 >= XK_a) && (ks2 <= XK_f))
+	lo_digit = ks2 - XK_a + 10;
+    else	/* out of range */
+	return NoSymbol;
+
+    tactis_code = hi_digit * 0x10 + lo_digit ;
+
+    return (KeySym)tactis_code;
+
+}
+
+/*
+ * routine determines
+ *	1) whether key event should cancel a compose sequence
+ *	2) whether cancelling key event should be processed or ignored
+ */
+
+Private
+int IsCancelComposeKey(
+    KeySym *symbol,
+    XKeyEvent *event)
+{
+    if (*symbol==XK_Delete && !IsControl(event->state) &&
+						!IsMod1(event->state)) {
+	*symbol=NoSymbol;  /* cancel compose sequence, and ignore key */
+	return True;
+    }
+    if (IsComposeKey(*symbol, event)) return False;
+    return (
+	IsControl (event->state) ||
+	IsMod1(event->state) ||
+	IsKeypadKey (*symbol) ||
+	IsFunctionKey (*symbol) ||
+	IsMiscFunctionKey (*symbol) ||
+#ifdef DXK_PRIVATE /* DEC private keysyms */
+	*symbol == DXK_Remove ||
+#endif
+	IsPFKey (*symbol) ||
+	IsCursorKey (*symbol) ||
+	(*symbol >= XK_Tab && *symbol < XK_Multi_key)
+		? True : False);	/* cancel compose sequence and pass */
+					/* cancelling key through	    */
+}
+
+
+/*
+ *	set specified keyboard LED on or off
+ */
+
+Private
+void SetLed(
+    Display *dpy,
+    int num,
+    int state)
+{
+    XKeyboardControl led_control;
+
+    led_control.led_mode = state;
+    led_control.led = num;
+    XChangeKeyboardControl (dpy, KBLed | KBLedMode,	&led_control);
+}
+#endif
+
+/*
+ * Initialize ISC mode from im modifier
+ */
+Private void InitIscMode(Xic ic)
+{
+    Xim im;
+    char *im_modifier_name;
+
+    /* If already defined, just return */
+
+    if (IC_IscMode(ic)) return;
+
+    /* Get IM modifier */
+
+    im = (Xim) XIMOfIC((XIC)ic);
+    im_modifier_name = im->core.im_name;
+
+    /* Match with predefined value, default is Basic Check */
+
+    if (!strncmp(im_modifier_name,"BasicCheck",MAXTHAIIMMODLEN+1))
+	IC_IscMode(ic) = WTT_ISC1;
+    else if (!strncmp(im_modifier_name,"Strict",MAXTHAIIMMODLEN+1))
+	IC_IscMode(ic) = WTT_ISC2;
+    else if (!strncmp(im_modifier_name,"Thaicat",MAXTHAIIMMODLEN+1))
+	IC_IscMode(ic) = THAICAT_ISC;
+    else if (!strncmp(im_modifier_name,"Passthrough",MAXTHAIIMMODLEN+1))
+	IC_IscMode(ic) = NOISC;
+    else
+	IC_IscMode(ic) = WTT_ISC1;
+
+    return;
+}
+
+/*
+ * Helper functions for _XimThaiFilter()
+ */
+Private Bool
+ThaiFltAcceptInput(Xic ic, unsigned char new_char, KeySym symbol)
+{
+    DefTreeBase *b = &ic->private.local.base;
+    b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char);
+    b->wc[b->tree[ic->private.local.composed].wc+1] = '\0';
+
+    if ((new_char <= 0x1f) || (new_char == 0x7f))
+        b->tree[ic->private.local.composed].keysym = symbol;
+    else
+        b->tree[ic->private.local.composed].keysym = NoSymbol;
+
+    return True;
+}
+
+Private Bool
+ThaiFltReorderInput(Xic ic, unsigned char previous_char, unsigned char new_char)
+{
+    DefTreeBase *b = &ic->private.local.base;
+    if (!IC_DeletePreviousChar(ic)) return False;
+    b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char);
+    b->wc[b->tree[ic->private.local.composed].wc+1] = tis2ucs(previous_char);
+    b->wc[b->tree[ic->private.local.composed].wc+2] = '\0';
+
+    b->tree[ic->private.local.composed].keysym = NoSymbol;
+
+    return True;
+}
+
+Private Bool
+ThaiFltReplaceInput(Xic ic, unsigned char new_char, KeySym symbol)
+{
+    DefTreeBase *b = &ic->private.local.base;
+    if (!IC_DeletePreviousChar(ic)) return False;
+    b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char);
+    b->wc[b->tree[ic->private.local.composed].wc+1] = '\0';
+
+    if ((new_char <= 0x1f) || (new_char == 0x7f))
+        b->tree[ic->private.local.composed].keysym = symbol;
+    else
+        b->tree[ic->private.local.composed].keysym = NoSymbol;
+
+    return True;
+}
+
+Private unsigned
+NumLockMask(Display *d)
+{
+    int i;
+    XModifierKeymap *map;
+    KeyCode numlock_keycode = XKeysymToKeycode (d, XK_Num_Lock);
+    if (numlock_keycode == NoSymbol)
+        return 0;
+
+    map = XGetModifierMapping (d);
+    if (!map)
+        return 0;
+
+    for (i = 0; i < 8; i++) {
+        if (map->modifiermap[map->max_keypermod * i] == numlock_keycode) {
+            XFreeModifiermap(map);
+            return 1 << i;
+        }
+    }
+    XFreeModifiermap(map);
+    return 0;
+}
+
+/*
+ * Filter function for TACTIS
+ */
+Bool
+_XimThaiFilter(Display *d, Window w, XEvent *ev, XPointer client_data)
+{
+    Xic		    ic = (Xic)client_data;
+    KeySym 	    symbol;
+    int 	    isc_mode; /* Thai Input Sequence Check mode */
+    unsigned char   previous_char; /* Last inputted Thai char */
+    unsigned char   new_char;
+#ifdef UNUSED
+    unsigned int    modifiers;
+    KeySym	    lsym,usym;
+    int		    state;
+    XicThaiPart     *thai_part;
+    char	    buf[10];
+#endif
+    wchar_t	    wbuf[10];
+    Bool            isReject;
+    DefTreeBase    *b = &ic->private.local.base;
+
+    if ((ev->type != KeyPress)
+        || (ev->xkey.keycode == 0))
+        return False;
+
+    if (!IC_IscMode(ic)) InitIscMode(ic);
+
+    XwcLookupString((XIC)ic, &ev->xkey, wbuf, sizeof(wbuf) / sizeof(wbuf[0]),
+		    &symbol, NULL);
+
+    if ((ev->xkey.state & (AllMods & ~(ShiftMask|LockMask|NumLockMask(d)))) ||
+         ((symbol >> 8 == 0xFF) &&
+         ((XK_BackSpace <= symbol && symbol <= XK_Clear) ||
+           (symbol == XK_Return) ||
+           (symbol == XK_Pause) ||
+           (symbol == XK_Scroll_Lock) ||
+           (symbol == XK_Sys_Req) ||
+           (symbol == XK_Escape) ||
+           (symbol == XK_Delete) ||
+           IsCursorKey(symbol) ||
+           IsKeypadKey(symbol) ||
+           IsMiscFunctionKey(symbol) ||
+           IsFunctionKey(symbol))))
+        {
+            IC_ClearPreviousChar(ic);
+            return False;
+        }
+    if (((symbol >> 8 == 0xFF) &&
+         IsModifierKey(symbol)) ||
+#ifdef XK_XKB_KEYS
+        ((symbol >> 8 == 0xFE) &&
+         (XK_ISO_Lock <= symbol && symbol <= XK_ISO_Last_Group_Lock)) ||
+#endif
+        (symbol == NoSymbol))
+    {
+        return False;
+    }
+#ifdef UNUSED
+    if (! XThaiTranslateKey(ev->xkey.display, ev->xkey.keycode, ev->xkey.state,
+	 		&modifiers, &symbol, &lsym, &usym))
+	return False;
+
+    /*
+     *  Hex input method processing
+     */
+
+    thai_part = &ic->private.local.thai;
+    state = thai_part->comp_state;
+    if (state >= 0 && state < nstate_handlers) /* call handler for state */
+    {
+        symbol = (* state_handler[state])(thai_part, symbol, (XKeyEvent *)ev);
+    }
+
+    /*
+     *  Translate KeySym into mb.
+     */
+    count = XThaiTranslateKeySym(ev->xkey.display, symbol, lsym,
+				usym, ev->xkey.state, buf, 10);
+
+    if (!symbol && !count)
+	return True;
+
+    /* Return symbol if cannot convert to character */
+    if (!count)
+	return False;
+#endif
+
+    /*
+     *  Thai Input sequence check
+     */
+    isc_mode = IC_IscMode(ic);
+    if (!(previous_char = IC_GetPreviousChar(ic))) previous_char = ' ';
+    new_char = ucs2tis(wbuf[0]);
+    isReject = True;
+    if (THAI_isaccepted(new_char, previous_char, isc_mode)) {
+        ThaiFltAcceptInput(ic, new_char, symbol);
+        isReject = False;
+    } else {
+        unsigned char context_char;
+
+        context_char = IC_GetContextChar(ic);
+        if (context_char) {
+            if (THAI_iscomposible(new_char, context_char)) {
+                if (THAI_iscomposible(previous_char, new_char)) {
+                    isReject = !ThaiFltReorderInput(ic, previous_char, new_char);
+                } else if (THAI_iscomposible(previous_char, context_char)) {
+                    isReject = !ThaiFltReplaceInput(ic, new_char, symbol);
+                } else if (THAI_chtype(previous_char) == FV1
+                           && THAI_chtype(new_char) == TONE) {
+                    isReject = !ThaiFltReorderInput(ic, previous_char, new_char);
+                }
+            } else if (THAI_isaccepted(new_char, context_char, isc_mode)) {
+                isReject = !ThaiFltReplaceInput(ic, new_char, symbol);
+            }
+        }
+    }
+    if (isReject) {
+        /* reject character */
+        XBell(ev->xkey.display, BellVolume);
+        return True;
+    }
+
+    _Xlcwcstombs(ic->core.im->core.lcd, &b->mb[b->tree[ic->private.local.composed].mb],
+		 &b->wc[b->tree[ic->private.local.composed].wc], 10);
+
+    _Xlcmbstoutf8(ic->core.im->core.lcd, &b->utf8[b->tree[ic->private.local.composed].utf8],
+		  &b->mb[b->tree[ic->private.local.composed].mb], 10);
+
+    /* Remember the last character inputted
+     * (as fallback in case StringConversionCallback is not provided)
+     */
+    IC_SavePreviousChar(ic, new_char);
+
+    ev->xkey.keycode = 0;
+    XPutBackEvent(d, ev);
+    return True;
+}
-- 
cgit v1.2.3