Index: gtk/gtkimcontextsimple.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkimcontextsimple.c,v
retrieving revision 1.34.2.2
diff -u -p -r1.34.2.2 gtkimcontextsimple.c
--- gtk/gtkimcontextsimple.c	21 May 2003 21:10:31 -0000	1.34.2.2
+++ gtk/gtkimcontextsimple.c	13 Jun 2003 23:14:10 -0000
@@ -18,6 +18,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 
 #include <gdk/gdkkeysyms.h>
 #include "gtkaccelgroup.h"
@@ -32,6 +33,18 @@ struct _GtkComposeTable 
   gint n_seqs;
 };
 
+typedef struct _GtkComposeRecord GtkComposeRecord;
+
+struct _GtkComposeRecord
+{
+  guint16 *compose_table;
+  gchar *outstr_table;
+  gint n_records;
+  gsize record_size;
+  gint n_compose;
+  gsize str_offset;
+};
+
 /* The following table was generated from the X compose tables include with
  * XFree86 4.0 using a set of Perl scripts. Contact Owen Taylor <otaylor@redhat.com>
  * to obtain the relevant perl scripts.
@@ -981,6 +994,13 @@ gtk_im_context_simple_init (GtkIMContext
 }
 
 static void
+free_record (GtkComposeRecord *record)
+{
+  g_free ((gchar*)record->compose_table);
+  g_free ((gchar*)record->outstr_table);
+}
+
+static void
 gtk_im_context_simple_finalize (GObject *obj)
 {
   GtkIMContextSimple *context_simple = GTK_IM_CONTEXT_SIMPLE (obj);
@@ -993,6 +1013,14 @@ gtk_im_context_simple_finalize (GObject 
       context_simple->tables = NULL;
     }
 
+  if (context_simple->records)
+    {
+      g_slist_foreach (context_simple->records, (GFunc)free_record, NULL);
+      g_slist_free (context_simple->records);
+
+      context_simple->records = NULL;
+    }
+
   parent_class->finalize (obj);
 }
 
@@ -1010,6 +1038,26 @@ gtk_im_context_simple_new (void)
 }
 
 static void
+gtk_im_context_simple_commit_utf8 (GtkIMContext *context,
+				   gchar *str)
+{
+  GtkIMContextSimple *context_simple = GTK_IM_CONTEXT_SIMPLE (context);
+
+  g_return_if_fail (str);
+  
+  context_simple->in_hex_sequence = FALSE;
+  
+  if (context_simple->tentative_match_utf8)
+    {
+      context_simple->tentative_match_utf8 = NULL;
+      context_simple->tentative_match_len = 0;
+      g_signal_emit_by_name (context_simple, "preedit_changed");
+    }
+
+  g_signal_emit_by_name (context, "commit", str);
+}
+
+static void
 gtk_im_context_simple_commit_char (GtkIMContext *context,
 				   gunichar ch)
 {
@@ -1035,6 +1083,21 @@ gtk_im_context_simple_commit_char (GtkIM
   g_signal_emit_by_name (context, "commit", &buf);
 }
 
+static gboolean
+gtk_im_context_simple_commit_tentative (GtkIMContext *context)
+{
+  GtkIMContextSimple *context_simple = GTK_IM_CONTEXT_SIMPLE (context);
+
+  if (context_simple->tentative_match_utf8)
+    gtk_im_context_simple_commit_utf8 (context, context_simple->tentative_match_utf8);
+  else if (context_simple->tentative_match)
+    gtk_im_context_simple_commit_char (context, context_simple->tentative_match);
+  else
+    return FALSE;
+
+  return TRUE;
+}
+
 static int
 compare_seq (const void *key, const void *value)
 {
@@ -1056,6 +1119,67 @@ compare_seq (const void *key, const void
 }
 
 static gboolean
+check_record (GtkIMContextSimple	*context_simple,
+	      const GtkComposeRecord	*record,
+	      gint			n_compose)
+{
+  gint row_stride = record->n_compose;
+  guint16 *seq = bsearch (context_simple->compose_buffer,
+			  record->compose_table, record->n_records,
+			  sizeof (guint16) *  row_stride,
+			  compare_seq);
+
+  if (seq)
+    {
+      guint16 *prev_seq;
+
+      /* Back up to the first sequence that matches to make sure
+       * we find the exact match if their is one.
+       */
+      while (seq > record->compose_table)
+	{
+	  prev_seq = seq - row_stride;
+	  if (compare_seq (context_simple->compose_buffer, prev_seq) != 0)
+	    break;
+	  seq = prev_seq;
+	}
+      
+      if (n_compose == record->n_compose ||
+	  seq[n_compose] == 0) /* complete sequence */
+	{
+	  guint16 *next_seq;
+	  gsize outstr_len = record->record_size - record->str_offset;
+	  gint n = (seq - record->compose_table)/record->n_compose;
+	  gchar *value = &record->outstr_table[n * outstr_len];
+
+	  /* We found a tentative match. See if there are any longer
+	   * sequences containing this subsequence
+	   */
+	  next_seq = seq + row_stride;
+	  if (next_seq < record->compose_table + record->n_records * record->n_compose)
+	    {
+	      if (compare_seq (context_simple->compose_buffer, next_seq) == 0)
+		{
+		  context_simple->tentative_match_utf8 = value;
+		  context_simple->tentative_match_len = n_compose;
+
+		  g_signal_emit_by_name (context_simple, "preedit_changed");
+
+		  return TRUE;
+		}
+	    }
+
+	  gtk_im_context_simple_commit_utf8 (GTK_IM_CONTEXT (context_simple), value);
+	  context_simple->compose_buffer[0] = 0;
+	}
+      
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
 check_table (GtkIMContextSimple    *context_simple,
 	     const GtkComposeTable *table,
 	     gint                   n_compose)
@@ -1197,12 +1321,12 @@ no_sequence_matches (GtkIMContextSimple 
   /* No compose sequences found, check first if we have a partial
    * match pending.
    */
-  if (context_simple->tentative_match)
+  if (context_simple->tentative_match || context_simple->tentative_match_utf8)
     {
       gint len = context_simple->tentative_match_len;
       int i;
-      
-      gtk_im_context_simple_commit_char (context, context_simple->tentative_match);
+
+      gtk_im_context_simple_commit_tentative (context);
       context_simple->compose_buffer[0] = 0;
       
       for (i=0; i < n_compose - len - 1; i++)
@@ -1305,11 +1429,9 @@ gtk_im_context_simple_filter_keypress (G
 	  (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R ||
 	   event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R))
 	{
-	  if (context_simple->tentative_match)
-	    {
-	      gtk_im_context_simple_commit_char (context, context_simple->tentative_match);
-	      context_simple->compose_buffer[0] = 0;
-	    }
+
+	  if (gtk_im_context_simple_commit_tentative (context))
+	    context_simple->compose_buffer[0] = 0;
 	  else
 	    context_simple->in_hex_sequence = 0;
 
@@ -1365,7 +1487,7 @@ gtk_im_context_simple_filter_keypress (G
               (event->keyval == GDK_space ||
                event->keyval == GDK_KP_Space))
             {
-              gtk_im_context_simple_commit_char (context, context_simple->tentative_match);
+	      gtk_im_context_simple_commit_tentative (context);
               context_simple->compose_buffer[0] = 0;
               return TRUE;
             }
@@ -1375,6 +1497,14 @@ gtk_im_context_simple_filter_keypress (G
     }
   else
     {
+      tmp_list = context_simple->records;
+      while (tmp_list)
+        {
+          if (check_record (context_simple, tmp_list->data, n_compose))
+            return TRUE;
+          tmp_list = tmp_list->next;
+        }
+
       tmp_list = context_simple->tables;
       while (tmp_list)
         {
@@ -1398,9 +1528,7 @@ gtk_im_context_simple_reset (GtkIMContex
   
   context_simple->compose_buffer[0] = 0;
 
-  if (context_simple->tentative_match)
-    gtk_im_context_simple_commit_char (context, context_simple->tentative_match);
-
+  gtk_im_context_simple_commit_tentative (context);
   context_simple->in_hex_sequence = FALSE;
 }
 
@@ -1415,34 +1543,42 @@ gtk_im_context_simple_get_preedit_string
   
   GtkIMContextSimple *context_simple = GTK_IM_CONTEXT_SIMPLE (context);
 
-  if (context_simple->tentative_match)
+  if (context_simple->tentative_match_utf8)
     {
-      if (context_simple->in_hex_sequence)
-        {
-          int hexchars = 0;
-          
-          while (context_simple->compose_buffer[hexchars] != 0)
-            {
-              len += g_unichar_to_utf8 (gdk_keyval_to_unicode (context_simple->compose_buffer[hexchars]),
-                                        outbuf + len);
-              ++hexchars;
-            }
-        }
-      else
-        {
-          len = g_unichar_to_utf8 (context_simple->tentative_match, outbuf);
-        }
-      
-      g_assert (len < 25);
-      outbuf[len] = '\0';      
-    }
-  else
-    {
-      outbuf[0] = '\0';
+      if (str)
+	*str = g_strdup (context_simple->tentative_match_utf8);
+      len = strlen (context_simple->tentative_match_utf8);
     }
+  else {
+    if (context_simple->tentative_match)
+      {
+	if (context_simple->in_hex_sequence)
+	  {
+	    int hexchars = 0;
+
+	    while (context_simple->compose_buffer[hexchars] != 0)
+	      {
+		len += g_unichar_to_utf8 (gdk_keyval_to_unicode (context_simple->compose_buffer[hexchars]),
+					  outbuf + len);
+		++hexchars;
+	      }
+	  }
+	else
+	  {
+	    len = g_unichar_to_utf8 (context_simple->tentative_match, outbuf);
+	  }
+      
+	g_assert (len < 25);
+	outbuf[len] = '\0';      
+      }
+    else
+      {
+	outbuf[0] = '\0';
+      }
   
-  if (str)
-    *str = g_strdup (outbuf);
+    if (str)
+      *str = g_strdup (outbuf);
+  }
 
   if (attrs)
     {
@@ -1458,7 +1594,7 @@ gtk_im_context_simple_get_preedit_string
     }
 
   if (cursor_pos)
-    *cursor_pos = (context_simple->tentative_match ? len : 0);
+    *cursor_pos = (context_simple->tentative_match || context_simple->tentative_match_utf8 ? len : 0);
 }
 
 /**
@@ -1499,3 +1635,75 @@ gtk_im_context_simple_add_table (GtkIMCo
   context_simple->tables = g_slist_prepend (context_simple->tables, table);
 }
 
+/**
+ * gtk_im_context_simple_add_records:
+ * @context_simple: A #GtkIMContextSimple
+ * @data: the records
+ * @n_records: number of record struct elements in the records
+ * @record_size: the size of the record struct
+ * @n_compose: length of a compose sequence in the record
+ *             (cannot be greater than #GTK_MAX_COMPOSE_LEN)
+ * @str_offset: offset to output_str member in the record struct
+ *	The 1st byte of the output_str in each record [n=0, 1, 
+ *	..., (n_records - 1) is obtained like:
+ *	 	guchar *output_str = record[n] + str_offset;
+ *
+ * Adds an additional record to search to the input context.
+ *
+ * The compose sequences in the records must be sorted in dictionary order
+ * on the numeric value of the key symbol fields. (Values beyond
+ * the length of the sequence should be zero.)
+ *
+ * The record struct should be defined by each input method backend
+ * like:
+ *
+ *  struct MyRecord {
+ *	guint16 compose_keys[MAX_COMPOSE_LEN];
+ *	guchar output_str[MAX_STR_LEN]; /* UTF-8 encoded;
+ *	};
+ *  The compose_keys and output_str must be NULL-terminated if
+ *  they are shorter than MAX_COMPOSE_LEN, MAX_STR_LEN, respectively.
+ *
+ **/
+void
+gtk_im_context_simple_add_records (GtkIMContextSimple *context_simple,
+                                   void               *data,
+                                   gint                n_records,
+                                   gsize               record_size,
+                                   gint                n_compose,
+                                   gsize               str_offset)
+{
+  GtkComposeRecord *records;
+  gchar *datap;
+  guint16 *compose_seq;
+  gchar *outstr;
+  gsize outstr_len;
+  int i;
+
+  g_return_if_fail (GTK_IS_IM_CONTEXT_SIMPLE (context_simple));
+  g_return_if_fail (data != NULL);
+  g_return_if_fail (n_compose <= GTK_MAX_COMPOSE_LEN);
+  
+  outstr_len = record_size - str_offset;
+
+  records = g_new (GtkComposeRecord, 1);
+  records->n_records = n_records;
+  records->record_size = record_size;
+  records->n_compose = n_compose;
+  records->str_offset = str_offset;
+
+  /* generate compose_table and str_table from the data */
+  records->compose_table = g_new (guint16, n_records * n_compose);
+  records->outstr_table = g_new (gchar, n_records * outstr_len);
+  compose_seq = records->compose_table;
+  outstr = records->outstr_table;
+  datap = (gchar*)data;
+  for (i = 0; i < n_records; i++, datap += record_size)
+    {
+      g_memmove (compose_seq, datap, sizeof (guint16) * n_compose);
+      strlcpy (outstr, datap + str_offset, outstr_len);
+      compose_seq += n_compose;
+      outstr += outstr_len;
+    }
+  context_simple->records  = g_slist_prepend (context_simple->records, records);
+}
Index: modules/input/Makefile.am
===================================================================
RCS file: /cvs/gnome/gtk+/modules/input/Makefile.am,v
retrieving revision 1.25.2.1
diff -u -p -r1.25.2.1 Makefile.am
--- modules/input/Makefile.am	18 Apr 2003 20:53:49 -0000	1.25.2.1
+++ modules/input/Makefile.am	13 Jun 2003 23:14:10 -0000
@@ -77,6 +77,10 @@ im_hangul_la_LDFLAGS = -rpath $(moduledi
 im_hangul_la_SOURCES = imhangul.c imhangul-defs.h
 im_hangul_la_LIBADD = $(LDADDS)
 
+im_hiragana_la_LDFLAGS =  -rpath $(moduledir) -avoid-version -module $(no_undefined)
+im_hiragana_la_SOURCES = imhiragana.c
+im_hiragana_la_LIBADD = $(LDADDS)
+
 if CROSS_COMPILING
 RUN_QUERY_IMMODULES_TEST=false
 else
@@ -105,6 +109,7 @@ module_LTLIBRARIES =				\
 	im-am-et.la				\
 	im-cyrillic-translit.la			\
 	im-hangul.la				\
+	im-hiragana.la				\
 	im-inuktitut.la				\
 	im-ipa.la				\
 	im-thai-broken.la			\
