(update_selection): Fix for the case that the selection
[m17n/m17n-lib.git] / example / medit.c
index 07f34c7..e1477df 100644 (file)
 #include <m17n-misc.h>
 #include <m17n-X.h>
 
-#define VERSION "1.0.1"
+#define VERSION "1.1"
 
 /* Global variables.  */
 
@@ -334,8 +334,8 @@ update_top (int pos)
   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;
 }
 
 
@@ -382,21 +382,21 @@ redraw (int y0, int y1, int clear, int scroll_bar)
 
   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;
-  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);
     }
-  y0 = y - info.this.y;
+  y0 = y - info.metrics.y;
   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)
@@ -408,10 +408,10 @@ redraw (int y0, int y1, int clear, int scroll_bar)
       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;
-         y += info.this.height;
+         y += info.metrics.height;
        }
       update_scroll_bar (top.from, to);
     }
@@ -481,7 +481,7 @@ redraw_cursor (int clear)
 
          if (control.orientation_reversed)
            x += win_width - cursor.logical_width;
-         CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.this.height);
+         CLEAR_AREA (x, cur.y0, cursor.logical_width, cursor.metrics.height);
        }
       DRAW_TEXT (cursor.x, cur.y0 + cur.ascent, cursor.from, cursor.to);
     }
@@ -501,7 +501,7 @@ update_cursor (int pos, int full)
     {
       /* 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)
     {
@@ -509,7 +509,7 @@ update_cursor (int pos, int full)
 
       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)
     {
@@ -518,13 +518,13 @@ update_cursor (int pos, int full)
   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.y1 = cur.y0 + cursor.this.height;
-  cur.ascent = - cursor.this.y;
+  cur.y1 = cur.y0 + cursor.metrics.height;
+  cur.ascent = - cursor.metrics.y;
 }
 
 
@@ -550,34 +550,28 @@ update_selection ()
       sel_start.ascent = - rect.y;
       GLYPH_INFO (pos, from, info);
       if (pos < info.line_from)
-       sel_start.y0 += - rect.y + info.y + info.this.y;
+       sel_start.y0 += - rect.y + info.y + info.metrics.y;
     }
   else
     {
       GLYPH_INFO (top.from, from, info);
-      sel_start.y0 = top.ascent + info.y + info.this.y;
+      sel_start.y0 = top.ascent + info.y + info.metrics.y;
     }
-  sel_start.ascent = -info.this.y;
-  sel_start.y1 = sel_start.y0 + info.this.height;
+  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_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
     {
       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;
     }
@@ -1003,6 +997,7 @@ covert_selection (Widget w, Atom *selection_atom,
   int from = mtext_property_start (selection);
   int to = mtext_property_end (selection);
   MSymbol coding;
+  int len;
 
   mtext_copy (this_mt, 0, mt, from, to);
   if (*target == XA_TEXT)
@@ -1015,11 +1010,16 @@ covert_selection (Widget w, Atom *selection_atom,
       *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 len = to - from;
       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 */
@@ -1032,10 +1032,14 @@ covert_selection (Widget w, Atom *selection_atom,
       coding = Mcoding_compound_text;
       *return_type = XA_COMPOUND_TEXT;
     }
-  *length = mconv_encode_buffer (coding, this_mt, buf, 4096);
+  else
+    return False;
+
+  len = mconv_encode_buffer (coding, this_mt, buf, 4096);
   m17n_object_unref (this_mt);
-  if (*length == 0)
+  if (len < 0)
     return False;
+  *length = len;
   *value = (XtPointer) buf;
   *format = 8;
   return True;
@@ -1123,6 +1127,19 @@ ExposeProc (Widget w, XEvent *event, String *str, Cardinal *num)
       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
@@ -1329,9 +1346,9 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position)
        {
          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;
-         height += info.this.height;
+         height += info.metrics.height;
          from = info.line_from;
        }
       if (cursor_pos >= top.to)
@@ -1341,9 +1358,9 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position)
          while (cursor_pos < nchars)
            {
              GLYPH_INFO (pos, pos, info);
-             if (height + info.this.height > win_height)
+             if (height + info.metrics.height > win_height)
                break;
-             height += info.this.height;
+             height += info.metrics.height;
              cursor_pos = pos;
              pos = info.line_to;
            }
@@ -1357,10 +1374,10 @@ ScrollProc (Widget w, XtPointer client_data, XtPointer position)
       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;
-         height += info.this.height;
+         height += info.metrics.height;
          from = info.line_to;
        }
       if (from == nchars)
@@ -1770,6 +1787,7 @@ CursorProc (Widget w, XtPointer client_data, XtPointer call_data)
       XtSetValues (CursorMenus[i], arg, 1);
     }
 
+  update_cursor (cursor.from, 0);
   redraw (0, win_height, 1, 0);
 }
 
@@ -2001,12 +2019,22 @@ compare_input_method (const void *elt1, const void *elt2)
 }
 
 void
-setup_input_methods (int with_xim)
+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;
   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);
 
@@ -2058,6 +2086,17 @@ setup_input_methods (int with_xim)
              (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;
+       }
 }
 
 
@@ -2318,8 +2357,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 ("  %-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");
+         
   exit (exit_code);
 }
 
@@ -2328,6 +2373,8 @@ main (int argc, char **argv)
 {
   Widget form, BodyWidget, w;
   char *fontset_name = NULL;
+  int fontsize = 120;
+  char *initial_input_method = NULL;
   int col = 80, row = 32;
   /* Translation table for TextWidget.  */
   String trans = "<Expose>: Expose()\n\
@@ -2381,11 +2428,23 @@ main (int argc, char **argv)
          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], "--im"))
+       {
+         i++;
+         initial_input_method = strdup (argv[i]);
+       }
       else if (! strcmp (argv[i], "--with-xim"))
        {
          with_xim = 1;
@@ -2396,7 +2455,7 @@ main (int argc, char **argv)
        }
       else
        {
-         fprintf (stderr, "Unknown option: %s", argv[i]);
+         fprintf (stderr, "Unknown option: %s\n", argv[i]);
          help_exit (argv[0], 1);
        }
     }
@@ -2440,12 +2499,13 @@ main (int argc, char **argv)
     MFont *font;
 
     mplist_put (plist, msymbol ("widget"), ShellWidget);
-    if (fontset_name)
+    if (fontset_name || fontsize != 120)
       {
        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);
@@ -2535,7 +2595,7 @@ main (int argc, char **argv)
     free (tib_font);
   }
 
-  setup_input_methods (with_xim);
+  setup_input_methods (with_xim, initial_input_method);
 
   gc = DefaultGC (display, screen);