Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/gtk+/modules/input/Makefile.am,v
retrieving revision 1.33
diff -u -r1.33 Makefile.am
--- Makefile.am	30 Aug 2004 04:53:23 -0000	1.33
+++ Makefile.am	2 Nov 2004 12:15:35 -0000
@@ -63,6 +63,15 @@
 im_thai_broken_la_SOURCES = imthai-broken.c
 im_thai_broken_la_LIBADD = $(LDADDS)
 
+im_thai_la_LDFLAGS = -rpath $(moduledir) -avoid-version -module $(no_undefined)
+im_thai_la_SOURCES = 		\
+	thai-charprop.c 	\
+	thai-charprop.h 	\
+	gtkimcontextthai.c 	\
+	gtkimcontextthai.h	\
+	imthai.c
+im_thai_la_LIBADD = $(LDADDS)
+
 im_viqr_la_LDFLAGS = -rpath $(moduledir) -avoid-version -module $(no_undefined)
 im_viqr_la_SOURCES = imviqr.c
 im_viqr_la_LIBADD = $(LDADDS)
@@ -125,6 +134,7 @@
 	im-inuktitut.la				\
 	im-ipa.la				\
 	im-thai-broken.la			\
+	im-thai.la				\
 	im-ti-er.la				\
 	im-ti-et.la				\
 	im-viqr.la				\
Index: gtkimcontextthai.c
===================================================================
RCS file: gtkimcontextthai.c
diff -N gtkimcontextthai.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtkimcontextthai.c	2 Nov 2004 12:15:35 -0000
@@ -0,0 +1,345 @@
+/* GTK - The GIMP Toolkit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:  Theppitak Karoonboonyanan <thep@linux.thai.net>
+ *
+ */
+
+#include <string.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkkeys.h>
+#include "gtkimcontextthai.h"
+#include "thai-charprop.h"
+
+static void     gtk_im_context_thai_class_init          (GtkIMContextThaiClass *class);
+static void     gtk_im_context_thai_init                (GtkIMContextThai      *im_context_thai);
+static gboolean gtk_im_context_thai_filter_keypress     (GtkIMContext          *context,
+						         GdkEventKey           *key);
+
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+static void     forget_previous_chars (GtkIMContextThai *context_thai);
+static void     remember_previous_char (GtkIMContextThai *context_thai,
+                                        gunichar new_char);
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+
+static GObjectClass *parent_class;
+
+GType gtk_type_im_context_thai = 0;
+
+void
+gtk_im_context_thai_register_type (GTypeModule *type_module)
+{
+  static const GTypeInfo im_context_thai_info =
+  {
+    sizeof (GtkIMContextThaiClass),
+    (GBaseInitFunc) NULL,
+    (GBaseFinalizeFunc) NULL,
+    (GClassInitFunc) gtk_im_context_thai_class_init,
+    NULL,           /* class_finalize */    
+    NULL,           /* class_data */
+    sizeof (GtkIMContextThai),
+    0,
+    (GInstanceInitFunc) gtk_im_context_thai_init,
+  };
+
+  gtk_type_im_context_thai = 
+    g_type_module_register_type (type_module,
+                                 GTK_TYPE_IM_CONTEXT,
+                                 "GtkIMContextThai",
+                                 &im_context_thai_info, 0);
+}
+
+static void
+gtk_im_context_thai_class_init (GtkIMContextThaiClass *class)
+{
+  GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
+
+  parent_class = g_type_class_peek_parent (class);
+
+  im_context_class->filter_keypress = gtk_im_context_thai_filter_keypress;
+}
+
+static void
+gtk_im_context_thai_init (GtkIMContextThai *context_thai)
+{
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+  forget_previous_chars (context_thai);
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+  context_thai->isc_mode = ISC_BASICCHECK;
+}
+
+GtkIMContext *
+gtk_im_context_thai_new (void)
+{
+  GtkIMContextThai *result;
+
+  result = GTK_IM_CONTEXT_THAI (g_object_new (GTK_TYPE_IM_CONTEXT_THAI, NULL));
+
+  return GTK_IM_CONTEXT (result);
+}
+
+GtkIMContextThaiISCMode
+gtk_im_context_thai_get_isc_mode (GtkIMContextThai *context_thai)
+{
+  return context_thai->isc_mode;
+}
+
+GtkIMContextThaiISCMode
+gtk_im_context_thai_set_isc_mode (GtkIMContextThai *context_thai,
+                                  GtkIMContextThaiISCMode mode)
+{
+  GtkIMContextThaiISCMode prev_mode = context_thai->isc_mode;
+  context_thai->isc_mode = mode;
+  return prev_mode;
+}
+
+static gboolean
+is_context_lost_key(guint keyval)
+{
+  return ((keyval & 0xFF00) == 0xFF00) &&
+         (keyval == GDK_BackSpace ||
+          keyval == GDK_Tab ||
+          keyval == GDK_Linefeed ||
+          keyval == GDK_Clear ||
+          keyval == GDK_Return ||
+          keyval == GDK_Pause ||
+          keyval == GDK_Scroll_Lock ||
+          keyval == GDK_Sys_Req ||
+          keyval == GDK_Escape ||
+          keyval == GDK_Delete ||
+          (GDK_Home <= keyval && keyval <= GDK_Begin) || /* IsCursorkey */
+          (GDK_KP_Space <= keyval && keyval <= GDK_KP_Equal) || /* IsKeypadKey */
+          (GDK_Select <= keyval && keyval <= GDK_Break) || /* IsMiscFunctionKey */
+          (GDK_F1 <= keyval && keyval <= GDK_F35)); /* IsFunctionKey */
+}
+
+static gboolean
+is_context_intact_key(guint keyval)
+{
+  return (((keyval & 0xFF00) == 0xFF00) &&
+           ((GDK_Shift_L <= keyval && keyval <= GDK_Hyper_R) || /* IsModifierKey */
+            (keyval == GDK_Mode_switch) ||
+            (keyval == GDK_Num_Lock))) ||
+         (((keyval & 0xFE00) == 0xFE00) &&
+          (GDK_ISO_Lock <= keyval && keyval <= GDK_ISO_Last_Group_Lock));
+}
+
+static gboolean
+thai_is_accept (gunichar new_char, gunichar prev_char, gint isc_mode)
+{
+  switch (isc_mode)
+    {
+    case ISC_PASSTHROUGH:
+      return TRUE;
+
+    case ISC_BASICCHECK:
+      return TAC_compose_input (prev_char, new_char) != 'R';
+
+    case ISC_STRICT:
+      {
+        int op = TAC_compose_input (prev_char, new_char);
+        return op != 'R' && op != 'S';
+      }
+
+    default:
+      return FALSE;
+    }
+}
+
+#define thai_is_composible(n,p)  (TAC_compose_input ((p), (n)) == 'C')
+
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+static void
+forget_previous_chars (GtkIMContextThai *context_thai)
+{
+  memset (context_thai->char_buff, 0, sizeof (context_thai->char_buff));
+}
+
+static void
+remember_previous_char (GtkIMContextThai *context_thai, gunichar new_char)
+{
+  memmove (context_thai->char_buff + 1, context_thai->char_buff,
+           (GTK_IM_CONTEXT_THAI_BUFF_SIZE - 1) * sizeof (context_thai->char_buff[0]));
+  context_thai->char_buff[0] = new_char;
+}
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+
+static gunichar
+get_previous_char (GtkIMContextThai *context_thai, gint offset)
+{
+  gchar *surrounding;
+  gint  cursor_index;
+
+  if (gtk_im_context_get_surrounding ((GtkIMContext *)context_thai,
+                                      &surrounding, &cursor_index))
+    {
+      gunichar prev_char;
+      gchar *p, *q;
+
+      prev_char = 0;
+      p = surrounding + cursor_index;
+      for (q = p; offset < 0 && q > surrounding; ++offset)
+        q = g_utf8_prev_char (q);
+      if (offset == 0)
+        {
+          prev_char = g_utf8_get_char_validated (q, p - q);
+          if (prev_char < 0)
+            prev_char = 0;
+        }
+      g_free (surrounding);
+      return prev_char;
+    }
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+  else
+    {
+      offset = -offset - 1;
+      if (0 <= offset && offset < GTK_IM_CONTEXT_THAI_BUFF_SIZE)
+        return context_thai->char_buff[offset];
+    }
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+
+    return 0;
+}
+
+static gboolean
+gtk_im_context_thai_commit_chars (GtkIMContextThai *context_thai,
+                                  gunichar *s, gsize len)
+{
+  gchar *utf8;
+
+  utf8 = g_ucs4_to_utf8 (s, len, NULL, NULL, NULL);
+  if (!utf8)
+    return FALSE;
+
+  g_signal_emit_by_name (context_thai, "commit", utf8);
+
+  g_free (utf8);
+  return TRUE;
+}
+
+static gboolean
+accept_input (GtkIMContextThai *context_thai, gunichar new_char)
+{
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+  remember_previous_char (context_thai, new_char);
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+
+  return gtk_im_context_thai_commit_chars (context_thai, &new_char, 1);
+}
+
+static gboolean
+reorder_input (GtkIMContextThai *context_thai,
+               gunichar prev_char, gunichar new_char)
+{
+  gunichar buf[2];
+
+  if (!gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context_thai), -1, 1))
+    return FALSE;
+
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+  forget_previous_chars (context_thai);
+  remember_previous_char (context_thai, new_char);
+  remember_previous_char (context_thai, prev_char);
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+
+  buf[0] = new_char;
+  buf[1] = prev_char;
+  return gtk_im_context_thai_commit_chars (context_thai, buf, 2);
+}
+
+static gboolean
+replace_input (GtkIMContextThai *context_thai, gunichar new_char)
+{
+  if (!gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context_thai), -1, 1))
+    return FALSE;
+
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+  forget_previous_chars (context_thai);
+  remember_previous_char (context_thai, new_char);
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+
+  return gtk_im_context_thai_commit_chars (context_thai, &new_char, 1);
+}
+
+static gboolean
+gtk_im_context_thai_filter_keypress (GtkIMContext *context,
+                                     GdkEventKey  *event)
+{
+  GtkIMContextThai *context_thai = GTK_IM_CONTEXT_THAI (context);
+  gunichar prev_char, new_char;
+  gboolean is_reject;
+  GtkIMContextThaiISCMode isc_mode;
+
+  if (event->type != GDK_KEY_PRESS)
+    return FALSE;
+
+  if (event->state & (GDK_MODIFIER_MASK & ~GDK_SHIFT_MASK) ||
+      is_context_lost_key (event->keyval))
+    {
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+      forget_previous_chars (context_thai);
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+      return FALSE;
+    }
+  if (event->keyval == 0 || is_context_intact_key (event->keyval))
+    {
+      return FALSE;
+    }
+
+  prev_char = get_previous_char (context_thai, -1);
+  if (!prev_char)
+    prev_char = ' ';
+  new_char = gdk_keyval_to_unicode (event->keyval);
+  is_reject = TRUE;
+  isc_mode = gtk_im_context_thai_get_isc_mode (context_thai);
+  if (thai_is_accept (new_char, prev_char, isc_mode))
+    {
+      accept_input (context_thai, new_char);
+      is_reject = FALSE;
+    }
+  else
+    {
+      gunichar context_char;
+
+      /* rejected, trying to correct */
+      context_char = get_previous_char (context_thai, -2);
+      if (context_char)
+        {
+          if (thai_is_composible (new_char, context_char))
+            {
+              if (thai_is_composible (prev_char, new_char))
+                is_reject = !reorder_input (context_thai, prev_char, new_char);
+              else if (thai_is_composible (prev_char, context_char))
+                is_reject = !replace_input (context_thai, new_char);
+              else if ((TAC_char_class (prev_char) == FV1
+                        || TAC_char_class (prev_char) == AM)
+                       && TAC_char_class (new_char) == TONE)
+                is_reject = !reorder_input (context_thai, prev_char, new_char);
+            }
+	  else if (thai_is_accept (new_char, context_char, isc_mode))
+            is_reject = !replace_input (context_thai, new_char);
+        }
+    }
+  if (is_reject)
+    {
+      /* reject character */
+      gdk_beep ();
+    }
+  return TRUE;
+}
+
Index: gtkimcontextthai.h
===================================================================
RCS file: gtkimcontextthai.h
diff -N gtkimcontextthai.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gtkimcontextthai.h	2 Nov 2004 12:15:37 -0000
@@ -0,0 +1,82 @@
+/* GTK - The GIMP Toolkit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:  Theppitak Karoonboonyanan <thep@linux.thai.net>
+ *
+ */
+
+#ifndef __GTK_IM_CONTEXT_THAI_H__
+#define __GTK_IM_CONTEXT_THAI_H__
+
+#include <gtk/gtkimcontext.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+extern GType gtk_type_im_context_thai;
+
+#define GTK_TYPE_IM_CONTEXT_THAI             gtk_type_im_context_thai
+#define GTK_IM_CONTEXT_THAI(obj)             (GTK_CHECK_CAST ((obj), GTK_TYPE_IM_CONTEXT_THAI, GtkIMContextThai))
+#define GTK_IM_CONTEXT_THAI_CLASS(klass)     (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_IM_CONTEXT_THAI, GtkIMContextThaiClass))
+#define GTK_IS_IM_CONTEXT_THAI(obj)          (GTK_CHECK_TYPE ((obj), GTK_TYPE_IM_CONTEXT_THAI))
+#define GTK_IS_IM_CONTEXT_THAI_CLASS(klass)  (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IM_CONTEXT_THAI))
+#define GTK_IM_CONTEXT_THAI_GET_CLASS(obj)   (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_IM_CONTEXT_THAI, GtkIMContextThaiClass))
+
+
+typedef struct _GtkIMContextThai       GtkIMContextThai;
+typedef struct _GtkIMContextThaiClass  GtkIMContextThaiClass;
+
+typedef enum
+{
+  ISC_PASSTHROUGH,
+  ISC_BASICCHECK,
+  ISC_STRICT
+} GtkIMContextThaiISCMode;
+#define GTK_IM_CONTEXT_THAI_BUFF_SIZE 2
+
+struct _GtkIMContextThai
+{
+  GtkIMContext object;
+
+#ifndef GTK_IM_CONTEXT_THAI_NO_FALLBACK
+  gunichar                char_buff[GTK_IM_CONTEXT_THAI_BUFF_SIZE];
+#endif /* !GTK_IM_CONTEXT_THAI_NO_FALLBACK */
+  GtkIMContextThaiISCMode isc_mode;
+};
+
+struct _GtkIMContextThaiClass
+{
+  GtkIMContextClass parent_class;
+};
+
+void gtk_im_context_thai_register_type (GTypeModule *type_module);
+GtkIMContext *gtk_im_context_thai_new (void);
+
+GtkIMContextThaiISCMode
+  gtk_im_context_thai_get_isc_mode (GtkIMContextThai *context_thai);
+
+GtkIMContextThaiISCMode
+  gtk_im_context_thai_set_isc_mode (GtkIMContextThai *context_thai,
+                                    GtkIMContextThaiISCMode mode);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_IM_CONTEXT_THAI_H__ */
Index: imthai.c
===================================================================
RCS file: imthai.c
diff -N imthai.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ imthai.c	2 Nov 2004 12:15:37 -0000
@@ -0,0 +1,70 @@
+/* GTK - The GIMP Toolkit
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Theppitak Karoonboonyanan <thep@linux.thai.net>
+ *
+ */
+
+#include <string.h>
+
+#include <gdk/gdkkeysyms.h>
+
+#include "gtk/gtkintl.h"
+#include "gtk/gtkimmodule.h"
+#include "gtkimcontextthai.h"
+
+GType type_thai = 0;
+
+static const GtkIMContextInfo thai_info = { 
+  "thai",	   /* ID */
+  N_("Thai-Lao"),  /* Human readable name */
+  "gtk+",	   /* Translation domain */
+   GTK_LOCALEDIR,  /* Dir for bindtextdomain (not strictly needed for "gtk+") */
+  "lo:th"	   /* Languages for which this module is the default */
+};
+
+static const GtkIMContextInfo *info_list[] = {
+  &thai_info
+};
+
+void
+im_module_init (GTypeModule *module)
+{
+  gtk_im_context_thai_register_type (module);
+}
+
+void 
+im_module_exit (void)
+{
+}
+
+void 
+im_module_list (const GtkIMContextInfo ***contexts,
+		int                      *n_contexts)
+{
+  *contexts = info_list;
+  *n_contexts = G_N_ELEMENTS (info_list);
+}
+
+GtkIMContext *
+im_module_create (const gchar *context_id)
+{
+  if (strcmp (context_id, "thai") == 0)
+    return gtk_im_context_thai_new ();
+  else
+    return NULL;
+}
Index: thai-charprop.c
===================================================================
RCS file: thai-charprop.c
diff -N thai-charprop.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ thai-charprop.c	2 Nov 2004 12:15:38 -0000
@@ -0,0 +1,138 @@
+#include "thai-charprop.h"
+
+const gshort thai_char_type[256] = {
+  /*       0,   1,   2,   3,   4,   5,   6,   7,
+           8,   9,   A,   B,   C,   D,   E,   F  */
+
+         /* CL1 */
+  /*00*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+  /*10*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+
+         /* Lao zone: [U+0E80..U+0EDF] */
+  /*20*/ _ND, _NC, _NC, _ND, _NC, _ND, _ND, _NC,
+         _NC, _ND, _NC, _ND, _ND, _NC, _ND, _ND,
+  /*30*/ _ND, _ND, _ND, _ND, _NC, _NC, _NC, _NC,
+         _ND, _NC, _NC, _UC, _NC, _UC, _NC, _UC,
+  /*40*/ _ND, _NC, _UC, _NC, _ND, _NC, _ND, _NC,
+         _ND, _ND, _NC, _NC, _ND, _NC, _NC, _ND,
+  /*50*/ _ND, _AV, _ND, _AM, _AV, _AV, _AV, _AV,
+         _BV, _BV, _ND, _AV, _BD, _NC, _ND, _ND,
+  /*60*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _AD,
+         _TN, _TN, _TN, _TN, _AD, _AD, _ND, _ND,
+  /*70*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+         _ND, _ND, _ND, _ND, _NC, _NC, _ND, _ND,
+
+         /* CL2 */
+  /*80*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+  /*90*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+
+         /* Thai zone: [U+0E00..U+0E5F] */
+  /*A0*/ _ND, _NC, _NC, _NC, _NC, _NC, _NC, _NC,
+         _NC, _NC, _NC, _NC, _NC, _SC, _BC, _BC,
+  /*B0*/ _SC, _NC, _NC, _NC, _NC, _NC, _NC, _NC,
+         _NC, _NC, _NC, _UC, _NC, _UC, _NC, _UC,
+  /*C0*/ _NC, _NC, _NC, _NC, _ND, _NC, _ND, _NC,
+         _NC, _NC, _NC, _NC, _UC, _NC, _NC, _ND,
+  /*D0*/ _ND, _AV, _ND, _AM, _AV, _AV, _AV, _AV,
+         _BV, _BV, _BD, _ND, _ND, _ND, _ND, _ND,
+  /*E0*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _AD,
+         _TN, _TN, _TN, _TN, _AD, _AD, _AD, _ND,
+  /*F0*/ _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+         _ND, _ND, _ND, _ND, _ND, _ND, _ND, _ND,
+};
+
+const gshort thai_TAC_char_class[256] = {
+  /*	   0,   1,   2,   3,   4,   5,   6,   7,
+           8,   9,   A,   B,   C,   D,   E,   F  */
+
+         /* CL1 */
+  /*00*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+         CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+  /*10*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+         CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+
+         /* Lao zone: [U+0E80..U+0EDF] */
+  /*20*/  NON,CONS,CONS, NON,CONS, NON, NON,CONS,
+         CONS, NON,CONS, NON, NON,CONS, NON, NON,
+  /*30*/  NON, NON, NON, NON,CONS,CONS,CONS,CONS,
+          NON,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+  /*40*/  NON,CONS,CONS,CONS, NON,CONS, NON,CONS,
+          NON, NON,CONS,CONS, NON,CONS,CONS, NON,
+  /*50*/  FV1, AV2, FV1,  AM, AV1, AV3, AV2, AV3,
+          BV1, BV2, NON, AV2,BCON, FV3, NON, NON,
+  /*60*/   LV,  LV,  LV,  LV,  LV, NON, NON, NON,
+         TONE,TONE,TONE,TONE, AD1, AD4, NON, NON,
+  /*70*/  NON, NON, NON, NON, NON, NON, NON, NON,
+          NON, NON, NON, NON,CONS,CONS, NON,CTRL,
+
+         /* CL2 */
+  /*80*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+         CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+  /*90*/ CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+         CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,CTRL,
+
+         /* Thai zone: [U+0E00..U+0E5F] */
+  /*A0*/  NON,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+         CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+  /*B0*/ CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+         CONS,CONS,CONS,CONS,CONS,CONS,CONS,CONS,
+  /*C0*/ CONS,CONS,CONS,CONS, FV3,CONS, FV3,CONS,
+         CONS,CONS,CONS,CONS,CONS,CONS,CONS, NON,
+  /*D0*/  FV1, AV2, FV1,  AM, AV1, AV3, AV2, AV3,
+          BV1, BV2,  BD, NON, NON, NON, NON, NON,
+  /*E0*/   LV,  LV,  LV,  LV,  LV, FV2, NON, AD2,
+         TONE,TONE,TONE,TONE, AD1, AD4, AD3, NON,
+  /*F0*/  NON, NON, NON, NON, NON, NON, NON, NON,
+          NON, NON, NON, NON, NON, NON, NON,CTRL,
+};
+
+const gchar thai_TAC_compose_input[20][20] = {
+      /* row: Cn-1,  column: Cn */
+      /*CTRL NON CONS LV FV1 FV2 FV3  AM BV1 BV2
+       * BD TONE AD1 AD2 AD3 AD4 AV1 AV2 AV3 BCON*/
+/*CTRL*/{'X','A','A','A','A','A','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*NON */{'X','A','A','A','S','S','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*CONS*/{'X','A','A','A','A','S','A','C','C','C',
+         'C','C','C','C','C','C','C','C','C','C'},
+/*LV  */{'X','S','A','S','S','S','S','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*FV1 */{'X','A','A','A','A','S','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*FV2 */{'X','A','A','A','A','S','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*FV3 */{'X','A','A','A','S','A','S','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*AM  */{'X','A','A','A','S','S','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*BV1 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','C','C','R','R','C','R','R','R','R'},
+/*BV2 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','C','R','R','R','R','R','R','R','R'},
+/*BD  */{'X','A','A','A','S','S','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*TONE*/{'X','A','A','A','A','A','A','C','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*AD1 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*AD2 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*AD3 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','R','R','R','R','R','R','R','R','R'},
+/*AD4 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','C','R','R','R','R','R','R','R','R'},
+/*AV1 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','C','C','R','R','C','R','R','R','R'},
+/*AV2 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','C','R','R','R','R','R','R','R','R'},
+/*AV3 */{'X','A','A','A','S','S','A','R','R','R',
+         'R','C','R','C','R','R','R','R','R','R'},
+/*BCON*/{'X','A','A','A','A','S','A','C','C','C',
+         'R','C','R','R','R','C','C','C','C','R'},
+};
+
Index: thai-charprop.h
===================================================================
RCS file: thai-charprop.h
diff -N thai-charprop.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ thai-charprop.h	2 Nov 2004 12:15:39 -0000
@@ -0,0 +1,98 @@
+/* Pango
+ * thai-charprop.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Author: Owen Taylor <otaylor@redhat.com>
+ *
+ * Software and Language Engineering Laboratory, NECTEC
+ * Author: Theppitak Karoonboonyanan <thep@links.nectec.or.th>
+ *
+ * Copyright (c) 1996-2000 by Sun Microsystems, Inc.
+ * Author: Chookij Vanatham <Chookij.Vanatham@Eng.Sun.COM>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __THAI_CHARPROP_H__
+#define __THAI_CHARPROP_H__
+
+#include <glib.h>
+
+#define isthai(wc)      (0x0E00 <= (wc) && (wc) < 0x0E60)
+#define islao(wc)       (0x0E80 <= (wc) && (wc) < 0x0EE0)
+/* ucs2tis()
+ * Lao:  [0x0E80..0x0EDF] -> [0x20..0x7F]
+ * Thai: [0x0E00..0x0E5F] -> [0xA0..0xFF]
+ */
+#define ucs2tis(wc)     (((wc) - 0x0E00 + 0x20)^0x80)
+
+/* Define TACTIS character classes */
+#define CTRL		0
+#define NON		1
+#define CONS		2
+#define LV		3
+#define FV1		4
+#define FV2		5
+#define FV3		6
+#define AM		7
+#define BV1		8
+#define BV2		9
+#define BD		10
+#define TONE		11
+#define AD1		12
+#define AD2		13
+#define AD3		14
+#define AD4		15
+#define AV1		16
+#define AV2		17
+#define AV3		18
+#define BCON		19
+
+#define _ND		0
+#define _NC		1
+#define _UC		(1<<1)
+#define _BC		(1<<2)
+#define _SC		(1<<3)
+#define _AV		(1<<4)
+#define _BV		(1<<5)
+#define _TN		(1<<6)
+#define _AD		(1<<7)
+#define _BD		(1<<8)
+#define _AM		(1<<9)
+
+#define NoTailCons	_NC
+#define UpTailCons	_UC
+#define BotTailCons	_BC
+#define SpltTailCons	_SC
+#define Cons		(NoTailCons|UpTailCons|BotTailCons|SpltTailCons)
+#define AboveVowel	_AV
+#define BelowVowel	_BV
+#define Tone		_TN
+#define AboveDiac	_AD
+#define BelowDiac	_BD
+#define SaraAm		_AM
+
+#define is_char_type(wc, mask)	(thai_char_type[ucs2tis ((wc))] & (mask))
+#define TAC_char_class(wc) \
+	(isthai(wc)||islao(wc) ? thai_TAC_char_class[ucs2tis (wc)] : NON)
+#define TAC_compose_input(wc1,wc2) \
+	thai_TAC_compose_input[TAC_char_class(wc1)][TAC_char_class(wc2)]
+
+extern const gshort thai_char_type[256];
+extern const gshort thai_TAC_char_class[256];
+extern const gchar  thai_TAC_compose_input[20][20];
+
+#endif /* __THAI_CHARPROP_H__ */
