*** empty log message ***
authorhanda <handa>
Wed, 19 Jul 2006 07:28:03 +0000 (07:28 +0000)
committerhanda <handa>
Wed, 19 Jul 2006 07:28:03 +0000 (07:28 +0000)
fifotest1.c [new file with mode: 0644]
fifotest2.c [new file with mode: 0644]
findfont.c
gdkdraw.c
imtest.c [new file with mode: 0644]
mimdaemon.c [new file with mode: 0644]
mimdemo.c [new file with mode: 0644]

diff --git a/fifotest1.c b/fifotest1.c
new file mode 100644 (file)
index 0000000..5a8aee9
--- /dev/null
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#define PIPE_IN "/tmp/mimdemo-in"
+#define PIPE_OUT "/tmp/mimdemo-out"
+
+int
+main ()
+{
+  FILE *in, *out;
+  mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  int c;
+
+  umask (0);
+  if (mkfifo (PIPE_IN, mode) < 0 && errno != EEXIST)
+    {
+      fprintf (stderr, "Failed to make a named pipe.\n");
+      exit (1);
+    }
+
+  if (mkfifo (PIPE_OUT, mode) < 0 && errno != EEXIST)
+    {
+      fprintf (stderr, "Failed to make a named pipe.\n");
+      exit (1);
+    }
+
+  do {
+    printf ("accepting...");
+    fflush (stdout);
+    in = fopen (PIPE_IN, "r");
+    printf ("\nconnecting...");
+    fflush (stdout);
+    out = fopen (PIPE_OUT, "w");
+    printf ("done\n");
+    if (! in || ! out)
+      {
+       fprintf (stderr, "Failed to open a named pipe.\n");
+       exit (1);
+      }
+    while ((c = getc (in)) != EOF && c != '!')
+      {
+       putchar (c);
+       putc (toupper (c), out);
+       fflush (out);
+      }
+    fclose (in);
+    fclose (out);
+  } while (c != '!'); 
+
+  unlink (PIPE_IN);
+  unlink (PIPE_OUT);
+  exit (0);
+}
diff --git a/fifotest2.c b/fifotest2.c
new file mode 100644 (file)
index 0000000..7d6d88f
--- /dev/null
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define PIPE_IN "/tmp/mimdemo-in"
+#define PIPE_OUT "/tmp/mimdemo-out"
+
+int
+main (int argc, char **argv)
+{
+  FILE *out = fopen (PIPE_IN, "w");
+  FILE *in = fopen (PIPE_OUT, "r");
+  int c;
+
+  fprintf (out, "%s %s %s", argv[1], argv[2], argv[3]);
+  fclose (out);
+
+  while ((c = getc (in)) != EOF)
+    putchar (c);
+  fclose (in);
+  exit (0);
+}
index e942cc4..d12de2f 100644 (file)
@@ -72,7 +72,6 @@ print_font (MFont *font)
 {
   MSymbol family, foundry, weight, slant, stretch;
   char *weight_name, *slant_name, *stretch_name;
-  int len;
   char style_name[1024];
 
   family = mfont_get_prop (font, Mfamily);
@@ -94,7 +93,6 @@ main (int argc, char **argv)
 {
   MPlist *plist, *p;
   MFrame *frame;
-  char buf[256];
   
   M17N_INIT ();
 
@@ -114,7 +112,6 @@ main (int argc, char **argv)
   else if (argc == 2)
     {
       MFont *font = parse_font_name (argv[1]);
-      MPlist *p0;
 
       plist = mfont_list (frame, font, Mnil, 0);
       free (font);
index 710817b..e66b710 100644 (file)
--- a/gdkdraw.c
+++ b/gdkdraw.c
@@ -102,7 +102,6 @@ main (int argc, char **argv)
     int array_size, num_glyphs;
     MPlist *family_list;
     int family_name_len;
-    char *p;
 
     memset (&control, 0, sizeof (control));
     control.anti_alias = 1;
@@ -150,7 +149,6 @@ main (int argc, char **argv)
                             - metric.x, - metric.y,
                             mt, 0, mtext_len (mt), &control);
     m17n_object_unref (frame);
-    m17n_object_unref (mt);
 
     if (family_list)
       {
@@ -182,9 +180,11 @@ main (int argc, char **argv)
     attr_list = pango_attr_list_new ();
     attr_size = pango_attr_size_new (FONT_PT_SIZE * PANGO_SCALE);
     attr_family = family_names ? pango_attr_family_new (family_names) : NULL;
-    pango_attr_list_insert (attr_list, attr_size);
+#if 0
     if (attr_family)
-      pango_attr_list_insert (attr_list, attr_family);
+      pango_attr_list_change (attr_list, attr_family);
+#endif
+    pango_attr_list_change (attr_list, attr_size);
 
     pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8,
                             metric.width, metric.height);
diff --git a/imtest.c b/imtest.c
new file mode 100644 (file)
index 0000000..10f5ed4
--- /dev/null
+++ b/imtest.c
@@ -0,0 +1,503 @@
+#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
+
diff --git a/mimdaemon.c b/mimdaemon.c
new file mode 100644 (file)
index 0000000..268fc2a
--- /dev/null
@@ -0,0 +1,312 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+
+#include <gd.h>
+
+#include <m17n-gui.h>
+#include <m17n-misc.h>
+
+#define PIPE_IN "/tmp/mimdemo-in"
+#define PIPE_OUT "/tmp/mimdemo-out"
+
+/* Format MSG by FMT and print the result to the stderr, and exit.  */
+
+#define FATAL_ERROR(fmt, arg)  \
+  do {                         \
+    fprintf (out, "0\n");      \
+    fprintf (out, fmt, arg);   \
+    fprintf (out, "\n");       \
+    goto err;                  \
+  } while (0)
+
+char base64_encode_table[] =
+  { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', '+', '/' };
+
+void
+base64_encode (const unsigned char *src, int length, FILE *fp)
+{
+  int i = 0;
+  int c;
+  unsigned int value;
+
+  while (i < length)
+    {
+      c = src[i++];
+      putc (base64_encode_table[0x3f & c >> 2], fp);
+      value = (0x03 & c) << 4;
+      if (i == length)
+       {
+         putc (base64_encode_table[value], fp);
+         putc ('=', fp);
+         putc ('=', fp);
+         break;
+       }
+      c = src[i++];
+      putc (base64_encode_table[value | (0x0f & c >> 4)], fp);
+      value = (0x0f & c) << 2;
+      if (i == length)
+       {
+         putc (base64_encode_table[value], fp);
+         putc ('=', fp);
+         break;
+       }
+      c = src[i++];
+      putc (base64_encode_table[value | (0x03 & c >> 6)], fp);
+      putc (base64_encode_table[0x3f & c], fp);
+    }
+}
+  
+int
+main (int argc, char **argv)
+{
+  FILE *in, *out;
+  mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  int c;
+
+  int fontsize = 240;
+  int dpi = 100;
+
+  MText *mt;
+  int i;
+  MSymbol lang, name;
+  MInputMethod *im;
+  MInputContext *ic;
+
+  int len, from, to;
+  MConverter *converter;
+  MFrame *frame;
+  MDrawControl control;
+  MDrawMetric ink, logical;
+  int ascent, descent, height, width;
+#if 0
+  int indent = 0;
+  int left_adjust;
+#endif
+  gdImagePtr work;
+  int work_white;
+
+  umask (0);
+  if (mkfifo (PIPE_IN, mode) < 0 && errno != EEXIST)
+    {
+      fprintf (stderr, "Failed to make a named pipe.\n");
+      exit (1);
+    }
+
+  if (mkfifo (PIPE_OUT, mode) < 0 && errno != EEXIST)
+    {
+      fprintf (stderr, "Failed to make a named pipe.\n");
+      exit (1);
+    }
+
+  M17N_INIT ();
+  if (merror_code != MERROR_NONE)
+    {
+      fprintf (stderr, "Failed to initialize the m17n library.\n");
+      exit (1);
+    }
+
+  {
+    MPlist *plist = mplist (), *p;
+    MFontset *fontset = mfontset ("generic");
+    MFace *face = mface ();
+
+    mface_put_prop (face, Mfontset, fontset);
+    mface_put_prop (face, Msize, (void *) (fontsize * dpi / 100));
+    p = mplist_add (plist, Mdevice, msymbol ("gd"));
+    p = mplist_add (p, Mface, face);
+    m17n_object_unref (face);
+    frame = mframe (plist);
+    m17n_object_unref (plist);
+    if (! frame)
+      {
+       fprintf (stderr, "Failed to open a frame.\n");
+       exit (1);
+      }
+  }
+
+  while (1)
+    {
+      char langname[256], imname[256];
+      
+      printf ("accepting...");
+      fflush (stdout);
+      in = fopen (PIPE_IN, "r");
+      printf ("\nconnecting...");
+      fflush (stdout);
+      out = fopen (PIPE_OUT, "w");
+      if (! in || ! out)
+       {
+         fprintf (stderr, "Failed to open a named pipe.\n");
+         exit (1);
+       }
+      printf ("done\nreading...");
+      fflush (stdout);
+
+      memset (langname, 0, 256);
+      memset (imname, 0, 256);
+
+      i = 0;
+      while ((c = getc (in)) != EOF && c != '-')
+       {
+         if (i == 255)
+           FATAL_ERROR ("Too long lang name: %s.", langname);
+         langname[i++] = c;
+       }
+      if (c != '-')
+       FATAL_ERROR ("No input method name for %s.", langname);
+      i = 0;
+      while ((c = getc (in)) != EOF && c != ' ')
+       {
+         if (i == 255)
+           FATAL_ERROR ("Too long input method name: %s", imname);
+         imname[i++] = c;
+       }
+      if (c != ' ')
+       FATAL_ERROR ("%s", "No key sequence");
+
+      lang = msymbol (langname);
+      name = msymbol (imname);
+
+      im = minput_open_im (lang, name, NULL);
+      if (! im)
+       FATAL_ERROR ("Failed to open input method \"%s\".", imname);
+      ic = minput_create_ic (im, NULL);
+      if (! im)
+       FATAL_ERROR ("%s", "Failed to create the input context.");
+      mt = mtext ();
+      while ((c = getc (in)) != EOF)
+       {
+         char keybuf[2];
+         MSymbol key;
+
+         keybuf[0] = c;
+         keybuf[1] = '\0';
+         key = msymbol (keybuf);
+         if (minput_filter (ic, key, NULL) == 1)
+           continue;
+         if (minput_lookup (ic, key, NULL, mt) < 0)
+           {
+             mtext_cat_char (mt, c);
+           }
+       }
+      if (ic->preedit)
+       mtext_cat (mt, ic->preedit);
+      minput_destroy_ic (ic);
+      minput_close_im (im);
+
+      len = mtext_len (mt);
+      if (len == 0)
+       {
+         m17n_object_unref (mt);
+         goto err;
+       }
+
+      mtext_put_prop (mt, 0, len, Mlanguage, lang);
+
+      memset (&control, 0, sizeof control);
+      control.enable_bidi = 1;
+
+      mdraw_text_extents (frame, mt, 0, len, &control, &ink, &logical, NULL);
+      ascent = - logical.y;
+      if (ascent < - ink.y)
+       ascent = -ink.y;
+      descent = logical.height + logical.y;
+      if (descent < ink.height + ink.y)
+       descent = ink.height + ink.y;
+      height = ascent + descent;
+      width = logical.width;
+      if (height == 0 || width == 0)
+       {
+         m17n_object_unref (mt);
+         goto err;
+       }
+
+      work = gdImageCreate (width, height);
+      work_white = gdImageColorAllocate (work, 255, 255, 255); 
+      gdImageColorTransparent (work, work_white);
+      gdImageFilledRectangle (work, 0, 0, width - 1, height - 1, work_white);
+      mdraw_text_with_control (frame, work, 0, ascent, mt, 0, len, &control);
+
+      converter = mconv_stream_converter (msymbol ("utf-8"), out);
+
+      fprintf (out, "1\n");
+      from = 0;
+      {
+       MDrawMetric *ink_array, *logical_array;
+       int array_size = len * 2;
+       int num_chars;
+       unsigned char *buf;
+       int size;
+    
+       ink_array = malloc (sizeof (MDrawMetric) * array_size);
+       logical_array = malloc (sizeof (MDrawMetric) * array_size);
+
+       if (mdraw_text_per_char_extents (frame, mt, 0, len, &control,
+                                        ink_array, logical_array,
+                                        array_size, &num_chars, NULL, NULL) < 0)
+         {
+           ink_array = realloc (ink_array, sizeof (MDrawMetric) * num_chars);
+           logical_array = realloc (logical_array, sizeof (MDrawMetric) * num_chars);
+           mdraw_text_per_char_extents (frame, mt, 0, len, &control,
+                                        ink_array, logical_array,
+                                        num_chars, &num_chars, NULL, NULL);
+         }
+
+       for (from = 0, i = 0; i < num_chars;)
+         {
+           gdImagePtr image;
+           int white;
+           int x = logical_array[i].x;
+
+           image = gdImageCreate (logical_array[i].width, height);
+           white = gdImageColorAllocate (image, 255, 255, 255); 
+           gdImageColorTransparent (image, white);
+           gdImageCopy (image, work, 0, 0,
+                        logical_array[i].x, 0, logical_array[i].width, height);
+           fprintf (out, "<img src=\"data:image/png;base64,");
+           buf = gdImagePngPtr (image, &size);
+           base64_encode (buf, size, out);
+           gdFree (buf);
+           gdImageDestroy (image);
+
+           while (++i < num_chars && logical_array[i].x == x);
+           if (i == num_chars)
+             to = len;
+           else
+             to = mdraw_coordinates_position (frame, mt, 0, len,
+                                              logical_array[i].x, 0, &control);
+           fprintf (out, "\" alt=\"");
+           mconv_encode_range (converter, mt, from, to);
+           fprintf (out, "\">");
+           from = to;
+         }
+       free (ink_array);
+       free (logical_array);
+      }
+      fprintf (out, "\n");
+      gdImageDestroy (work);
+      m17n_object_unref (mt);
+
+    err:
+      fclose (in);
+      fclose (out);
+    }
+
+  M17N_FINI ();
+  unlink (PIPE_IN);
+  unlink (PIPE_OUT);
+  exit (0);
+}
+       
diff --git a/mimdemo.c b/mimdemo.c
new file mode 100644 (file)
index 0000000..7a51754
--- /dev/null
+++ b/mimdemo.c
@@ -0,0 +1,217 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <libgen.h>
+
+#include <gd.h>
+
+#include <m17n-gui.h>
+#include <m17n-misc.h>
+
+/* Format MSG by FMT and print the result to the stderr, and exit.  */
+
+#define FATAL_ERROR(fmt, arg)  \
+  do {                         \
+    printf ("0\n");            \
+    printf (fmt, arg);         \
+    exit (0);                  \
+  } while (0)
+
+char base64_encode_table[] =
+  { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
+    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', '+', '/' };
+
+void
+base64_encode (const unsigned char *src, int length, FILE *fp)
+{
+  int i = 0;
+  int c;
+  unsigned int value;
+
+  while (i < length)
+    {
+      c = src[i++];
+      putc (base64_encode_table[0x3f & c >> 2], fp);
+      value = (0x03 & c) << 4;
+      if (i == length)
+       {
+         putc (base64_encode_table[value], fp);
+         putc ('=', fp);
+         putc ('=', fp);
+         break;
+       }
+      c = src[i++];
+      putc (base64_encode_table[value | (0x0f & c >> 4)], fp);
+      value = (0x0f & c) << 2;
+      if (i == length)
+       {
+         putc (base64_encode_table[value], fp);
+         putc ('=', fp);
+         break;
+       }
+      c = src[i++];
+      putc (base64_encode_table[value | (0x03 & c >> 6)], fp);
+      putc (base64_encode_table[0x3f & c], fp);
+    }
+}
+  
+int
+main (int argc, char **argv)
+{
+  int fontsize = 240;
+  int dpi = 100;
+
+  MText *mt;
+  int i;
+  MSymbol lang, name;
+  MInputMethod *im;
+  MInputContext *ic;
+
+  int len, from, to;
+  MConverter *converter;
+  MFrame *frame;
+  MDrawControl control;
+  MDrawMetric ink, logical;
+  int ascent, descent, height, width;
+#if 0
+  int indent = 0;
+  int left_adjust;
+#endif
+  gdImagePtr work;
+  int work_white;
+
+  if (argc != 4)
+    FATAL_ERROR ("Number of arguments %d must be 4\n", argc);
+
+  M17N_INIT ();
+  if (merror_code != MERROR_NONE)
+    FATAL_ERROR ("%s\n", "Failed to initialize the m17n library.");
+
+  lang = msymbol (argv[1]);
+  name = msymbol (argv[2]);
+  im = minput_open_im (lang, name, NULL);
+  if (! im)
+    FATAL_ERROR ("%s\n", "Failed to open the input method.");
+  ic = minput_create_ic (im, NULL);
+  if (! im)
+    FATAL_ERROR ("%s\n", "Failed to create the input context.");
+  mt = mtext ();
+  for (i = 0; argv[3][i]; i++)
+    {
+      char keybuf[2];
+      MSymbol key;
+
+      keybuf[0] = argv[3][i];
+      keybuf[1] = '\0';
+      key = msymbol (keybuf);
+      if (minput_filter (ic, key, NULL) == 1)
+       continue;
+      minput_lookup (ic, key, NULL, mt);
+    }
+  if (ic->preedit)
+    mtext_cat (mt, ic->preedit);
+  len = mtext_len (mt);
+
+  mtext_put_prop (mt, 0, len, Mlanguage, lang);
+
+  {
+    MPlist *plist = mplist (), *p;
+    MFontset *fontset = mfontset ("generic");
+    MFace *face = mface ();
+
+    mface_put_prop (face, Mfontset, fontset);
+    mface_put_prop (face, Msize, (void *) (fontsize * dpi / 100));
+    p = mplist_add (plist, Mdevice, msymbol ("gd"));
+    p = mplist_add (p, Mface, face);
+    m17n_object_unref (face);
+    frame = mframe (plist);
+    m17n_object_unref (plist);
+    if (! frame)
+      FATAL_ERROR ("%s\n", "Failed to open a frame.");
+  }
+
+  memset (&control, 0, sizeof control);
+  control.enable_bidi = 1;
+
+  mdraw_text_extents (frame, mt, 0, len, &control, &ink, &logical, NULL);
+  ascent = - logical.y;
+  if (ascent < - ink.y)
+    ascent = -ink.y;
+  descent = logical.height + logical.y;
+  if (descent < ink.height + ink.y)
+    descent = ink.height + ink.y;
+  height = ascent + descent;
+  width = logical.width;
+
+  work = gdImageCreate (width, height);
+  work_white = gdImageColorAllocate (work, 255, 255, 255); 
+  gdImageColorTransparent (work, work_white);
+  gdImageFilledRectangle (work, 0, 0, width - 1, height - 1, work_white);
+  mdraw_text_with_control (frame, work, 0, ascent, mt, 0, len, &control);
+
+  converter = mconv_stream_converter (msymbol ("utf-8"), stdout);
+
+  printf ("1\n");
+  from = 0;
+  {
+    MDrawMetric *ink_array, *logical_array;
+    int array_size = len * 2;
+    int num_chars;
+    unsigned char *buf;
+    int size;
+    
+    ink_array = malloc (sizeof (MDrawMetric) * array_size);
+    logical_array = malloc (sizeof (MDrawMetric) * array_size);
+
+    if (mdraw_text_per_char_extents (frame, mt, 0, len, &control,
+                                    ink_array, logical_array,
+                                    array_size, &num_chars, NULL, NULL) < 0)
+      {
+       ink_array = realloc (ink_array, sizeof (MDrawMetric) * num_chars);
+       logical_array = realloc (logical_array, sizeof (MDrawMetric) * num_chars);
+       mdraw_text_per_char_extents (frame, mt, 0, len, &control,
+                                    ink_array, logical_array,
+                                    num_chars, &num_chars, NULL, NULL);
+      }
+
+    for (from = 0, i = 0; i < num_chars;)
+      {
+       gdImagePtr image;
+       int white;
+       int x = logical_array[i].x;
+
+       image = gdImageCreate (logical_array[i].width, height);
+       white = gdImageColorAllocate (image, 255, 255, 255); 
+       gdImageColorTransparent (image, white);
+       gdImageCopy (image, work, 0, 0,
+                    logical_array[i].x, 0, logical_array[i].width, height);
+       printf ("<img src=\"data:image/png;base64,");
+       buf = gdImagePngPtr (image, &size);
+       base64_encode (buf, size, stdout);
+       gdFree (buf);
+       gdImageDestroy (image);
+
+       while (++i < num_chars && logical_array[i].x == x);
+       if (i == num_chars)
+         to = len;
+       else
+         to = mdraw_coordinates_position (frame, mt, 0, len,
+                                          logical_array[i].x, 0, &control);
+       printf ("\" alt=\"");
+       mconv_encode_range (converter, mt, from, to);
+       printf ("\">");
+       from = to;
+      }
+  }
+  printf ("\n");
+
+  M17N_FINI ();
+  exit (0);
+}
+