+#include <stdio.h>
+#include <string.h>
+
+#include <m17n.h>
+#include <m17n-misc.h>
+
+MSymbol utf8;
+
+void
+show_description (MText *mt, int indent)
+{
+ if (mt)
+ {
+ printf ("\n%*sdescription: ", indent, "");
+ mconv_encode_stream (utf8, mt, stdout);
+ }
+ else
+ printf ("\n%*sno-description", indent, "");
+}
+
+void
+show_input_method (MSymbol lang, MSymbol name, int indent)
+{
+ MText *mt;
+ MSymbol language;
+
+ if (lang == Mt)
+ language = msymbol ("generic");
+ else if ((language = msymbol_get (lang, Mlanguage)) == Mnil)
+ language = lang;
+ printf ("\n%*slanguage: %s name: %s",
+ indent, "", msymbol_name (language), msymbol_name (name));
+ mt = minput_get_description (lang, name);
+ show_description (mt, indent + 2);
+ if (mt)
+ m17n_object_unref (mt);
+}
+
+void
+show_command (MSymbol cmd, MPlist *p, int indent)
+{
+ printf ("\n%*sname: %s", indent, "", msymbol_name (cmd));
+ indent += 2;
+ show_description (mplist_value (p), indent);
+ p = mplist_next (p);
+ if (mplist_key (p) == Mnil)
+ printf ("\n%*skey-sequence: global assignments are effective", indent, "");
+ else
+ for (; mplist_key (p) != Mnil; p = mplist_next (p))
+ if (mplist_key (p) == Mplist)
+ {
+ MPlist *p0 = mplist_value (p);
+
+ if (mplist_key (p0) != Mnil)
+ {
+ printf ("\n%*skey-sequence:", indent, "");
+ for (; mplist_key (p0) != Mnil; p0 = mplist_next (p0))
+ printf (" %s", msymbol_name ((MSymbol) mplist_value (p0)));
+ }
+ }
+}
+
+void
+show_variable (MSymbol var, MPlist *p, int indent)
+{
+ MSymbol type;
+
+ printf ("\n%*sname: %s", indent, "", msymbol_name (var));
+ indent += 2;
+ show_description (mplist_value (p), indent);
+ p = mplist_next (p);
+ printf ("\n%*sinitial-value: ", indent, "");
+ type = mplist_key (p);
+ if (type == Minteger)
+ printf ("%d", (int) mplist_value (p));
+ else if (type == Msymbol)
+ printf ("%s", msymbol_name ((MSymbol) mplist_value (p)));
+ else /* type == Mtext */
+ {
+ printf ("\"");
+ mconv_encode_stream (utf8, (MText *) mplist_value (p), stdout);
+ printf ("\"");
+ }
+ p = mplist_next (p);
+ printf ("\n%*svalid-value:", indent, "");
+ if (mplist_key (p) == Mnil)
+ printf (" any value of type %s", msymbol_name (type));
+ else
+ for (; mplist_key (p) != Mnil; p = mplist_next (p))
+ {
+ MSymbol this_type = mplist_key (p);
+
+ if (type != this_type && (type != Minteger || this_type != Mplist))
+ /* This shouldn't happen. */
+ continue;
+ if (this_type == Minteger)
+ printf (" %d", (int) mplist_value (p));
+ else if (this_type == Msymbol)
+ printf (" %s", msymbol_name ((MSymbol) mplist_value (p)));
+ else if (this_type == Mtext)
+ {
+ printf (" \"");
+ mconv_encode_stream (utf8, (MText *) mplist_value (p), stdout);
+ printf ("\"");
+ }
+ else /* type == Mplist */
+ {
+ MPlist *p0 = mplist_value (p);
+
+ printf (" %d", (int) mplist_value (p0));
+ p0 = mplist_next (p0);
+ printf ("-%d", (int) mplist_value (p0));
+ }
+ }
+}
+
+#if 0
+MPlist *im_list = NULL;
+
+MInputMethod *
+get_im (MSymbol lang, MSymbol name)
+{
+ MInputMethod *im;
+ MPlist *p;
+
+ if (! im_list)
+ im_list = mplist ();
+ for (p = im_list; mplist_key (p) != Mnil; p = mplist_next (p))
+ {
+ im = mplist_value (p);
+ if (im->language == lang && im->name == name)
+ return im;
+ }
+ im = minput_open_im (lang, name, NULL);
+ if (! im)
+ return NULL;
+ mplist_push (im_list, Mt, im);
+ return im;
+}
+
+void
+close_ims ()
+{
+ MInputMethod *im;
+ MPlist *p;
+
+ if (! im_list)
+ return;
+ for (p = im_list; mplist_key (p) != Mnil; p = mplist_next (p))
+ {
+ im = mplist_value (p);
+ minput_close_im (im);
+ }
+ m17n_object_unref (im_list);
+}
+
+void
+show_preedit (MInputContext *ic)
+{
+ int len = mtext_len (ic->preedit);
+ int i;
+
+ printf ("preedit:");
+ for (i = 0; i < len; i++)
+ printf (" U+%04X", mtext_ref_char (ic->preedit, i));
+ printf ("\n");
+ fflush (stdout);
+}
+
+void
+show_candidates (MInputContext *ic)
+{
+ MPlist *plist = ic->candidate_list;
+ int idx = ic->candidate_index;
+ int items;
+ int i, j, len;
+ MText *mt;
+
+ printf ("candidates:");
+ while (1)
+ {
+ if (mplist_key (plist) == Mtext)
+ items = mtext_len ((MText *) mplist_value (plist));
+ else
+ items = mplist_length ((MPlist *) mplist_value (plist));
+ if (idx < items)
+ break;
+ idx -= items;
+ plist = mplist_next (plist);
+ }
+ if (mplist_key (plist) == Mtext)
+ {
+ mt = (MText *) mplist_value (plist);
+ for (i = 0; i < items; i++)
+ {
+ if (i == idx)
+ printf ("[U+%04X]", mtext_ref_char (mt, i));
+ else
+ printf (" U+%04X ", mtext_ref_char (mt, i));
+ }
+ }
+ else
+ {
+ plist = (MPlist *) mplist_value (plist);
+ for (i = 0; i < items; i++, plist = mplist_next (plist))
+ {
+ mt = (MText *) mplist_value (plist);
+ len = mtext_len (mt);
+ if (i == idx)
+ printf ("[");
+ else
+ printf (" ");
+ for (j = 0; j < len; j++)
+ {
+ if (j > 0)
+ printf (",");
+ printf ("U+%04X", mtext_ref_char (mt, j));
+ }
+ if (i == idx)
+ printf ("[");
+ else
+ printf (" ");
+ }
+ }
+ printf ("\n");
+ fflush (stdout);
+}
+
+void
+show_produced (MText *mt)
+{
+ int len = mtext_len (mt);
+ int i;
+
+ printf ("produced:");
+ for (i = 0; i < len; i++)
+ printf (" U+%04X", mtext_ref_char (mt, i));
+ printf ("\n");
+ fflush (stdout);
+}
+
+int
+main (int argc, char **argv)
+{
+ char line[256];
+ MSymbol lang, name;
+ MInputMethod *im = NULL;
+ MInputContext *ic = NULL;
+
+ M17N_INIT ();
+
+ while (fgets (line, 256, stdin))
+ {
+ if (strncmp (line, "open", 4) == 0)
+ {
+ char langstr[16], namestr[16];
+
+ if (ic)
+ minput_destroy_ic (ic);
+ if (sscanf (line + 4, "%s %s", langstr, namestr) != 2)
+ continue;
+ lang = msymbol (langstr);
+ name = msymbol (namestr);
+ printf ("opening im \"%s\" \"%s\" ...", langstr, namestr);
+ im = get_im (lang, name);
+ if (! im)
+ {
+ printf (" failed\n");
+ fflush (stdout);
+ continue;
+ }
+ printf (" done\n");
+ printf ("creating context ...");
+ ic = minput_create_ic (im, NULL);
+ if (! ic)
+ {
+ printf ("failed\n");
+ fflush (stdout);
+ minput_close_im (im);
+ im = NULL;
+ continue;
+ }
+ printf (" done\n");
+ fflush (stdout);
+ }
+ else if (! ic)
+ {
+ printf ("no input method is available\n");
+ fflush (stdout);
+ continue;
+ }
+ else
+ {
+ int i;
+ char keystr[4];
+ MSymbol key;
+
+ for (i = 0; line[i] != '\n'; i++)
+ {
+ int c = line[i];
+ int result;
+ MText *mt;
+
+ if (c < 32)
+ sprintf (keystr, "C-%c", c + 64);
+ else
+ sprintf (keystr, "%c", c);
+ key = msymbol (keystr);
+ result = minput_filter (ic, key, NULL);
+ if (ic->preedit_changed)
+ show_preedit (ic);
+ if (ic->candidates_changed && ic->candidate_show
+ && ic->candidate_list)
+ show_candidates (ic);
+ if (result > 0)
+ continue;
+ mt = mtext ();
+ minput_lookup (ic, key, NULL, mt);
+ show_produced (mt);
+ m17n_object_unref (mt);
+ }
+ }
+ }
+
+ if (ic)
+ minput_destroy_ic (ic);
+ close_ims ();
+ M17N_FINI ();
+ exit (0);
+}
+
+#else
+int
+main (int argc, char **argv)
+{
+ MPlist *plist, *pl;
+ MSymbol unicode, test, commit;
+ MPlist *keyseq;
+ int test_input_method_found = 0;
+
+ /* To make database module find test.mim in this directory. */
+ mdatabase_dir = ".";
+
+ M17N_INIT ();
+ utf8 = msymbol ("utf-8");
+ unicode = msymbol ("unicode");
+ test = msymbol ("test");
+ commit = msymbol ("commit");
+
+ mdatabase_define (msymbol ("input"), msymbol ("command"), Mnil, Mnil,
+ NULL, "im-cmd.tbl");
+ printf ("List all available input methods:");
+ plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
+ if (! plist)
+ goto err;
+ for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
+ {
+ MDatabase *mdb = mplist_value (pl);
+ MSymbol *tag = mdatabase_tag (mdb);
+
+ show_input_method (tag[1], tag[2], 2);
+ if (tag[1] == Mt && tag[2] == test)
+ test_input_method_found = 1;
+ }
+ printf ("\n");
+ m17n_object_unref (plist);
+
+ printf ("Is test input method found?\n");
+ if (! test_input_method_found)
+ goto err;
+ printf (" Found\n");
+
+ printf ("Describe commit command and its global key assignment:");
+ plist = minput_get_commands (Mnil, Mnil);
+ if (! plist || ! (plist = mplist_get (plist, commit)))
+ goto err;
+ show_command (commit, plist, 2);
+ printf ("\n");
+
+ /* Assign S-space to the command "commit" globally. */
+ printf ("Assign S-space to commit globally:");
+ keyseq = mplist ();
+ mplist_add (keyseq, Msymbol, msymbol ("S-space"));
+ if (minput_assign_command_keys (Mnil, Mnil, commit, keyseq) < 0)
+ goto err;
+ /* Check the above assignment. */
+ plist = minput_get_commands (Mnil, Mnil);
+ plist = mplist_get (plist, commit);
+ show_command (commit, plist, 2);
+ printf ("\n");
+
+ printf ("Describe commit command and its local key assignment in \"test\":");
+ plist = minput_get_commands (Mt, test);
+ if (! plist
+ || ! (plist = mplist_get (plist, commit)))
+ goto err;
+ show_command (commit, plist, 2);
+ printf ("\n");
+
+ printf ("Assign A-space to commit locally in \"test\":");
+ mplist_put (keyseq, Msymbol, msymbol ("A-space"));
+ if (minput_assign_command_keys (Mt, test, commit, keyseq) < 0
+ || ! (plist = minput_get_commands (Mt, test))
+ || ! (plist = mplist_get (plist, commit)))
+ goto err;
+ show_command (commit, plist, 2);
+ printf ("\n");
+
+ printf ("Cancel the above locale assignment:");
+ if (minput_assign_command_keys (Mt, test, commit, NULL) < 0
+ || ! (plist = minput_get_commands (Mt, test))
+ || ! (plist = mplist_get (plist, commit)))
+ goto err;
+ show_command (commit, plist, 2);
+ printf ("\n");
+
+ printf ("Assign A-space in addition to global assignments to commit:");
+ minput_assign_command_keys (Mt, test, commit, keyseq);
+ plist = mplist_next (mplist_get (minput_get_commands (Mnil, Mnil), commit));
+ for (; mplist_key (plist) != Mnil; plist = mplist_next (plist))
+ minput_assign_command_keys (Mt, test, commit, mplist_value (plist));
+
+ if (! (plist = minput_get_commands (Mt, test))
+ || ! (plist = mplist_get (plist, commit)))
+ goto err;
+ show_command (commit, plist, 2);
+ printf ("\n");
+
+ printf ("Cancel the assignment without making global assignment effective:");
+ /* Make KEYSEQ an empty plist. */
+ mplist_pop (keyseq);
+ minput_assign_command_keys (Mt, test, commit, NULL);
+ minput_assign_command_keys (Mt, test, commit, keyseq);
+ if (! (plist = minput_get_commands (Mt, test))
+ || ! (plist = mplist_get (plist, commit)))
+ goto err;
+ show_command (commit, plist, 2);
+ printf ("\n");
+ m17n_object_unref (keyseq);
+
+ printf ("List variables used in \"test\":");
+ plist = minput_get_variables (Mt, test);
+ if (! plist)
+ goto err;
+ for (; mplist_key (plist) != Mnil; plist = mplist_next (plist))
+ show_variable (mplist_key (plist), mplist_value (plist), 2);
+ printf ("\n");
+
+ printf ("Set the first variable to hello ... should fail:\n");
+ plist = minput_get_variables (Mt, test);
+ if (minput_set_variable (Mt, test, mplist_key (plist), msymbol ("hello")) < 0)
+ printf (" Correctly failed\n");
+ else
+ printf (" Incorrectly succeeded\n");
+
+ printf ("Set the first variable to no ... should succeed:\n");
+ if (minput_set_variable (Mt, test, mplist_key (plist), msymbol ("no")) < 0)
+ printf (" Incorrectly failed\n");
+ else
+ printf (" Correctly succeeded\n");
+
+ plist = mplist_next (plist);
+ printf ("Set the second variable to 5 ... should fail:\n");
+ if (minput_set_variable (Mt, test, mplist_key (plist), (void *) 5) < 0)
+ printf (" Correctly failed\n");
+ else
+ printf (" Incorrectly succeeded\n");
+ printf ("Set the second variable to 10 ... should succeeded:\n");
+ if (minput_set_variable (Mt, test, mplist_key (plist), (void *) 10) < 0)
+ printf (" Incorrectly failed\n");
+ else
+ printf (" Correctly succeeded\n");
+
+ plist = mplist_next (plist);
+ {
+ char *str = "hello";
+ MText *mt = mtext_from_data (str, strlen (str), MTEXT_FORMAT_US_ASCII);
+
+ printf ("Set the third variable to \"hello\" ... should succeed:\n");
+ if (minput_set_variable (Mt, test, mplist_key (plist), mt) < 0)
+ printf (" Incorrectly failed\n");
+ else
+ printf (" Correctly succeeded\n");
+ m17n_object_unref (mt);
+ }
+
+ printf ("List variables used in \"test\" again:");
+ plist = minput_get_variables (Mt, test);
+ if (! plist)
+ goto err;
+ for (; mplist_key (plist) != Mnil; plist = mplist_next (plist))
+ show_variable (mplist_key (plist), mplist_value (plist), 2);
+ printf ("\n");
+
+ M17N_FINI ();
+ exit (0);
+
+ err:
+ printf (" ...failed!\n");
+ exit (1);
+}
+#endif
+