*** empty log message ***
[m17n/m17n-lib.git] / example / medit.c
index 725ffdc..fe6fad2 100644 (file)
@@ -1,5 +1,5 @@
 /* medit.c -- simple multilingual editor.              -*- coding: euc-jp; -*-
 /* medit.c -- simple multilingual editor.              -*- coding: euc-jp; -*-
-   Copyright (C) 2003, 2004
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
 /***en
    02111-1307, USA.  */
 
 /***en
-    @enpage medit edit multilingual text
+    @enpage m17n-edit edit multilingual text
 
 
-    @section medit-synopsis SYNOPSIS
+    @section m17n-edit-synopsis SYNOPSIS
 
 
-    medit [ XT-OPTION ...] [ OPTION ... ] FILE
+    m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
 
 
-    @section medit-description DESCRIPTION
+    @section m17n-edit-description DESCRIPTION
 
     Display FILE on a window and allow users to edit it.
 
 
     Display FILE on a window and allow users to edit it.
 
     </ul>
 
     This program is to demonstrate how to use the m17n GUI API.
     </ul>
 
     This program is to demonstrate how to use the m17n GUI API.
-    Although medit directly uses the GUI API, the API is mainly for
-    toolkit libraries or to implement XOM (X Outout Method), not for
-    direct use from application programs.
+    Although m17n-edit directly uses the GUI API, the API is mainly
+    for toolkit libraries or to implement XOM (X Output Method), not
+    for direct use from application programs.
 */
 /***ja
 */
 /***ja
-    @japage medit Â¿¸À¸ì¥Æ¥­¥¹¥È¤ÎÊÔ½¸
+    @japage m17n-edit Â¿¸À¸ì¥Æ¥­¥¹¥È¤ÎÊÔ½¸
 
 
-    @section medit-synopsis SYNOPSIS
+    @section m17n-edit-synopsis SYNOPSIS
 
 
-    medit [ XT-OPTION ...] [ OPTION ... ] FILE
+    m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
 
 
-    @section medit-description DESCRIPTION
+    @section m17n-edit-description DESCRIPTION
 
     FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë¡£
 
 
     FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë¡£
 
 
     </ul>
 
 
     </ul>
 
-    ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£medit ¤Ïľ 
-    ÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥­¥Ã¥È¥é¥¤¥Ö¥é¥ê¤ä
-    XOM (X Outout Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é ¥à
-    ¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
+    ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£m17n-edit
+    ¤ÏľÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥­¥Ã¥È¥é¥¤¥Ö¥é
+    ¥ê¤äXOM (X Output Method) ¤Î¼ÂÁõÍѤǤ¢¤ê¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
+    ¥à¤«¤é¤ÎľÀܤÎÍøÍѤò°Õ¿Þ¤·¤Æ¤¤¤Ê¤¤¡£
 */
 
 #ifndef FOR_DOXYGEN
 */
 
 #ifndef FOR_DOXYGEN
 #include <unistd.h>
 #include <libgen.h>
 #include <locale.h>
 #include <unistd.h>
 #include <libgen.h>
 #include <locale.h>
+#include <dlfcn.h>
+
+#ifdef HAVE_X11_XAW_COMMAND_H
 
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
 
 #include <X11/keysym.h>
 #include <X11/Xatom.h>
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include <X11/Shell.h>
+
+#include <m17n-gui.h>
+#include <m17n-misc.h>
+#include <m17n-X.h>
+
 #include <X11/Xaw/Command.h>
 #include <X11/Xaw/Box.h>
 #include <X11/Xaw/Form.h>
 #include <X11/Xaw/Command.h>
 #include <X11/Xaw/Box.h>
 #include <X11/Xaw/Form.h>
 #include <X11/Xaw/SmeLine.h>
 #include <X11/Xaw/MenuButton.h>
 
 #include <X11/Xaw/SmeLine.h>
 #include <X11/Xaw/MenuButton.h>
 
-#include <m17n-gui.h>
-#include <m17n-misc.h>
-#include <m17n-X.h>
-
-#define VERSION "1.2.0"
-
 /* Global variables.  */
 
 char *filename;
 /* Global variables.  */
 
 char *filename;
@@ -169,9 +171,12 @@ Pixmap CheckPixmap;
 MFrame *frame;
 MText *mt;
 int nchars;                    /* == mtext_len (mt) */
 MFrame *frame;
 MText *mt;
 int nchars;                    /* == mtext_len (mt) */
+int mt_modified;
 MDrawControl control, input_status_control;
 MTextProperty *selection;
 
 MDrawControl control, input_status_control;
 MTextProperty *selection;
 
+MSymbol Mword;
+
 MFace *face_default;
 MFace *face_xxx_large;
 MFace *face_box;
 MFace *face_default;
 MFace *face_xxx_large;
 MFace *face_box;
@@ -194,7 +199,9 @@ InputMethodInfo *input_method_table;
 
 int num_input_methods;
 int current_input_method = -1; /* i.e. none */
 
 int num_input_methods;
 int current_input_method = -1; /* i.e. none */
+int unicode_input_method = -1;
 int auto_input_method = 0;
 int auto_input_method = 0;
+int saved_input_method = -3;
 MInputContext *current_input_context;
 
 struct FaceRec
 MInputContext *current_input_context;
 
 struct FaceRec
@@ -251,7 +258,7 @@ struct LineInfo
 {
   int from;                    /* BOL position of the line.  */
   int to;                      /* BOL position of the next line.  */
 {
   int from;                    /* BOL position of the line.  */
   int to;                      /* BOL position of the next line.  */
-  int y0, y1;           /* Top and bottom Y position of the line.  */
+  int y0, y1;                  /* Top and bottom Y position of the line.  */
   int ascent;                  /* Height of the top Y position.  */
 };
 
   int ascent;                  /* Height of the top Y position.  */
 };
 
@@ -346,12 +353,8 @@ update_scroll_bar (int from, int to)
 {
   float top = (float) from / nchars;
   float shown = (float) (to - from) / nchars;
 {
   float top = (float) from / nchars;
   float shown = (float) (to - from) / nchars;
-  XtArgVal *l_top = (XtArgVal *) &top;
-  XtArgVal *l_shown = (XtArgVal *) &shown;
 
 
-  XtSetArg (arg[0], XtNtopOfThumb, *l_top);
-  XtSetArg (arg[1], XtNshown, *l_shown);
-  XtSetValues (SbarWidget, arg, 2);
+  XawScrollbarSetThumb (SbarWidget, top, shown);
 }
 
 
 }
 
 
@@ -385,12 +388,17 @@ redraw (int y0, int y1, int clear, int scroll_bar)
   info.metrics.height = line->y1 - y;
   info.metrics.y = - line->ascent;
   info.line_to = line->to;
   info.metrics.height = line->y1 - y;
   info.metrics.y = - line->ascent;
   info.line_to = line->to;
-  while (from < nchars && y + info.metrics.height <= y0)
+  while (y + info.metrics.height <= y0)
     {
       y += info.metrics.height;
       from = info.line_to;
     {
       y += info.metrics.height;
       from = info.line_to;
+      if (from >= nchars)
+       break;
       GLYPH_INFO (from, from, info);
     }
       GLYPH_INFO (from, from, info);
     }
+  if (y + info.metrics.height <= y0)
+    return;
+
   y0 = y - info.metrics.y;
   to = from;
   while (to < nchars && y < y1)
   y0 = y - info.metrics.y;
   to = from;
   while (to < nchars && y < y1)
@@ -490,13 +498,14 @@ redraw_cursor (int clear)
 
 /* Update the information about the location of cursor to the position
    $POS.  If $FULL is nonzero, update the information fully only from
 
 /* Update the information about the location of cursor to the position
    $POS.  If $FULL is nonzero, update the information fully only from
-   the information about the top line.  Otherwise, truct the current
+   the information about the top line.  Otherwise, trust the current
    information in the structure $CUR.  */
 void
 update_cursor (int pos, int full)
 {
   MDrawMetric rect;
 
    information in the structure $CUR.  */
 void
 update_cursor (int pos, int full)
 {
   MDrawMetric rect;
 
+  control.cursor_pos = pos;
   if (full)
     {
       /* CUR is inaccurate.  We can trust only TOP.  */
   if (full)
     {
       /* CUR is inaccurate.  We can trust only TOP.  */
@@ -655,53 +664,101 @@ static void MenuHelpProc (Widget, XEvent *, String *, Cardinal *);
 void
 select_input_method (idx)
 {
 void
 select_input_method (idx)
 {
+  int previous_input_method = current_input_method;
+
   if (idx == current_input_method)
     return;
   if (idx == current_input_method)
     return;
-  if (current_input_context)
+  if (current_input_method >= 0)
     {
       minput_destroy_ic (current_input_context);
       current_input_context = NULL;
       current_input_method = -1;
     }
     {
       minput_destroy_ic (current_input_context);
       current_input_context = NULL;
       current_input_method = -1;
     }
-  if (idx >= 0)
+
+  if (idx >= 0
+      && input_method_table[idx].available >= 0)
     {
       InputMethodInfo *im = input_method_table + idx;
 
     {
       InputMethodInfo *im = input_method_table + idx;
 
-      if (im->language == Mnil)
+      if (im->available == 0)
        {
        {
-         MInputXIMArgIC arg_xic;
-         Window win = XtWindow (TextWidget);
-
-         arg_xic.input_style = 0;
-         arg_xic.client_win = arg_xic.focus_win = win;
-         arg_xic.preedit_attrs =  arg_xic.status_attrs = NULL;
-         current_input_context = minput_create_ic (im->im, &arg_xic);
+         if (im->language)
+           im->im = minput_open_im (im->language, im->name, NULL);
+         else
+           {
+             MInputXIMArgIM arg_xim;
+
+             arg_xim.display = display;
+             arg_xim.db = NULL;  
+             arg_xim.res_name = arg_xim.res_class = NULL;
+             arg_xim.locale = NULL;
+             arg_xim.modifier_list = NULL;
+             im->im = minput_open_im (Mnil, im->name, &arg_xim);
+           }
+         im->available = im->im ? 1 : -1;
        }
        }
-      else
+      if (im->im)
        {
        {
-         MInputGUIArgIC arg_ic;
+         if (im->language == Mnil)
+           {
+             MInputXIMArgIC arg_xic;
+             Window win = XtWindow (TextWidget);
 
 
-         arg_ic.frame = frame;
-         arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
-         arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
-         current_input_context = minput_create_ic (im->im, &arg_ic);
-       }
+             arg_xic.input_style = 0;
+             arg_xic.client_win = arg_xic.focus_win = win;
+             arg_xic.preedit_attrs =  arg_xic.status_attrs = NULL;
+             current_input_context = minput_create_ic (im->im, &arg_xic);
+           }
+         else
+           {
+             MInputGUIArgIC arg_ic;
 
 
-      if (current_input_context)
-       {
-         set_input_method_spot ();
-         current_input_method = idx;
+             arg_ic.frame = frame;
+             arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
+             arg_ic.focus = (MDrawWindow) XtWindow (TextWidget);
+             current_input_context = minput_create_ic (im->im, &arg_ic);
+           }
+
+         if (current_input_context)
+           {
+             current_input_method = idx;
+             set_input_method_spot ();
+           }
+         else
+           {
+             minput_close_im (im->im);
+             im->im = NULL;
+             im->available = -1;
+             current_input_method = -1;
+           }
        }
     }
        }
     }
+  if (! auto_input_method)
+    {
+      XtSetArg (arg[0], XtNleftBitmap, None);
+      if (previous_input_method >= 0)
+       XtSetValues (InputMethodMenus[previous_input_method + 2], arg, 1);
+      else
+       XtSetValues (InputMethodMenus[0], arg, 1);
+      XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
+      if (current_input_method >= 0)
+       XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
+      else
+       XtSetValues (InputMethodMenus[0], arg, 1);
+    }
+
   if (current_input_method >= 0)
     {
       char *label;
   if (current_input_method >= 0)
     {
       char *label;
+
       XtSetArg (arg[0], XtNlabel, &label);
       XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
       XtSetArg (arg[0], XtNlabel, label);
     }
   else
       XtSetArg (arg[0], XtNlabel, &label);
       XtGetValues (InputMethodMenus[current_input_method + 2], arg, 1);
       XtSetArg (arg[0], XtNlabel, label);
     }
   else
-    XtSetArg (arg[0], XtNlabel, "");
+    {
+      XtSetArg (arg[0], XtNlabel, "");
+    }
   XtSetValues (CurIMLang, arg, 1);
 }
 
   XtSetValues (CurIMLang, arg, 1);
 }
 
@@ -795,14 +852,8 @@ show_cursor (XtPointer client_data)
 
   if (control.cursor_pos < nchars)
     {
 
   if (control.cursor_pos < nchars)
     {
-      MSymbol sym = Mnil;
+      MSymbol sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
 
 
-      if (control.cursor_pos > 0
-         && mtext_ref_char (mt, control.cursor_pos - 1) != '\n')
-       sym = mtext_get_prop (mt, control.cursor_pos - 1, Mlanguage);
-      if (sym == Mnil)
-       sym = mtext_get_prop (mt, control.cursor_pos, Mlanguage);
-    
       if (sym == Mnil)
        {
          XtSetArg (arg[0], XtNborderWidth, 0);
       if (sym == Mnil)
        {
          XtSetArg (arg[0], XtNborderWidth, 0);
@@ -811,8 +862,8 @@ show_cursor (XtPointer client_data)
       else
        {
          XtSetArg (arg[0], XtNborderWidth, 1);
       else
        {
          XtSetArg (arg[0], XtNborderWidth, 1);
-         XtSetArg (arg[1], XtNlabel,
-                   msymbol_name (msymbol_get (sym, Mlanguage)));
+         sym = mlanguage_name (sym);
+         XtSetArg (arg[1], XtNlabel, msymbol_name (sym));
          XtSetValues (CurLangWidget, arg, 2);
        }
       XtSetValues (CurLangWidget, arg, 2);
          XtSetValues (CurLangWidget, arg, 2);
        }
       XtSetValues (CurLangWidget, arg, 2);
@@ -826,24 +877,11 @@ show_cursor (XtPointer client_data)
              int i;
 
              for (i = 0; i < num_input_methods; i++)
              int i;
 
              for (i = 0; i < num_input_methods; i++)
-               if (input_method_table[i].language == sym)
+               if (input_method_table[i].language == sym
+                   && input_method_table[i].available >= 0)
                  break;
                  break;
-             if (i < num_input_methods
-                 && input_method_table[i].available >= 0)
-               {
-                 if (! input_method_table[i].im)
-                   {
-                     input_method_table[i].im = 
-                       minput_open_im (input_method_table[i].language,
-                                       input_method_table[i].name, NULL);
-                     if (! input_method_table[i].im)
-                       input_method_table[i].available = -1;
-                   }
-                 if (input_method_table[i].im)
-                   select_input_method (i);
-                 else
-                   select_input_method (-1);
-               }
+             if (i < num_input_methods)
+               select_input_method (i);
              else
                select_input_method (-1);
            }
              else
                select_input_method (-1);
            }
@@ -902,13 +940,16 @@ delete_char (int n)
 {
   MDrawMetric rect;
   MDrawGlyphInfo info;
 {
   MDrawMetric rect;
   MDrawGlyphInfo info;
-  int old_y1, new_y1;
+  int y0, old_y1, new_y1;
   int from, to;
   int from, to;
+  int line_from = cursor.line_from;
 
   if (n > 0)
     from = cursor.from, to = from + n;
   else
     {
 
   if (n > 0)
     from = cursor.from, to = from + n;
   else
     {
+      from = cursor.from + n;
+      to = cursor.from;
       if (cursor.from == cur.from)
        {
          /* We are at the beginning of line.  */
       if (cursor.from == cur.from)
        {
          /* We are at the beginning of line.  */
@@ -922,13 +963,6 @@ delete_char (int n)
              reseat (info.line_from);
            }
          update_cursor (pos, 1);
              reseat (info.line_from);
            }
          update_cursor (pos, 1);
-         from = cursor.from;
-         to = cursor.to;
-       }
-      else
-       {
-         from = cursor.from - 1;
-         to = cursor.from;
        }
     }
 
        }
     }
 
@@ -942,6 +976,10 @@ delete_char (int n)
     update_top (top.from);
   update_cursor (from, 1);
 
     update_top (top.from);
   update_cursor (from, 1);
 
+  y0 = cur.y0;
+  if (line_from != cursor.line_from)
+    y0 -= 1;
+
   TEXT_EXTENTS (cur.from, bol (to, 1), rect);
   new_y1 = cur.y0 + rect.height;
 
   TEXT_EXTENTS (cur.from, bol (to, 1), rect);
   new_y1 = cur.y0 + rect.height;
 
@@ -956,6 +994,7 @@ insert_chars (MText *newtext)
   int n = mtext_len (newtext);
   MDrawMetric rect;
   int y0, old_y1, new_y1;
   int n = mtext_len (newtext);
   MDrawMetric rect;
   int y0, old_y1, new_y1;
+  int line_from;
 
   if (SELECTEDP ())
     {
 
   if (SELECTEDP ())
     {
@@ -966,9 +1005,15 @@ insert_chars (MText *newtext)
     }
 
   y0 = cur.y0;
     }
 
   y0 = cur.y0;
+  if (cursor.line_from > 0
+      && mtext_ref_char (mt, cursor.line_from - 1) != '\n')
+    y0 -= control.min_line_descent;
+
   TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
   old_y1 = y0 + rect.height;
 
   TEXT_EXTENTS (cur.from, bol (cur.to - 1, 1), rect);
   old_y1 = y0 + rect.height;
 
+  line_from = cursor.line_from;
+
   /* Now insert chars.  */
   mtext_ins (mt, cursor.from, newtext);
   nchars += n;
   /* Now insert chars.  */
   mtext_ins (mt, cursor.from, newtext);
   nchars += n;
@@ -984,6 +1029,57 @@ insert_chars (MText *newtext)
 }
 
 
 }
 
 
+int
+word_constituent_p (int c)
+{
+  MSymbol category = (MSymbol) mchar_get_prop (c, Mcategory);
+  char *name = category != Mnil ? msymbol_name (category) : NULL;
+
+  return (name && (name[0] == 'L' || name[0] == 'M'));
+}
+
+
+void
+forward_word ()
+{
+  int pos = cursor.from;
+
+  while (pos < nchars && ! word_constituent_p (mtext_ref_char (mt, pos)))
+    pos++;
+  if (pos < nchars)
+    {
+      MTextProperty *prop = mtext_get_property (mt, pos, Mword);
+
+      if (prop)
+       pos = mtext_property_end (prop);
+      else
+       while (pos < nchars && word_constituent_p (mtext_ref_char (mt, pos)))
+         pos++;
+    }
+  update_cursor (pos, 0);
+}
+
+void
+backward_word ()
+{
+  int pos = cursor.from;
+
+  while (pos > 0 && ! word_constituent_p (mtext_ref_char (mt, pos - 1)))
+    pos--;
+  if (pos > 0)
+    {
+      MTextProperty *prop = mtext_get_property (mt, pos - 1, Mword);
+
+      if (prop)
+       pos = mtext_property_start (prop);
+      else
+       while (pos > 0 && word_constituent_p (mtext_ref_char (mt, pos - 1)))
+         pos--;
+    }
+  update_cursor (pos, 0);
+}
+
+
 /* Convert the currently selected text to UTF8-STRING or
    COMPOUND-TEXT.  It is called when someone requests the current
    value of the selection.  */
 /* Convert the currently selected text to UTF8-STRING or
    COMPOUND-TEXT.  It is called when someone requests the current
    value of the selection.  */
@@ -1128,18 +1224,12 @@ ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
       update_cursor (0, 1);
       redraw (0, win_height, 0, 1);
       if (current_input_method >= 0)
       update_cursor (0, 1);
       redraw (0, win_height, 0, 1);
       if (current_input_method >= 0)
-      {
-       int idx = current_input_method;
+       {
+         int idx = current_input_method;
 
 
-       current_input_method = -1;
-       input_method_table[idx].im = 
-         minput_open_im (input_method_table[idx].language,
-                           input_method_table[idx].name, NULL);
-       if (input_method_table[idx].im)
+         current_input_method = -1;
          select_input_method (idx);
          select_input_method (idx);
-       else
-         input_method_table[idx].available = -1;
-      }
+       }
       show_cursor (NULL);
     }
   else
       show_cursor (NULL);
     }
   else
@@ -1184,11 +1274,11 @@ ButtonProc (Widget w, XEvent *event, String *str, Cardinal *num)
       redraw (sel_start.y0, sel_end.y1, 1, 0);
     }
   hide_cursor ();
       redraw (sel_start.y0, sel_end.y1, 1, 0);
     }
   hide_cursor ();
-  if (current_input_context)
+  if (current_input_context
+      && minput_filter (current_input_context, Minput_focus_move, NULL) == 0)
     {
       MText *produced = mtext ();
 
     {
       MText *produced = mtext ();
 
-      minput_reset_ic (current_input_context);
       minput_lookup (current_input_context, Mnil, NULL, produced);
       if (mtext_len (produced) > 0)
        {
       minput_lookup (current_input_context, Mnil, NULL, produced);
       if (mtext_len (produced) > 0)
        {
@@ -1342,6 +1432,42 @@ ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
 }
 
 void
 }
 
 void
+FocusInProc (Widget w, XEvent *event, String *str, Cardinal *num)
+{
+  if (current_input_context
+      && minput_filter (current_input_context, Minput_focus_in, NULL) == 0)
+    {
+      MText *produced = mtext ();
+
+      minput_lookup (current_input_context, Mnil, NULL, produced);
+      if (mtext_len (produced) > 0)
+       {
+         hide_cursor ();
+         insert_chars (produced);
+       }
+      m17n_object_unref (produced);
+    }
+}
+
+void
+FocusOutProc (Widget w, XEvent *event, String *str, Cardinal *num)
+{
+  if (current_input_context
+      && minput_filter (current_input_context, Minput_focus_out, NULL) == 0)
+    {
+      MText *produced = mtext ();
+
+      minput_lookup (current_input_context, Mnil, NULL, produced);
+      if (mtext_len (produced) > 0)
+       {
+         hide_cursor ();
+         insert_chars (produced);
+       }
+      m17n_object_unref (produced);
+    }
+}
+
+void
 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
 {
   int from;
 ScrollProc (Widget w, XtPointer client_data, XtPointer position)
 {
   int from;
@@ -1422,6 +1548,7 @@ JumpProc (Widget w, XtPointer client_data, XtPointer persent_ptr)
   update_cursor (pos1, 1);
 }
 
   update_cursor (pos1, 1);
 }
 
+static void InputMethodProc (Widget, XtPointer, XtPointer);
 
 static void
 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
 
 static void
 KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
@@ -1433,15 +1560,26 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
   /* If set to 1, do not update target_x_position.  */
   int keep_target_x_position = 0;
   MText *produced;
   /* If set to 1, do not update target_x_position.  */
   int keep_target_x_position = 0;
   MText *produced;
+  int y0, old_y1, new_y1;
 
 
+  hide_cursor ();
+
+  mt_modified = 0;
+  y0 = cur.y0;
+  old_y1 = cur.y1;
   if (current_input_context
       && minput_filter (current_input_context, Mnil, event))
   if (current_input_context
       && minput_filter (current_input_context, Mnil, event))
-    return;
+    {
+      if (mt_modified)
+       {
+         new_y1 = cur.y1;
+         update_region (y0, old_y1, new_y1);
+       }
+      return;
+    }
   if (event->type == KeyRelease)
     return;
 
   if (event->type == KeyRelease)
     return;
 
-  hide_cursor ();
-
   produced = mtext ();
   ret = minput_lookup (current_input_context, Mnil, event, produced);
   if (mtext_len (produced) > 0)
   produced = mtext ();
   ret = minput_lookup (current_input_context, Mnil, event, produced);
   if (mtext_len (produced) > 0)
@@ -1450,6 +1588,12 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
     ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
   m17n_object_unref (produced);
 
     ret = XLookupString (key_event, buf, sizeof (buf), &keysym, NULL);
   m17n_object_unref (produced);
 
+  if (saved_input_method > -3)
+    {
+      InputMethodProc (w, (XtPointer) saved_input_method, NULL);
+      saved_input_method = -3;
+    }
+
   switch (keysym)
     {
     case XK_Delete:
   switch (keysym)
     {
     case XK_Delete:
@@ -1589,6 +1733,22 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
        ScrollProc (w, NULL, (XtPointer) -1);
       break;
 
        ScrollProc (w, NULL, (XtPointer) -1);
       break;
 
+    case XK_b:
+      if (key_event->state >= Mod1Mask)
+       {
+         lose_selection (NULL, NULL);
+         backward_word ();
+         break;
+       }
+
+    case XK_f:
+      if (key_event->state >= Mod1Mask)
+       {
+         lose_selection (NULL, NULL);
+         forward_word ();
+         break;
+       }
+
     default:
       if (ret > 0)
        {
     default:
       if (ret > 0)
        {
@@ -1602,6 +1762,14 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
              redraw (0, win_height, 1, 1);
              return;
            }
              redraw (0, win_height, 1, 1);
              return;
            }
+         else if (buf[0] == '='
+                  && (event->xkey.state & ControlMask)
+                  && unicode_input_method >= 0)
+           {
+             saved_input_method = current_input_method;
+             InputMethodProc (w, (XtPointer) unicode_input_method, NULL);
+             minput_filter (current_input_context, msymbol ("C-u"), NULL);
+           }
          else
            {
              MText *temp = mtext ();
          else
            {
              MText *temp = mtext ();
@@ -1735,8 +1903,6 @@ BidiProc (Widget w, XtPointer client_data, XtPointer call_data)
   redraw (0, win_height, 1, 0);
 }
 
   redraw (0, win_height, 1, 0);
 }
 
-extern int line_break (MText *mt, int pos, int from, int to, int line, int y);
-
 void
 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
 void
 LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
@@ -1748,7 +1914,7 @@ LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
   else
     {
       control.max_line_width = win_width;
   else
     {
       control.max_line_width = win_width;
-      control.line_break = (data == 1 ? NULL : line_break);
+      control.line_break = (data == 1 ? NULL : mdraw_default_line_break);
     }
   for (i = 0; i < 3; i++)
     {
     }
   for (i = 0; i < 3; i++)
     {
@@ -1764,6 +1930,25 @@ LineBreakProc (Widget w, XtPointer client_data, XtPointer call_data)
 }
 
 void
 }
 
 void
+FilterProc (Widget w, XtPointer client_data, XtPointer call_data)
+{
+  char *filter_module = (char *) client_data;
+  void *handle;
+  void (*func) (MText *, int, int);
+
+  if (! SELECTEDP ())
+    return;
+  handle = dlopen (filter_module, RTLD_NOW);
+  if (! handle)
+    return;
+  func = (void (*) (MText *, int, int)) dlsym (handle, "filter");
+  if (func)
+    (*func) (mt, mtext_property_start (selection),
+            mtext_property_end (selection));
+  dlclose (handle);
+}
+
+void
 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
   int data = (int) client_data;
 CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
   int data = (int) client_data;
@@ -1811,42 +1996,33 @@ InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
   int idx = (int) client_data;
 
 {
   int idx = (int) client_data;
 
-  if (idx == -2 ? current_input_method < 0
+  if (idx == -2 ? (! auto_input_method && current_input_method < 0)
       : idx == -1 ? auto_input_method
       : idx == current_input_method)
     return;
 
       : idx == -1 ? auto_input_method
       : idx == current_input_method)
     return;
 
-  XtSetArg (arg[0], XtNleftBitmap, None);
   if (auto_input_method)
     {
   if (auto_input_method)
     {
+      select_input_method (-1);
+      XtSetArg (arg[0], XtNleftBitmap, None);
       XtSetValues (InputMethodMenus[1], arg, 1);
       auto_input_method = 0;
     }
       XtSetValues (InputMethodMenus[1], arg, 1);
       auto_input_method = 0;
     }
-  else if (current_input_method < 0)
-    XtSetValues (InputMethodMenus[0], arg, 1);
-  else
-    XtSetValues (InputMethodMenus[current_input_method + 2], arg, 1);
 
   if (idx == -1)
     {
 
   if (idx == -1)
     {
+      select_input_method (-1);
+      XtSetArg (arg[0], XtNleftBitmap, None);
+      XtSetValues (InputMethodMenus[0], arg, 1);
+      XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
+      XtSetValues (InputMethodMenus[1], arg, 1);
       auto_input_method = 1;
       hide_cursor ();
     }
       auto_input_method = 1;
       hide_cursor ();
     }
-  else if (input_method_table[idx].available >= 0)
+  else
     {
     {
-      if (! input_method_table[idx].im)
-       {
-         input_method_table[idx].im = 
-           minput_open_im (input_method_table[idx].language,
-                           input_method_table[idx].name, NULL);
-         if (! input_method_table[idx].im)
-           input_method_table[idx].available = -1;
-       }
-      if (input_method_table[idx].im)
-       select_input_method (idx);
+      select_input_method (idx);
     }
     }
-  XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
-  XtSetValues (InputMethodMenus[idx + 2], arg, 1);
 }
 
 MPlist *default_face_list;
 }
 
 MPlist *default_face_list;
@@ -2014,6 +2190,59 @@ input_status (MInputContext *ic, MSymbol command)
   XtSetValues (CurIMStatus, arg, 1);
 }
 
   XtSetValues (CurIMStatus, arg, 1);
 }
 
+void
+surrounding_text_handler (MInputContext *ic, MSymbol command)
+{
+  if (command == Minput_get_surrounding_text)
+    {
+      int len = (int) mplist_value (ic->plist);
+      int pos;
+      MText *surround;
+
+      if (len < 0)
+       {
+         pos = cursor.from + len;
+         if (pos < 0)
+           pos = 0;
+         surround = mtext_duplicate (mt, pos, cursor.from);
+       }
+      else if (len > 0)
+       {
+         pos = cursor.from + len;
+         if (pos > nchars)
+           pos = nchars;
+         surround = mtext_duplicate (mt, cursor.from, pos);
+       }
+      else
+       surround = mtext ();
+      mplist_set (ic->plist, Mtext, surround);
+      m17n_object_unref (surround);
+    }
+  else if (command == Minput_delete_surrounding_text)
+    {
+      int len = (int) mplist_value (ic->plist);      
+
+      if (len < 0)
+       {
+         if (cursor.from + len < 0)
+           len = - cursor.from;
+         mtext_del (mt, cursor.from + len, cursor.from);
+         nchars += len;
+         update_cursor (cursor.from + len, 1);
+       }
+      else if (len > 0)
+       {
+         if (cursor.from + len > nchars)
+           len = nchars - cursor.from;
+         mtext_del (mt, cursor.from, cursor.from + len);
+         nchars -= len;
+         update_cursor (cursor.from, 1);
+       }
+      if (len)
+       mt_modified = 1;
+    }
+}
+
 int
 compare_input_method (const void *elt1, const void *elt2)
 {
 int
 compare_input_method (const void *elt1, const void *elt2)
 {
@@ -2029,90 +2258,91 @@ compare_input_method (const void *elt1, const void *elt2)
     return 1;
   if (im2->language == Mt)
     return -1;
     return 1;
   if (im2->language == Mt)
     return -1;
-  lang1 = msymbol_get (im1->language, Mlanguage);
-  lang2 = msymbol_get (im2->language, Mlanguage);
+  lang1 = mlanguage_name (im1->language);
+  lang2 = mlanguage_name (im2->language);
   return strcmp (msymbol_name (lang1), msymbol_name (lang2));
 }
 
 void
 setup_input_methods (int with_xim, char *initial_input_method)
 {
   return strcmp (msymbol_name (lang1), msymbol_name (lang2));
 }
 
 void
 setup_input_methods (int with_xim, char *initial_input_method)
 {
-  MInputMethod *im = NULL;
   MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
   MPlist *pl;
   MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
   MPlist *pl;
-  int i = 0;
-  char *lang_name = NULL, *method_name = NULL;
-
-  if (initial_input_method)
-    {
-      char *p = strchr (initial_input_method, '-');
-      if (p)
-       lang_name = initial_input_method, method_name = p + 1, *p = '\0';
-      else
-       method_name = initial_input_method;
-    }
-
-  num_input_methods = mplist_length (plist);
+  int i;
+  MSymbol Municode = msymbol ("unicode");
 
 
+  num_input_methods = plist ? mplist_length (plist) : 0;
   if (with_xim)
   if (with_xim)
+    num_input_methods++;
+  input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
+
+  i = 0;
+  if (plist)
     {
     {
-      MInputXIMArgIM arg_xim;
+      for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl), i++)
+       {
+         MDatabase *mdb = mplist_value (pl);
+         MSymbol *tag = mdatabase_tag (mdb);
 
 
-      arg_xim.display = display;
-      arg_xim.db = NULL;  
-      arg_xim.res_name = arg_xim.res_class = NULL;
-      arg_xim.locale = NULL;
-      arg_xim.modifier_list = NULL;
-      im = minput_open_im (Mnil, msymbol ("xim"), &arg_xim);
-      if (im)
-       num_input_methods++;
+         if (tag[2] == Mnil)
+           i--, num_input_methods--;
+         else
+           {
+             input_method_table[i].language = tag[1];
+             input_method_table[i].name = tag[2];
+           }
+       }
+      m17n_object_unref (plist);
     }
     }
-  input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
-  if (im)
+  if (with_xim)
     {
     {
-      input_method_table[i].available = 1;
       input_method_table[i].language = Mnil;
       input_method_table[i].language = Mnil;
-      input_method_table[i].name = im->name;
-      input_method_table[i].im = im;
+      input_method_table[i].name = msymbol ("xim");
       i++;
     }
 
       i++;
     }
 
-  for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
-    {
-      MDatabase *mdb = mplist_value (pl);
-      MSymbol *tag = mdatabase_tag (mdb);
-
-      if (tag[1] != Mnil)
-       {
-         input_method_table[i].language = tag[1];
-         input_method_table[i].name = tag[2];
-         i++;
-       }
-    }
-
-  m17n_object_unref (plist);
-  num_input_methods = i;
   qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
         compare_input_method);
   qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
         compare_input_method);
+  for (i = 0; i < num_input_methods; i++)
+    if (input_method_table[i].language == Mt
+       && input_method_table[i].name == Municode)
+      {
+       unicode_input_method = i;
+       break;
+      }
+  mplist_put_func (minput_driver->callback_list, Minput_status_start,
+                  M17N_FUNC (input_status));
+  mplist_put_func (minput_driver->callback_list, Minput_status_draw,
+                  M17N_FUNC (input_status));
+  mplist_put_func (minput_driver->callback_list, Minput_status_done,
+                  M17N_FUNC (input_status));
+  mplist_put_func (minput_driver->callback_list, Minput_get_surrounding_text,
+                  M17N_FUNC (surrounding_text_handler));
+  mplist_put_func (minput_driver->callback_list, Minput_delete_surrounding_text,
+                  M17N_FUNC (surrounding_text_handler));
+
   current_input_context = NULL;
   current_input_context = NULL;
+  current_input_method = -1;
 
 
-  mplist_put (minput_driver->callback_list, Minput_status_start,
-             (void *) input_status);
-  mplist_put (minput_driver->callback_list, Minput_status_draw,
-             (void *) input_status);
-  mplist_put (minput_driver->callback_list, Minput_status_done,
-             (void *) input_status);
+  if (initial_input_method)
+    {
+      char *lang_name, *method_name;
+      char *p = strchr (initial_input_method, '-');
 
 
-  if (method_name)
-    for (i = 0; i < num_input_methods; i++)
-      if (strcmp (method_name, msymbol_name (input_method_table[i].name)) == 0
-         && (lang_name
-             ? strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0
-             : input_method_table[i].language == Mt))
-       {
-         current_input_method = i;
-         break;
-       }
+      if (p && p[1])
+       lang_name = initial_input_method, *p = '\0', method_name = p + 1;
+      else
+       lang_name = "t", method_name = initial_input_method;
+
+      for (i = 0; i < num_input_methods; i++)
+       if ((strcmp (method_name, msymbol_name (input_method_table[i].name))
+            == 0)
+           && (strcmp (lang_name, msymbol_name (input_method_table[i].language)) == 0))
+         {
+           current_input_method = i;
+           break;
+         }
+    }
 }
 
 
 }
 
 
@@ -2295,7 +2525,8 @@ create_menu_button (Widget top, Widget parent, Widget left, char *button_name,
   XtSetArg (arg[3], XtNhighlightThickness, 1);
   XtSetArg (arg[4], XtNleft, XawChainLeft);
   XtSetArg (arg[5], XtNright, XawChainLeft);
   XtSetArg (arg[3], XtNhighlightThickness, 1);
   XtSetArg (arg[4], XtNleft, XawChainLeft);
   XtSetArg (arg[5], XtNright, XawChainLeft);
-  i = 6;
+  XtSetArg (arg[6], XtNinternational, True);
+  i = 7;
   if (left)
     XtSetArg (arg[i], XtNfromHoriz, left), i++;
   button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
   if (left)
     XtSetArg (arg[i], XtNfromHoriz, left), i++;
   button = XtCreateManagedWidget (button_name, menuButtonWidgetClass, parent,
@@ -2353,7 +2584,9 @@ XtActionsRec actions[] = {
   {"ButtonRelease", ButtonReleaseProc},
   {"ButtonMotion", ButtonMoveProc},
   {"Button2Press", Button2Proc},
   {"ButtonRelease", ButtonReleaseProc},
   {"ButtonMotion", ButtonMoveProc},
   {"Button2Press", Button2Proc},
-  {"MenuHelp", MenuHelpProc}
+  {"MenuHelp", MenuHelpProc},
+  {"FocusIn", FocusInProc},
+  {"FocusOut", FocusOutProc}
 };
 
 
 };
 
 
@@ -2389,6 +2622,7 @@ main (int argc, char **argv)
 {
   Widget form, BodyWidget, w;
   char *fontset_name = NULL;
 {
   Widget form, BodyWidget, w;
   char *fontset_name = NULL;
+  char *font_name = NULL;
   int fontsize = 0;
   char *initial_input_method = NULL;
   int col = 80, row = 32;
   int fontsize = 0;
   char *initial_input_method = NULL;
   int col = 80, row = 32;
@@ -2403,7 +2637,9 @@ main (int argc, char **argv)
                  <Btn2Down>: Button2Press()";
   /* Translation table for the top form widget.  */
   String trans2 = "<Key>: Key()\n\
                  <Btn2Down>: Button2Press()";
   /* Translation table for the top form widget.  */
   String trans2 = "<Key>: Key()\n\
-                  <KeyUp>: Key()";
+                  <KeyUp>: Key()\n\
+                  <FocusIn>: FocusIn()\n\
+                  <FocusOut>: FocusOut()";
   String pop_face_trans
     = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
        <LeaveWindow>: MenuHelp() reset()\n\
   String pop_face_trans
     = "<EnterWindow>: MenuHelp(Pop face property) highlight()\n\
        <LeaveWindow>: MenuHelp() reset()\n\
@@ -2417,11 +2653,13 @@ main (int argc, char **argv)
   int font_width, font_ascent, font_descent;
   int with_xim = 0;
   int i, j;
   int font_width, font_ascent, font_descent;
   int with_xim = 0;
   int i, j;
+  char *filter = NULL;
+  MFont *font = NULL;
 
   setlocale (LC_ALL, "");
   /* Create the top shell.  */
   XtSetLanguageProc (NULL, NULL, NULL);
 
   setlocale (LC_ALL, "");
   /* Create the top shell.  */
   XtSetLanguageProc (NULL, NULL, NULL);
-  ShellWidget = XtOpenApplication (&context, "MEdit", NULL, 0, &argc, argv,
+  ShellWidget = XtOpenApplication (&context, "M17NEdit", NULL, 0, &argc, argv,
                                   NULL, sessionShellWidgetClass, NULL, 0);
   display = XtDisplay (ShellWidget);
   screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
                                   NULL, sessionShellWidgetClass, NULL, 0);
   display = XtDisplay (ShellWidget);
   screen = XScreenNumberOfScreen (XtScreen (ShellWidget));
@@ -2434,8 +2672,8 @@ main (int argc, char **argv)
        help_exit (argv[0], 0);
       else if (! strcmp (argv[i], "--version"))
        {
        help_exit (argv[0], 0);
       else if (! strcmp (argv[i], "--version"))
        {
-         printf ("medit (m17n library) %s\n", VERSION);
-         printf ("Copyright (C) 2003 AIST, JAPAN\n");
+         printf ("m17n-edit (m17n library) %s\n", M17NLIB_VERSION_NAME);
+         printf ("Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 AIST, JAPAN\n");
          exit (0);
        }
       else if (! strcmp (argv[i], "--geometry"))
          exit (0);
        }
       else if (! strcmp (argv[i], "--geometry"))
@@ -2456,6 +2694,11 @@ main (int argc, char **argv)
          i++;
          fontset_name = strdup (argv[i]);
        }
          i++;
          fontset_name = strdup (argv[i]);
        }
+      else if (! strcmp (argv[i], "--font"))
+       {
+         i++;
+         font_name = strdup (argv[i]);
+       }
       else if (! strcmp (argv[i], "--im"))
        {
          i++;
       else if (! strcmp (argv[i], "--im"))
        {
          i++;
@@ -2465,6 +2708,11 @@ main (int argc, char **argv)
        {
          with_xim = 1;
        }
        {
          with_xim = 1;
        }
+      else if (! strcmp (argv[i], "--filter"))
+       {
+         i++;
+         filter = argv[i];
+       }
       else if (argv[i][0] != '-')
        {
          filename = strdup (argv[i]);
       else if (argv[i][0] != '-')
        {
          filename = strdup (argv[i]);
@@ -2483,12 +2731,15 @@ main (int argc, char **argv)
   M17N_INIT ();
   if (merror_code != MERROR_NONE)
     FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
   M17N_INIT ();
   if (merror_code != MERROR_NONE)
     FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
+  minput_driver = &minput_gui_driver;
 
   mt = read_file (filename);
   serialized = 0;
 
   nchars = mtext_len (mt);
 
 
   mt = read_file (filename);
   serialized = 0;
 
   nchars = mtext_len (mt);
 
+  Mword = msymbol ("word");
+
   {
     MFace *face = mface ();
 
   {
     MFace *face = mface ();
 
@@ -2511,18 +2762,32 @@ main (int argc, char **argv)
 
   {
     MPlist *plist = mplist ();
 
   {
     MPlist *plist = mplist ();
-    MFace *face;
     MFont *font;
 
     mplist_put (plist, msymbol ("widget"), ShellWidget);
     MFont *font;
 
     mplist_put (plist, msymbol ("widget"), ShellWidget);
-    if (fontset_name || fontsize > 0)
+    if (fontset_name || font_name || fontsize > 0)
       {
       {
-       MFontset *fontset = mfontset (fontset_name);
-       
-       face = mface ();
-       mface_put_prop (face, Mfontset, fontset);
-       mface_put_prop (face, Msize, (void *) fontsize);
-       m17n_object_unref (fontset);
+       MFace *face;
+
+       if (font_name)
+         {
+           font = mfont_parse_name (font_name, Mnil);
+           if (font)
+             face = mface_from_font (font);
+           else
+             face = mface ();
+         }
+       else
+         face = mface ();
+       if (fontset_name)
+         {
+           MFontset *fontset = mfontset (fontset_name);
+
+           mface_put_prop (face, Mfontset, fontset);
+           m17n_object_unref (fontset);
+         }
+       if (fontsize > 0)
+         mface_put_prop (face, Msize, (void *) fontsize);
        mplist_add (plist, Mface, face);
        m17n_object_unref (face);
       }
        mplist_add (plist, Mface, face);
        m17n_object_unref (face);
       }
@@ -2582,7 +2847,7 @@ main (int argc, char **argv)
     MFont *dev_font = mfont ();
     MFont *thai_font = mfont ();
     MFont *tib_font = mfont ();
     MFont *dev_font = mfont ();
     MFont *thai_font = mfont ();
     MFont *tib_font = mfont ();
-    MFontset *fontset;
+    MFontset *fontset, *fontset_no_ctl;
     MSymbol unicode_bmp = msymbol ("unicode-bmp");
     MSymbol no_ctl = msymbol ("no-ctl");
 
     MSymbol unicode_bmp = msymbol ("unicode-bmp");
     MSymbol no_ctl = msymbol ("no-ctl");
 
@@ -2593,18 +2858,20 @@ main (int argc, char **argv)
     mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
     mfont_put_prop (tib_font, Mregistry, unicode_bmp);
 
     mfont_put_prop (tib_font, Mfamily, msymbol ("mtib"));
     mfont_put_prop (tib_font, Mregistry, unicode_bmp);
 
-    fontset = mfontset_copy (mfontset (fontset_name), "no-ctl");
-    mfontset_modify_entry (fontset, msymbol ("latin"), Mnil, Mnil,
+    fontset = mfontset (fontset_name);
+    fontset_no_ctl = mfontset_copy (fontset, "no-ctl");
+    m17n_object_unref (fontset);
+    mfontset_modify_entry (fontset_no_ctl, msymbol ("latin"), Mnil, Mnil,
                           latin_font, Mnil, 0);
                           latin_font, Mnil, 0);
-    mfontset_modify_entry (fontset, msymbol ("devanagari"), Mnil, Mnil,
+    mfontset_modify_entry (fontset_no_ctl, msymbol ("devanagari"), Mnil, Mnil,
                           dev_font, no_ctl, 0);
                           dev_font, no_ctl, 0);
-    mfontset_modify_entry (fontset, msymbol ("thai"), Mnil, Mnil,
+    mfontset_modify_entry (fontset_no_ctl, msymbol ("thai"), Mnil, Mnil,
                           thai_font, no_ctl, 0);
                           thai_font, no_ctl, 0);
-    mfontset_modify_entry (fontset, msymbol ("tibetan"), Mnil, Mnil,
+    mfontset_modify_entry (fontset_no_ctl, msymbol ("tibetan"), Mnil, Mnil,
                           tib_font, no_ctl, 0);
     face_no_ctl_fontset = mface ();
                           tib_font, no_ctl, 0);
     face_no_ctl_fontset = mface ();
-    mface_put_prop (face_no_ctl_fontset, Mfontset, fontset);
-    m17n_object_unref (fontset);
+    mface_put_prop (face_no_ctl_fontset, Mfontset, fontset_no_ctl);
+    m17n_object_unref (fontset_no_ctl);
 
     free (dev_font);
     free (thai_font);
 
     free (dev_font);
     free (thai_font);
@@ -2716,7 +2983,7 @@ main (int argc, char **argv)
 
        if (im->language != Mnil && im->language != Mt)
          {
 
        if (im->language != Mnil && im->language != Mt)
          {
-           MSymbol sym = msymbol_get (im->language, Mlanguage);
+           MSymbol sym = mlanguage_name (im->language);
            if (sym == Mnil)
              name1 = msymbol_name (im->language);
            else
            if (sym == Mnil)
              name1 = msymbol_name (im->language);
            else
@@ -2746,6 +3013,14 @@ main (int argc, char **argv)
     for (i = 0; i < num_input_methods + 2; i++)
       InputMethodMenus[i] = menus[i].w;
 
     for (i = 0; i < num_input_methods + 2; i++)
       InputMethodMenus[i] = menus[i].w;
 
+    if (filter)
+      {
+       SetMenu (menus[0], 0, filter, NULL, FilterProc, filter, 0);
+       w = create_menu_button (ShellWidget, HeadWidget, w, "Filter",
+                               "Filter Menu", menus, 1,
+                               "Select filter to run");
+      }
+
     input_status_width = font_width * 8;
     input_status_height = (font_ascent + font_descent) * 2.4;
     input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
     input_status_width = font_width * 8;
     input_status_height = (font_ascent + font_descent) * 2.4;
     input_status_pixmap = XCreatePixmap (display, RootWindow (display, screen),
@@ -2835,14 +3110,14 @@ main (int argc, char **argv)
            MSymbol fullname;
 
            if (sym != Mnil
            MSymbol fullname;
 
            if (sym != Mnil
-               && ((fullname = msymbol_get (sym, Mlanguage)) != Mnil))
+               && ((fullname = mlanguage_name (sym)) != Mnil))
              {
                char *name = msymbol_name (fullname);
                char c = name[0];
 
              {
                char *name = msymbol_name (fullname);
                char c = name[0];
 
-               if (c >= 'A' && c <= 'Z')
+               if (c >= 'a' && c <= 'z')
                  {
                  {
-                   int idx = (c < 'U') ? (c - 'A') / 2 : 10;
+                   int idx = (c < 'u') ? (c - 'a') / 2 : 10;
 
                    pl = plist[idx];
                    if (! pl)
 
                    pl = plist[idx];
                    if (! pl)
@@ -2966,6 +3241,8 @@ main (int argc, char **argv)
   m17n_object_unref (face_default);
   m17n_object_unref (default_face_list);
   m17n_object_unref (selection);
   m17n_object_unref (face_default);
   m17n_object_unref (default_face_list);
   m17n_object_unref (selection);
+  if (font)
+    free (font);
 
   XFreeGC (display, mono_gc);
   XFreeGC (display, mono_gc_inv);
 
   XFreeGC (display, mono_gc);
   XFreeGC (display, mono_gc_inv);
@@ -2977,6 +3254,7 @@ main (int argc, char **argv)
 
   M17N_FINI ();
 
 
   M17N_FINI ();
 
+  free (font_name);
   free (fontset_name);
   free (filename);
   free (input_method_table);
   free (fontset_name);
   free (filename);
   free (input_method_table);
@@ -2984,4 +3262,17 @@ main (int argc, char **argv)
 
   exit (0);
 }
 
   exit (0);
 }
+
+#else  /* not HAVE_X11_XAW_COMMAND_H */
+
+int
+main (int argc, char **argv)
+{
+  fprintf (stderr,
+          "Building of this program failed (lack of some header files)\n");
+  exit (1);
+}
+
+#endif /* not HAVE_X11_XAW_COMMAND_H */
+
 #endif /* not FOR_DOXYGEN */
 #endif /* not FOR_DOXYGEN */