Print debug information to mdebug__output instead of stderr.
[m17n/m17n-lib.git] / src / mtext.c
index 26e265d..8efe58e 100644 (file)
@@ -1,5 +1,5 @@
 /* mtext.c -- M-text module.
 /* mtext.c -- M-text 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
 
      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
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
 /***en
    02111-1307, USA.  */
 
 /***en
 
     M-text ¤Ë¤Ï¡¢C-string ¤Ë¤Ê¤¤°Ê²¼¤ÎÆÃħ¤¬¤¢¤ë¡£     
 
 
     M-text ¤Ë¤Ï¡¢C-string ¤Ë¤Ê¤¤°Ê²¼¤ÎÆÃħ¤¬¤¢¤ë¡£     
 
-    @li M-text ¤ÏÈó¾ï¤Ë¿¤¯¤Î¼ïÎà¤Îʸ»ú¤ò¡¢Æ±»þ¤Ë¡¢º®ºß¤µ¤»¤Æ¡¢Æ±Åù¤Ë
-    °·¤¦¤³¤È¤¬¤Ç¤­¤ë¡£Unicode ¤ÎÁ´¤Æ¤Îʸ»ú¤Ï¤â¤Á¤í¤ó¡¢¤è¤ê¿¤¯¤Îʸ»ú¤Þ
-    ¤Ç°·¤¨¤ë¡£¤³¤ì¤Ï¿¸À¸ì¥Æ¥­¥¹¥È¤ò°·¤¦¾å¤Ç¤Ïɬ¿Ü¤Îµ¡Ç½¤Ç¤¢¤ë¡£
+    @li M-text ¤ÏÈó¾ï¤Ë¿¤¯¤Î¼ïÎà¤Îʸ»ú¤ò¡¢Æ±»þ¤Ë¡¢º®ºß¤µ¤»¤Æ¡¢Æ±Åù¤Ë°·¤¦¤³¤È¤¬¤Ç¤­¤ë¡£
+    Unicode ¤ÎÁ´¤Æ¤Îʸ»ú¤Ï¤â¤Á¤í¤ó¡¢¤è¤ê¿¤¯¤Îʸ»ú¤Þ¤Ç¤â°·¤¦¤³¤È¤¬¤Ç¤­¤ë¡£
+    ¤³¤ì¤Ï¿¸À¸ì¥Æ¥­¥¹¥È¤ò°·¤¦¾å¤Ç¤Ïɬ¿Ü¤Îµ¡Ç½¤Ç¤¢¤ë¡£
 
 
-    @li M-text Æâ¤Î³Æʸ»ú¤Ï¡¢@e ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ ¤È¸Æ¤Ð¤ì¤ë¥×¥í¥Ñ¥Æ¥£
-    ¤ò»ý¤Ä¤³¤È¤¬¤Ç¤­¤ë¡£¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ë¤è¤Ã¤Æ¡¢¥Æ¥­¥¹¥È¤Î³ÆÉô°Ì¤Ë
-    ´Ø¤¹¤ëÍÍ¡¹¤Ê¾ðÊó¤ò M-text Æâ¤ËÊÝ»ý¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£¤½¤Î¤¿¤á¡¢¤½¤ì
-    ¤é¤Î¾ðÊó¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥àÆâ¤ÇÅý°ìŪ¤Ë°·¤¦¤³¤È¤¬¤Ç¤­¤ë¡£
-    ¤Þ¤¿¡¢M-text ¼«ÂΤ¬Ë­É٤ʾðÊó¤ò»ý¤Ä¤¿¤á¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
-    ¥àÃæ¤Î³Æ´Ø¿ô¤ò´ÊÁDz½¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
+    @li M-text Æâ¤Î³Æʸ»ú¤Ï¡¢@e ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ 
+    ¤È¸Æ¤Ð¤ì¤ë¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Á¡¢
+    ¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ë¤è¤Ã¤Æ¡¢¥Æ¥­¥¹¥È¤Î³ÆÉô°Ì¤Ë´Ø¤¹¤ëÍÍ¡¹¤Ê¾ðÊó¤ò
+    M-text Æâ¤ËÊÝ»ý¤¹¤ë¤³¤È¤¬²Äǽ¤Ë¤Ê¤ë¡£
+    ¤½¤Î¤¿¤á¡¢¤½¤ì¤é¤Î¾ðÊó¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥àÆâ¤ÇÅý°ìŪ¤Ë°·¤¦¤³¤È¤¬²Äǽ¤Ë¤Ê¤ë¡£
+    ¤Þ¤¿¡¢M-text 
+    ¼«ÂΤ¬Ë­É٤ʾðÊó¤ò»ý¤Ä¤¿¤á¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥àÃæ¤Î³Æ´Ø¿ô¤ò´ÊÁDz½¤¹¤ë¤³¤È¤¬¤Ç¤­¤ë¡£
 
 
-    ¤µ¤é¤Ëm17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢ C-string ¤òÁàºî¤¹¤ë¤¿¤á¤ËÄ󶡤µ¤ì¤ë¼ï¡¹
-    ¤Î´Ø¿ô¤ÈƱÅù¤Î¤â¤Î¤ò M-text ¤òÁàºî¤¹¤ë¤¿¤á¤Ë¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£  */
+    ¤µ¤é¤Ëm17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢ C-string 
+    ¤òÁàºî¤¹¤ë¤¿¤á¤ËÄ󶡤µ¤ì¤ë¼ï¡¹¤Î´Ø¿ô¤ÈƱÅù¤Î¤â¤Î¤ò M-text 
+    ¤òÁàºî¤¹¤ë¤¿¤á¤Ë¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£  */
 
 /*=*/
 
 
 /*=*/
 
@@ -96,14 +98,6 @@ static M17NObjectArray mtext_table;
 
 static MSymbol M_charbag;
 
 
 static MSymbol M_charbag;
 
-#ifdef WORDS_BIGENDIAN
-static enum MTextFormat default_utf_16 = MTEXT_FORMAT_UTF_16BE;
-static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32BE;
-#else
-static enum MTextFormat default_utf_16 = MTEXT_FORMAT_UTF_16LE;
-static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32LE;
-#endif
-
 /** Increment character position CHAR_POS and unit position UNIT_POS
     so that they point to the next character in M-text MT.  No range
     check for CHAR_POS and UNIT_POS.  */
 /** Increment character position CHAR_POS and unit position UNIT_POS
     so that they point to the next character in M-text MT.  No range
     check for CHAR_POS and UNIT_POS.  */
@@ -121,7 +115,7 @@ static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32LE;
       {                                                                \
        c = ((unsigned short *) ((mt)->data))[(unit_pos)];      \
                                                                \
       {                                                                \
        c = ((unsigned short *) ((mt)->data))[(unit_pos)];      \
                                                                \
-       if ((mt)->format != default_utf_16)                     \
+       if ((mt)->format != MTEXT_FORMAT_UTF_16)                \
          c = SWAP_16 (c);                                      \
        (unit_pos) += CHAR_UNITS_BY_HEAD_UTF16 (c);             \
       }                                                                \
          c = SWAP_16 (c);                                      \
        (unit_pos) += CHAR_UNITS_BY_HEAD_UTF16 (c);             \
       }                                                                \
@@ -149,7 +143,7 @@ static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32LE;
       {                                                                        \
        int c = ((unsigned short *) ((mt)->data))[(unit_pos) - 1];      \
                                                                        \
       {                                                                        \
        int c = ((unsigned short *) ((mt)->data))[(unit_pos) - 1];      \
                                                                        \
-       if ((mt)->format != default_utf_16)                             \
+       if ((mt)->format != MTEXT_FORMAT_UTF_16)                        \
          c = SWAP_16 (c);                                              \
        (unit_pos) -= 2 - (c < 0xD800 || c >= 0xE000);                  \
       }                                                                        \
          c = SWAP_16 (c);                                              \
        (unit_pos) -= 2 - (c < 0xD800 || c >= 0xE000);                  \
       }                                                                        \
@@ -158,6 +152,11 @@ static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32LE;
     (char_pos)--;                                                      \
   } while (0)
 
     (char_pos)--;                                                      \
   } while (0)
 
+#define FORMAT_COVERAGE(fmt)                                   \
+  (fmt == MTEXT_FORMAT_UTF_8 ? MTEXT_COVERAGE_FULL             \
+   : fmt == MTEXT_FORMAT_US_ASCII ? MTEXT_COVERAGE_ASCII       \
+   : fmt >= MTEXT_FORMAT_UTF_32LE ? MTEXT_COVERAGE_FULL                \
+   : MTEXT_COVERAGE_UNICODE)
 
 /* Compoare sub-texts in MT1 (range FROM1 and TO1) and MT2 (range
    FROM2 to TO2). */
 
 /* Compoare sub-texts in MT1 (range FROM1 and TO1) and MT2 (range
    FROM2 to TO2). */
@@ -245,23 +244,23 @@ insert (MText *mt1, int pos, MText *mt2, int from, int to)
   int unit_bytes;
 
   if (mt1->nchars == 0)
   int unit_bytes;
 
   if (mt1->nchars == 0)
-    mt1->format = mt2->format;
+    mt1->format = mt2->format, mt1->coverage = mt2->coverage;
   else if (mt1->format != mt2->format)
     {
       /* Be sure to make mt1->format sufficient to contain all
         characters in mt2.  */
       if (mt1->format == MTEXT_FORMAT_UTF_8
   else if (mt1->format != mt2->format)
     {
       /* Be sure to make mt1->format sufficient to contain all
         characters in mt2.  */
       if (mt1->format == MTEXT_FORMAT_UTF_8
-         || mt1->format == default_utf_32
-         || (mt1->format == default_utf_16
+         || mt1->format == MTEXT_FORMAT_UTF_32
+         || (mt1->format == MTEXT_FORMAT_UTF_16
              && mt2->format <= MTEXT_FORMAT_UTF_16BE
              && mt2->format != MTEXT_FORMAT_UTF_8))
        ;
       else if (mt1->format == MTEXT_FORMAT_US_ASCII)
        {
          if (mt2->format == MTEXT_FORMAT_UTF_8)
              && mt2->format <= MTEXT_FORMAT_UTF_16BE
              && mt2->format != MTEXT_FORMAT_UTF_8))
        ;
       else if (mt1->format == MTEXT_FORMAT_US_ASCII)
        {
          if (mt2->format == MTEXT_FORMAT_UTF_8)
-           mt1->format = MTEXT_FORMAT_UTF_8;
-         else if (mt2->format == default_utf_16
-                  || mt2->format == default_utf_32)
+           mt1->format = MTEXT_FORMAT_UTF_8, mt1->coverage = mt2->coverage;
+         else if (mt2->format == MTEXT_FORMAT_UTF_16
+                  || mt2->format == MTEXT_FORMAT_UTF_32)
            mtext__adjust_format (mt1, mt2->format);
          else
            mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
            mtext__adjust_format (mt1, mt2->format);
          else
            mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
@@ -313,7 +312,7 @@ insert (MText *mt1, int pos, MText *mt2, int from, int to)
          p += CHAR_STRING_UTF8 (c, p);
        }
     }
          p += CHAR_STRING_UTF8 (c, p);
        }
     }
-  else if (mt1->format == default_utf_16)
+  else if (mt1->format == MTEXT_FORMAT_UTF_16)
     {
       unsigned short *p;
       int total_bytes, i, c;
     {
       unsigned short *p;
       int total_bytes, i, c;
@@ -335,7 +334,7 @@ insert (MText *mt1, int pos, MText *mt2, int from, int to)
          p += CHAR_STRING_UTF16 (c, p);
        }
     }
          p += CHAR_STRING_UTF16 (c, p);
        }
     }
-  else                         /* default_utf_32 */
+  else                         /* MTEXT_FORMAT_UTF_32 */
     {
       unsigned int *p;
       int total_bytes, i;
     {
       unsigned int *p;
       int total_bytes, i;
@@ -413,7 +412,7 @@ span (MText *mt1, MText *mt2, int pos, MSymbol not)
 
 
 static int
 
 
 static int
-count_utf_8_chars (void *data, int nitems)
+count_utf_8_chars (const void *data, int nitems)
 {
   unsigned char *p = (unsigned char *) data;
   unsigned char *pend = p + nitems;
 {
   unsigned char *p = (unsigned char *) data;
   unsigned char *pend = p + nitems;
@@ -441,7 +440,7 @@ count_utf_8_chars (void *data, int nitems)
 }
 
 static int
 }
 
 static int
-count_utf_16_chars (void *data, int nitems, int swap)
+count_utf_16_chars (const void *data, int nitems, int swap)
 {
   unsigned short *p = (unsigned short *) data;
   unsigned short *pend = p + nitems;
 {
   unsigned short *p = (unsigned short *) data;
   unsigned short *pend = p + nitems;
@@ -457,22 +456,18 @@ count_utf_16_chars (void *data, int nitems, int swap)
       if (prev_surrogate)
        {
          if (c < 0xDC00 || c >= 0xE000)
       if (prev_surrogate)
        {
          if (c < 0xDC00 || c >= 0xE000)
-           return -1;
-         prev_surrogate = 0;
+           /* Invalid surrogate */
+           nchars++;
        }
       else
        {
        }
       else
        {
-         if (c < 0xD800)
-           ;
-         else if (c < 0xDC00)
+         if (c >= 0xD800 && c < 0xDC00)
            prev_surrogate = 1;
            prev_surrogate = 1;
-         else if (c < 0xE000)
-           return -1;
          nchars++;
        }
     }
   if (prev_surrogate)
          nchars++;
        }
     }
   if (prev_surrogate)
-    return -1;
+    nchars++;
   return nchars;
 }
 
   return nchars;
 }
 
@@ -492,7 +487,7 @@ find_char_forward (MText *mt, int from, int to, int c)
     {
       unsigned short *p = (unsigned short *) (mt->data) + from_byte;
 
     {
       unsigned short *p = (unsigned short *) (mt->data) + from_byte;
 
-      if (mt->format == default_utf_16)
+      if (mt->format == MTEXT_FORMAT_UTF_16)
        while (from < to && STRING_CHAR_ADVANCE_UTF16 (p) != c) from++;
       else if (c < 0x10000)
        {
        while (from < to && STRING_CHAR_ADVANCE_UTF16 (p) != c) from++;
       else if (c < 0x10000)
        {
@@ -524,7 +519,7 @@ find_char_forward (MText *mt, int from, int to, int c)
       unsigned *p = (unsigned *) (mt->data) + from_byte;
       unsigned c1 = c;
 
       unsigned *p = (unsigned *) (mt->data) + from_byte;
       unsigned c1 = c;
 
-      if (mt->format != default_utf_32)
+      if (mt->format != MTEXT_FORMAT_UTF_32)
        c1 = SWAP_32 (c1);
       while (from < to && *p++ != c1) from++;
     }
        c1 = SWAP_32 (c1);
       while (from < to && *p++ != c1) from++;
     }
@@ -554,7 +549,7 @@ find_char_backward (MText *mt, int from, int to, int c)
     {
       unsigned short *p = (unsigned short *) (mt->data) + to_byte;
 
     {
       unsigned short *p = (unsigned short *) (mt->data) + to_byte;
 
-      if (mt->format == default_utf_16)
+      if (mt->format == MTEXT_FORMAT_UTF_16)
        {
          while (from < to)
            {
        {
          while (from < to)
            {
@@ -594,7 +589,7 @@ find_char_backward (MText *mt, int from, int to, int c)
       unsigned *p = (unsigned *) (mt->data) + to_byte;
       unsigned c1 = c;
 
       unsigned *p = (unsigned *) (mt->data) + to_byte;
       unsigned c1 = c;
 
-      if (mt->format != default_utf_32)
+      if (mt->format != MTEXT_FORMAT_UTF_32)
        c1 = SWAP_32 (c1);
       while (from < to && p[-1] != c1) to--, p--;
     }
        c1 = SWAP_32 (c1);
       while (from < to && p[-1] != c1) to--, p--;
     }
@@ -616,6 +611,8 @@ free_mtext (void *object)
   free (object);
 }
 
   free (object);
 }
 
+/** Case handler (case-folding comparison and case conversion) */
+
 /** Structure for an iterator used in case-fold comparison.  */
 
 struct casecmp_iterator {
 /** Structure for an iterator used in case-fold comparison.  */
 
 struct casecmp_iterator {
@@ -689,14 +686,292 @@ case_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
   return (it2.pos == to2 ? (it1.pos < to1) : -1);
 }
 
   return (it2.pos == to2 ? (it1.pos < to1) : -1);
 }
 
+static MCharTable *tricky_chars, *cased, *soft_dotted, *case_mapping;
+static MCharTable *combining_class;
+
+/* Languages that require special handling in case-conversion.  */
+static MSymbol Mlt, Mtr, Maz;
+
+static MText *gr03A3;
+static MText *lt0049, *lt004A, *lt012E, *lt00CC, *lt00CD, *lt0128;
+static MText *tr0130, *tr0049, *tr0069;
+
+static int
+init_case_conversion ()
+{
+  Mlt = msymbol ("lt");
+  Mtr = msymbol ("tr");
+  Maz = msymbol ("az");
+
+  gr03A3 = mtext ();
+  mtext_cat_char (gr03A3, 0x03C2);
+
+  lt0049 = mtext ();
+  mtext_cat_char (lt0049, 0x0069);
+  mtext_cat_char (lt0049, 0x0307);
+
+  lt004A = mtext ();
+  mtext_cat_char (lt004A, 0x006A);
+  mtext_cat_char (lt004A, 0x0307);
+
+  lt012E = mtext ();
+  mtext_cat_char (lt012E, 0x012F);
+  mtext_cat_char (lt012E, 0x0307);
+
+  lt00CC = mtext ();
+  mtext_cat_char (lt00CC, 0x0069);
+  mtext_cat_char (lt00CC, 0x0307);
+  mtext_cat_char (lt00CC, 0x0300);
+
+  lt00CD = mtext ();
+  mtext_cat_char (lt00CD, 0x0069);
+  mtext_cat_char (lt00CD, 0x0307);
+  mtext_cat_char (lt00CD, 0x0301);
+
+  lt0128 = mtext ();
+  mtext_cat_char (lt0128, 0x0069);
+  mtext_cat_char (lt0128, 0x0307);
+  mtext_cat_char (lt0128, 0x0303);
+
+  tr0130 = mtext ();
+  mtext_cat_char (tr0130, 0x0069);
+
+  tr0049 = mtext ();
+  mtext_cat_char (tr0049, 0x0131);
+
+  tr0069 = mtext ();
+  mtext_cat_char (tr0069, 0x0130);
+
+  if (! (cased = mchar_get_prop_table (msymbol ("cased"), NULL)))
+    return -1;
+  if (! (soft_dotted = mchar_get_prop_table (msymbol ("soft-dotted"), NULL)))
+    return -1;
+  if (! (case_mapping = mchar_get_prop_table (msymbol ("case-mapping"), NULL)))
+    return -1;
+  if (! (combining_class = mchar_get_prop_table (Mcombining_class, NULL)))
+    return -1;
+
+  tricky_chars = mchartable (Mnil, 0);
+  mchartable_set (tricky_chars, 0x0049, (void *) 1);
+  mchartable_set (tricky_chars, 0x004A, (void *) 1);
+  mchartable_set (tricky_chars, 0x00CC, (void *) 1);
+  mchartable_set (tricky_chars, 0x00CD, (void *) 1);
+  mchartable_set (tricky_chars, 0x0128, (void *) 1);
+  mchartable_set (tricky_chars, 0x012E, (void *) 1);
+  mchartable_set (tricky_chars, 0x0130, (void *) 1);
+  mchartable_set (tricky_chars, 0x0307, (void *) 1);
+  mchartable_set (tricky_chars, 0x03A3, (void *) 1);
+  return 0;
+}
+
+#define CASE_CONV_INIT(ret)            \
+  do {                                 \
+    if (! tricky_chars                 \
+       && init_case_conversion () < 0) \
+      MERROR (MERROR_MTEXT, ret);      \
+  } while (0)
+
+/* Replace the character at POS of MT with VAR and increment I and LEN.  */
+
+#define REPLACE(var)                                   \
+  do {                                                 \
+    int varlen = var->nchars;                          \
+                                                       \
+    mtext_replace (mt, pos, pos + 1, var, 0, varlen);  \
+    pos += varlen;                                     \
+    end += varlen - 1;                                 \
+  } while (0)
+
+/* Delete the character at POS of MT and decrement LEN.  */
+
+#define DELETE                         \
+  do {                                 \
+    mtext_del (mt, pos, pos + 1);      \
+    end--;                             \
+  } while (0)
+
+#define LOOKUP                                                         \
+  do {                                                                 \
+    MPlist *pl = (MPlist *) mchartable_lookup (case_mapping, c);       \
+                                                                       \
+    if (pl)                                                            \
+      {                                                                        \
+       /* Lowercase is the 1st element. */                             \
+       MText *lower = MPLIST_VAL ((MPlist *) MPLIST_VAL (pl));         \
+       int llen = mtext_nchars (lower);                                \
+                                                                       \
+       if (mtext_ref_char (lower, 0) != c || llen > 1)                 \
+         {                                                             \
+           mtext_replace (mt, pos, pos + 1, lower, 0, llen);           \
+           pos += llen;                                                \
+           end += llen - 1;                                            \
+         }                                                             \
+       else                                                            \
+         pos++;                                                        \
+      }                                                                        \
+    else                                                               \
+      pos++;                                                           \
+  } while (0)
+
+
+int
+uppercase_precheck (MText *mt, int pos, int end)
+{
+  for (; pos < end; pos++)
+    if (mtext_ref_char (mt, pos) == 0x0307 &&
+       (MSymbol) mtext_get_prop (mt, pos, Mlanguage) == Mlt)
+      return 1;
+  return 0;
+}
+
+int
+lowercase_precheck (MText *mt, int pos, int end)
+{
+  int c;
+  MSymbol lang;
+
+  for (; pos < end; pos++)
+    {
+      c = mtext_ref_char (mt, pos);
+
+      if ((int) mchartable_lookup (tricky_chars, c) == 1)
+      {
+       if (c == 0x03A3)
+         return 1;
+
+       lang = mtext_get_prop (mt, pos, Mlanguage);
+
+       if (lang == Mlt &&
+           (c == 0x0049 || c == 0x004A || c == 0x012E))
+         return 1;
+
+       if ((lang == Mtr || lang == Maz) &&
+           (c == 0x0307 || c == 0x0049))
+         return 1;
+      }
+    }
+  return 0;
+}
+
+#define CASED 1
+#define CASE_IGNORABLE 2
+
+int
+final_sigma (MText *mt, int pos)
+{
+  int i, len = mtext_len (mt);
+  int c;
+
+  for (i = pos - 1; i >= 0; i--)
+    {
+      c = (int) mchartable_lookup (cased, mtext_ref_char (mt, i));
+      if (c == -1)
+       c = 0;
+      if (c & CASED)
+       break;
+      if (! (c & CASE_IGNORABLE))
+       return 0;
+    }
+
+  if (i == -1)
+    return 0;
+
+  for (i = pos + 1; i < len; i++)
+    {
+      c = (int) mchartable_lookup (cased, mtext_ref_char (mt, i));
+      if (c == -1)
+       c = 0;
+      if (c & CASED)
+       return 0;
+      if (! (c & CASE_IGNORABLE))
+       return 1;
+    }
+
+  return 1;
+}
+
+int
+after_soft_dotted (MText *mt, int i)
+{
+  int c, class;
+
+  for (i--; i >= 0; i--)
+    {
+      c = mtext_ref_char (mt, i);
+      if ((MSymbol) mchartable_lookup (soft_dotted, c) == Mt)
+       return 1;
+      class = (int) mchartable_lookup (combining_class, c);
+      if (class == 0 || class == 230)
+       return 0;
+    }
+
+  return 0;
+}
+
+int
+more_above (MText *mt, int i)
+{
+  int class, len = mtext_len (mt);
+
+  for (i++; i < len; i++)
+    {
+      class = (int) mchartable_lookup (combining_class,
+                                      mtext_ref_char (mt, i));
+      if (class == 230)
+       return 1;
+      if (class == 0)
+       return 0;
+    }
+
+  return 0;
+}
+
+int
+before_dot (MText *mt, int i)
+{
+  int c, class, len = mtext_len (mt);
+
+  for (i++; i < len; i++)
+    {
+      c = mtext_ref_char (mt, i);
+      if (c == 0x0307)
+       return 1;
+      class = (int) mchartable_lookup (combining_class, c);
+      if (class == 230 || class == 0)
+       return 0;
+    }
+
+  return 0;
+}
+
+int
+after_i (MText *mt, int i)
+{
+  int c, class;
+
+  for (i--; i >= 0; i--)
+    {
+      c = mtext_ref_char (mt, i);
+      if (c == (int) 'I')
+       return 1;
+      class = (int) mchartable_lookup (combining_class, c);
+      if (class == 230 || class == 0)
+       return 0;
+    }
+
+  return 0;
+}
+
 \f
 /* Internal API */
 
 int
 mtext__init ()
 {
 \f
 /* Internal API */
 
 int
 mtext__init ()
 {
+  M17N_OBJECT_ADD_ARRAY (mtext_table, "M-text");
   M_charbag = msymbol_as_managing_key ("  charbag");
   mtext_table.count = 0;
   M_charbag = msymbol_as_managing_key ("  charbag");
   mtext_table.count = 0;
+  Mlanguage = msymbol ("language");
   return 0;
 }
 
   return 0;
 }
 
@@ -704,7 +979,7 @@ mtext__init ()
 void
 mtext__fini (void)
 {
 void
 mtext__fini (void)
 {
-  mdebug__report_object ("M-text", &mtext_table);
+  mtext__wseg_fini ();
 }
 
 
 }
 
 
@@ -861,7 +1136,7 @@ mtext__cat_data (MText *mt, unsigned char *p, int nbytes,
 }
 
 MText *
 }
 
 MText *
-mtext__from_data (void *data, int nitems, enum MTextFormat format,
+mtext__from_data (const void *data, int nitems, enum MTextFormat format,
                  int need_copy)
 {
   MText *mt;
                  int need_copy)
 {
   MText *mt;
@@ -869,7 +1144,7 @@ mtext__from_data (void *data, int nitems, enum MTextFormat format,
 
   if (format == MTEXT_FORMAT_US_ASCII)
     {
 
   if (format == MTEXT_FORMAT_US_ASCII)
     {
-      char *p = (char *) data, *pend = p + nitems;
+      const char *p = (char *) data, *pend = p + nitems;
 
       while (p < pend)
        if (*p++ < 0)
 
       while (p < pend)
        if (*p++ < 0)
@@ -887,7 +1162,7 @@ mtext__from_data (void *data, int nitems, enum MTextFormat format,
   else if (format <= MTEXT_FORMAT_UTF_16BE)
     {
       if ((nchars = count_utf_16_chars (data, nitems,
   else if (format <= MTEXT_FORMAT_UTF_16BE)
     {
       if ((nchars = count_utf_16_chars (data, nitems,
-                                       format != default_utf_16)) < 0)
+                                       format != MTEXT_FORMAT_UTF_16)) < 0)
        MERROR (MERROR_MTEXT, NULL);
       nbytes = USHORT_SIZE * nitems;
       unit_bytes = USHORT_SIZE;
        MERROR (MERROR_MTEXT, NULL);
       nbytes = USHORT_SIZE * nitems;
       unit_bytes = USHORT_SIZE;
@@ -901,6 +1176,7 @@ mtext__from_data (void *data, int nitems, enum MTextFormat format,
 
   mt = mtext ();
   mt->format = format;
 
   mt = mtext ();
   mt->format = format;
+  mt->coverage = FORMAT_COVERAGE (format);
   mt->allocated = need_copy ? nbytes + unit_bytes : -1;
   mt->nchars = nchars;
   mt->nbytes = nitems;
   mt->allocated = need_copy ? nbytes + unit_bytes : -1;
   mt->nchars = nchars;
   mt->nbytes = nitems;
@@ -956,7 +1232,7 @@ mtext__adjust_format (MText *mt, enum MTextFormat format)
        }
 
       default:
        }
 
       default:
-       if (format == default_utf_16)
+       if (format == MTEXT_FORMAT_UTF_16)
          {
            unsigned short *p0, *p1;
 
          {
            unsigned short *p0, *p1;
 
@@ -991,6 +1267,7 @@ mtext__adjust_format (MText *mt, enum MTextFormat format)
          }
       }
   mt->format = format;
          }
       }
   mt->format = format;
+  mt->coverage = FORMAT_COVERAGE (format);
 }
 
 
 }
 
 
@@ -1022,7 +1299,8 @@ mtext__bol (MText *mt, int pos)
   else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
     {
       unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
   else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
     {
       unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
-      unsigned short newline = mt->format == default_utf_16 ? 0x0A00 : 0x000A;
+      unsigned short newline = (mt->format == MTEXT_FORMAT_UTF_16
+                               ? 0x0A00 : 0x000A);
 
       if (p[-1] == newline)
        return pos;
 
       if (p[-1] == newline)
        return pos;
@@ -1037,7 +1315,8 @@ mtext__bol (MText *mt, int pos)
   else
     {
       unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
   else
     {
       unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
-      unsigned newline = mt->format == default_utf_32 ? 0x0A000000 : 0x0000000A;
+      unsigned newline = (mt->format == MTEXT_FORMAT_UTF_32
+                         ? 0x0A000000 : 0x0000000A);
 
       if (p[-1] == newline)
        return pos;
 
       if (p[-1] == newline)
        return pos;
@@ -1080,7 +1359,8 @@ mtext__eol (MText *mt, int pos)
     {
       unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
       unsigned short *endp;
     {
       unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
       unsigned short *endp;
-      unsigned short newline = mt->format == default_utf_16 ? 0x0A00 : 0x000A;
+      unsigned short newline = (mt->format == MTEXT_FORMAT_UTF_16
+                               ? 0x0A00 : 0x000A);
 
       if (*p == newline)
        return pos + 1;
 
       if (*p == newline)
        return pos + 1;
@@ -1097,7 +1377,8 @@ mtext__eol (MText *mt, int pos)
     {
       unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
       unsigned *endp;
     {
       unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
       unsigned *endp;
-      unsigned newline = mt->format == default_utf_32 ? 0x0A000000 : 0x0000000A;
+      unsigned newline = (mt->format == MTEXT_FORMAT_UTF_32
+                         ? 0x0A000000 : 0x0000000A);
 
       if (*p == newline)
        return pos + 1;
 
       if (*p == newline)
        return pos + 1;
@@ -1109,36 +1390,228 @@ mtext__eol (MText *mt, int pos)
     }
 }
 
     }
 }
 
+int
+mtext__lowercase (MText *mt, int pos, int end)
+{
+  int opos = pos;
+  int c;
+  MText *orig = NULL;
+  MSymbol lang;
+
+  if (lowercase_precheck (mt, pos, end))
+    orig = mtext_dup (mt);
+
+  for (; pos < end; opos++)
+    {
+      c = mtext_ref_char (mt, pos);
+      lang = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
+
+      if (c == 0x03A3 && final_sigma (orig, opos))
+       REPLACE (gr03A3);
+
+      else if (lang == Mlt)
+       {
+         if (c == 0x00CC)
+           REPLACE (lt00CC);
+         else if (c == 0x00CD)
+           REPLACE (lt00CD);
+         else if (c == 0x0128)
+           REPLACE (lt0128);
+         else if (orig && more_above (orig, opos))
+           {
+             if (c == 0x0049)
+               REPLACE (lt0049);
+             else if (c == 0x004A)
+               REPLACE (lt004A);
+             else if (c == 0x012E)
+               REPLACE (lt012E);
+             else
+               LOOKUP;
+           }
+         else
+           LOOKUP;
+       }
+
+      else if (lang == Mtr || lang == Maz)
+       {
+         if (c == 0x0130)
+           REPLACE (tr0130);
+         else if (c == 0x0307 && after_i (orig, opos))
+           DELETE;
+         else if (c == 0x0049 && ! before_dot (orig, opos))
+           REPLACE (tr0049);
+         else
+           LOOKUP;
+       }
+
+      else
+       LOOKUP;
+    }
+
+  if (orig)
+    m17n_object_unref (orig);
+
+  return end;
+}
+
+int
+mtext__titlecase (MText *mt, int pos, int end)
+{
+  int opos = pos;
+  int c;
+  MText *orig = NULL;
+  MSymbol lang;
+  MPlist *pl;
+
+  /* Precheck for titlecase is identical to that for uppercase. */
+  if (uppercase_precheck (mt, pos, end))
+    orig = mtext_dup (mt);
+
+  for (; pos < end; opos++)
+    {
+      c = mtext_ref_char (mt, pos);
+      lang = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
+
+      if ((lang == Mtr || lang == Maz) && c == 0x0069)
+       REPLACE (tr0069);
+
+      else if (lang == Mlt && c == 0x0307 && after_soft_dotted (orig, opos))
+       DELETE;
+
+      else if ((pl = (MPlist *) mchartable_lookup (case_mapping, c)))
+       {
+         /* Titlecase is the 2nd element. */
+         MText *title
+           = (MText *) mplist_value (mplist_next (mplist_value (pl)));
+         int tlen = mtext_len (title);
+
+         if (mtext_ref_char (title, 0) != c || tlen > 1)
+           {
+             mtext_replace (mt, pos, pos + 1, title, 0, tlen);
+             pos += tlen;
+             end += tlen - 1;
+           }
+
+         else
+           pos++;
+       }
+
+      else
+       pos++;
+    }
+
+  if (orig)
+    m17n_object_unref (orig);
+
+  return end;
+}
+
+int
+mtext__uppercase (MText *mt, int pos, int end)
+{
+  int opos = pos;
+  int c;
+  MText *orig = NULL;
+  MSymbol lang;
+  MPlist *pl;
+
+  CASE_CONV_INIT (-1);
+
+  if (uppercase_precheck (mt, 0, end))
+    orig = mtext_dup (mt);
+
+  for (; pos < end; opos++)
+    {
+      c = mtext_ref_char (mt, pos);
+      lang = (MSymbol) mtext_get_prop (mt, pos, Mlanguage);
+
+      if (lang == Mlt && c == 0x0307 && after_soft_dotted (orig, opos))
+       DELETE;
+
+      else if ((lang == Mtr || lang == Maz) && c == 0x0069)
+       REPLACE (tr0069);
+              
+      else
+       {
+         if ((pl = (MPlist *) mchartable_lookup (case_mapping, c)) != NULL)
+           {
+             MText *upper;
+             int ulen;
+
+             /* Uppercase is the 3rd element. */
+             upper = (MText *) mplist_value (mplist_next (mplist_next (mplist_value (pl))));
+             ulen = mtext_len (upper);
+
+             if (mtext_ref_char (upper, 0) != c || ulen > 1)
+               {
+                 mtext_replace (mt, pos, pos + 1, upper, 0, ulen);
+                 pos += ulen;
+                 end += ulen - 1;
+               }
+
+             else
+               pos++;
+           }
+
+         else                                           /* pl == NULL */
+           pos++;
+       }
+    }
+
+  if (orig)
+    m17n_object_unref (orig);
+
+  return end;
+}
+
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 
 \f
 /* External API */
 
 /*** @} */
 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
 
 \f
 /* External API */
 
+#ifdef WORDS_BIGENDIAN
+const enum MTextFormat MTEXT_FORMAT_UTF_16 = MTEXT_FORMAT_UTF_16BE;
+#else
+const enum MTextFormat MTEXT_FORMAT_UTF_16 = MTEXT_FORMAT_UTF_16LE;
+#endif
+
+#ifdef WORDS_BIGENDIAN
+const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32BE;
+#else
+const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32LE;
+#endif
+
 /*** @addtogroup m17nMtext */
 /*** @{ */
 /*=*/
 
 /*** @addtogroup m17nMtext */
 /*** @{ */
 /*=*/
 
+/***en The symbol whose name is "language".  */
+/***ja "language" ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¥·¥ó¥Ü¥ë.  */
+MSymbol Mlanguage;
+
+/*=*/
+
 /***en
     @brief Allocate a new M-text.
 
     The mtext () function allocates a new M-text of length 0 and
     returns a pointer to it.  The allocated M-text will not be freed
 /***en
     @brief Allocate a new M-text.
 
     The mtext () function allocates a new M-text of length 0 and
     returns a pointer to it.  The allocated M-text will not be freed
-    unless the user explicitly does so with the m17n_object_free ()
+    unless the user explicitly does so with the m17n_object_unref ()
     function.  */
 
 /***ja
     @brief ¿·¤·¤¤M-text¤ò³ä¤êÅö¤Æ¤ë.
 
     function.  */
 
 /***ja
     @brief ¿·¤·¤¤M-text¤ò³ä¤êÅö¤Æ¤ë.
 
-    ´Ø¿ô mtext () ¤Ï¡¢Ä¹¤µ 0 ¤Î¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¡¢¤½¤ì¤Ø¤Î¥Ý¥¤
-    ¥ó¥¿¤òÊÖ¤¹¡£³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_free () ¤Ë
-    ¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£
+    ´Ø¿ô mtext () ¤Ï¡¢Ä¹¤µ 0 ¤Î¿·¤·¤¤ M-text 
+    ¤ò³ä¤êÅö¤Æ¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô
+    m17n_object_unref () ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£
 
     @latexonly \IPAlabel{mtext} @endlatexonly  */
 
 /***
     @seealso
 
     @latexonly \IPAlabel{mtext} @endlatexonly  */
 
 /***
     @seealso
-    m17n_object_free ()  */
+    m17n_object_unref ()  */
 
 MText *
 mtext ()
 
 MText *
 mtext ()
@@ -1146,7 +1619,8 @@ mtext ()
   MText *mt;
 
   M17N_OBJECT (mt, free_mtext, MERROR_MTEXT);
   MText *mt;
 
   M17N_OBJECT (mt, free_mtext, MERROR_MTEXT);
-  mt->format = MTEXT_FORMAT_UTF_8;
+  mt->format = MTEXT_FORMAT_US_ASCII;
+  mt->coverage = MTEXT_COVERAGE_ASCII;
   M17N_OBJECT_REGISTER (mtext_table, mt);
   return mt;
 }
   M17N_OBJECT_REGISTER (mtext_table, mt);
   return mt;
 }
@@ -1174,7 +1648,7 @@ mtext ()
     The contents of $DATA must not be modified while the M-text is alive.
 
     The allocated M-text will not be freed unless the user explicitly
     The contents of $DATA must not be modified while the M-text is alive.
 
     The allocated M-text will not be freed unless the user explicitly
-    does so with the m17n_object_free () function.  Even in that case,
+    does so with the m17n_object_unref () function.  Even in that case,
     $DATA is not freed.
 
     @return
     $DATA is not freed.
 
     @return
@@ -1184,39 +1658,38 @@ mtext ()
 /***ja
     @brief »ØÄê¤Î¥Ç¡¼¥¿¤ò¸µ¤Ë¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë.
 
 /***ja
     @brief »ØÄê¤Î¥Ç¡¼¥¿¤ò¸µ¤Ë¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë.
 
-    ´Ø¿ô mtext_from_data () ¤Ï¡¢Í×ÁÇ¿ô $NITEMS ¤ÎÇÛÎó $DATA ¤Ç»ØÄꤵ¤ì
-    ¤¿Ê¸»úÎó¤ò»ý¤Ä¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë¡£$FORMAT ¤Ï $DATA ¤Î¥Õ¥©¡¼
-    ¥Þ¥Ã¥È¤ò¼¨¤¹¡£
+    ´Ø¿ô mtext_from_data () ¤Ï¡¢Í×ÁÇ¿ô $NITEMS ¤ÎÇÛÎó $DATA 
+    ¤Ç»ØÄꤵ¤ì¤¿Ê¸»úÎó¤ò»ý¤Ä¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë¡£$FORMAT ¤Ï $DATA
+    ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤ò¼¨¤¹¡£
 
     $FORMAT ¤¬ #MTEXT_FORMAT_US_ASCII ¤« #MTEXT_FORMAT_UTF_8 ¤Ê¤é¤Ð¡¢
 
     $FORMAT ¤¬ #MTEXT_FORMAT_US_ASCII ¤« #MTEXT_FORMAT_UTF_8 ¤Ê¤é¤Ð¡¢
-    $DATA ¤ÎÆâÍƤϠ@c unsigned @c char ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¥Ð¥¤¥Èñ°Ì
-    ¤Çɽ¤µ¤ì¤Æ¤¤¤ë¡£
+    $DATA ¤ÎÆâÍƤϠ@c unsigned @c char ·¿¤Ç¤¢¤ê¡¢$NITEMS 
+    ¤Ï¥Ð¥¤¥Èñ°Ì¤Çɽ¤µ¤ì¤Æ¤¤¤ë¡£
 
     $FORMAT ¤¬ #MTEXT_FORMAT_UTF_16LE ¤« #MTEXT_FORMAT_UTF_16BE ¤Ê¤é¤Ð¡¢
     $DATA ¤ÎÆâÍƤϠ@c unsigned @c short ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned
     short Ã±°Ì¤Ç¤¢¤ë¡£
 
     $FORMAT ¤¬ #MTEXT_FORMAT_UTF_32LE ¤« #MTEXT_FORMAT_UTF_32BE ¤Ê¤é¤Ð¡¢
 
     $FORMAT ¤¬ #MTEXT_FORMAT_UTF_16LE ¤« #MTEXT_FORMAT_UTF_16BE ¤Ê¤é¤Ð¡¢
     $DATA ¤ÎÆâÍƤϠ@c unsigned @c short ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned
     short Ã±°Ì¤Ç¤¢¤ë¡£
 
     $FORMAT ¤¬ #MTEXT_FORMAT_UTF_32LE ¤« #MTEXT_FORMAT_UTF_32BE ¤Ê¤é¤Ð¡¢
-    $DATA ¤ÎÆâÍƤÏ@c unsigned ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned Ã±°Ì¤Ç¤¢¤ë¡£
+    $DATA ¤ÎÆâÍƤϠ@c unsigned ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned Ã±°Ì¤Ç¤¢¤ë¡£
 
     ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Îʸ»úÎó¤ÏÊѹ¹¤Ç¤­¤Ê¤¤¡£$DATA ¤ÎÆâÍƤϠ
     M-text ¤¬Í­¸ú¤Ê´Ö¤ÏÊѹ¹¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
 
     ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Îʸ»úÎó¤ÏÊѹ¹¤Ç¤­¤Ê¤¤¡£$DATA ¤ÎÆâÍƤϠ
     M-text ¤¬Í­¸ú¤Ê´Ö¤ÏÊѹ¹¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
 
-    ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_free () ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶
-    ¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£¤½¤Î¾ì¹ç¤Ç¤â $DATA ¤Ï²òÊü
-    ¤µ¤ì¤Ê¤¤¡£
+    ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_unref () 
+    ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£¤½¤Î¾ì¹ç¤Ç¤â $DATA ¤Ï²òÊü¤µ¤ì¤Ê¤¤¡£
 
     @return 
 
     @return 
-    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_from_data () ¤Ï³ä¤êÅö¤Æ¤é¤ì¤¿M-text ¤Ø¤Î¥Ý
-    ¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·³°ÉôÊÑ¿ô #merror_code ¤Ë
-    ¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_from_data () ¤Ï³ä¤êÅö¤Æ¤é¤ì¤¿M-text 
+    ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·³°ÉôÊÑ¿ô #merror_code 
+    ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
 
 /***
     @errors
     @c MERROR_MTEXT  */
 
 MText *
 
 /***
     @errors
     @c MERROR_MTEXT  */
 
 MText *
-mtext_from_data (void *data, int nitems, enum MTextFormat format)
+mtext_from_data (const void *data, int nitems, enum MTextFormat format)
 {
   if (nitems < 0
       || format < MTEXT_FORMAT_US_ASCII || format >= MTEXT_FORMAT_MAX)
 {
   if (nitems < 0
       || format < MTEXT_FORMAT_US_ASCII || format >= MTEXT_FORMAT_MAX)
@@ -1227,6 +1700,86 @@ mtext_from_data (void *data, int nitems, enum MTextFormat format)
 /*=*/
 
 /***en
 /*=*/
 
 /***en
+    @brief Get information about the text data in M-text.
+
+    The mtext_data () function returns a pointer to the text data of
+    M-text $MT.  If $FMT is not NULL, the format of the text data is
+    stored in it.  If $NUNITS is not NULL, the number of units of the
+    text data is stored in it.
+
+    If $POS_IDX is not NULL and it points to a non-negative number,
+    what it points to is a character position.  In this case, the
+    return value is a pointer to the text data of a character at that
+    position.
+
+    Otherwise, if $UNIT_IDX is not NULL, it points to a unit position.
+    In this case, the return value is a pointer to the text data of a
+    character containing that unit.
+
+    The character position and unit position of the return value are
+    stored in $POS_IDX and $UNIT_DIX respectively if they are not
+    NULL.
+
+    <ul>
+
+    <li> If the format of the text data is MTEXT_FORMAT_US_ASCII or
+    MTEXT_FORMAT_UTF_8, one unit is unsigned char.
+
+    <li> If the format is MTEXT_FORMAT_UTF_16LE or
+    MTEXT_FORMAT_UTF_16BE, one unit is unsigned short.
+
+    <li> If the format is MTEXT_FORMAT_UTF_32LE or
+    MTEXT_FORMAT_UTF_32BE, one unit is unsigned int.
+
+    </ul> */
+
+void *
+mtext_data (MText *mt, enum MTextFormat *fmt, int *nunits,
+           int *pos_idx, int *unit_idx)
+{
+  void *data;
+  int pos = 0, unit_pos = 0;
+
+  if (fmt)
+    *fmt = mt->format;
+  data = MTEXT_DATA (mt);
+  if (pos_idx && *pos_idx >= 0)
+    {
+      pos = *pos_idx;
+      if (pos > mtext_nchars (mt))
+       MERROR (MERROR_MTEXT, NULL);
+      unit_pos = POS_CHAR_TO_BYTE (mt, pos);
+    }
+  else if (unit_idx)
+    {
+      unit_pos = *unit_idx;
+
+      if (unit_pos < 0 || unit_pos > mtext_nbytes (mt))
+       MERROR (MERROR_MTEXT, NULL);
+      pos = POS_BYTE_TO_CHAR (mt, unit_pos);
+      unit_pos = POS_CHAR_TO_BYTE (mt, pos);
+    }
+  if (nunits)
+    *nunits = mtext_nbytes (mt) - unit_pos;
+  if (pos_idx)
+    *pos_idx = pos;
+  if (unit_idx)
+    *unit_idx = unit_pos;
+  if (unit_pos > 0)
+    {
+      if (mt->format <= MTEXT_FORMAT_UTF_8)
+       data = (unsigned char *) data + unit_pos;
+      else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
+       data = (unsigned short *) data + unit_pos;
+      else
+       data = (unsigned int *) data + unit_pos;
+    }
+  return data;
+}
+
+/*=*/
+
+/***en
     @brief Number of characters in M-text.
 
     The mtext_len () function returns the number of characters in
     @brief Number of characters in M-text.
 
     The mtext_len () function returns the number of characters in
@@ -1257,8 +1810,8 @@ mtext_len (MText *mt)
 /***ja
     @brief M-text Ãæ¤Î»ØÄꤵ¤ì¤¿°ÌÃÖ¤Îʸ»ú¤òÊÖ¤¹.
 
 /***ja
     @brief M-text Ãæ¤Î»ØÄꤵ¤ì¤¿°ÌÃÖ¤Îʸ»ú¤òÊÖ¤¹.
 
-    ´Ø¿ô mtext_ref_char () ¤Ï¡¢M-text $MT ¤Î°ÌÃÖ $POS ¤Îʸ»ú¤òÊÖ¤¹¡£
-    ¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code
+    ´Ø¿ô mtext_ref_char () ¤Ï¡¢M-text $MT ¤Î°ÌÃÖ $POS 
+    ¤Îʸ»ú¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code
     ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_ref_char} @endlatexonly  */
     ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_ref_char} @endlatexonly  */
@@ -1285,7 +1838,7 @@ mtext_ref_char (MText *mt, int pos)
        = (unsigned short *) (mt->data) + POS_CHAR_TO_BYTE (mt, pos);
       unsigned short p1[2];
 
        = (unsigned short *) (mt->data) + POS_CHAR_TO_BYTE (mt, pos);
       unsigned short p1[2];
 
-      if (mt->format != default_utf_16)
+      if (mt->format != MTEXT_FORMAT_UTF_16)
        {
          p1[0] = SWAP_16 (*p);
          if (p1[0] >= 0xD800 || p1[0] < 0xDC00)
        {
          p1[0] = SWAP_16 (*p);
          if (p1[0] >= 0xD800 || p1[0] < 0xDC00)
@@ -1297,7 +1850,7 @@ mtext_ref_char (MText *mt, int pos)
   else
     {
       c = ((unsigned *) (mt->data))[pos];
   else
     {
       c = ((unsigned *) (mt->data))[pos];
-      if (mt->format != default_utf_32)
+      if (mt->format != MTEXT_FORMAT_UTF_32)
        c = SWAP_32 (c);
     }
   return c;
        c = SWAP_32 (c);
     }
   return c;
@@ -1323,8 +1876,8 @@ mtext_ref_char (MText *mt, int pos)
     M-text $MT ¤Î°ÌÃÖ $POS ¤ËÀßÄꤹ¤ë¡£
 
     @return
     M-text $MT ¤Î°ÌÃÖ $POS ¤ËÀßÄꤹ¤ë¡£
 
     @return
-    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mtext_set_char () ¤Ï 0 ¤òÊÖ¤¹¡£¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ
-    ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
+    ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mtext_set_char () ¤Ï 0 ¤òÊÖ¤¹¡£¼ºÇÔ¤¹¤ì¤Ð -1 
+    ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_set_char} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_set_char} @endlatexonly  */
 
@@ -1344,22 +1897,22 @@ mtext_set_char (MText *mt, int pos, int c)
   M_CHECK_POS (mt, pos, -1);
   M_CHECK_READONLY (mt, -1);
 
   M_CHECK_POS (mt, pos, -1);
   M_CHECK_READONLY (mt, -1);
 
-  mtext__adjust_plist_for_change (mt, pos, pos + 1);
+  mtext__adjust_plist_for_change (mt, pos, 1, 1);
 
   if (mt->format <= MTEXT_FORMAT_UTF_8)
     {
       if (c >= 0x80)
 
   if (mt->format <= MTEXT_FORMAT_UTF_8)
     {
       if (c >= 0x80)
-       mt->format = MTEXT_FORMAT_UTF_8;
+       mt->format = MTEXT_FORMAT_UTF_8, mt->coverage = MTEXT_COVERAGE_FULL;
     }
   else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
     {
       if (c >= 0x110000)
        mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
     }
   else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
     {
       if (c >= 0x110000)
        mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
-      else if (mt->format != default_utf_16)
-       mtext__adjust_format (mt, default_utf_16);
+      else if (mt->format != MTEXT_FORMAT_UTF_16)
+       mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
     }
     }
-  else if (mt->format != default_utf_32)
-    mtext__adjust_format (mt, default_utf_32);
+  else if (mt->format != MTEXT_FORMAT_UTF_32)
+    mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
 
   unit_bytes = UNIT_BYTES (mt->format);
   pos_unit = POS_CHAR_TO_BYTE (mt, pos);
 
   unit_bytes = UNIT_BYTES (mt->format);
   pos_unit = POS_CHAR_TO_BYTE (mt, pos);
@@ -1397,7 +1950,7 @@ mtext_set_char (MText *mt, int pos, int c)
        break;
       }
     default:
        break;
       }
     default:
-      if (mt->format == default_utf_16)
+      if (mt->format == MTEXT_FORMAT_UTF_16)
        {
          unsigned short *p = (unsigned short *) mt->data + pos_unit;
 
        {
          unsigned short *p = (unsigned short *) mt->data + pos_unit;
 
@@ -1428,8 +1981,8 @@ mtext_set_char (MText *mt, int pos, int c)
     M-text $MT ¤ÎËöÈø¤ËÄɲ乤롣
 
     @return
     M-text $MT ¤ÎËöÈø¤ËÄɲ乤롣
 
     @return
-    ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$C ¤¬Àµ¤·¤¤Ê¸
-    »ú¤Ç¤Ê¤¤¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£  */
+    ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$C 
+    ¤¬Àµ¤·¤¤Ê¸»ú¤Ç¤Ê¤¤¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£  */
 
 /***
     @seealso
 
 /***
     @seealso
@@ -1458,19 +2011,19 @@ mtext_cat_char (MText *mt, int c)
     }
   else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
     {
     }
   else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
     {
-      if (mt->format != default_utf_32)
-       mtext__adjust_format (mt, default_utf_32);
+      if (mt->format != MTEXT_FORMAT_UTF_32)
+       mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
     }
   else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
     {
     }
   else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
     {
-      if (mt->format != default_utf_16)
-       mtext__adjust_format (mt, default_utf_16);
+      if (mt->format != MTEXT_FORMAT_UTF_16)
+       mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
     }
 
   nunits = CHAR_UNITS (c, mt->format);
   if ((mt->nbytes + nunits + 1) * unit_bytes > mt->allocated)
     {
     }
 
   nunits = CHAR_UNITS (c, mt->format);
   if ((mt->nbytes + nunits + 1) * unit_bytes > mt->allocated)
     {
-      mt->allocated = (mt->nbytes + nunits + 1) * unit_bytes;
+      mt->allocated = (mt->nbytes + nunits * 16 + 1) * unit_bytes;
       MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
     }
   
       MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
     }
   
@@ -1480,7 +2033,7 @@ mtext_cat_char (MText *mt, int c)
       p += CHAR_STRING_UTF8 (c, p);
       *p = 0;
     }
       p += CHAR_STRING_UTF8 (c, p);
       *p = 0;
     }
-  else if (mt->format == default_utf_16)
+  else if (mt->format == MTEXT_FORMAT_UTF_16)
     {
       unsigned short *p = (unsigned short *) mt->data + mt->nbytes;
       p += CHAR_STRING_UTF16 (c, p);
     {
       unsigned short *p = (unsigned short *) mt->data + mt->nbytes;
       p += CHAR_STRING_UTF16 (c, p);
@@ -1512,8 +2065,8 @@ mtext_cat_char (MText *mt, int c)
 /***ja
     @brief M-text ¤Î¥³¥Ô¡¼¤òºî¤ë.
 
 /***ja
     @brief M-text ¤Î¥³¥Ô¡¼¤òºî¤ë.
 
-    ´Ø¿ô mtext_dup () ¤Ï¡¢M-text $MT ¤Î¥³¥Ô¡¼¤òºî¤ë¡£$MT ¤Î¥Æ¥­¥¹¥È¥×
-    ¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
+    ´Ø¿ô mtext_dup () ¤Ï¡¢M-text $MT ¤Î¥³¥Ô¡¼¤òºî¤ë¡£$MT 
+    ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
 
     @return
     ¤³¤Î´Ø¿ô¤Ïºî¤é¤ì¤¿¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
 
     @return
     ¤³¤Î´Ø¿ô¤Ïºî¤é¤ì¤¿¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
@@ -1527,19 +2080,7 @@ mtext_cat_char (MText *mt, int c)
 MText *
 mtext_dup (MText *mt)
 {
 MText *
 mtext_dup (MText *mt)
 {
-  MText *new = mtext ();
-  int unit_bytes = UNIT_BYTES (mt->format);
-
-  *new = *mt;
-  if (mt->nchars > 0)
-    {
-      new->allocated = (mt->nbytes + 1) * unit_bytes;
-      MTABLE_MALLOC (new->data, new->allocated, MERROR_MTEXT);
-      memcpy (new->data, mt->data, new->allocated);
-      if (mt->plist)
-       new->plist = mtext__copy_plist (mt->plist, 0, mt->nchars, new, 0);
-    }
-  return new;
+  return mtext_duplicate (mt, 0, mtext_nchars (mt));
 }
 
 /*=*/
 }
 
 /*=*/
@@ -1557,9 +2098,8 @@ mtext_dup (MText *mt)
 /***ja
     @brief 2¸Ä¤Î M-text¤òÏ¢·ë¤¹¤ë.
 
 /***ja
     @brief 2¸Ä¤Î M-text¤òÏ¢·ë¤¹¤ë.
 
-    ´Ø¿ô mtext_cat () ¤Ï¡¢ M-text $MT2 ¤ò M-text $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨
-    ¤ë¡£$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê
-    ¤¤¡£
+    ´Ø¿ô mtext_cat () ¤Ï¡¢ M-text $MT2 ¤ò M-text $MT1 
+    ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨¤ë¡£$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
 
     @return
     ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
 
     @return
     ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
@@ -1597,18 +2137,16 @@ mtext_cat (MText *mt1, MText *mt2)
     returns @c NULL and assigns an error code to the global variable
     #merror_code.  */
 
     returns @c NULL and assigns an error code to the global variable
     #merror_code.  */
 
-
 /***ja
     @brief M-text ¤Î°ìÉô¤òÊ̤ΠM-text ¤ËÉղ乤ë.
 
     ´Ø¿ô mtext_ncat () ¤Ï¡¢M-text $MT2 ¤Î¤Ï¤¸¤á¤Î $N Ê¸»ú¤ò M-text
 /***ja
     @brief M-text ¤Î°ìÉô¤òÊ̤ΠM-text ¤ËÉղ乤ë.
 
     ´Ø¿ô mtext_ncat () ¤Ï¡¢M-text $MT2 ¤Î¤Ï¤¸¤á¤Î $N Ê¸»ú¤ò M-text
-    $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨¤ë¡£$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì
-    ¤ë¡£$MT2 ¤ÎŤµ¤¬ $N °Ê²¼¤Ê¤é¤Ð¡¢$MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤¬Éղ䵤ì¤ë¡£
-    $MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
+    $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨¤ë¡£$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2
+    ¤ÎŤµ¤¬ $N °Ê²¼¤Ê¤é¤Ð¡¢$MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤¬Éղ䵤ì¤ë¡£ $MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
 
     @return
 
     @return
-    ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncat () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý
-    ¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
+    ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncat () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1
+    ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_ncat} @endlatexonly  */
     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_ncat} @endlatexonly  */
@@ -1649,8 +2187,8 @@ mtext_ncat (MText *mt1, MText *mt2, int n)
     @brief M-text ¤òÊ̤ΠM-text ¤Ë¥³¥Ô¡¼¤¹¤ë.
 
     ´Ø¿ô mtext_cpy () ¤Ï M-text $MT2 ¤ò M-text $MT1 ¤Ë¾å½ñ¤­¥³¥Ô¡¼¤¹¤ë¡£
     @brief M-text ¤òÊ̤ΠM-text ¤Ë¥³¥Ô¡¼¤¹¤ë.
 
     ´Ø¿ô mtext_cpy () ¤Ï M-text $MT2 ¤ò M-text $MT1 ¤Ë¾å½ñ¤­¥³¥Ô¡¼¤¹¤ë¡£
-    $MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 ¤ÎŤµ¤ÏɬÍפ˱þ
-    ¤¸¤Æ¿­¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
+    $MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 
+    ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿­¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
 
     @return
     ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
 
     @return
     ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
@@ -1692,13 +2230,13 @@ mtext_cpy (MText *mt1, MText *mt2)
     @brief M-text ¤Ë´Þ¤Þ¤ì¤ëºÇ½é¤Î²¿Ê¸»ú¤«¤ò¥³¥Ô¡¼¤¹¤ë.
 
     ´Ø¿ô mtext_ncpy () ¤Ï¡¢M-text $MT2 ¤ÎºÇ½é¤Î $N Ê¸»ú¤ò M-text $MT1 
     @brief M-text ¤Ë´Þ¤Þ¤ì¤ëºÇ½é¤Î²¿Ê¸»ú¤«¤ò¥³¥Ô¡¼¤¹¤ë.
 
     ´Ø¿ô mtext_ncpy () ¤Ï¡¢M-text $MT2 ¤ÎºÇ½é¤Î $N Ê¸»ú¤ò M-text $MT1 
-    ¤Ë¾å½ñ¤­¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
-    ¤â¤· $MT2 ¤ÎŤµ¤¬ $N ¤è¤ê¤â¾®¤µ¤±¤ì¤Ð $MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ò¥³¥Ô¡¼
-    ¤¹¤ë¡£$MT1 ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿­¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
+    ¤Ë¾å½ñ¤­¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£¤â¤· $MT2
+    ¤ÎŤµ¤¬ $N ¤è¤ê¤â¾®¤µ¤±¤ì¤Ð $MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ò¥³¥Ô¡¼¤¹¤ë¡£$MT1 
+    ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿­¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
 
     @return 
 
     @return 
-    ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncpy () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý
-    ¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô 
+    ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncpy () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 
+    ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô 
     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_ncpy} @endlatexonly  */
     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_ncpy} @endlatexonly  */
@@ -1732,21 +2270,22 @@ mtext_ncpy (MText *mt1, MText *mt2, int n)
     (exclusive) while inheriting all the text properties of $MT.  $MT
     itself is not modified.
 
     (exclusive) while inheriting all the text properties of $MT.  $MT
     itself is not modified.
 
-    @return
-    If the operation was successful, mtext_duplicate () returns a
-    pointer to the created M-text.  If an error is detected, it returns 0
-    and assigns an error code to the external variable #merror_code.  */
+    @return 
+    If the operation was successful, mtext_duplicate ()
+    returns a pointer to the created M-text.  If an error is detected,
+    it returns NULL and assigns an error code to the external variable
+    #merror_code.  */
 
 /***ja
     @brief ´û¸¤Î M-text ¤Î°ìÉô¤«¤é¿·¤·¤¤ M-text ¤ò¤Ä¤¯¤ë.
 
 
 /***ja
     @brief ´û¸¤Î M-text ¤Î°ìÉô¤«¤é¿·¤·¤¤ M-text ¤ò¤Ä¤¯¤ë.
 
-    ´Ø¿ô mtext_duplicate () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO 
-    ¡Ê´Þ¤Þ¤Ê¤¤¡Ë¤Þ¤Ç¤ÎÉôʬ¤Î¥³¥Ô¡¼¤òºî¤ë¡£¤³¤Î¤È¤­ $MT ¤Î¥Æ¥­¥¹¥È¥×¥í
-    ¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
+    ´Ø¿ô mtext_duplicate () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê$FROM ¼«ÂΤâ´Þ¤à¡Ë¤«¤é
+    $TO ¡Ê$TO ¼«ÂΤϴޤޤʤ¤¡Ë¤Þ¤Ç¤ÎÉôʬ¤Î¥³¥Ô¡¼¤òºî¤ë¡£¤³¤Î¤È¤­ $MT 
+    ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
 
     @return
 
     @return
-    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_duplicate () ¤Ïºî¤é¤ì¤¿ M-text ¤Ø¤Î¥Ý¥¤¥ó
-    ¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô 
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_duplicate () ¤Ïºî¤é¤ì¤¿ M-text 
+    ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô 
     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_duplicate} @endlatexonly  */
     #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_duplicate} @endlatexonly  */
@@ -1761,13 +2300,12 @@ mtext_ncpy (MText *mt1, MText *mt2, int n)
 MText *
 mtext_duplicate (MText *mt, int from, int to)
 {
 MText *
 mtext_duplicate (MText *mt, int from, int to)
 {
-  MText *new;
+  MText *new = mtext ();
 
 
-  M_CHECK_RANGE_X (mt, from, to, NULL);
-  new = mtext ();
+  M_CHECK_RANGE (mt, from, to, NULL, new);
   new->format = mt->format;
   new->format = mt->format;
-  if (from < to)
-    insert (new, 0, mt, from, to);
+  new->coverage = mt->coverage;
+  insert (new, 0, mt, from, to);
   return new;
 }
 
   return new;
 }
 
@@ -1790,17 +2328,17 @@ mtext_duplicate (MText *mt, int from, int to)
 /***ja
     @brief M-text ¤Ë»ØÄêÈϰϤÎʸ»ú¤ò¥³¥Ô¡¼¤¹¤ë.
 
 /***ja
     @brief M-text ¤Ë»ØÄêÈϰϤÎʸ»ú¤ò¥³¥Ô¡¼¤¹¤ë.
 
-    ´Ø¿ô mtext_copy () ¤Ï¡¢ M-text $MT2 ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO ¡Ê´Þ
-    ¤Þ¤Ê¤¤¡Ë¤Þ¤Ç¤ÎÈϰϤΥƥ­¥¹¥È¤ò M-text $MT1 ¤Î°ÌÃÖ $POS ¤«¤é¾å½ñ¤­
-    ¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 ¤ÎĹ
-    ¤µ¤ÏɬÍפ˱þ¤¸¤Æ¿­¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
+    ´Ø¿ô mtext_copy () ¤Ï¡¢ M-text $MT2 ¤Î $FROM ¡Ê$FROM ¼«ÂΤâ´Þ¤à¡Ë¤«¤é 
+    $TO ¡Ê$TO ¼«ÂΤϴޤޤʤ¤¡Ë¤Þ¤Ç¤ÎÈϰϤΥƥ­¥¹¥È¤ò M-text $MT1 ¤Î°ÌÃÖ $POS
+    ¤«¤é¾å½ñ¤­¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 
+    ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿­¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
 
     @latexonly \IPAlabel{mtext_copy} @endlatexonly
 
     @return
 
     @latexonly \IPAlabel{mtext_copy} @endlatexonly
 
     @return
-    ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_copy () ¤ÏÊѹ¹¤µ¤ì¤¿ $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò
-    ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼
-    ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
+    ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_copy () ¤ÏÊѹ¹¤µ¤ì¤¿ $MT1 
+    ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code 
+    ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
 
 /***
     @errors
 
 /***
     @errors
@@ -1838,13 +2376,13 @@ mtext_copy (MText *mt1, int pos, MText *mt2, int from, int to)
 /***ja
     @brief »ØÄêÈϰϤÎʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯.
 
 /***ja
     @brief »ØÄêÈϰϤÎʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯.
 
-    ´Ø¿ô mtext_del () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO ¡Ê´Þ¤Þ
-    ¤Ê¤¤¡Ë¤Þ¤Ç¤Îʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯¡£·ë²ÌŪ¤Ë $MT ¤ÏŤµ¤¬ ($TO @c
-    - $FROM) ¤À¤±½Ì¤à¤³¤È¤Ë¤Ê¤ë¡£
+    ´Ø¿ô mtext_del () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê$FROM ¼«ÂΤâ´Þ¤à¡Ë¤«¤é
+    $TO ¡Ê$TO ¼«ÂΤϴޤޤʤ¤¡Ë¤Þ¤Ç¤Îʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯¡£·ë²ÌŪ¤Ë
+    $MT ¤ÏŤµ¤¬ ($TO @c - $FROM) ¤À¤±½Ì¤à¤³¤È¤Ë¤Ê¤ë¡£
 
     @return
 
     @return
-    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_del () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ
-    ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_del () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
+    ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
 
 /***
     @errors
 
 /***
     @errors
@@ -1906,21 +2444,20 @@ mtext_del (MText *mt, int from, int to)
 /***ja
     @brief M-text ¤òÊ̤ΠM-text ¤ËÁÞÆþ¤¹¤ë.
 
 /***ja
     @brief M-text ¤òÊ̤ΠM-text ¤ËÁÞÆþ¤¹¤ë.
 
-    ´Ø¿ô mtext_ins () ¤Ï M-text $MT1 ¤Î $POS ¤Î°ÌÃ֤ˠÊ̤ΠM-text $MT2 
-    ¤òÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $MT2 ¤ÎŤµÊ¬¤À¤±Áý¤¨¤ë¡£ÁÞÆþ¤Î
-    ºÝ¡¢$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤½¤Î¤â¤Î¤ÏÊÑ
-    ¹¹¤µ¤ì¤Ê¤¤¡£
+    ´Ø¿ô mtext_ins () ¤Ï M-text $MT1 ¤Î $POS ¤Î°ÌÃÖ¤ËÊ̤ΠM-text $MT2 
+    ¤òÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $MT2 ¤ÎŤµÊ¬¤À¤±Áý¤¨¤ë¡£ÁÞÆþ¤ÎºÝ¡¢$MT2
+    ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
 
     @return
 
     @return
-    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ
-    ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
+    ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
 
 /***
     @errors
 
 /***
     @errors
-    @c MERROR_RANGE
+    @c MERROR_RANGE , @c MERROR_MTEXT
 
     @seealso
 
     @seealso
-    mtext_del ()  */
+    mtext_del () , mtext_insert ()  */
 
 int
 mtext_ins (MText *mt1, int pos, MText *mt2)
 
 int
 mtext_ins (MText *mt1, int pos, MText *mt2)
@@ -1934,6 +2471,52 @@ mtext_ins (MText *mt1, int pos, MText *mt2)
   return 0;
 }
 
   return 0;
 }
 
+/*=*/
+
+/***en
+    @brief Insert sub-text of an M-text into another M-text.
+
+    The mtext_insert () function inserts sub-text of M-text $MT2
+    between $FROM (inclusive) and $TO (exclusive) into M-text $MT1, at
+    position $POS.  As a result, $MT1 is lengthen by ($TO - $FROM).
+    On insertion, all the text properties of the sub-text of $MT2 are
+    inherited.
+
+    @return 
+    If the operation was successful, mtext_insert () returns
+    0.  Otherwise, it returns -1 and assigns an error code to the
+    external variable #merror_code.  */
+
+/***ja
+    @brief M-text ¤Î°ìÉô¤òÊ̤ΠM-text ¤ËÁÞÆþ¤¹¤ë.
+
+    ´Ø¿ô mtext_insert () ¤Ï M-text $MT1 Ãæ¤Î $POS ¤Î°ÌÃ֤ˡ¢Ê̤Π
+    M-text $MT2 ¤Î $FROM ¡Ê$FROM ¼«ÂΤâ´Þ¤à¡Ë¤«¤é $TO ¡Ê$TO ¼«ÂΤϴޤÞ
+    ¤Ê¤¤¡Ë¤Þ¤Ç¤Îʸ»ú¤òÁÞÆþ¤¹¤ë¡£·ë²ÌŪ¤Ë $MT1 ¤ÏŤµ¤¬ ($TO - $FROM) 
+    ¤À¤±¿­¤Ó¤ë¡£ÁÞÆþ¤ÎºÝ¡¢ $MT2 Ãæ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì
+    ¤ë¡£
+
+    @return
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_insert () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 
+    ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
+
+/***
+    @errors
+    @c MERROR_MTEXT , @c MERROR_RANGE
+
+    @seealso
+    mtext_ins ()  */
+
+int
+mtext_insert (MText *mt1, int pos, MText *mt2, int from, int to)
+{
+  M_CHECK_READONLY (mt1, -1);
+  M_CHECK_POS_X (mt1, pos, -1);
+  M_CHECK_RANGE (mt2, from, to, -1, 0);
+
+  insert (mt1, pos, mt2, from, to);
+  return 0;
+}
 
 /*=*/
 
 
 /*=*/
 
@@ -1952,7 +2535,7 @@ mtext_ins (MText *mt1, int pos, MText *mt2)
 /***ja
     @brief M-text ¤Ëʸ»ú¤òÁÞÆþ¤¹¤ë.
 
 /***ja
     @brief M-text ¤Ëʸ»ú¤òÁÞÆþ¤¹¤ë.
 
-    ´Ø¿ô mtext_ins_char () ¤Ï M-text $MT ¤Î $POS ¤Î°ÌÃÖ¤Ëʸ»ú $C ¤ò $N
+    ´Ø¿ô mtext_ins_char () ¤Ï M-text $MT ¤Î $POS ¤Î°ÌÃÖ¤Ëʸ»ú $C ¤Î¥³¥Ô¡¼¤ò $N
     ¸ÄÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $N ¤À¤±Áý¤¨¤ë¡£
 
     @return
     ¸ÄÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $N ¤À¤±Áý¤¨¤ë¡£
 
     @return
@@ -1992,13 +2575,13 @@ mtext_ins_char (MText *mt, int pos, int c, int n)
     }
   else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
     {
     }
   else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
     {
-      if (mt->format != default_utf_32)
-       mtext__adjust_format (mt, default_utf_32);
+      if (mt->format != MTEXT_FORMAT_UTF_32)
+       mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
     }
   else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
     {
     }
   else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
     {
-      if (mt->format != default_utf_16)
-       mtext__adjust_format (mt, default_utf_16);
+      if (mt->format != MTEXT_FORMAT_UTF_16)
+       mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
     }
 
   nunits = CHAR_UNITS (c, mt->format);
     }
 
   nunits = CHAR_UNITS (c, mt->format);
@@ -2011,7 +2594,7 @@ mtext_ins_char (MText *mt, int pos, int c, int n)
   if (mt->cache_char_pos > pos)
     {
       mt->cache_char_pos += n;
   if (mt->cache_char_pos > pos)
     {
       mt->cache_char_pos += n;
-      mt->cache_byte_pos += nunits + n;
+      mt->cache_byte_pos += nunits * n;
     }
   memmove (mt->data + (pos_unit + nunits * n) * unit_bytes,
           mt->data + pos_unit * unit_bytes,
     }
   memmove (mt->data + (pos_unit + nunits * n) * unit_bytes,
           mt->data + pos_unit * unit_bytes,
@@ -2023,7 +2606,7 @@ mtext_ins_char (MText *mt, int pos, int c, int n)
       for (i = 0; i < n; i++)
        p += CHAR_STRING_UTF8 (c, p);
     }
       for (i = 0; i < n; i++)
        p += CHAR_STRING_UTF8 (c, p);
     }
-  else if (mt->format == default_utf_16)
+  else if (mt->format == MTEXT_FORMAT_UTF_16)
     {
       unsigned short *p = (unsigned short *) mt->data + pos_unit;
 
     {
       unsigned short *p = (unsigned short *) mt->data + pos_unit;
 
@@ -2045,6 +2628,132 @@ mtext_ins_char (MText *mt, int pos, int c, int n)
 /*=*/
 
 /***en
 /*=*/
 
 /***en
+    @brief Replace sub-text of M-text with another.
+
+    The mtext_replace () function replaces sub-text of M-text $MT1
+    between $FROM1 (inclusive) and $TO1 (exclusive) with the sub-text
+    of M-text $MT2 between $FROM2 (inclusive) and $TO2 (exclusive).
+    The new sub-text inherits text properties of the old sub-text.
+
+    @return 
+    If the operation was successful, mtext_replace () returns
+    0.  Otherwise, it returns -1 and assigns an error code to the
+    external variable #merror_code.  */
+
+/***ja
+    @brief M-text ¤Î°ìÉô¤òÊ̤ΠM-text ¤Î°ìÉô¤ÇÃÖ´¹¤¹¤ë.
+
+    ´Ø¿ô mtext_replace () ¤Ï¡¢ M-text $MT1 ¤Î $FROM1 ¡Ê$FROM1 ¼«ÂΤâ´Þ
+    ¤à¡Ë¤«¤é $TO1 ¡Ê$TO1 ¼«ÂΤϴޤޤʤ¤¡Ë¤Þ¤Ç¤ò¡¢ M-text $MT2 ¤Î 
+    $FROM2 ¡Ê$FROM2 ¼«ÂΤâ´Þ¤à¡Ë¤«¤é $TO2 ¡Ê$TO2 ¼«ÂΤϴޤޤʤ¤¡Ë¤ÇÃÖ
+    ¤­´¹¤¨¤ë¡£¿·¤·¤¯ÁÞÆþ¤µ¤ì¤¿Éôʬ¤Ï¡¢ÃÖ¤­´¹¤¨¤ëÁ°¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£
+    ¤¹¤Ù¤Æ¤ò·Ñ¾µ¤¹¤ë¡£
+
+    @return 
+    ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢ mtext_replace () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê
+    ¤±¤ì¤Ð -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
+
+/***
+    @errors
+    @c MERROR_MTEXT , @c MERROR_RANGE
+
+    @seealso
+    mtext_insert ()  */
+
+int
+mtext_replace (MText *mt1, int from1, int to1,
+              MText *mt2, int from2, int to2)
+{
+  int len1, len2;
+  int from1_byte, from2_byte, old_bytes, new_bytes;
+  int unit_bytes, total_bytes;
+  unsigned char *p;
+  int free_mt2 = 0;
+
+  M_CHECK_READONLY (mt1, -1);
+  M_CHECK_RANGE_X (mt1, from1, to1, -1);
+  M_CHECK_RANGE_X (mt2, from2, to2, -1);
+
+  if (from1 == to1)
+    {
+      struct MTextPlist *saved = mt2->plist;
+
+      mt2->plist = NULL;
+      insert (mt1, from1, mt2, from2, to2);
+      mt2->plist = saved;
+      return 0;
+    }
+
+  if (from2 == to2)
+    {
+      return mtext_del (mt1, from1, to1);
+    }
+
+  if (mt1 == mt2)
+    {
+      mt2 = mtext_duplicate (mt2, from2, to2);
+      to2 -= from2;
+      from2 = 0;
+      free_mt2 = 1;
+    }
+
+  if (mt1->format != mt2->format
+      && mt1->format == MTEXT_FORMAT_US_ASCII)
+    mt1->format = MTEXT_FORMAT_UTF_8;
+  if (mt1->format != mt2->format
+      && mt1->coverage < mt2->coverage)
+    mtext__adjust_format (mt1, mt2->format);
+  if (mt1->format != mt2->format)
+    {
+      mt2 = mtext_duplicate (mt2, from2, to2);
+      mtext__adjust_format (mt2, mt1->format);
+      to2 -= from2;
+      from2 = 0;
+      free_mt2 = 1;
+    }
+
+  len1 = to1 - from1;
+  len2 = to2 - from2;
+  mtext__adjust_plist_for_change (mt1, from1, len1, len2);
+
+  unit_bytes = UNIT_BYTES (mt1->format);
+  from1_byte = POS_CHAR_TO_BYTE (mt1, from1) * unit_bytes;
+  from2_byte = POS_CHAR_TO_BYTE (mt2, from2) * unit_bytes;
+  old_bytes = POS_CHAR_TO_BYTE (mt1, to1) * unit_bytes - from1_byte;
+  new_bytes = POS_CHAR_TO_BYTE (mt2, to2) * unit_bytes - from2_byte;
+  total_bytes = mt1->nbytes * unit_bytes + (new_bytes - old_bytes);
+  if (total_bytes + unit_bytes > mt1->allocated)
+    {
+      mt1->allocated = total_bytes + unit_bytes;
+      MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
+    }
+  p = mt1->data + from1_byte;
+  if (to1 < mt1->nchars
+      && old_bytes != new_bytes)
+    memmove (p + new_bytes, p + old_bytes,
+            (mt1->nbytes + 1) * unit_bytes - (from1_byte + old_bytes));
+  memcpy (p, mt2->data + from2_byte, new_bytes);
+  mt1->nchars += len2 - len1;
+  mt1->nbytes += (new_bytes - old_bytes) / unit_bytes;
+  if (mt1->cache_char_pos >= to1)
+    {
+      mt1->cache_char_pos += len2 - len1;
+      mt1->cache_byte_pos += new_bytes - old_bytes;
+    }
+  else if (mt1->cache_char_pos > from1)
+    {
+      mt1->cache_char_pos = from1;
+      mt1->cache_byte_pos = from1_byte;
+    }
+
+  if (free_mt2)
+    M17N_OBJECT_UNREF (mt2);
+  return 0;
+}
+
+/*=*/
+
+/***en
     @brief Search a character in an M-text.
 
     The mtext_character () function searches M-text $MT for character
     @brief Search a character in an M-text.
 
     The mtext_character () function searches M-text $MT for character
@@ -2065,15 +2774,15 @@ mtext_ins_char (MText *mt, int pos, int c, int n)
 
     ´Ø¿ô mtext_character () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£¤â¤· 
     $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ð¡¢Ãµº÷¤Ï°ÌÃÖ $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢ºÇÂç 
 
     ´Ø¿ô mtext_character () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£¤â¤· 
     $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ð¡¢Ãµº÷¤Ï°ÌÃÖ $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢ºÇÂç 
-    ($TO - 1) ¤Þ¤Ç¿Ê¤à¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð°ÌÃÖ ($FROM - 1) ¤«¤éÀèƬÊý¸þ¤Ø¡¢
-    ºÇÂç $TO ¤Þ¤Ç¿Ê¤à¡£°ÌÃ֤λØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM ¤È $TO ¤Îξ
-    Êý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
+    ($TO - 1) ¤Þ¤Ç¿Ê¤à¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð°ÌÃÖ ($FROM - 1) ¤«¤éÀèƬÊý¸þ¤Ø¡¢ºÇÂç
+    $TO ¤Þ¤Ç¿Ê¤à¡£°ÌÃ֤λØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM ¤È $TO 
+    ¤ÎξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¤ß¤Ê¤¹¡£
 
     @return
 
     @return
-    ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_character () ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
-    ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code ¤òÊѹ¹¤»¤º¤Ë -1 ¤òÊÖ
-    ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼
-    ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
+    ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_character () 
+    ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code
+    ¤òÊѹ¹¤»¤º¤Ë -1 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
+    #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£  */
 
 /***
     @seealso
 
 /***
     @seealso
@@ -2115,12 +2824,12 @@ mtext_character (MText *mt, int from, int to, int c)
 /***ja
     @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
 
 /***ja
     @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
 
-    ´Ø¿ô mtext_chr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT ¤Î
-    ÀèƬ¤«¤éËöÈøÊý¸þ¤Ë¿Ê¤à¡£
+    ´Ø¿ô mtext_chr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT 
+    ¤ÎÀèƬ¤«¤éËöÈøÊý¸þ¤Ë¿Ê¤à¡£
 
     @return
 
     @return
-    ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_chr () ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é
-    ¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
+    ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_chr () 
+    ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_chr} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_chr} @endlatexonly  */
 
@@ -2153,12 +2862,12 @@ mtext_chr (MText *mt, int c)
 /***ja
     @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ¸å¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
 
 /***ja
     @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ¸å¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
 
-    ´Ø¿ô mtext_rchr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT ¤Î
-    ºÇ¸å¤«¤éÀèƬÊý¸þ¤Ø¤È¸å¸þ¤­¤Ë¿Ê¤à¡£
+    ´Ø¿ô mtext_rchr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT 
+    ¤ÎºÇ¸å¤«¤éÀèƬÊý¸þ¤Ø¤È¸å¸þ¤­¤Ë¿Ê¤à¡£
 
     @return
 
     @return
-    ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_rchr () ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é
-    ¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
+    ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_rchr () 
+    ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_rchr} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_rchr} @endlatexonly  */
 
@@ -2195,9 +2904,8 @@ mtext_rchr (MText *mt, int c)
     ´Ø¿ô mtext_cmp () ¤Ï¡¢ M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£
 
     @return
     ´Ø¿ô mtext_cmp () ¤Ï¡¢ M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£
 
     @return
-    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì
-    ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å
-    ¤¯¡£
+    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì¤Ð
+    1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£
 
     @latexonly \IPAlabel{mtext_cmp} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_cmp} @endlatexonly  */
 
@@ -2228,12 +2936,12 @@ mtext_cmp (MText *mt1, MText *mt2)
 /***ja
     @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
 
 /***ja
     @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
 
-    ´Ø¿ô mtext_ncmp () ¤Ï¡¢´Ø¿ô mtext_cmp () Æ±ÍͤΠM-text Æ±»Î¤ÎÈæ³Ó
-    ¤òÀèƬ¤«¤éºÇÂç $N Ê¸»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
+    ´Ø¿ô mtext_ncmp () ¤Ï¡¢´Ø¿ô mtext_cmp () Æ±ÍͤΠM-text 
+    Æ±»Î¤ÎÈæ³Ó¤òÀèƬ¤«¤éºÇÂç $N Ê¸»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
 
     @return
 
     @return
-    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì
-    ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
+    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì¤Ð 
+    1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_ncmp} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_ncmp} @endlatexonly  */
 
@@ -2272,18 +2980,16 @@ mtext_ncmp (MText *mt1, MText *mt2, int n)
 /***ja
     @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿ÎΰèƱ»Î¤òÈæ³Ó¤¹¤ë.
 
 /***ja
     @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿ÎΰèƱ»Î¤òÈæ³Ó¤¹¤ë.
 
-    ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ
-    ³Ó¤¹¤ë¡£Èæ³ÓÂоݤȤʤë¤Î¤Ï $MT1 ¤Ç¤Ï $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2 
-    ¤Ç¤Ï $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£$FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1 
-    ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë
-    ¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì
-    ¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë Î¾Êý¤Ë 0 ¤¬»ØÄꤵ
-    ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
+    ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 
+    ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£Èæ³Ó¤ÎÂоݤϠ$MT1 ¤Î¤¦¤Á $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¤È¡¢$MT2 
+    ¤Î¤¦¤Á $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£$FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1 
+    ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 
+    ¡Ë¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢
+    $FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë Î¾Êý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¤ß¤Ê¤¹¡£
 
     @return
 
     @return
-    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì
-    ¤Ð 1 ¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð
-    ¤Å¤¯¡£  */
+    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì¤Ð
+    1 ¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£  */
 
 /***
     @seealso
 
 /***
     @seealso
@@ -2314,8 +3020,8 @@ mtext_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
 /***ja
     @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
 
 /***ja
     @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
 
-    ´Ø¿ô mtext_spn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2 ¤Ë´Þ¤Þ
-    ¤ì¤ëʸ»ú¤À¤±¤Ç¤Ç¤­¤Æ¤¤¤ëÉôʬ¤ÎºÇÂ獵¤òÊÖ¤¹¡£
+    ´Ø¿ô mtext_spn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬ¤«¤é M-text $MT2 
+    ¤Ë´Þ¤Þ¤ì¤ëʸ»ú¤À¤±¤Ç¤Ç¤­¤Æ¤¤¤ëÉôʬ¤ÎŤµ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_spn} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_spn} @endlatexonly  */
 
@@ -2340,8 +3046,8 @@ mtext_spn (MText *mt, MText *accept)
 /***ja
     @brief ¤¢¤ë½¸¹ç¤Ë°¤µ¤Ê¤¤Ê¸»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
 
 /***ja
     @brief ¤¢¤ë½¸¹ç¤Ë°¤µ¤Ê¤¤Ê¸»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
 
-    ´Ø¿ô mtext_cspn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2 ¤Ë´Þ¤Þ
-    ¤ì¤Ê¤¤Ê¸»ú¤À¤±¤Ç¤Ç¤­¤Æ¤¤¤ëÉôʬ¤ÎºÇÂ獵¤òÊÖ¤¹¡£
+    ´Ø¿ô mtext_cspn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2
+    ¤Ë´Þ¤Þ¤ì¤Ê¤¤Ê¸»ú¤À¤±¤Ç¤Ç¤­¤Æ¤¤¤ëÉôʬ¤ÎŤµ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_cspn} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_cspn} @endlatexonly  */
 
@@ -2368,14 +3074,14 @@ mtext_cspn (MText *mt, MText *reject)
     If no such character is found, it returns -1. */
 
 /***ja
     If no such character is found, it returns -1. */
 
 /***ja
-    @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤Î¤É¤ì¤«¤ò M-text ¤ÎÃæ¤Çõ¤¹.
+    @brief ¤¢¤ë½¸¹ç¤Ë°¤¹Ê¸»ú¤ò M-text ¤ÎÃ椫¤éõ¤¹.
 
 
-    ´Ø¿ô mtext_pbrk () ¤Ï¡¢M-text $MT1 Ãæ¤Ç M-text $MT2 ¤Î¤¤¤º¤ì¤«¤Îʸ
-    »ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£
+    ´Ø¿ô mtext_pbrk () ¤Ï¡¢M-text $MT1 Ãæ¤Ç M-text $MT2 
+    ¤Îʸ»ú¤Î¤É¤ì¤«¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£
 
     @return 
 
     @return 
-    ¸«¤Ä¤«¤Ã¤¿Ê¸»ú¤Î¡¢$MT1 Æâ¤Ë¤ª¤±¤ë½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¤â¤·¤½¤Î¤è¤¦¤Êʸ
-    »ú¤¬¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
+    ¸«¤Ä¤«¤Ã¤¿Ê¸»ú¤Î¡¢$MT1 
+    Æâ¤Ë¤ª¤±¤ë½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¤â¤·¤½¤Î¤è¤¦¤Êʸ»ú¤¬¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_pbrk} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_pbrk} @endlatexonly  */
 
@@ -2409,18 +3115,17 @@ mtext_pbrk (MText *mt, MText *accept)
 /***ja
     @brief M-text Ãæ¤Î¥È¡¼¥¯¥ó¤òõ¤¹.
 
 /***ja
     @brief M-text Ãæ¤Î¥È¡¼¥¯¥ó¤òõ¤¹.
 
-    ´Ø¿ô mtext_tok () ¤Ï¡¢M-text $MT ¤ÎÃæ¤Ç°ÌÃÖ $POS °Ê¹ßºÇ½é¤Ë¸½¤ì¤ë
-    ¥È¡¼¥¯¥ó¤òõ¤¹¡£¤³¤³¤Ç¥È¡¼¥¯¥ó¤È¤Ï M-text $DELIM ¤ÎÃæ¤Ë¸½¤ï¤ì¤Ê¤¤
-    Ê¸»ú¤À¤±¤«¤é¤Ê¤ëÉôʬʸ»úÎó¤Ç¤¢¤ë¡£$POS ¤Î·¿¤¬ @c int ¤Ç¤Ï¤Ê¤¯¤Æ @c
+    ´Ø¿ô mtext_tok () ¤Ï¡¢M-text $MT ¤ÎÃæ¤Ç°ÌÃÖ $POS 
+    °Ê¹ßºÇ½é¤Ë¸½¤ì¤ë¥È¡¼¥¯¥ó¤òõ¤¹¡£¤³¤³¤Ç¥È¡¼¥¯¥ó¤È¤Ï M-text $DELIM
+    ¤ÎÃæ¤Ë¸½¤ï¤ì¤Ê¤¤Ê¸»ú¤À¤±¤«¤é¤Ê¤ëÉôʬʸ»úÎó¤Ç¤¢¤ë¡£$POS ¤Î·¿¤¬ @c int ¤Ç¤Ï¤Ê¤¯¤Æ @c
     int ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤³¤È¤ËÃí°Õ¡£
 
     @return
     int ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤³¤È¤ËÃí°Õ¡£
 
     @return
-    ¤â¤·¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤ì¤Ð mtext_tok ()¤Ï¤½¤Î¥È¡¼¥¯¥ó¤ËÁêÅö¤¹¤ëÉôʬ
-    ¤Î $MT ¤ò¥³¥Ô¡¼¤·¡¢¤½¤Î¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢$POS ¤Ï
-    ¸«¤Ä¤«¤Ã¤¿¥È¡¼¥¯¥ó¤Î½ªÃ¼¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿
-    ¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code ¤òÊѤ¨¤º¤Ë @c NULL ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
-    ¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢ÊÑÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤ò
-    ÀßÄꤹ¤ë¡£
+    ¤â¤·¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤ì¤Ð mtext_tok ()¤Ï¤½¤Î¥È¡¼¥¯¥ó¤ËÁêÅö¤¹¤ëÉôʬ¤Î 
+    $MT ¤ò¥³¥Ô¡¼¤·¡¢¤½¤Î¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢$POS 
+    ¤Ï¸«¤Ä¤«¤Ã¤¿¥È¡¼¥¯¥ó¤Î½ªÃ¼¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï³°ÉôÊÑ¿ô
+    #merror_code ¤òÊѤ¨¤º¤Ë @c NULL ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï 
+    @c NULL ¤òÊÖ¤·¡¢ÊÑÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
 
     @latexonly \IPAlabel{mtext_tok} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_tok} @endlatexonly  */
 
@@ -2468,12 +3173,11 @@ mtext_tok (MText *mt, MText *delim, int *pos)
     @brief M-text Ãæ¤ÇÊ̤ΠM-text ¤òõ¤¹.
 
     ´Ø¿ô mtext_text () ¤Ï¡¢M-text $MT1 Ãæ¤Ç°ÌÃÖ $POS °Ê¹ß¤Ë¸½¤ï¤ì¤ë 
     @brief M-text Ãæ¤ÇÊ̤ΠM-text ¤òõ¤¹.
 
     ´Ø¿ô mtext_text () ¤Ï¡¢M-text $MT1 Ãæ¤Ç°ÌÃÖ $POS °Ê¹ß¤Ë¸½¤ï¤ì¤ë 
-    M-text $MT2 ¤ÎºÇ½é¤Î°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î°ã¤¤¤Ï̵»ë¤µ
-    ¤ì¤ë¡£
+    M-text $MT2 ¤ÎºÇ½é¤Î°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î°ã¤¤¤Ï̵»ë¤µ¤ì¤ë¡£
 
     @return
 
     @return
-    $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_text() ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
-    ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
+    $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_text() 
+    ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_text} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_text} @endlatexonly  */
 
@@ -2481,9 +3185,7 @@ int
 mtext_text (MText *mt1, int pos, MText *mt2)
 {
   int from = pos;
 mtext_text (MText *mt1, int pos, MText *mt2)
 {
   int from = pos;
-  int pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
   int c = mtext_ref_char (mt2, 0);
   int c = mtext_ref_char (mt2, 0);
-  int nbytes1 = mtext_nbytes (mt1);
   int nbytes2 = mtext_nbytes (mt2);
   int limit;
   int use_memcmp = (mt1->format == mt2->format
   int nbytes2 = mtext_nbytes (mt2);
   int limit;
   int use_memcmp = (mt1->format == mt2->format
@@ -2491,13 +3193,14 @@ mtext_text (MText *mt1, int pos, MText *mt2)
                        && mt2->format == MTEXT_FORMAT_UTF_8));
   int unit_bytes = UNIT_BYTES (mt1->format);
 
                        && mt2->format == MTEXT_FORMAT_UTF_8));
   int unit_bytes = UNIT_BYTES (mt1->format);
 
-  if (nbytes2 > pos_byte + nbytes1)
+  if (from + mtext_nchars (mt2) > mtext_nchars (mt1))
     return -1;
     return -1;
-  pos_byte = nbytes1 - nbytes2;
-  limit = POS_BYTE_TO_CHAR (mt1, pos_byte);
+  limit = mtext_nchars (mt1) - mtext_nchars (mt2) + 1;
 
   while (1)
     {
 
   while (1)
     {
+      int pos_byte;
+
       if ((pos = mtext_character (mt1, from, limit, c)) < 0)
        return -1;
       pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
       if ((pos = mtext_character (mt1, from, limit, c)) < 0)
        return -1;
       pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
@@ -2528,15 +3231,15 @@ mtext_text (MText *mt1, int pos, MText *mt2)
 /***ja
     @brief M-text Ãæ¤ÎÆÃÄê¤ÎÎΰè¤ÇÊ̤ΠM-text ¤òõ¤¹.
 
 /***ja
     @brief M-text Ãæ¤ÎÆÃÄê¤ÎÎΰè¤ÇÊ̤ΠM-text ¤òõ¤¹.
 
-    ´Ø¿ô mtext_search () ¤Ï¡¢M-text $MT1 Ãæ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î´Ö¤Î
-    Îΰè¤ÇM-text $MT2 ¤¬ºÇ½é¤Ë¸½¤ï¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£
-    ¤Î°ã¤¤¤Ï̵»ë¤µ¤ì¤ë¡£¤â¤· $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ðõº÷¤Ï°ÌÃÖ 
-    $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð $TO ¤«¤éÀèƬÊý¸þ¤ØºÇÂç $TO ¤Þ
-    ¤Ç¿Ê¤à¡£
+    ´Ø¿ô mtext_search () ¤Ï¡¢M-text $MT1 Ãæ¤Î $FROM ¤«¤é $TO 
+    ¤Þ¤Ç¤Î´Ö¤ÎÎΰè¤ÇM-text $MT2 
+    ¤¬ºÇ½é¤Ë¸½¤ï¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î°ã¤¤¤Ï̵»ë¤µ¤ì¤ë¡£¤â¤·
+    $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ðõº÷¤Ï°ÌÃÖ $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
+    $TO ¤«¤éÀèƬÊý¸þ¤Ø¿Ê¤à¡£
 
     @return
 
     @return
-    $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_search() ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
-    ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
+    $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_search() 
+    ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
     */
 
 int
     */
 
 int
@@ -2572,7 +3275,7 @@ mtext_search (MText *mt1, int from, int to, MText *mt2)
        return -1;
       while (1)
        {
        return -1;
       while (1)
        {
-         if ((from = find_char_backward (mt1, from, to, c)) < 0)
+         if ((from = find_char_backward (mt1, to, from + 1, c)) < 0)
            return -1;
          from_byte = POS_CHAR_TO_BYTE (mt1, from);
          if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
            return -1;
          from_byte = POS_CHAR_TO_BYTE (mt1, from);
          if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
@@ -2599,12 +3302,12 @@ mtext_search (MText *mt1, int from, int to, MText *mt2)
 /***ja
     @brief Æó¤Ä¤Î M-text ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
 
 /***ja
     @brief Æó¤Ä¤Î M-text ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
 
-    ´Ø¿ô mtext_casecmp () ¤Ï¡¢´Ø¿ô mtext_cmp () Æ±ÍͤΠM-text Æ±»Î¤ÎÈæ
-    ³Ó¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æ¹Ô¤Ê¤¦¡£
+    ´Ø¿ô mtext_casecmp () ¤Ï¡¢´Ø¿ô mtext_cmp () Æ±ÍͤΠM-text 
+    Æ±»Î¤ÎÈæ³Ó¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æ¹Ô¤Ê¤¦¡£
 
     @return
 
     @return
-    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì
-    ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
+    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 
+    ¤è¤êÂ礭¤±¤ì¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_casecmp} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_casecmp} @endlatexonly  */
 
@@ -2634,12 +3337,12 @@ mtext_casecmp (MText *mt1, MText *mt2)
 /***ja
     @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
 
 /***ja
     @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
 
-    ´Ø¿ô mtext_ncasecmp () ¤Ï¡¢´Ø¿ô mtext_casecmp () Æ±ÍͤΠM-text Æ±
-    »Î¤ÎÈæ³Ó¤òÀèƬ¤«¤éºÇÂç $N Ê¸»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
+    ´Ø¿ô mtext_ncasecmp () ¤Ï¡¢´Ø¿ô mtext_casecmp () Æ±ÍͤΠM-text 
+    Æ±»Î¤ÎÈæ³Ó¤òÀèƬ¤«¤éºÇÂç $N Ê¸»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
 
     @return
 
     @return
-    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì
-    ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
+    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 
+    ¤è¤êÂ礭¤±¤ì¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
 
     @latexonly \IPAlabel{mtext_ncasecmp} @endlatexonly  */
 
 
     @latexonly \IPAlabel{mtext_ncasecmp} @endlatexonly  */
 
@@ -2679,17 +3382,17 @@ mtext_ncasecmp (MText *mt1, MText *mt2, int n)
 /***ja 
     @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿Îΰè¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
 
 /***ja 
     @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿Îΰè¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
 
-    ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 ¤ò¡¢Âçʸ»ú¡¿¾®
-    Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£Èæ³ÓÂоݤȤʤë¤Î¤Ï $MT1 
-    ¤Ç¤Ï $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2 ¤Ç¤Ï $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£
-    $FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È 
-    $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text 
+    ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 
+    ¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£Èæ³Ó¤ÎÂоݤϠ$MT1 
+    ¤Î $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2 ¤Î $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£
+    $FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È $TO1
+    ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text 
     ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï 
     $FROM2 ¤È $TO2 ¡ËξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
 
     @return
     ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï 
     $FROM2 ¤È $TO2 ¡ËξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
 
     @return
-    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì
-    ¤Ð1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð-1¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£
+    ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礭¤±¤ì¤Ð
+    1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£
 
   @latexonly \IPAlabel{mtext_case_compare} @endlatexonly
 */
 
   @latexonly \IPAlabel{mtext_case_compare} @endlatexonly
 */
@@ -2712,6 +3415,161 @@ mtext_case_compare (MText *mt1, int from1, int to1,
   return case_compare (mt1, from1, to1, mt2, from2, to2);
 }
 
   return case_compare (mt1, from1, to1, mt2, from2, to2);
 }
 
+/*=*/
+
+/***en
+    @brief Lowercase an M-text.
+
+    The mtext_lowercase () function destructively converts each
+    character in M-text $MT to lowercase.  Adjacent characters in $MT
+    may affect the case conversion.  If the Mlanguage text property is
+    attached to $MT, it may also affect the conversion.  The length of
+    $MT may change.  Characters that cannot be converted to lowercase
+    is left unchanged.  All the text properties are inherited.
+
+    @return
+    This function returns the length of the updated $MT.
+*/
+
+/***ja
+    @brief M-text ¤ò¾®Ê¸»ú¤Ë¤¹¤ë.
+
+    ´Ø¿ô mtext_lowercase () ¤Ï M-text $MT Ãæ¤Î³Æʸ»ú¤òÇ˲õŪ¤Ë¾®Ê¸»ú¤ËÊÑ
+    ´¹¤¹¤ë¡£ÊÑ´¹¤ËºÝ¤·¤ÆÎÙÀܤ¹¤ëʸ»ú¤Î±Æ¶Á¤ò¼õ¤±¤ë¤³¤È¤¬¤¢¤ë¡£$MT ¤Ë¥Æ
+    ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ Mlanguage ¤¬ÉÕ¤¤¤Æ¤¤¤ë¾ì¹ç¤Ï¡¢¤½¤ì¤âÊÑ´¹¤Ë±Æ¶Á¤ò
+    Í¿¤¨¤¦¤ë¡£$MT ¤ÎŤµ¤ÏÊѤï¤ë¤³¤È¤¬¤¢¤ë¡£¾®Ê¸»ú¤ËÊÑ´¹¤Ç¤­¤Ê¤«¤Ã¤¿Ê¸
+    »ú¤Ï¤½¤Î¤Þ¤Þ»Ä¤ë¡£¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
+
+    @return
+    ¤³¤Î´Ø¿ô¤Ï¹¹¿·¸å¤Î $MT ¤ÎŤµ¤òÊÖ¤¹¡£
+*/
+
+/***
+    @seealso
+     mtext_titlecase (), mtext_uppercase ()
+*/
+
+int
+mtext_lowercase (MText *mt)
+
+{
+  CASE_CONV_INIT (-1);
+
+  return mtext__lowercase (mt, 0, mtext_len (mt));
+}
+
+/*=*/
+
+/***en
+    @brief Titlecase an M-text.
+
+    The mtext_titlecase () function destructively converts the first
+    character with the cased property in M-text $MT to titlecase and
+    the others to lowercase.  The length of $MT may change.  If the
+    character cannot be converted to titlecase, it is left unchanged.
+    All the text properties are inherited.
+
+    @return
+    This function returns the length of the updated $MT.
+*/
+
+/***ja
+    @brief M-text ¤ò¥¿¥¤¥È¥ë¥±¡¼¥¹¤Ë¤¹¤ë.
+
+    ´Ø¿ô mtext_titlecase () ¤Ï M-text $MT Ãæ¤Ç cased ¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä
+    ºÇ½é¤Îʸ»ú¤ò¥¿¥¤¥È¥ë¥±¡¼¥¹¤Ë¡¢¤½¤·¤Æ¤½¤ì°Ê¹ß¤Îʸ»ú¤ò¾®Ê¸»ú¤ËÇ˲õŪ
+    ¤ËÊÑ´¹¤¹¤ë¡£$MT ¤ÎŤµ¤ÏÊѤï¤ë¤³¤È¤¬¤¢¤ë¡£¥¿¥¤¥È¥ë¥±¡¼¥¹¤Ë¤ËÊÑ´¹¤Ç
+    ¤­¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï¤½¤Î¤Þ¤Þ¤ÇÊѤï¤é¤Ê¤¤¡£¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ
+    ¾µ¤µ¤ì¤ë¡£
+
+    @return
+    ¤³¤Î´Ø¿ô¤Ï¹¹¿·¸å¤Î $MT ¤ÎŤµ¤òÊÖ¤¹¡£
+*/
+
+/***
+    @seealso
+     mtext_lowercase (), mtext_uppercase ()
+*/
+
+int
+mtext_titlecase (MText *mt)
+{
+  int len = mtext_len (mt), from, to;
+
+  CASE_CONV_INIT (-1);
+
+  /* Find 1st cased character. */
+  for (from = 0; from < len; from++)
+    {
+      int csd = (int) mchartable_lookup (cased, mtext_ref_char (mt, from));
+
+      if (csd > 0 && csd & CASED)
+       break;
+    }
+
+  if (from == len)
+    return len;
+
+  if (from == len - 1)
+    return (mtext__titlecase (mt, from, len));
+
+  /* Go through following combining characters. */
+  for (to = from + 1;
+       (to < len
+       && ((int) mchartable_lookup (combining_class, mtext_ref_char (mt, to))
+           > 0));
+       to++);
+
+  /* Titlecase the region and prepare for next lowercase operation.
+     MT may be shortened or lengthened. */
+  from = mtext__titlecase (mt, from, to);
+
+  return (mtext__lowercase (mt, from, mtext_len (mt)));
+}
+
+/*=*/
+
+/***en
+    @brief Uppercase an M-text.
+
+
+    The mtext_uppercase () function destructively converts each
+    character in M-text $MT to uppercase.  Adjacent characters in $MT
+    may affect the case conversion.  If the Mlanguage text property is
+    attached to $MT, it may also affect the conversion.  The length of
+    $MT may change.  Characters that cannot be converted to uppercase
+    is left unchanged.  All the text properties are inherited.
+
+    @return
+    This function returns the length of the updated $MT.
+*/
+
+/***ja
+    @brief M-text ¤òÂçʸ»ú¤Ë¤¹¤ë.
+
+    ´Ø¿ô mtext_uppercase () ¤Ï M-text $MT Ãæ¤Î³Æʸ»ú¤òÇ˲õŪ¤ËÂçʸ»ú¤ËÊÑ
+    ´¹¤¹¤ë¡£ÊÑ´¹¤ËºÝ¤·¤ÆÎÙÀܤ¹¤ëʸ»ú¤Î±Æ¶Á¤ò¼õ¤±¤ë¤³¤È¤¬¤¢¤ë¡£$MT ¤Ë¥Æ
+    ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£ Mlanguage ¤¬ÉÕ¤¤¤Æ¤¤¤ë¾ì¹ç¤Ï¡¢¤½¤ì¤âÊÑ´¹¤Ë±Æ¶Á¤ò
+    Í¿¤¨¤¦¤ë¡£$MT ¤ÎŤµ¤ÏÊѤï¤ë¤³¤È¤¬¤¢¤ë¡£Âçʸ»ú¤ËÊÑ´¹¤Ç¤­¤Ê¤«¤Ã¤¿Ê¸
+    »ú¤Ï¤½¤Î¤Þ¤Þ»Ä¤ë¡£¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
+
+    @return
+    ¤³¤Î´Ø¿ô¤Ï¹¹¿·¸å¤Î $MT ¤ÎŤµ¤òÊÖ¤¹¡£
+*/
+
+/***
+    @seealso
+     mtext_lowercase (), mtext_titlecase ()
+*/
+
+int
+mtext_uppercase (MText *mt)
+{
+  CASE_CONV_INIT (-1);
+
+  return (mtext__uppercase (mt, 0, mtext_len (mt)));
+}
+
 /*** @} */
 
 #include <stdio.h>
 /*** @} */
 
 #include <stdio.h>
@@ -2724,8 +3582,9 @@ mtext_case_compare (MText *mt1, int from1, int to1,
     @brief Dump an M-text.
 
     The mdebug_dump_mtext () function prints the M-text $MT in a human
     @brief Dump an M-text.
 
     The mdebug_dump_mtext () function prints the M-text $MT in a human
-    readable way to the stderr.  $INDENT specifies how many columns to
-    indent the lines but the first one.  If $FULLP is zero, this
+    readable way to the stderr or to what specified by the environment
+    variable MDEBUG_OUTPUT_FILE.  $INDENT specifies how many columns
+    to indent the lines but the first one.  If $FULLP is zero, this
     function prints only a character code sequence.  Otherwise, it
     prints the internal byte sequence and text properties as well.
 
     function prints only a character code sequence.  Otherwise, it
     prints the internal byte sequence and text properties as well.
 
@@ -2734,10 +3593,11 @@ mtext_case_compare (MText *mt1, int from1, int to1,
 /***ja
     @brief M-text ¤ò¥À¥ó¥×¤¹¤ë.
 
 /***ja
     @brief M-text ¤ò¥À¥ó¥×¤¹¤ë.
 
-    ´Ø¿ô mdebug_dump_mtext () ¤Ï M-text $MT ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤʠ
-    ·Á¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£$FULLP 
-    ¤¬ 0 ¤Ê¤é¤Ð¡¢Ê¸»ú¥³¡¼¥ÉÎó¤À¤±¤ò°õºþ¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢ÆâÉô¥Ð¥¤
-    ¥ÈÎó¤È¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤â°õºþ¤¹¤ë¡£
+    ´Ø¿ô mdebug_dump_mtext () ¤Ï M-text $MT ¤òɸ½à¥¨¥é¡¼½ÐÎϤ⤷¤¯¤Ï´Ä
+    ¶­ÊÑ¿ô MDEBUG_DUMP_FONT ¤Ç»ØÄꤵ¤ì¤¿¥Õ¥¡¥¤¥ë¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ
+    ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£$FULLP ¤¬ 0 ¤Ê¤é
+    ¤Ð¡¢Ê¸»ú¥³¡¼¥ÉÎó¤À¤±¤ò°õºþ¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢ÆâÉô¥Ð¥¤¥ÈÎó¤È¥Æ¥­
+    ¥¹¥È¥×¥í¥Ñ¥Æ¥£¤â°õºþ¤¹¤ë¡£
 
     @return
     ¤³¤Î´Ø¿ô¤Ï $MT ¤òÊÖ¤¹¡£  */
 
     @return
     ¤³¤Î´Ø¿ô¤Ï $MT ¤òÊÖ¤¹¡£  */
@@ -2745,59 +3605,66 @@ mtext_case_compare (MText *mt1, int from1, int to1,
 MText *
 mdebug_dump_mtext (MText *mt, int indent, int fullp)
 {
 MText *
 mdebug_dump_mtext (MText *mt, int indent, int fullp)
 {
-  char *prefix = (char *) alloca (indent + 1);
   int i;
   int i;
-  unsigned char *p;
-
-  memset (prefix, 32, indent);
-  prefix[indent] = 0;
 
   if (! fullp)
     {
 
   if (! fullp)
     {
-      fprintf (stderr, "\"");
-      for (i = 0; i < mt->nbytes; i++)
+      fprintf (mdebug__output, "\"");
+      for (i = 0; i < mt->nchars; i++)
        {
        {
-         int c = mt->data[i];
-         if (c >= ' ' && c < 127)
-           fprintf (stderr, "%c", c);
+         int c = mtext_ref_char (mt, i);
+
+         if (c == '"' || c == '\\')
+           fprintf (mdebug__output, "\\%c", c);
+         else if ((c >= ' ' && c < 127) || c == '\n')
+           fprintf (mdebug__output, "%c", c);
          else
          else
-           fprintf (stderr, "\\x%02X", c);
+           fprintf (mdebug__output, "\\x%02X", c);
        }
        }
-      fprintf (stderr, "\"");
+      fprintf (mdebug__output, "\"");
       return mt;
     }
 
       return mt;
     }
 
-  fprintf (stderr,
+  fprintf (mdebug__output,
           "(mtext (size %d %d %d) (cache %d %d)",
           mt->nchars, mt->nbytes, mt->allocated,
           mt->cache_char_pos, mt->cache_byte_pos);
           "(mtext (size %d %d %d) (cache %d %d)",
           mt->nchars, mt->nbytes, mt->allocated,
           mt->cache_char_pos, mt->cache_byte_pos);
+
   if (mt->nchars > 0)
     {
   if (mt->nchars > 0)
     {
-      fprintf (stderr, "\n%s (bytes \"", prefix);
+      char *prefix = (char *) alloca (indent + 1);
+      unsigned char *p;
+
+      memset (prefix, 32, indent);
+      prefix[indent] = 0;
+
+      fprintf (mdebug__output, "\n%s (bytes \"", prefix);
       for (i = 0; i < mt->nbytes; i++)
       for (i = 0; i < mt->nbytes; i++)
-       fprintf (stderr, "\\x%02x", mt->data[i]);
-      fprintf (stderr, "\")\n");
-      fprintf (stderr, "%s (chars \"", prefix);
+       fprintf (mdebug__output, "\\x%02x", mt->data[i]);
+      fprintf (mdebug__output, "\")\n");
+      fprintf (mdebug__output, "%s (chars \"", prefix);
       p = mt->data;
       for (i = 0; i < mt->nchars; i++)
        {
          int len;
          int c = STRING_CHAR_AND_BYTES (p, len);
 
       p = mt->data;
       for (i = 0; i < mt->nchars; i++)
        {
          int len;
          int c = STRING_CHAR_AND_BYTES (p, len);
 
-         if (c >= ' ' && c < 127 && c != '\\' && c != '"')
-           fputc (c, stderr);
+         if (c == '"' || c == '\\')
+           fprintf (mdebug__output, "\\%c", c);
+         else if (c >= ' ' && c < 127)
+           fputc (c, mdebug__output);
          else
          else
-           fprintf (stderr, "\\x%X", c);
+           fprintf (mdebug__output, "\\x%X", c);
          p += len;
        }
          p += len;
        }
-      fprintf (stderr, "\")");
+      fprintf (mdebug__output, "\")");
       if (mt->plist)
        {
       if (mt->plist)
        {
-         fprintf (stderr, "\n%s ", prefix);
+         fprintf (mdebug__output, "\n%s ", prefix);
          dump_textplist (mt->plist, indent + 1);
        }
     }
          dump_textplist (mt->plist, indent + 1);
        }
     }
-  fprintf (stderr, ")");
+  fprintf (mdebug__output, ")");
   return mt;
 }
 
   return mt;
 }