(mdatabase__dir_list, M_database_hook)
[m17n/m17n-lib.git] / src / input.c
index 46512b2..928da5b 100644 (file)
@@ -239,7 +239,7 @@ integer_value (MInputContext *ic, MPlist *arg)
   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
   int code;
   MText *preedit = ic->preedit;
-  int len = mtext_nbytes (preedit);
+  int len = mtext_nchars (preedit);
 
   if (MPLIST_INTEGER_P (arg))
     return MPLIST_INTEGER (arg);
@@ -256,7 +256,7 @@ integer_value (MInputContext *ic, MPlist *arg)
     code = ic->cursor_pos + 1;
   else if (code == '<')
     code = 0;
-  else if (code == '<')
+  else if (code == '>')
     code = len;
   return (code >= 0 && code < len ? mtext_ref_char (preedit, code) : -1);
 }
@@ -692,8 +692,6 @@ load_input_method (MSymbol language, MSymbol name, MPlist *plist,
   MPlist *macros = NULL;
   MPlist *elt;
 
-  if (! MPLIST_PLIST_P (plist))
-    MERROR (MERROR_IM, -1);
   for (; MPLIST_PLIST_P (plist); plist = MPLIST_NEXT (plist))
     {
       elt = MPLIST_PLIST (plist);
@@ -753,9 +751,12 @@ load_input_method (MSymbol language, MSymbol name, MPlist *plist,
        }
     }
 
-  MPLIST_DO (elt, maps)
-    M17N_OBJECT_UNREF (MPLIST_VAL (elt));
-  M17N_OBJECT_UNREF (maps);
+  if (maps)
+    {
+      MPLIST_DO (elt, maps)
+       M17N_OBJECT_UNREF (MPLIST_VAL (elt));
+      M17N_OBJECT_UNREF (maps);
+    }
   if (! title)
     title = mtext_from_data (MSYMBOL_NAME (name), MSYMBOL_NAMELEN (name),
                             MTEXT_FORMAT_US_ASCII);
@@ -813,7 +814,7 @@ shift_state (MInputContext *ic, MSymbol state_name)
 {
   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
-  MIMState *state = ic_info->state;
+  MIMState *state;
 
   /* Find a state to shift to.  If not found, shift to the initial
      state.  */
@@ -876,6 +877,11 @@ shift_state (MInputContext *ic, MSymbol state_name)
     }
 }
 
+/* Find a candidate group that contains a candidate number INDEX from
+   PLIST.  Set START_INDEX to the first candidate number of the group,
+   END_INDEX to the last candidate number plus 1, GROUP_INDEX to the
+   candidate group number if they are non-NULL.  If INDEX is -1, find
+   the last candidate group.  */
 
 static MPlist *
 find_candidates_group (MPlist *plist, int index,
@@ -889,7 +895,8 @@ find_candidates_group (MPlist *plist, int index,
        len = mtext_nchars (MPLIST_MTEXT (plist));
       else
        len = mplist_length (MPLIST_PLIST (plist));
-      if (i + len > index)
+      if (index < 0 ? MPLIST_TAIL_P (MPLIST_NEXT (plist))
+         : i + len > index)
        {
          if (start_index)
            *start_index = i;
@@ -984,7 +991,7 @@ new_index (MInputContext *ic, int current, int limit, MSymbol sym, MText *mt)
 }
 
 static void
-udpate_candidate (MInputContext *ic, MTextProperty *prop, int idx)
+update_candidate (MInputContext *ic, MTextProperty *prop, int idx)
 {
   int from = mtext_property_start (prop);
   int to = mtext_property_end (prop);
@@ -1119,9 +1126,14 @@ take_action_list (MInputContext *ic, MPlist *action_list)
                                     end - start - 1, MPLIST_SYMBOL (args),
                                     NULL)
                        : MPLIST_INTEGER (args)));
-             if (idx < 0
-                 || (idx >= end
-                     && MPLIST_TAIL_P (MPLIST_NEXT (group))))
+             if (idx < 0)
+               {
+                 find_candidates_group (mtext_property_value (prop), -1,
+                                        NULL, &end, NULL);
+                 idx = end - 1;
+               }
+             else if (idx >= end
+                      && MPLIST_TAIL_P (MPLIST_NEXT (group)))
                idx = 0;
            }
          else
@@ -1154,7 +1166,7 @@ take_action_list (MInputContext *ic, MPlist *action_list)
                ingroup_index = len - 1;
              idx += ingroup_index;
            }
-         udpate_candidate (ic, prop, idx);
+         update_candidate (ic, prop, idx);
        }
       else if (name == Mshow)
        ic->candidate_show = 1;
@@ -1307,12 +1319,13 @@ take_action_list (MInputContext *ic, MPlist *action_list)
          else
            val1 /= val2;
          mplist_put (ic_info->vars, sym, (void *) val1);
+         MDEBUG_PRINT2 ("(%s=%d)", MSYMBOL_NAME (sym), val1);
        }
       else if (name == Mequal || name == Mless || name == Mgreater)
        {
          int val1, val2;
          MPlist *actions1, *actions2;
-         int ret;
+         int ret = 0;
 
          val1 = integer_value (ic, args);
          args = MPLIST_NEXT (args);
@@ -1488,23 +1501,28 @@ handle_key (MInputContext *ic)
 }
 
 static void
-reset_ic (MInputContext *ic)
+reset_ic (MInputContext *ic, MSymbol ignore)
 {
   MInputMethodInfo *im_info = (MInputMethodInfo *) ic->im->info;
   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
 
+  if (im_info->states)
+    /* Shift to the initial state.  */
+    shift_state (ic, Mnil);
+  else
+    ic_info->state = NULL;
   MLIST_RESET (ic_info);
-  ic_info->state = (MIMState *) MPLIST_VAL (im_info->states);
-  ic_info->map = ic_info->state->map;
+  ic_info->map = ic_info->state ? ic_info->state->map : NULL;
   ic_info->state_key_head = ic_info->key_head = 0;
+  ic_info->key_unhandled = 0;
   ic->cursor_pos = ic_info->state_pos = 0;
-  ic->status = ic_info->state->title;
+  ic->status = ic_info->state ? ic_info->state->title : NULL;
   if (! ic->status)
     ic->status = im_info->title;
   ic->candidate_list = NULL;
   ic->candidate_show = 0;
   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 1;
-  if (ic_info->map->map_actions)
+  if (ic_info->map && ic_info->map->map_actions)
     take_action_list (ic, ic_info->map->map_actions);
 }
 
@@ -1613,7 +1631,7 @@ create_ic (MInputContext *ic)
        }
       M17N_OBJECT_UNREF (func_args);
     }
-  reset_ic (ic);
+  reset_ic (ic, Mnil);
   return 0;
 }
 
@@ -1660,6 +1678,11 @@ filter (MInputContext *ic, MSymbol key, void *arg)
   MInputContextInfo *ic_info = (MInputContextInfo *) ic->info;
   int i = 0;
 
+  if (! ic_info->state)
+    {
+      ic_info->key_unhandled = 1;
+      return 0;
+    }
   mtext_reset (ic->produced);
   ic->status_changed = ic->preedit_changed = ic->candidates_changed = 0;
   MLIST_APPEND1 (ic_info, keys, key, MERROR_IM);
@@ -1669,7 +1692,7 @@ filter (MInputContext *ic, MSymbol key, void *arg)
       {
        /* KEY was not handled.  Reset the status and break the
           loop.  */
-       reset_ic (ic);
+       reset_ic (ic, Mnil);
        /* This forces returning 1.  */
        ic_info->key_unhandled = 1;
        break;
@@ -1677,7 +1700,7 @@ filter (MInputContext *ic, MSymbol key, void *arg)
     if (i++ == 100)
       {
        mdebug_hook ();
-       reset_ic (ic);
+       reset_ic (ic, Mnil);
        ic_info->key_unhandled = 1;
        break;
       }
@@ -1826,6 +1849,7 @@ minput__init ()
   Minput_candidates_draw = msymbol ("input-candidates-draw");
   Minput_set_spot = msymbol ("input-set-spot");
   Minput_toggle = msymbol ("input-toggle");
+  Minput_reset = msymbol ("input-reset");
 
   Mcandidate_list = msymbol_as_managing_key ("  candidate-list");
   Mcandidate_index = msymbol ("  candidate-index");
@@ -1871,7 +1895,9 @@ minput__init ()
   minput_default_driver.destroy_ic = destroy_ic;
   minput_default_driver.filter = filter;
   minput_default_driver.lookup = lookup;
-  minput_default_driver.callback_list = NULL;
+  minput_default_driver.callback_list = mplist ();
+  mplist_put (minput_default_driver.callback_list, Minput_reset,
+             (void *) reset_ic);
   minput_driver = &minput_default_driver;
   return 0;
 }
@@ -1950,6 +1976,7 @@ MSymbol Minput_candidates_done;
 MSymbol Minput_candidates_draw;
 MSymbol Minput_set_spot;
 MSymbol Minput_toggle;
+MSymbol Minput_reset;
 /*** @} */
 /*=*/
 
@@ -2005,15 +2032,16 @@ MInputDriver minput_default_driver;
     The variable #minput_driver is a pointer to the input method
     driver that is used by internal input methods.  The macro
     M17N_INIT () initializes it to a pointer to #minput_default_driver
-    (if <m17n.h> is included) or to #minput_gui_driver (if
-    <m17n-gui.h> is included).  */ 
+    (if <m17n<EM></EM>.h> is included) or to #minput_gui_driver (if
+    <m17n-gui<EM></EM>.h> is included).  */ 
 /***ja
     @brief ÆâÉôÆþÎϥ᥽¥Ã¥ÉÍѥɥ饤¥Ð.
 
     ÊÑ¿ô #minput_driver ¤ÏÆâÉôÆþÎϥ᥽¥Ã¥É¤Ë¤è¤Ã¤Æ»ÈÍѤµ¤ì¤Æ¤¤¤ëÆþÎÏ¥á
-    ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥íM17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
-    ¥¿¤ò #minput_default_driver (<m17n.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï 
-    #minput_gui_driver ( <m17n-gui.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹¤ë¡£  */ 
+    ¥½¥Ã¥É¥É¥é¥¤¥Ð¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£¥Þ¥¯¥í M17N_INIT () ¤Ï¤³¤Î¥Ý¥¤¥ó
+    ¥¿¤ò #minput_default_driver (<m17n<EM></EM>.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Þ¤¿¤Ï
+    #minput_gui_driver ( <m17n-gui<EM></EM>.h> ¤¬´Þ¤Þ¤ì¤ë»þ) ¤Ë½é´ü²½¤¹
+    ¤ë¡£  */ 
 
 MInputDriver *minput_driver;
 
@@ -2270,7 +2298,6 @@ minput_filter (MInputContext *ic, MSymbol key, void *arg)
        minput__callback (ic, Minput_status_draw);
       if (ic->candidates_changed)
        minput__callback (ic, Minput_candidates_draw);
-      ic->preedit_changed = ic->status_changed = ic->candidates_changed = 0;
     }
 
   return ret;
@@ -2397,6 +2424,32 @@ minput_toggle (MInputContext *ic)
   ic->active = ! ic->active;
 }
 
+/***en
+    @brief Reset an input context.
+
+    The minput_reset_ic () function resets the input context $IC by
+    calling a callback functions corresponding to #Minput_reset.  It
+    actually shifts the state to the initial one, and thus the current
+    preediting text (if any) is committed.  If necessary, a program
+    can extract that text by calling minput_lookup () just after the
+    call of minput_reset_ic ().  In that case, the arguments @c KEY
+    and @c ARG of minput_lookup () are ignored.  */
+/***ja
+    @brief ÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È¤ò¥ê¥»¥Ã¥È¤¹¤ë.
+
+    ´Ø¿ô minput_reset_ic () ¤Ï #Minput_reset ¤ËÂбþ¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯´Ø¿ô
+    ¤ò¸Æ¤Ö¤³¤È¤Ë¤è¤Ã¤ÆÆþÎÏ¥³¥ó¥Æ¥¯¥¹¥È $IC ¤ò¥ê¥»¥Ã¥È¤¹¤ë¡£¤³¤ì¤Ï¼ÂºÝ¤Ï
+    ÆþÎϥ᥽¥Ã¥É¤ò½é´ü¾õÂ֤˥·¥Õ¥È¤µ¤»¤ë¡£¤·¤¿¤¬¤Ã¤Æ¡¢¤â¤·¸½ºßÆþÎÏÃæ¤Î
+    ¥Æ¥­¥¹¥È¤¬¤¢¤ì¤Ð¡¢¤½¤ì¤Ï¥³¥ß¥Ã¥È¤µ¤ì¤ë¡£É¬Íפʤ饢¥×¥ê¥±¡¼¥·¥ç¥ó¥×
+    ¥í¥°¥é¥à¤Ï minput_lookup () ¤òÆɤó¤Ç¤½¤Î¥Æ¥­¥¹¥È¤ò¼è¤ê½Ð¤»¤ë¡£¤½¤Î
+    ºÝ¡¢minput_lookup () ¤Î°ú¿ô @c KEY ¤È @c ARG ¤Ï̵»ë¤µ¤ì¤ë¡£ */
+void
+minput_reset_ic (MInputContext *ic)
+{
+  if (ic->im->driver.callback_list)
+    minput__callback (ic, Minput_reset);
+}
+
 
 /*** @} */
 /*=*/