(minput_list): Extern it.
[m17n/m17n-lib.git] / src / textprop.c
index 0158314..4a39e9b 100644 (file)
@@ -1,5 +1,5 @@
 /* textprop.c -- text property module.
-   Copyright (C) 2003, 2004
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H15PRO112
 
@@ -17,7 +17,7 @@
 
    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
@@ -32,8 +32,8 @@
     application programs can be simple.
 
     A text property consists of a @e key and @e values, where key is a
-    symbol and values are anything that can be cast to <tt>(void
-    *)</tt>.  Unlike other types of properties, a text property can
+    symbol and values are anything that can be cast to <tt>(void *)
+    </tt>.  Unlike other types of properties, a text property can
     have multiple values.  "The text property whose key is K" may be
     shortened to "K property".  */
 
@@ -512,7 +512,7 @@ adjust_intervals (MInterval *head, MInterval *tail, int diff)
 
   if (diff < 0)
     {
-      /* Adjust end poistions of properties starting before HEAD.  */
+      /* Adjust end positions of properties starting before HEAD.  */
       for (i = 0; i < head->nprops; i++)
        {
          prop = head->stack[i];
@@ -1021,20 +1021,19 @@ pop_all_properties (MTextPlist *plist, int from, int to)
 }
 
 
-/* Delete volatile text properties between FROM and TO.  If KEY is
-   Mnil, we are going to delete text, thus both strongly and weakly
-   volatile properties must be deleted.  Otherwise we are going to
-   modify a text property KEY, thus only strongly volatile properties
-   whose key is not KEY must be deleted.  */
+/* Delete volatile text properties between FROM and TO.  If DELETING
+   is nonzero, we are going to delete text, thus both strongly and
+   weakly volatile properties must be deleted.  Otherwise we are going
+   to modify a text property KEY, thus only strongly volatile
+   properties whose key is not KEY must be deleted.  */
 
 static void
-prepare_to_modify (MText *mt, int from, int to, MSymbol key)
+prepare_to_modify (MText *mt, int from, int to, MSymbol key, int deleting)
 {
   MTextPlist *plist = mt->plist, *prev = NULL;
   int mask_bits = MTEXTPROP_VOLATILE_STRONG;
-  int deleting = (key == Mnil) && (from < to);
 
-  if (key == Mnil)
+  if (deleting)
     mask_bits |= MTEXTPROP_VOLATILE_WEAK;
   while (plist)
     {
@@ -1128,16 +1127,16 @@ dump_interval (MInterval *interval, int indent)
   memset (prefix, 32, indent);
   prefix[indent] = 0;
 
-  fprintf (stderr, "(interval %d-%d (%d)", interval->start, interval->end,
-          interval->nprops);
+  fprintf (mdebug__output, "(interval %d-%d (%d)",
+          interval->start, interval->end, interval->nprops);
   for (i = 0; i < interval->nprops; i++)
-    fprintf (stderr, "\n%s (%d %d/%d %d-%d 0x%x)",
+    fprintf (mdebug__output, "\n%s (%d %d/%d %d-%d 0x%x)",
             prefix, i,
             interval->stack[i]->control.ref_count,
             interval->stack[i]->attach_count,
             interval->stack[i]->start, interval->stack[i]->end,
             (unsigned) interval->stack[i]->val);
-  fprintf (stderr, ")");
+  fprintf (mdebug__output, ")");
 }
 
 void
@@ -1148,31 +1147,33 @@ dump_textplist (MTextPlist *plist, int indent)
   memset (prefix, 32, indent);
   prefix[indent] = 0;
 
-  fprintf (stderr, "(properties");
+  fprintf (mdebug__output, "(properties");
   if (! plist)
-    fprintf (stderr, ")\n");
+    fprintf (mdebug__output, ")\n");
   else
     {
-      fprintf (stderr, "\n");
+      fprintf (mdebug__output, "\n");
       while (plist)
        {
          MInterval *interval = plist->head;
 
-         fprintf (stderr, "%s (%s", prefix, msymbol_name (plist->key));
+         fprintf (mdebug__output, "%s (%s", prefix, msymbol_name (plist->key));
          while (interval)
            {
-             fprintf (stderr, " (%d %d", interval->start, interval->end);
+             fprintf (mdebug__output, " (%d %d",
+                      interval->start, interval->end);
              if (interval->nprops > 0)
                {
                  int i;
 
                  for (i = 0; i < interval->nprops; i++)
-                   fprintf (stderr, " 0x%x", (int) interval->stack[i]->val);
+                   fprintf (mdebug__output, " 0x%x",
+                            (int) interval->stack[i]->val);
                }
-             fprintf (stderr, ")");
+             fprintf (mdebug__output, ")");
              interval = interval->next;
            }
-         fprintf (stderr, ")\n");
+         fprintf (mdebug__output, ")\n");
          xassert (check_plist (plist, 0) == 0);
          plist = plist->next;
        }
@@ -1185,7 +1186,7 @@ dump_textplist (MTextPlist *plist, int indent)
 int
 mtext__prop_init ()
 {
-  text_property_table.count = 0;
+  M17N_OBJECT_ADD_ARRAY (text_property_table, "Text property");
   Mtext_prop_serializer = msymbol ("text-prop-serializer");
   Mtext_prop_deserializer = msymbol ("text-prop-deserializer");
   return 0;
@@ -1203,7 +1204,6 @@ mtext__prop_fini ()
       pool = next;
     }
   interval_pool_root.next = NULL;  
-  mdebug__report_object ("Text property", &text_property_table);
 }
 
 
@@ -1260,7 +1260,7 @@ mtext__adjust_plist_for_delete (MText *mt, int pos, int len)
     }      
 
   to = pos + len;
-  prepare_to_modify (mt, pos, to, Mnil);
+  prepare_to_modify (mt, pos, to, Mnil, 1);
   for (plist = mt->plist; plist; plist = plist->next)
     {
       MInterval *interval = pop_all_properties (plist, pos, to);
@@ -1300,7 +1300,7 @@ mtext__adjust_plist_for_insert (MText *mt, int pos, int nchars,
       return;
     }
   if (pos > 0 && pos < mtext_nchars (mt))
-    prepare_to_modify (mt, pos, pos, Mnil);
+    prepare_to_modify (mt, pos, pos, Mnil, 0);
 
   for (pl_last = NULL, pl = mt->plist; pl; pl_last = pl, pl = pl->next)
     {
@@ -1429,6 +1429,56 @@ mtext__adjust_plist_for_insert (MText *mt, int pos, int nchars,
     }
 }
 
+/* len1 > 0 && len2 > 0 */
+
+void
+mtext__adjust_plist_for_change (MText *mt, int pos, int len1, int len2)
+{
+  int pos2 = pos + len1;
+
+  prepare_to_modify (mt, pos, pos2, Mnil, 0);
+
+  if (len1 < len2)
+    {
+      int diff = len2 - len1;
+      MTextPlist *plist;
+
+      for (plist = mt->plist; plist; plist = plist->next)
+       {
+         MInterval *head = find_interval (plist, pos2);
+         MInterval *tail = plist->tail;
+         MTextProperty *prop;
+         int i;
+
+         if (head)
+           {
+             if (head->start == pos2)
+               head = head->prev;
+             while (tail != head)
+               {
+                 for (i = 0; i < tail->nprops; i++)
+                   {
+                     prop = tail->stack[i];
+                     if (prop->start == tail->start)
+                       prop->start += diff, prop->end += diff;
+                   }
+                 tail->start += diff;
+                 tail->end += diff;
+                 tail = tail->prev;
+               }
+           }
+         for (i = 0; i < tail->nprops; i++)
+           tail->stack[i]->end += diff;
+         tail->end += diff;
+       }
+    }
+  else if (len1 > len2)
+    {
+      mtext__adjust_plist_for_delete (mt, pos + len2, len1 - len2);
+    }
+}
+
+
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 
@@ -1597,7 +1647,7 @@ mtext_get_prop_values (MText *mt, int pos, MSymbol key,
 /*=*/
 
 /***en
-    @brief Get list of text property keys at a position of an M-text.
+    @brief Get a list of text property keys at a position of an M-text.
 
     The mtext_get_prop_keys () function creates an array whose
     elements are the keys of text properties found at position $POS in
@@ -1733,7 +1783,7 @@ mtext_put_prop (MText *mt, int from, int to, MSymbol key, void *val)
 
   M_CHECK_RANGE (mt, from, to, -1, 0);
 
-  prepare_to_modify (mt, from, to, key);
+  prepare_to_modify (mt, from, to, key, 0);
   plist = get_plist_create (mt, key, 1);
   interval = pop_all_properties (plist, from, to);
   prop = new_text_property (mt, from, to, key, val, 0);
@@ -1794,7 +1844,7 @@ mtext_put_prop_values (MText *mt, int from, int to,
 
   M_CHECK_RANGE (mt, from, to, -1, 0);
 
-  prepare_to_modify (mt, from, to, key);
+  prepare_to_modify (mt, from, to, key, 0);
   plist = get_plist_create (mt, key, 1);
   interval = pop_all_properties (plist, from, to);
   if (num > 0)
@@ -1823,7 +1873,8 @@ mtext_put_prop_values (MText *mt, int from, int to,
 
     The mtext_push_prop () function pushes a text property whose key
     is $KEY and value is $VAL to the characters between $FROM
-    (inclusive) and $TO (exclusive) in $MT.  With this functio,
+    (inclusive) and $TO (exclusive) in M-text $MT.  With this
+    function,
 
 @verbatim
                     FROM                    TO
@@ -1891,7 +1942,7 @@ mtext_push_prop (MText *mt, int from, int to,
 
   M_CHECK_RANGE (mt, from, to, -1, 0);
 
-  prepare_to_modify (mt, from, to, key);
+  prepare_to_modify (mt, from, to, key, 0);
   plist = get_plist_create (mt, key, 1);
 
   /* Find an interval that covers the position FROM.  */
@@ -2056,7 +2107,7 @@ mtext_pop_prop (MText *mt, int from, int to, MSymbol key)
     /* No property to pop.  */
     return 0;
 
-  prepare_to_modify (mt, from, to, key);
+  prepare_to_modify (mt, from, to, key, 0);
 
   /* If the found interval starts before FROM and has value(s), divide
      it at FROM.  */
@@ -2140,7 +2191,7 @@ mtext_pop_prop (MText *mt, int from, int to, MSymbol key)
 
     ´Ø¿ô mtext_prop_range () ¤Ï¡¢»ØÄꤷ¤¿¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬Æ±¤¸
     ¤Ç¤¢¤ëϢ³¤·¤¿Ê¸»ú¤ÎÈϰϤòÄ´¤Ù¤ë¡£¤Þ¤º M-text $MT ¤Î $POS ¤Î°ÌÃÖ¤Ë
-    ¤¢¤ëʸ»ú¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼ $KEY ¤Ç»ØÄꤵ¤ì¤¿¤â¤Î¤ÎÃͤò¸«¤Ä¤±
+    ¤¢¤ëʸ»ú¤Î¥×¥í¥Ñ¥Æ¥£¤Î¤¦¤Á¡¢¥­¡¼ $KEY ¤Ç»ØÄꤵ¤ì¤¿¤â¤ÎÃͤò¸«¤Ä¤±
     ¤ë¡£¤½¤·¤ÆÁ°¸å¤Îʸ»ú¤â $KEY ¤Î¥×¥í¥Ñ¥Æ¥£¤ÎÃͤ¬Æ±¤¸¤Ç¤¢¤ë¤«¤É¤¦¤«¤ò
     Ä´¤Ù¤ë¡£¸«¤Ä¤±¤¿ÈϰϤκǽé¤ÈºÇ¸å¤ò¡¢¤½¤ì¤¾¤ì $FROM ¤È $TO ¤Ë¥Ý¥¤¥ó
     ¥È¤µ¤ì¤ëÊÑ¿ô¤ËÊݸ¤¹¤ë¡£$FROM ¤ËÊݸ¤µ¤ì¤ëʸ»ú¤Î°ÌÃ֤ϸ«¤Ä¤±¤¿ÈÏ°Ï
@@ -2235,6 +2286,7 @@ mtext_prop_range (MText *mt, MSymbol key, int pos,
 
     $CONTROL_BITS must be 0 or logical OR of @c enum @c
     MTextPropertyControl.  */
+
 /***ja
     @brief ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤òÀ¸À®¤¹¤ë.
 
@@ -2257,6 +2309,7 @@ mtext_property (MSymbol key, void *val, int control_bits)
     The mtext_property_mtext () function returns the M-text to which
     text property $PROP is attached.  If $PROP is currently detached,
     NULL is returned.  */
+
 /***ja
     @brief ¤¢¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä M-text ¤òÊÖ¤¹.
 
@@ -2275,6 +2328,7 @@ mtext_property_mtext (MTextProperty *prop)
 
     The mtext_property_key () function returns the key (symbol) of
     text property $PROP.  */
+
 /***ja
     @brief ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î¥­¡¼¤òÊÖ¤¹.
 
@@ -2292,6 +2346,7 @@ mtext_property_key (MTextProperty *prop)
 
     The mtext_property_value () function returns the value of text
     property $PROP.  */
+
 /***ja
     @brief ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ÎÃͤòÊÖ¤¹.
 
@@ -2311,6 +2366,7 @@ mtext_property_value (MTextProperty *prop)
     text property $PROP.  The start position is a character position
     of an M-text where $PROP begins.  If $PROP is detached, it returns
     -1.  */
+
 /***ja
     @brief ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î³«»Ï°ÌÃÖ¤òÊÖ¤¹.
 
@@ -2331,6 +2387,7 @@ mtext_property_start (MTextProperty *prop)
     text property $PROP.  The end position is a character position of
     an M-text where $PROP ends.  If $PROP is detached, it returns
     -1.  */
+
 /***ja
     @brief ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î½ªÎ»°ÌÃÖ¤òÊÖ¤¹.
 
@@ -2358,6 +2415,7 @@ mtext_property_end (MTextProperty *prop)
 
     If an error is detected, mtext_get_property () returns @c NULL and
     assigns an error code to the external variable #merror_code.  */
+
 /***ja
     @brief °ìÈÖ¾å¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤òÆÀ¤ë.
 
@@ -2405,6 +2463,7 @@ mtext_get_property (MText *mt, int pos, MSymbol key)
     $POS does not have a property whose key is $KEY, the return value
     is 0. If an error is detected, mtext_get_properties () returns -1
     and assigns an error code to the external variable #merror_code.  */
+
 /***ja
     @brief Ê£¿ô¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤òÆÀ¤ë.
 
@@ -2468,6 +2527,7 @@ mtext_get_properties (MText *mt, int pos, MSymbol key,
     If the operation was successful, mtext_attach_property () returns
     0.  Otherwise it returns -1 and assigns an error code to the
     external variable #merror_code.  */
+
 /***ja
     @brief  M-text¤Ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤òÉղ乤ë.
 
@@ -2480,6 +2540,7 @@ mtext_get_properties (MText *mt, int pos, MSymbol key,
     ¤ì¤Ð -1 ¤òÊÖ¤·¤Æ³°ÉôÊÑ¿ô#merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£      */
 
 
+int
 mtext_attach_property (MText *mt, int from, int to, MTextProperty *prop)
 {     
   MTextPlist *plist;
@@ -2490,7 +2551,7 @@ mtext_attach_property (MText *mt, int from, int to, MTextProperty *prop)
   M17N_OBJECT_REF (prop);
   if (prop->mt)
     mtext_detach_property (prop);
-  prepare_to_modify (mt, from, to, prop->key);
+  prepare_to_modify (mt, from, to, prop->key, 0);
   plist = get_plist_create (mt, prop->key, 1);
   xassert (check_plist (plist, 0) == 0);
   interval = pop_all_properties (plist, from, to);
@@ -2517,6 +2578,7 @@ mtext_attach_property (MText *mt, int from, int to, MTextProperty *prop)
 
     @return
     This function always returns 0.  */
+
 /***ja
     @brief  M-text ¤«¤é¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤òʬΥ¤¹¤ë.
 
@@ -2533,7 +2595,7 @@ mtext_detach_property (MTextProperty *prop)
 
   if (! prop->mt)
     return 0;
-  prepare_to_modify (prop->mt, start, end, prop->key);
+  prepare_to_modify (prop->mt, start, end, prop->key, 0);
   plist = get_plist_create (prop->mt, prop->key, 0);
   xassert (plist);
   detach_property (plist, prop, NULL);
@@ -2543,18 +2605,21 @@ mtext_detach_property (MTextProperty *prop)
 /***en
     @brief Push a text property onto an M-text.
 
-    The mtext_push_property () function attaches text property $PROP on
-    M-text $MT by the "push" manner.
+    The mtext_push_property () function pushes text property $PROP to
+    the characters between $FROM (inclusive) and $TO (exclusive) in
+    M-text $MT.
 
     @return
     If the operation was successful, mtext_push_property () returns
     0.  Otherwise it returns -1 and assigns an error code to the
     external variable #merror_code.  */
+
 /***ja
     @brief M-text ¤Ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥×¥Ã¥·¥å¤¹¤ë.
 
-    ´Ø¿ô mtext_push_property () ¤Ï¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ $PROP ¤òM-text
-    $MT ¤Ë¥×¥Ã¥·¥å¤·¤ÆÉղ乤롣
+    ´Ø¿ô mtext_push_property () ¤Ï¡¢¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ $PROP ¤ò¡¢
+    M-text $MT Ãæ¤Î $FROM ¡Ê´Þ¤Þ¤ì¤ë¡Ë¤«¤é $TO ¡Ê´Þ¤Þ¤ì¤Ê¤¤¡Ë¤ÎÈϰϤÎ
+    Ê¸»ú¤Ë¥×¥Ã¥·¥å¤¹¤ë¡£
 
     @return
     ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð¡¢mtext_push_property () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±
@@ -2573,7 +2638,7 @@ mtext_push_property (MText *mt, int from, int to, MTextProperty *prop)
   M17N_OBJECT_REF (prop);
   if (prop->mt)
     mtext_detach_property (prop);
-  prepare_to_modify (mt, from, to, prop->key);
+  prepare_to_modify (mt, from, to, prop->key, 0);
   plist = get_plist_create (mt, prop->key, 1);
   prop->mt = mt;
   prop->start = from;
@@ -2657,17 +2722,20 @@ mtext_push_property (MText *mt, int from, int to, MTextProperty *prop)
     property whose key is #Mtext_prop_serializer and value is a
     pointer to an appropriate serializer function.
 
-    @seealso Mtext_prop_serializer (), MTextPropSerializeFunc
+    @seealso
+    mtext_serialize (), #MTextPropSerializeFunc
   */
+
 /***ja
     @brief ¥·¥ê¥¢¥é¥¤¥¶´Ø¿ô¤ò»ØÄꤹ¤ë¥·¥ó¥Ü¥ë.
 
-    ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥·¥ê¥¢¥é¥¤¥º¤¹¤ë¤¿¤á¤Ë¡¢¥æ¡¼¥¶¤Ï¥Æ¥­¥¹¥È¥×¥í¥Ñ
+    ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥·¥ê¥¢¥é¥¤¥º¤¹¤ë¤¿¤á¤Ë¤Ï¡¢¤½¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ
     ¥Æ¥£ÍѤΥ·¥ê¥¢¥é¥¤¥¶´Ø¿ô¤òÍ¿¤¨¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¶ñÂÎŪ¤Ë¤Ï¡¢
     #Mtext_prop_serializer ¤ò¥­¡¼¤È¤·¡¢Å¬Àڤʥ·¥ê¥¢¥é¥¤¥º´Ø¿ô¤Ø¤Î¥Ý¥¤
-    ¥ó¥¿¤òÃͤȤ¹¤ë¥·¥ó¥Ü¥ë¤ò»ØÄꤹ¤ë¡£
+    ¥ó¥¿¤òÃͤȤ¹¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ë¡£
 
-    @seealso Mtext_prop_serializer (), MTextPropSerializeFunc
+    @seealso
+    mtext_serialize (), #MTextPropSerializeFunc
   */
 MSymbol Mtext_prop_serializer;
 
@@ -2679,17 +2747,20 @@ MSymbol Mtext_prop_serializer;
     property whose key is #Mtext_prop_deserializer and value is a
     pointer to an appropriate deserializer function.
 
-    @seealso Mtext_prop_serializer (), MTextPropSerializeFunc
+    @seealso
+    mtext_deserialize (), #MTextPropSerializeFunc
   */
+
 /***ja
     @brief ¥Ç¥·¥ê¥¢¥é¥¤¥¶´Ø¿ô¤ò»ØÄꤹ¤ë¥·¥ó¥Ü¥ë.
 
-    ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º¤¹¤ë¤¿¤á¤Ë¡¢¥æ¡¼¥¶¤Ï¥Æ¥­¥¹¥È¥×¥í
+    ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º¤¹¤ë¤¿¤á¤Ë¤Ï¡¢¤½¤Î¥Æ¥­¥¹¥È¥×¥í
     ¥Ñ¥Æ¥£ÍѤΥǥ·¥ê¥¢¥é¥¤¥¶´Ø¿ô¤òÍ¿¤¨¤Ê¤¯¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£¶ñÂÎŪ¤Ë¤Ï¡¢
     #Mtext_prop_deserializer ¤ò¥­¡¼¤È¤·¡¢Å¬Àڤʥǥ·¥ê¥¢¥é¥¤¥º´Ø¿ô¤Ø¤Î
-    ¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥·¥ó¥Ü¥ë¤ò»ØÄꤹ¤ë¡£
+    ¥Ý¥¤¥ó¥¿¤òÃͤȤ¹¤ë¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£¤ò»ØÄꤹ¤ë¡£
 
-    @seealso Mtext_prop_serializer (), MTextPropSerializeFunc
+    @seealso
+    mtext_deserialize (), #MTextPropSerializeFunc
   */
 MSymbol Mtext_prop_deserializer;
 
@@ -2697,14 +2768,15 @@ MSymbol Mtext_prop_deserializer;
     @brief Serialize text properties in an M-text.
 
     The mtext_serialize () function serializes the text between $FROM
-    and $TO in M-text $MT.  The serialized result is an M-text in the
+    and $TO in M-text $MT.  The serialized result is an M-text in a
     form of XML.  $PROPERTY_LIST limits the text properties to be
-    serialized.  If a symbol 
-    @li appears as the value of an element in $PROPERTY_LIST (the key must be @c Mt ), and 
-    @li has the symbol    property #Mtext_prop_serializer, 
-    
-    a text property having that symbol as its key is turned into the
-    "property" element in the resulting XML representation.
+    serialized. Only those text properties whose key 
+
+    @li appears as the value of an element in $PROPERTY_LIST, and
+    @li has the symbol property #Mtext_prop_serializer
+
+    are serialized as a "property" element in the resulting XML
+    representation.
 
     The DTD of the generated XML is as follows:
 
@@ -2730,19 +2802,21 @@ MSymbol Mtext_prop_deserializer;
     error code to the external variable #merror_code.
 
     @seealso
-    mtext_deserialize (), Mtext_prop_serializer  */
+    mtext_deserialize (), #Mtext_prop_serializer  */
+
 /***ja
     @brief M-text Ãæ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥·¥ê¥¢¥é¥¤¥º¤¹¤ë.
 
     ´Ø¿ô mtext_serialize () ¤Ï M-text $MT ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î¥Æ¥­
-    ¥¹¥È¤ò¥·¥ê¥¢¥é¥¤¥º¤¹¤ë¡£¥·¥ê¥¢¥é¥¤¥º¤·¤¿·ë²Ì XML ·Á¼°¤Î M-text ¤Ç
+    ¥¹¥È¤ò¥·¥ê¥¢¥é¥¤¥º¤¹¤ë¡£¥·¥ê¥¢¥é¥¤¥º¤·¤¿·ë²Ì¤Ï XML ·Á¼°¤Î M-text ¤Ç
     ¤¢¤ë¡£ $PROPERTY_LIST ¤Ï¥·¥ê¥¢¥é¥¤¥º¤µ¤ì¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¸ÂÄê
-    ¤¹¤ë¡£¥·¥ó¥Ü¥ë¤¬
-    @li $PROPERTY_LIST (¥­¡¼¤Ï @c Mt) ¤ÎÍ×ÁǤÎÃͤȤ·¤Æ¸½¤ï¤ì¡¢
-    @li ¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£ #Mtext_prop_serializer ¤ò»ý¤Ä¤Ê¤é¤Ð¡¢
+    ¤¹¤ë¡£ÂоݤȤʤë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¡¢¤½¤Î¥­¡¼¤¬
+
+    @li $PROPERTY_LIST ¤ÎÍ×ÁǤÎÃͤȤ·¤Æ¸½¤ï¤ì¡¢¤«¤Ä
+    @li ¥·¥ó¥Ü¥ë¥×¥í¥Ñ¥Æ¥£ #Mtext_prop_serializer ¤ò»ý¤Ä
     
-    ¤³¤Î¥·¥ó¥Ü¥ë¤ò¥­¡¼¤È¤¹¤ë¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¡¢À¸À®¤µ¤ì¤ë XML É½¸½
-    Ãæ¤Ç "property" Í×ÁǤËÊÑ´¹¤µ¤ì¤ë¡£
+    ¤â¤Î¤Î¤ß¤Ç¤¢¤ë¡£¤³¤Î¾ò·ï¤òËþ¤¿¤¹¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¡¢À¸À®¤µ¤ì¤ë 
+    XML É½¸½Ãæ¤Ç "property" Í×ÁǤ˥·¥ê¥¢¥é¥¤¥º¤µ¤ì¤ë¡£
 
     À¸À®¤µ¤ì¤ë XML ¤Î DTD ¤Ï°Ê²¼¤ÎÄ̤ê:
 
@@ -2768,7 +2842,7 @@ MSymbol Mtext_prop_deserializer;
     ¤òÀßÄꤹ¤ë¡£
 
     @seealso
-    mtext_deserialize (), Mtext_prop_serializer  */
+    mtext_deserialize (), #Mtext_prop_serializer  */
 
 MText *
 mtext_serialize (MText *mt, int from, int to, MPlist *property_list)
@@ -2783,6 +2857,11 @@ mtext_serialize (MText *mt, int from, int to, MPlist *property_list)
   int n;
 
   M_CHECK_RANGE (mt, from, to, NULL, NULL);
+  if (mt->format != MTEXT_FORMAT_US_ASCII
+      && mt->format != MTEXT_FORMAT_UTF_8)
+    mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
+  if (MTEXT_DATA (mt)[mtext_nbytes (mt)] != 0)
+    MTEXT_DATA (mt)[mtext_nbytes (mt)] = 0;
   doc = xmlParseMemory (XML_TEMPLATE, strlen (XML_TEMPLATE) + 1);
   node = xmlDocGetRootElement (doc);
 
@@ -2791,7 +2870,8 @@ mtext_serialize (MText *mt, int from, int to, MPlist *property_list)
     {
       MSymbol key = MPLIST_VAL (pl);
 
-      func = (MTextPropSerializeFunc) msymbol_get (key, Mtext_prop_serializer);
+      func = ((MTextPropSerializeFunc)
+             msymbol_get_func (key, Mtext_prop_serializer));
       if (func)
        extract_text_properties (mt, from, to, key, plist);
     }
@@ -2804,13 +2884,13 @@ mtext_serialize (MText *mt, int from, int to, MPlist *property_list)
       MPlist *serialized_plist;
       xmlNodePtr child;
 
-      func = (MTextPropSerializeFunc) msymbol_get (prop->key,
-                                                  Mtext_prop_serializer);
+      func = ((MTextPropSerializeFunc)
+             msymbol_get_func (prop->key, Mtext_prop_serializer));
       serialized_plist = (func) (prop->val);
       if (! serialized_plist)
        continue;
       mtext_reset (work);
-      mplist__serialize (work, serialized_plist);
+      mplist__serialize (work, serialized_plist, 0);
       child = xmlNewChild (node, NULL, (xmlChar *) "property", NULL);
       xmlSetProp (child, (xmlChar *) "key",
                  (xmlChar *) MSYMBOL_NAME (prop->key));
@@ -2857,7 +2937,7 @@ mtext_serialize (MText *mt, int from, int to, MPlist *property_list)
     @brief Deserialize text properties in an M-text.
 
     The mtext_deserialize () function deserializes M-text $MT.  $MT
-    must be an XML having the followng DTD.
+    must be an XML having the following DTD.
 
 @verbatim
 <!DOCTYPE mtext [
@@ -2881,7 +2961,8 @@ mtext_serialize (MText *mt, int from, int to, MPlist *property_list)
     code to the external variable #merror_code.
 
     @seealso
-    mtext_serialize (), Mtext_prop_deserializer  */
+    mtext_serialize (), #Mtext_prop_deserializer  */
+
 /***ja
     @brief M-text Ãæ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò¥Ç¥·¥ê¥¢¥é¥¤¥º¤¹¤ë.
 
@@ -2910,7 +2991,7 @@ mtext_serialize (MText *mt, int from, int to, MPlist *property_list)
     ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @seealso
-    mtext_serialize (), Mtext_prop_deserializer  */
+    mtext_serialize (), #Mtext_prop_deserializer  */
 
 MText *
 mtext_deserialize (MText *mt)
@@ -2985,7 +3066,7 @@ mtext_deserialize (MText *mt)
 
        key = msymbol ((char *) key_str);
        func = ((MTextPropDeserializeFunc)
-               msymbol_get (key, Mtext_prop_deserializer));
+               msymbol_get_func (key, Mtext_prop_deserializer));
        if (! func)
          continue;
        plist = mplist__from_string (val_str, strlen ((char *) val_str));