(AM_CPPFLAGS): Set it to @CONFIG_FLAGS@.
[m17n/m17n-lib.git] / example / medit.c
index cacfbcf..63701ca 100644 (file)
@@ -1,4 +1,4 @@
-/* medit.c -- simple multilingual editor.
+/* medit.c -- simple multilingual editor.              -*- coding: euc-jp; -*-
    Copyright (C) 2003, 2004
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
    Copyright (C) 2003, 2004
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
    02111-1307, USA.  */
 
 /***en
    02111-1307, USA.  */
 
 /***en
-    @page 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 Outout Method), not
+    for direct use from application programs.
+*/
+/***ja
+    @japage m17n-edit Â¿¸À¸ì¥Æ¥­¥¹¥È¤ÎÊÔ½¸
+
+    @section m17n-edit-synopsis SYNOPSIS
+
+    m17n-edit [ XT-OPTION ...] [ OPTION ... ] FILE
+
+    @section m17n-edit-description DESCRIPTION
+
+    FILE ¤ò¥¦¥£¥ó¥É¥¦¤Ëɽ¼¨¤·¡¢¥æ¡¼¥¶¤¬ÊÔ½¸¤Ç¤­¤ë¤è¤¦¤Ë¤¹¤ë¡£
+
+    XT-OPTIONs ¤Ï Xt ¤Îɸ½à¤Î°ú¿ô¤Ç¤¢¤ë¡£ (e.g. -fn, -fg). 
+
+    °Ê²¼¤Î¥ª¥×¥·¥ç¥ó¤¬ÍøÍѤǤ­¤ë¡£ 
+
+    <ul>
+
+    <li> --version
+
+    ¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤òɽ¼¨¤¹¤ë¡£ 
+
+    <li> -h, --help
+
+    ¤³¤Î¥á¥Ã¥»¡¼¥¸¤òɽ¼¨¤¹¤ë¡£ 
+
+    </ul>
+
+    ¤³¤Î¥×¥í¥°¥é¥à¤Ï m17n GUI API ¤Î»È¤¤Êý¤ò¼¨¤¹¤â¤Î¤Ç¤¢¤ë¡£m17n-edit
+    ¤ÏľÀÜ GUI API ¤ò»È¤Ã¤Æ¤¤¤ë¤¬¡¢¤³¤Î API ¤Ï¼ç¤Ë¥Ä¡¼¥ë¥­¥Ã¥È¥é¥¤¥Ö¥é
+    ¥ê¤äXOM (X Outout 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>
 
 #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 <config.h>
+
+#ifdef HAVE_X11_XAW_COMMAND_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.0"
+#define VERSION "1.2.0"
 
 /* Global variables.  */
 
 
 /* Global variables.  */
 
@@ -140,17 +178,28 @@ int nchars;                       /* == mtext_len (mt) */
 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_courier, *face_helvetica, *face_times;
 MFace *face_default;
 MFace *face_xxx_large;
 MFace *face_box;
 MFace *face_courier, *face_helvetica, *face_times;
-MFace *face_dv_ttyogesh, *face_freesans, *face_freemono;
+MFace *face_dv_ttyogesh, *face_freesans, *face_freeserif, *face_freemono;
 MFace *face_default_fontset, *face_no_ctl_fontset;
 MFace *face_input_status;
 
 MFace *face_default_fontset, *face_no_ctl_fontset;
 MFace *face_input_status;
 
+MSymbol Mcoding_compound_text;
+
 int logical_move = 1;          /* If 0, move cursor visually.  */
 
 int logical_move = 1;          /* If 0, move cursor visually.  */
 
-MInputMethod **input_method_table;
+typedef struct {
+  int available;
+  MSymbol language, name;
+  MInputMethod *im;
+} InputMethodInfo;
+
+InputMethodInfo *input_method_table;
+
 int num_input_methods;
 int current_input_method = -1; /* i.e. none */
 int auto_input_method = 0;
 int num_input_methods;
 int current_input_method = -1; /* i.e. none */
 int auto_input_method = 0;
@@ -177,6 +226,7 @@ struct FaceRec
     {"times", &face_times},
     {"dv-ttyogesh", &face_dv_ttyogesh},
     {"freesans", &face_freesans},
     {"times", &face_times},
     {"dv-ttyogesh", &face_dv_ttyogesh},
     {"freesans", &face_freesans},
+    {"freeserif", &face_freeserif},
     {"freemono", &face_freemono},
 
     {"Menu Style", NULL},
     {"freemono", &face_freemono},
 
     {"Menu Style", NULL},
@@ -292,8 +342,8 @@ update_top (int pos)
   top.from = info.line_from;
   top.to = info.line_to;
   top.y0 = 0;
   top.from = info.line_from;
   top.to = info.line_to;
   top.y0 = 0;
-  top.y1 = info.this.height;
-  top.ascent = - info.this.y;
+  top.y1 = info.metrics.height;
+  top.ascent = - info.metrics.y;
 }
 
 
 }
 
 
@@ -325,11 +375,11 @@ redraw (int y0, int y1, int clear, int scroll_bar)
   int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
   struct LineInfo *line;
   
   int sel_y0 = SELECTEDP () ? sel_start.y0 : 0;
   struct LineInfo *line;
   
-  if (clear)
+  if (clear || control.anti_alias)
     CLEAR_AREA (0, y0, win_width, y1 - y0);
 
     CLEAR_AREA (0, y0, win_width, y1 - y0);
 
-  /* Find a line closest to y0.  The lihe is a cursor line if the
-     cursor is at the position above Y0, otherwise the top line.  */
+  /* Find a line closest to y0.  It is a cursor line if the cursor is
+     Y0, otherwise the top line.  */
   if (y0 >= cur.y0)
     line = &cur;
   else
   if (y0 >= cur.y0)
     line = &cur;
   else
@@ -340,21 +390,21 @@ redraw (int y0, int y1, int clear, int scroll_bar)
 
   from = line->from;
   y = line->y0;
 
   from = line->from;
   y = line->y0;
-  info.this.height = line->y1 - y;
-  info.this.y = - line->ascent;
+  info.metrics.height = line->y1 - y;
+  info.metrics.y = - line->ascent;
   info.line_to = line->to;
   info.line_to = line->to;
-  while (from < nchars && y + info.this.height <= y0)
+  while (from < nchars && y + info.metrics.height <= y0)
     {
     {
-      y += info.this.height;
+      y += info.metrics.height;
       from = info.line_to;
       GLYPH_INFO (from, from, info);
     }
       from = info.line_to;
       GLYPH_INFO (from, from, info);
     }
-  y0 = y - info.this.y;
+  y0 = y - info.metrics.y;
   to = from;
   while (to < nchars && y < y1)
     {
       GLYPH_INFO (to, to, info);
   to = from;
   while (to < nchars && y < y1)
     {
       GLYPH_INFO (to, to, info);
-      y += info.this.height;
+      y += info.metrics.height;
       to = info.line_to;
     }
   if (to == nchars)
       to = info.line_to;
     }
   if (to == nchars)
@@ -366,10 +416,10 @@ redraw (int y0, int y1, int clear, int scroll_bar)
       while (to < nchars)
        {
          GLYPH_INFO (to, to, info);
       while (to < nchars)
        {
          GLYPH_INFO (to, to, info);
-         if (y + info.this.height >= win_height)
+         if (y + info.metrics.height >= win_height)
            break;
          to = info.line_to;
            break;
          to = info.line_to;
-         y += info.this.height;
+         y += info.metrics.height;
        }
       update_scroll_bar (top.from, to);
     }
        }
       update_scroll_bar (top.from, to);
     }
@@ -383,16 +433,19 @@ set_input_method_spot ()
   int x = cursor.x + (control.orientation_reversed ? win_width : 0);
   int pos = cursor.from > 0 ? cursor.from - 1 : 0;
   MFace *faces[256];
   int x = cursor.x + (control.orientation_reversed ? win_width : 0);
   int pos = cursor.from > 0 ? cursor.from - 1 : 0;
   MFace *faces[256];
-  int n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
+  int n = 0;
   int size = 0, ratio = 0, i;
 
   int size = 0, ratio = 0, i;
 
-  for (i = n - 1; i >= 0; i--)
-    {
-      if (! size)
-       size = (int) mface_get_prop (faces[i], Msize);
-      if (! ratio)
-       ratio = (int) mface_get_prop (faces[i], Mratio);
-    }
+  if (nchars > 0)
+    n = mtext_get_prop_values (mt, pos, Mface, (void **) faces, 256);
+  if (n > 0)
+    for (i = n - 1; i >= 0; i--)
+      {
+       if (! size)
+         size = (int) mface_get_prop (faces[i], Msize);
+       if (! ratio)
+         ratio = (int) mface_get_prop (faces[i], Mratio);
+      }
   if (! size)
     size = default_font_size;
   if (ratio)
   if (! size)
     size = default_font_size;
   if (ratio)
@@ -416,12 +469,12 @@ redraw_cursor (int clear)
       MDrawMetric rect;
       int y0 = cur.y0, y1 = cur.y1;
 
       MDrawMetric rect;
       int y0 = cur.y0, y1 = cur.y1;
 
-      if (beg != cur.from)
+      if (beg < cur.from)
        {
          TEXT_EXTENTS (beg, cur.from, rect);
          y0 -= rect.height;
        }
        {
          TEXT_EXTENTS (beg, cur.from, rect);
          y0 -= rect.height;
        }
-      if (end != cur.to)
+      if (end > cur.to)
        {
          TEXT_EXTENTS (cur.to, end, rect);
          y1 += rect.height; 
        {
          TEXT_EXTENTS (cur.to, end, rect);
          y1 += rect.height; 
@@ -435,8 +488,8 @@ redraw_cursor (int clear)
          int x = cursor.x;
 
          if (control.orientation_reversed)
          int x = cursor.x;
 
          if (control.orientation_reversed)
-           x += win_width - cursor.this.width;
-         CLEAR_AREA (x, cur.y0, cursor.this.width, cursor.this.height);
+           x += win_width - cursor.logical_width;
+         CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height);
        }
       DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
     }
        }
       DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
     }
@@ -445,7 +498,7 @@ 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)
    information in the structure $CUR.  */
 void
 update_cursor (int pos, int full)
@@ -456,7 +509,7 @@ update_cursor (int pos, int full)
     {
       /* CUR is inaccurate.  We can trust only TOP.  */
       GLYPH_INFO (top.from, pos, cursor);
     {
       /* CUR is inaccurate.  We can trust only TOP.  */
       GLYPH_INFO (top.from, pos, cursor);
-      cur.y0 = top.ascent + cursor.y + cursor.this.y;
+      cur.y0 = top.ascent + cursor.y + cursor.metrics.y;
     }
   else if (pos < cur.from)
     {
     }
   else if (pos < cur.from)
     {
@@ -464,7 +517,7 @@ update_cursor (int pos, int full)
 
       TEXT_EXTENTS (from, cur.from, rect);
       GLYPH_INFO (from, pos, cursor);
 
       TEXT_EXTENTS (from, cur.from, rect);
       GLYPH_INFO (from, pos, cursor);
-      cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.this.y);
+      cur.y0 -= (rect.height + rect.y) - (cursor.y + cursor.metrics.y);
     }
   else if (pos < cur.to)
     {
     }
   else if (pos < cur.to)
     {
@@ -473,13 +526,13 @@ update_cursor (int pos, int full)
   else
     {
       GLYPH_INFO (cur.from, pos, cursor);
   else
     {
       GLYPH_INFO (cur.from, pos, cursor);
-      cur.y0 += cur.ascent + cursor.y + cursor.this.y;
+      cur.y0 += cur.ascent + cursor.y + cursor.metrics.y;
     }
 
   cur.from = cursor.line_from;
   cur.to = cursor.line_to;
     }
 
   cur.from = cursor.line_from;
   cur.to = cursor.line_to;
-  cur.y1 = cur.y0 + cursor.this.height;
-  cur.ascent = - cursor.this.y;
+  cur.y1 = cur.y0 + cursor.metrics.height;
+  cur.ascent = - cursor.metrics.y;
 }
 
 
 }
 
 
@@ -498,42 +551,35 @@ update_selection ()
 
   if (from < top.from)
     {
 
   if (from < top.from)
     {
-      GLYPH_INFO (bol (from, 0), from, info);
-      sel_start.ascent = -info.this.y;
-      sel_start.from = info.line_from;
-      sel_start.to = info.line_to;
-      TEXT_EXTENTS (from, top.from, rect);      
-      sel_start.y0 = - rect.height;
-      sel_start.y1 = sel_start.y0 + info.this.height;
+      int pos = bol (from, 0);
+
+      TEXT_EXTENTS (pos, top.from, rect);
+      sel_start.y0 = top.y0 - rect.height;
+      sel_start.ascent = - rect.y;
+      GLYPH_INFO (pos, from, info);
+      if (pos < info.line_from)
+       sel_start.y0 += - rect.y + info.y + info.metrics.y;
     }
   else
     {
       GLYPH_INFO (top.from, from, info);
     }
   else
     {
       GLYPH_INFO (top.from, from, info);
-      sel_start.y0 = top.ascent + info.y + info.this.y;
-      sel_start.y1 = sel_start.y0 + info.this.height;
-      sel_start.ascent = -info.this.y;
-      sel_start.from = info.line_from;
-      sel_start.to = info.line_to;
+      sel_start.y0 = top.ascent + info.y + info.metrics.y;
     }
     }
+  sel_start.ascent = -info.metrics.y;
+  sel_start.y1 = sel_start.y0 + info.metrics.height;
+  sel_start.from = info.line_from;
+  sel_start.to = info.line_to;
 
   if (to <= sel_start.to)
     {
       sel_end = sel_start;
 
   if (to <= sel_start.to)
     {
       sel_end = sel_start;
-      to = bol (to - 1, 1) - 1;
-      if (to >= sel_end.to)
-       {
-         GLYPH_INFO (sel_start.from, to, info);
-         sel_end.y1 = sel_end.y0 + info.y + info.this.height;
-         sel_end.to = info.line_to;
-       }
     }
   else
     {
     }
   else
     {
-      to = bol (to - 1, 1) - 1;
       GLYPH_INFO (sel_start.from, to, info);
       GLYPH_INFO (sel_start.from, to, info);
-      sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.this.y;
-      sel_end.y1 = sel_end.y0 + info.this.height;
-      sel_end.ascent = - info.this.y;
+      sel_end.y0 = sel_start.y0 + sel_start.ascent + info.y + info.metrics.y;
+      sel_end.y1 = sel_end.y0 + info.metrics.height;
+      sel_end.ascent = - info.metrics.y;
       sel_end.from = info.line_from;
       sel_end.to = info.line_to;
     }
       sel_end.from = info.line_from;
       sel_end.to = info.line_to;
     }
@@ -627,7 +673,7 @@ select_input_method (idx)
     }
   if (idx >= 0)
     {
     }
   if (idx >= 0)
     {
-      MInputMethod *im = input_method_table[idx];
+      InputMethodInfo *im = input_method_table + idx;
 
       if (im->language == Mnil)
        {
 
       if (im->language == Mnil)
        {
@@ -637,7 +683,7 @@ select_input_method (idx)
          arg_xic.input_style = 0;
          arg_xic.client_win = arg_xic.focus_win = win;
          arg_xic.preedit_attrs =  arg_xic.status_attrs = NULL;
          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, &arg_xic);
+         current_input_context = minput_create_ic (im->im, &arg_xic);
        }
       else
        {
        }
       else
        {
@@ -646,7 +692,7 @@ select_input_method (idx)
          arg_ic.frame = frame;
          arg_ic.client = (MDrawWindow) XtWindow (ShellWidget);
          arg_ic.focus = (MDrawWindow) 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, &arg_ic);
+         current_input_context = minput_create_ic (im->im, &arg_ic);
        }
 
       if (current_input_context)
        }
 
       if (current_input_context)
@@ -677,6 +723,9 @@ static void MenuHelpProc (Widget w, XEvent *event, String *str, Cardinal *num);
 Boolean
 show_cursor (XtPointer client_data)
 {
 Boolean
 show_cursor (XtPointer client_data)
 {
+  MFaceHLineProp *hline;
+  MFaceBoxProp *box;
+
   if (cur.y0 < 0)
     {
       reseat (cur.from);
   if (cur.y0 < 0)
     {
       reseat (cur.from);
@@ -697,68 +746,65 @@ show_cursor (XtPointer client_data)
   if (current_input_context)
     set_input_method_spot ();
 
   if (current_input_context)
     set_input_method_spot ();
 
-  {
-    int pos = (SELECTEDP () ? mtext_property_start (selection)
-              : cursor.from > 0 ? cursor.from - 1
-              : cursor.from);
-    MFace *face = mface ();
-    MTextProperty *props[256];
-    int n = mtext_get_properties (mt, pos, Mface, props, 256);
-    int i;
-    char buf[256], *p = buf;
-    MSymbol sym;
-
-    buf[0] = '\0';
-    if (cursor.font)
-      {
-       int size = (int) mfont_get_prop (cursor.font, Msize);
-       MSymbol family = mfont_get_prop (cursor.font, Mfamily);
-       MSymbol weight = mfont_get_prop (cursor.font, Mweight);
-       MSymbol style = mfont_get_prop (cursor.font, Mstyle);
-       MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
-
-       sprintf (p, "%dpt", size / 10), p += strlen (p);
-       if (family)
-         strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
-       if (weight)
-         strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
-       if (style)
-         strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
-       if (registry)
-         strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
-       p += strlen (p);
-      }
+  if (nchars > 0)
+    {
+      int pos = (SELECTEDP () ? mtext_property_start (selection)
+                : cursor.from > 0 ? cursor.from - 1
+                : cursor.from);
+      MFace *face = mface ();
+      MTextProperty *props[256];
+      int n = mtext_get_properties (mt, pos, Mface, props, 256);
+      int i;
+      char buf[256], *p = buf;
+      MSymbol sym;
 
 
-    mface_merge (face, face_default);
-    for (i = 0; i < n; i++)
-      if (props[i] != selection)
-       mface_merge (face, (MFace *) mtext_property_value (props[i]));
-    sym = (MSymbol) mface_get_prop (face, Mforeground);
-    if (sym != Mnil)
-      strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
-    if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
-      strcat (p, ",rev"), p += strlen (p);
-    if (mface_get_prop (face, Mhline))
-      strcat (p, ",ul"), p += strlen (p);
-    if (mface_get_prop (face, Mbox))
-      strcat (p, ",box"), p += strlen (p);
-    m17n_object_unref (face);
+      buf[0] = '\0';
+      if (cursor.font)
+       {
+         int size = (int) mfont_get_prop (cursor.font, Msize);
+         MSymbol family = mfont_get_prop (cursor.font, Mfamily);
+         MSymbol weight = mfont_get_prop (cursor.font, Mweight);
+         MSymbol style = mfont_get_prop (cursor.font, Mstyle);
+         MSymbol registry = mfont_get_prop (cursor.font, Mregistry);
+
+         sprintf (p, "%dpt", size / 10), p += strlen (p);
+         if (family)
+           strcat (p, ","), strcat (p, msymbol_name (family)), p += strlen (p);
+         if (weight)
+           strcat (p, ","), strcat (p, msymbol_name (weight)), p += strlen (p);
+         if (style)
+           strcat (p, ","), strcat (p, msymbol_name (style)), p += strlen (p);
+         if (registry)
+           strcat (p, ","), strcat (p, msymbol_name (registry)), p += strlen (p);
+         p += strlen (p);
+       }
 
 
-    XtSetArg (arg[0], XtNborderWidth, 1);
-    XtSetArg (arg[1], XtNlabel, buf);
-    XtSetValues (CurFaceWidget, arg, 2);
-  }
+      mface_merge (face, face_default);
+      for (i = 0; i < n; i++)
+       if (props[i] != selection)
+         mface_merge (face, (MFace *) mtext_property_value (props[i]));
+      sym = (MSymbol) mface_get_prop (face, Mforeground);
+      if (sym != Mnil)
+       strcat (p, ","), strcat (p, msymbol_name (sym)), p += strlen (p);
+      if ((MSymbol) mface_get_prop (face, Mvideomode) == Mreverse)
+       strcat (p, ",rev"), p += strlen (p);
+      hline = mface_get_prop (face, Mhline);
+      if (hline && hline->width > 0)
+       strcat (p, ",ul"), p += strlen (p);
+      box = mface_get_prop (face, Mbox);
+      if (box && box->width > 0)
+       strcat (p, ",box"), p += strlen (p);
+      m17n_object_unref (face);
+
+      XtSetArg (arg[0], XtNborderWidth, 1);
+      XtSetArg (arg[1], XtNlabel, buf);
+      XtSetValues (CurFaceWidget, arg, 2);
+    }
 
   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);
@@ -782,10 +828,24 @@ 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)
                  break;
                  break;
-             if (i < num_input_methods)
-               select_input_method (i);
+             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);
+               }
              else
                select_input_method (-1);
            }
              else
                select_input_method (-1);
            }
@@ -844,8 +904,9 @@ 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;
 
   if (n > 0)
     from = cursor.from, to = from + n;
@@ -879,11 +940,15 @@ delete_char (int n)
 
   /* Now delete a character.  */
   mtext_del (mt, from, to);
 
   /* Now delete a character.  */
   mtext_del (mt, from, to);
-  nchars--;
+  nchars -= to - from;
   if (from >= top.from && from < top.to)
     update_top (top.from);
   update_cursor (from, 1);
 
   if (from >= top.from && from < top.to)
     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;
 
@@ -898,6 +963,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 ())
     {
@@ -908,9 +974,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;
@@ -926,8 +998,60 @@ insert_chars (MText *newtext)
 }
 
 
 }
 
 
-/* Convert the currently selected text to COMPOUND-TEXT.  It is called
-   when someone requests the current value of the selection.  */
+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.  */
 Boolean
 covert_selection (Widget w, Atom *selection_atom,
                  Atom *target, Atom *return_type,
 Boolean
 covert_selection (Widget w, Atom *selection_atom,
                  Atom *target, Atom *return_type,
@@ -937,14 +1061,52 @@ covert_selection (Widget w, Atom *selection_atom,
   MText *this_mt = mtext ();
   int from = mtext_property_start (selection);
   int to = mtext_property_end (selection);
   MText *this_mt = mtext ();
   int from = mtext_property_start (selection);
   int to = mtext_property_end (selection);
+  MSymbol coding;
+  int len;
 
   mtext_copy (this_mt, 0, mt, from, to);
 
   mtext_copy (this_mt, 0, mt, from, to);
-  *length = mconv_encode_buffer (msymbol ("compound-text"),
-                                this_mt, buf, 4096);
-  *return_type = XA_COMPOUND_TEXT;
+  if (*target == XA_TEXT)
+    {
+#ifdef X_HAVE_UTF8_STRING
+      coding = Mcoding_utf_8;
+      *return_type = XA_UTF8_STRING;
+#else
+      coding = Mcoding_compound_text;
+      *return_type = XA_COMPOUND_TEXT;
+#endif
+    }
+  else if (*target == XA_UTF8_STRING)
+    {
+      coding = Mcoding_utf_8;
+      *return_type = XA_UTF8_STRING;
+    }
+  else if (*target == XA_STRING)
+    {
+      int i;
+
+      len = to - from;
+      for (i = 0; i < len; i++)
+       if (mtext_ref_char (this_mt, i) >= 0x100)
+         /* Can't encode in XA_STRING */
+         return False;
+      coding = Mcoding_iso_8859_1;
+      *return_type = XA_STRING;
+    }
+  else if (*target == XA_COMPOUND_TEXT)
+    {
+      coding = Mcoding_compound_text;
+      *return_type = XA_COMPOUND_TEXT;
+    }
+  else
+    return False;
+
+  len = mconv_encode_buffer (coding, this_mt, buf, 4096);
+  m17n_object_unref (this_mt);
+  if (len < 0)
+    return False;
+  *length = len;
   *value = (XtPointer) buf;
   *format = 8;
   *value = (XtPointer) buf;
   *format = 8;
-  m17n_object_unref (this_mt);
   return True;
 }
 
   return True;
 }
 
@@ -973,12 +1135,20 @@ get_selection (Widget w, XtPointer cliend_data, Atom *selection,  Atom *type,
     coding = Mnil;
   else if (*type == XA_COMPOUND_TEXT)
     coding = msymbol ("compound-text");
     coding = Mnil;
   else if (*type == XA_COMPOUND_TEXT)
     coding = msymbol ("compound-text");
+#ifdef X_HAVE_UTF8_STRING
   else if (*type == XA_UTF8_STRING)
     coding = msymbol ("utf-8");
   else if (*type == XA_UTF8_STRING)
     coding = msymbol ("utf-8");
+#endif
   else
     goto err;
 
   this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
   else
     goto err;
 
   this_mt = mconv_decode_buffer (coding, (unsigned char *) value, *length);
+  if (! this_mt && *type != XA_UTF8_STRING)
+    {
+      XtGetSelectionValue (w, XA_PRIMARY, XA_UTF8_STRING, get_selection, NULL,
+                          CurrentTime);
+      goto err;
+    }
   if (this_mt)
     {
       hide_cursor ();
   if (this_mt)
     {
       hide_cursor ();
@@ -1022,6 +1192,19 @@ ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
       update_top (0);
       update_cursor (0, 1);
       redraw (0, win_height, 0, 1);
       update_top (0);
       update_cursor (0, 1);
       redraw (0, win_height, 0, 1);
+      if (current_input_method >= 0)
+      {
+       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)
+         select_input_method (idx);
+       else
+         input_method_table[idx].available = -1;
+      }
       show_cursor (NULL);
     }
   else
       show_cursor (NULL);
     }
   else
@@ -1066,6 +1249,20 @@ 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)
+    {
+      MText *produced = mtext ();
+
+      minput_reset_ic (current_input_context);
+      minput_lookup (current_input_context, Mnil, NULL, produced);
+      if (mtext_len (produced) > 0)
+       {
+         insert_chars (produced);
+         if (pos >= cursor.from)
+           pos += mtext_len (produced);
+       }
+      m17n_object_unref (produced);
+    }
   update_cursor (pos, 0);
 }
 
   update_cursor (pos, 0);
 }
 
@@ -1143,25 +1340,61 @@ ButtonMoveProc (Widget w, XEvent *event, String *str, Cardinal *num)
 
       if (cursor.from == from)
        {
 
       if (cursor.from == from)
        {
-         /* Start position of selection changed.  */
-         select_region (pos, to);
-         if (pos > from)
-           /* Shrunken.  Previous selection face must be cleared.  */
-           redraw (start_y0, sel_start.y1, 1, 0);
+         /* Starting position changed.  */
+         if (pos <= from)
+           {
+             /* Enlarged.  We can simply overdraw.  */
+             select_region (pos, to);
+             redraw (sel_start.y0, start_y1, 0, 0);
+           }
+         else if (pos < to)
+           {
+             /* Shrunken.  Previous selection face must be cleared.  */
+             select_region (pos, to);
+             redraw (start_y0, sel_start.y1, 1, 0);
+           }
+         else if (pos == to)
+           {
+             /* Shrunken to zero.  */
+             XtDisownSelection (w, XA_PRIMARY, CurrentTime);
+             mtext_detach_property (selection);
+             redraw (start_y0, end_y1, 1, 0);
+           }
          else
          else
-           /* Enlarged.  We can simply overdraw.  */
-           redraw (sel_start.y0, start_y1, 0, 0);
+           {
+             /* Full update is necessary.  */
+             select_region (to, pos);
+             redraw (start_y0, sel_end.y1, 1, 0);
+           }
        }
       else
        {
        }
       else
        {
-         /* End position of selection changed.  */
-         select_region (from, pos);
-         if (pos < to)
-           /* Shrunken.  Previous selection face must be cleared.  */
-           redraw (sel_end.y0, end_y1, 1, 0);
+         /* Ending position changed.  */
+         if (pos < from)
+           {
+             /* Full update is necessary.  */
+             select_region (pos, from);
+             redraw (sel_start.y0, end_y1, 1, 0);
+           }
+         else if (pos == from)
+           {
+             /* Shrunken to zero.  */
+             XtDisownSelection (w, XA_PRIMARY, CurrentTime);
+             mtext_detach_property (selection);
+             redraw (start_y0, end_y1, 1, 0);
+           }
+         else if (pos < to)
+           {
+             /* Shrunken.  Previous selection face must be cleared.  */
+             select_region (from, pos);
+             redraw (sel_end.y0, end_y1, 1, 0);
+           }
          else
          else
-           /* Enlarged.  We can simply overdraw.  */
-           redraw (end_y0, sel_end.y1, 0, 0);
+           {
+             /* Enlarged.  We can simply overdraw.  */
+             select_region (from, pos);
+             redraw (end_y0, sel_end.y1, 0, 0);
+           }
        }
     }
   else
        }
     }
   else
@@ -1192,9 +1425,9 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position)
        {
          pos = bol (from - 1, 0);
          GLYPH_INFO (pos, from - 1, info);
        {
          pos = bol (from - 1, 0);
          GLYPH_INFO (pos, from - 1, info);
-         if (height + info.this.height > win_height)
+         if (height + info.metrics.height > win_height)
            break;
            break;
-         height += info.this.height;
+         height += info.metrics.height;
          from = info.line_from;
        }
       if (cursor_pos >= top.to)
          from = info.line_from;
        }
       if (cursor_pos >= top.to)
@@ -1204,9 +1437,9 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position)
          while (cursor_pos < nchars)
            {
              GLYPH_INFO (pos, pos, info);
          while (cursor_pos < nchars)
            {
              GLYPH_INFO (pos, pos, info);
-             if (height + info.this.height > win_height)
+             if (height + info.metrics.height > win_height)
                break;
                break;
-             height += info.this.height;
+             height += info.metrics.height;
              cursor_pos = pos;
              pos = info.line_to;
            }
              cursor_pos = pos;
              pos = info.line_to;
            }
@@ -1220,10 +1453,10 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position)
       while (from < nchars)
        {
          GLYPH_INFO (from, from, info);
       while (from < nchars)
        {
          GLYPH_INFO (from, from, info);
-         if (height + info.this.height > win_height
+         if (height + info.metrics.height > win_height
              || info.line_to >= nchars)
            break;
              || info.line_to >= nchars)
            break;
-         height += info.this.height;
+         height += info.metrics.height;
          from = info.line_to;
        }
       if (from == nchars)
          from = info.line_to;
        }
       if (from == nchars)
@@ -1421,6 +1654,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)
        {
@@ -1438,7 +1687,8 @@ KeyProc (Widget w, XEvent *event, String *str, Cardinal *num)
            {
              MText *temp = mtext ();
 
            {
              MText *temp = mtext ();
 
-             mtext_cat_char (temp, buf[0] == '\r' ? '\n' : buf[0]);
+             mtext_cat_char (temp, buf[0] == '\r' ? '\n'
+                             : ((unsigned char *) buf)[0]);
              if (current_input_context)
                mtext_put_prop (temp, 0, 1, Mlanguage,
                                current_input_context->im->language);
              if (current_input_context)
                mtext_put_prop (temp, 0, 1, Mlanguage,
                                current_input_context->im->language);
@@ -1479,7 +1729,7 @@ SaveProc (Widget w, XtPointer client_data, XtPointer call_data)
       mtext_detach_property (selection);
     }
 
       mtext_detach_property (selection);
     }
 
-  mconv_encode_stream (Mcoding_utf_8, mt, fp);
+  mconv_encode_stream (Mcoding_utf_8_full, mt, fp);
   fclose (fp);
   if (from >= 0)
     select_region (from, to);
   fclose (fp);
   if (from >= 0)
     select_region (from, to);
@@ -1530,7 +1780,7 @@ read_file ()
 
   if (! fp)
     FATAL_ERROR ("Can't read \"%s\"!\n", filename);
 
   if (! fp)
     FATAL_ERROR ("Can't read \"%s\"!\n", filename);
-  mt = mconv_decode_stream (Mcoding_utf_8, fp);
+  mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
   fclose (fp);
   if (! mt)
     FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
   fclose (fp);
   if (! mt)
     FATAL_ERROR ("Can't decode \"%s\" by UTF-8!\n", filename);
@@ -1566,8 +1816,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)
 {
@@ -1579,7 +1827,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++)
     {
@@ -1595,6 +1843,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;
+  *(void **) (&func) = 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;
@@ -1633,6 +1900,7 @@ CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
       XtSetValues (CursorMenus[i], arg, 1);
     }
 
       XtSetValues (CursorMenus[i], arg, 1);
     }
 
+  update_cursor (cursor.from, 0);
   redraw (0, win_height, 1, 0);
 }
 
   redraw (0, win_height, 1, 0);
 }
 
@@ -1662,12 +1930,25 @@ InputMethodProc (Widget w, XtPointer client_data, XtPointer call_data)
       auto_input_method = 1;
       hide_cursor ();
     }
       auto_input_method = 1;
       hide_cursor ();
     }
-  else
-    select_input_method (idx);
+  else if (input_method_table[idx].available >= 0)
+    {
+      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);
+    }
   XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
   XtSetValues (InputMethodMenus[idx + 2], arg, 1);
 }
 
   XtSetArg (arg[0], XtNleftBitmap, CheckPixmap);
   XtSetValues (InputMethodMenus[idx + 2], arg, 1);
 }
 
+MPlist *default_face_list;
+
 void
 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
 void
 FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
 {
@@ -1675,8 +1956,37 @@ FaceProc (Widget w, XtPointer client_data, XtPointer call_data)
   int from, to;
   int old_y1;
 
   int from, to;
   int old_y1;
 
+  hide_cursor ();
   if (! SELECTEDP ())
   if (! SELECTEDP ())
-    return;
+    {
+      MPlist *plist;
+
+      if (idx >= 0)
+       {
+         MFace *face = mframe_get_prop (frame, Mface);
+
+         for (plist = default_face_list; mplist_key (plist) != Mnil;
+              plist = mplist_next (plist)) 
+           mface_merge (face, mplist_value (plist));
+         mplist_add (plist, Mt, *face_table[idx].face);
+         mface_merge (face, *face_table[idx].face);
+       }
+      else if (mplist_key (mplist_next (default_face_list)) != Mnil)
+       {
+         MFace *face = mframe_get_prop (frame, Mface);
+
+         for (plist = default_face_list;
+              mplist_key (mplist_next (plist)) != Mnil;
+              plist = mplist_next (plist)) 
+           mface_merge (face, mplist_value (plist));
+         mplist_pop (plist);
+       }
+      update_top (0);
+      update_cursor (0, 1);
+      redraw (0, win_height, 1, 1);
+      show_cursor (NULL);
+      return;
+    }
 
   XtAppAddWorkProc (context, show_cursor, NULL);
   from = mtext_property_start (selection);
 
   XtAppAddWorkProc (context, show_cursor, NULL);
   from = mtext_property_start (selection);
@@ -1771,7 +2081,7 @@ DumpImageProc (Widget w, XtPointer client_data, XtPointer call_data)
     mdump = popen ("mdump -q", "w");
   if (! mdump)
     return;
     mdump = popen ("mdump -q", "w");
   if (! mdump)
     return;
-  converter = mconv_stream_converter (Mcoding_utf_8, mdump);
+  converter = mconv_stream_converter (Mcoding_utf_8_full, mdump);
   mconv_encode_range (converter, mt, from, to);
   mconv_free_converter (converter);
   fclose (mdump);
   mconv_encode_range (converter, mt, from, to);
   mconv_free_converter (converter);
   fclose (mdump);
@@ -1805,8 +2115,8 @@ input_status (MInputContext *ic, MSymbol command)
 int
 compare_input_method (const void *elt1, const void *elt2)
 {
 int
 compare_input_method (const void *elt1, const void *elt2)
 {
-  const MInputMethod *im1 = *(MInputMethod **) elt1;
-  const MInputMethod *im2 = *(MInputMethod **) elt2;
+  const InputMethodInfo *im1 = elt1;
+  const InputMethodInfo *im2 = elt2;
   MSymbol lang1, lang2;
 
   if (im1->language == Mnil)
   MSymbol lang1, lang2;
 
   if (im1->language == Mnil)
@@ -1823,18 +2133,29 @@ compare_input_method (const void *elt1, const void *elt2)
 }
 
 void
 }
 
 void
-setup_input_methods (int with_xim)
+setup_input_methods (int with_xim, char *initial_input_method)
 {
   MInputMethod *im = NULL;
 {
   MInputMethod *im = NULL;
-  MInputXIMArgIM arg_xim;
   MPlist *plist = mdatabase_list (msymbol ("input-method"), Mnil, Mnil, Mnil);
   MPlist *pl;
   int i = 0;
   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);
+  num_input_methods = plist ? mplist_length (plist) : 0;
 
   if (with_xim)
     {
 
   if (with_xim)
     {
+      MInputXIMArgIM arg_xim;
+
       arg_xim.display = display;
       arg_xim.db = NULL;  
       arg_xim.res_name = arg_xim.res_class = NULL;
       arg_xim.display = display;
       arg_xim.db = NULL;  
       arg_xim.res_name = arg_xim.res_class = NULL;
@@ -1844,23 +2165,33 @@ setup_input_methods (int with_xim)
       if (im)
        num_input_methods++;
     }
       if (im)
        num_input_methods++;
     }
-  input_method_table = calloc (num_input_methods, sizeof (MInputMethod *));
+  input_method_table = calloc (num_input_methods, sizeof (InputMethodInfo));
   if (im)
   if (im)
-    input_method_table[i++] = im;
-  for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
     {
     {
-      MDatabase *mdb = mplist_value (pl);
-      MSymbol *tag = mdatabase_tag (mdb);
+      input_method_table[i].available = 1;
+      input_method_table[i].language = Mnil;
+      input_method_table[i].name = im->name;
+      input_method_table[i].im = im;
+      i++;
+    }
 
 
-      if (tag[1] != Mnil)
+  if (plist)
+    {
+      for (pl = plist; mplist_key (pl) != Mnil; pl = mplist_next (pl))
        {
        {
-         im = minput_open_im (tag[1], tag[2], NULL);
-         if (im)
-           input_method_table[i++] = im;
+         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);
+      m17n_object_unref (plist);
+    }
   num_input_methods = i;
   qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
         compare_input_method);
   num_input_methods = i;
   qsort (input_method_table, num_input_methods, sizeof input_method_table[0],
         compare_input_method);
@@ -1872,6 +2203,17 @@ setup_input_methods (int with_xim)
              (void *) input_status);
   mplist_put (minput_driver->callback_list, Minput_status_done,
              (void *) input_status);
              (void *) input_status);
   mplist_put (minput_driver->callback_list, Minput_status_done,
              (void *) input_status);
+
+  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;
+       }
 }
 
 
 }
 
 
@@ -1973,7 +2315,7 @@ FileDialogProc (Widget w, XtPointer client_data, XtPointer call_data)
       m17n_object_unref (mt);
       if (fp)
        {
       m17n_object_unref (mt);
       if (fp)
        {
-         mt = mconv_decode_stream (Mcoding_utf_8, fp);
+         mt = mconv_decode_stream (Mcoding_utf_8_full, fp);
          fclose (fp);
          if (! mt)
            mt = mtext ();
          fclose (fp);
          if (! mt)
            mt = mtext ();
@@ -2132,8 +2474,14 @@ help_exit (char *prog, int exit_code)
   printf ("Display FILE on a window and allow users to edit it.\n");
   printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
   printf ("The following OPTIONs are available.\n");
   printf ("Display FILE on a window and allow users to edit it.\n");
   printf ("XT-OPTIONs are standard Xt arguments (e.g. -fn, -fg).\n");
   printf ("The following OPTIONs are available.\n");
+  printf ("  %-13s\n\t\t%s", "--fontset FONTSET",
+         "Use the specified fontset\n");
+  printf ("  %-13s %s", "-s SIZE", "Font size in 1/10 point (default 120).\n");
+  printf ("  %-13s\n\t\t%s", "--im INPUT-METHOD",
+         "Input method activated initially.\n");
   printf ("  %-13s %s", "--version", "print version number\n");
   printf ("  %-13s %s", "-h, --help", "print this message\n");
   printf ("  %-13s %s", "--version", "print version number\n");
   printf ("  %-13s %s", "-h, --help", "print this message\n");
+         
   exit (exit_code);
 }
 
   exit (exit_code);
 }
 
@@ -2142,6 +2490,8 @@ main (int argc, char **argv)
 {
   Widget form, BodyWidget, w;
   char *fontset_name = NULL;
 {
   Widget form, BodyWidget, w;
   char *fontset_name = NULL;
+  int fontsize = 0;
+  char *initial_input_method = NULL;
   int col = 80, row = 32;
   /* Translation table for TextWidget.  */
   String trans = "<Expose>: Expose()\n\
   int col = 80, row = 32;
   /* Translation table for TextWidget.  */
   String trans = "<Expose>: Expose()\n\
@@ -2168,11 +2518,12 @@ 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;
 
   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));
@@ -2185,7 +2536,7 @@ 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 ("m17n-edit (m17n library) %s\n", VERSION);
          printf ("Copyright (C) 2003 AIST, JAPAN\n");
          exit (0);
        }
          printf ("Copyright (C) 2003 AIST, JAPAN\n");
          exit (0);
        }
@@ -2195,44 +2546,65 @@ main (int argc, char **argv)
          if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
            help_exit (argv[0], 1);
        }
          if (sscanf (argv[i], "%dx%d", &col, &row) != 2)
            help_exit (argv[0], 1);
        }
+      else if (! strcmp (argv[i], "-s"))
+       {
+         i++;
+         fontsize = atoi (argv[i]);
+         if (fontsize < 0)
+           fontsize = 120;
+       }
       else if (! strcmp (argv[i], "--fontset"))
        {
          i++;
          fontset_name = strdup (argv[i]);
        }
       else if (! strcmp (argv[i], "--fontset"))
        {
          i++;
          fontset_name = strdup (argv[i]);
        }
+      else if (! strcmp (argv[i], "--im"))
+       {
+         i++;
+         initial_input_method = strdup (argv[i]);
+       }
       else if (! strcmp (argv[i], "--with-xim"))
        {
          with_xim = 1;
        }
       else if (! strcmp (argv[i], "--with-xim"))
        {
          with_xim = 1;
        }
+      else if (! strcmp (argv[i], "--filter"))
+       {
+         i++;
+         filter = argv[i];
+       }
       else if (argv[i][0] != '-')
        {
          filename = strdup (argv[i]);
        }
       else
        {
       else if (argv[i][0] != '-')
        {
          filename = strdup (argv[i]);
        }
       else
        {
-         fprintf (stderr, "Unknown option: %s", argv[i]);
+         fprintf (stderr, "Unknown option: %s\n", argv[i]);
          help_exit (argv[0], 1);
        }
     }
   if (! filename)
          help_exit (argv[0], 1);
        }
     }
   if (! filename)
-    help_exit (argv[0], 1);
+    filename = strdup ("/dev/null");
 
   mdatabase_dir = ".";
   /* Initialize the m17n library.  */
   M17N_INIT ();
   if (merror_code != MERROR_NONE)
     FATAL_ERROR ("%s\n", "Fail to initialize the m17n library!");
 
   mdatabase_dir = ".";
   /* 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 ();
 
-    mface_put_prop (face, Mbackground, msymbol ("blue"));
-    mface_put_prop (face, Mforeground, msymbol ("yellow"));
+    mface_put_prop (face, Mforeground, msymbol ("blue"));
+    mface_put_prop (face, Mbackground, msymbol ("yellow"));
+    mface_put_prop (face, Mvideomode, Mreverse);
     selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
     m17n_object_unref (face);
   }
     selection = mtext_property (Mface, face, MTEXTPROP_NO_MERGE);
     m17n_object_unref (face);
   }
@@ -2243,25 +2615,34 @@ main (int argc, char **argv)
   XA_TEXT = XInternAtom (display, "TEXT", False);
   XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
   XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
   XA_TEXT = XInternAtom (display, "TEXT", False);
   XA_COMPOUND_TEXT = XInternAtom (display, "COMPOUND_TEXT", False);
   XA_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False);
+  Mcoding_compound_text = mconv_resolve_coding (msymbol ("compound-text"));
+  if (Mcoding_compound_text == Mnil)
+    FATAL_ERROR ("%s\n", "Don't know about COMPOUND-TEXT encoding!");
+
   {
     MPlist *plist = mplist ();
     MFace *face;
     MFont *font;
 
     mplist_put (plist, msymbol ("widget"), ShellWidget);
   {
     MPlist *plist = mplist ();
     MFace *face;
     MFont *font;
 
     mplist_put (plist, msymbol ("widget"), ShellWidget);
-    if (fontset_name)
+    if (fontset_name || fontsize > 0)
       {
        MFontset *fontset = mfontset (fontset_name);
        
        face = mface ();
        mface_put_prop (face, Mfontset, fontset);
       {
        MFontset *fontset = mfontset (fontset_name);
        
        face = mface ();
        mface_put_prop (face, Mfontset, fontset);
+       mface_put_prop (face, Msize, (void *) fontsize);
        m17n_object_unref (fontset);
        mplist_add (plist, Mface, face);
        m17n_object_unref (face);
       }
     frame = mframe (plist);
        m17n_object_unref (fontset);
        mplist_add (plist, Mface, face);
        m17n_object_unref (face);
       }
     frame = mframe (plist);
+    if (! frame)
+      FATAL_ERROR ("%s\n", "Fail to create a frame!");
     m17n_object_unref (plist);
     m17n_object_unref (plist);
-    face_default = (MFace *) mframe_get_prop (frame, Mface);
+    face_default = mface_copy ((MFace *) mframe_get_prop (frame, Mface));
+    default_face_list = mplist ();
+    mplist_add (default_face_list, Mt, face_default);
     face_default_fontset = mface ();
     mface_put_prop (face_default_fontset, Mfontset,
                    mface_get_prop (face_default, Mfontset));
     face_default_fontset = mface ();
     mface_put_prop (face_default_fontset, Mfontset,
                    mface_get_prop (face_default, Mfontset));
@@ -2299,6 +2680,8 @@ main (int argc, char **argv)
   mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
   face_freesans = mface ();
   mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
   mface_put_prop (face_dv_ttyogesh, Mfamily, msymbol ("dv-ttyogesh"));
   face_freesans = mface ();
   mface_put_prop (face_freesans, Mfamily, msymbol ("freesans"));
+  face_freeserif = mface ();
+  mface_put_prop (face_freeserif, Mfamily, msymbol ("freeserif"));
   face_freemono = mface ();
   mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
 
   face_freemono = mface ();
   mface_put_prop (face_freemono, Mfamily, msymbol ("freemono"));
 
@@ -2338,7 +2721,7 @@ main (int argc, char **argv)
     free (tib_font);
   }
 
     free (tib_font);
   }
 
-  setup_input_methods (with_xim);
+  setup_input_methods (with_xim, initial_input_method);
 
   gc = DefaultGC (display, screen);
 
 
   gc = DefaultGC (display, screen);
 
@@ -2438,7 +2821,7 @@ main (int argc, char **argv)
     SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
     for (i = 0; i < num_input_methods; i++)
       {
     SetMenu (menus[1], 0, "auto", NULL, InputMethodProc, -1, 0);
     for (i = 0; i < num_input_methods; i++)
       {
-       MInputMethod *im = input_method_table[i];
+       InputMethodInfo *im = input_method_table + i;
        char *name1, *name2;
 
        if (im->language != Mnil && im->language != Mt)
        char *name1, *name2;
 
        if (im->language != Mnil && im->language != Mt)
@@ -2473,6 +2856,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),
@@ -2487,7 +2878,7 @@ main (int argc, char **argv)
        = prop.color_left = prop.color_right = Mnil;
       prop.inner_hmargin = prop.inner_vmargin = 1;
       prop.outer_hmargin = prop.outer_vmargin = 0;
        = prop.color_left = prop.color_right = Mnil;
       prop.inner_hmargin = prop.inner_vmargin = 1;
       prop.outer_hmargin = prop.outer_vmargin = 0;
-      face_input_status = mface ();
+      face_input_status = mface_copy (face_default);
       mface_put_prop (face_input_status, Mbox, &prop);
     }
 
       mface_put_prop (face_input_status, Mbox, &prop);
     }
 
@@ -2567,9 +2958,9 @@ main (int argc, char **argv)
                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)
@@ -2585,7 +2976,7 @@ main (int argc, char **argv)
       for (i = 0; i < 11; i++)
        if (plist[i])
          {
       for (i = 0; i < 11; i++)
        if (plist[i])
          {
-           char *name = malloc (9);
+           char *name = alloca (9);
 
            sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
            if (i == 10)
 
            sprintf (name, "Menu %c-%c", 'A' + i * 2, 'A' + i * 2 + 1);
            if (i == 10)
@@ -2652,6 +3043,7 @@ main (int argc, char **argv)
   memset (&control, 0, sizeof control);
   control.two_dimensional = 1;
   control.enable_bidi = 1;
   memset (&control, 0, sizeof control);
   control.two_dimensional = 1;
   control.enable_bidi = 1;
+  control.anti_alias = 1;
   control.min_line_ascent = font_ascent;
   control.min_line_descent = font_descent;
   control.max_line_width = win_width;
   control.min_line_ascent = font_ascent;
   control.min_line_descent = font_descent;
   control.max_line_width = win_width;
@@ -2673,9 +3065,9 @@ main (int argc, char **argv)
   if (current_input_context)
     minput_destroy_ic (current_input_context);
   for (i = 0; i < num_input_methods; i++)
   if (current_input_context)
     minput_destroy_ic (current_input_context);
   for (i = 0; i < num_input_methods; i++)
-    minput_close_im (input_method_table[i]);
+    if (input_method_table[i].im)
+      minput_close_im (input_method_table[i].im);
   m17n_object_unref (frame);
   m17n_object_unref (frame);
-
   m17n_object_unref (mt);
   m17n_object_unref (face_xxx_large);
   m17n_object_unref (face_box);
   m17n_object_unref (mt);
   m17n_object_unref (face_xxx_large);
   m17n_object_unref (face_box);
@@ -2684,21 +3076,43 @@ main (int argc, char **argv)
   m17n_object_unref (face_times);
   m17n_object_unref (face_dv_ttyogesh);
   m17n_object_unref (face_freesans);
   m17n_object_unref (face_times);
   m17n_object_unref (face_dv_ttyogesh);
   m17n_object_unref (face_freesans);
+  m17n_object_unref (face_freeserif);
   m17n_object_unref (face_freemono);
   m17n_object_unref (face_default_fontset);
   m17n_object_unref (face_no_ctl_fontset);
   m17n_object_unref (face_input_status);
   m17n_object_unref (face_freemono);
   m17n_object_unref (face_default_fontset);
   m17n_object_unref (face_no_ctl_fontset);
   m17n_object_unref (face_input_status);
+  m17n_object_unref (face_default);
+  m17n_object_unref (default_face_list);
   m17n_object_unref (selection);
 
   m17n_object_unref (selection);
 
-  M17N_FINI ();
-
-  free (fontset_name);
-
+  XFreeGC (display, mono_gc);
+  XFreeGC (display, mono_gc_inv);
+  XFreeGC (display, gc_inv);
   XtUninstallTranslations (form);
   XtUninstallTranslations (TextWidget);
   XtDestroyWidget (ShellWidget);
   XtDestroyApplicationContext (context);
 
   XtUninstallTranslations (form);
   XtUninstallTranslations (TextWidget);
   XtDestroyWidget (ShellWidget);
   XtDestroyApplicationContext (context);
 
+  M17N_FINI ();
+
+  free (fontset_name);
+  free (filename);
+  free (input_method_table);
+  free (InputMethodMenus);
+
   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 */