X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fmtext.c;h=363bf2d5c539e30e63c12a97980cc2184edcbe09;hb=f4ad17a5404b97d84906a9bef9fa40671be58e1c;hp=b13ef8810e2f6c420313618e87a58600959d174a;hpb=8a979a3ef795162431744c9e8fb2d51181e9e890;p=m17n%2Fm17n-lib.git diff --git a/src/mtext.c b/src/mtext.c index b13ef88..363bf2d 100644 --- a/src/mtext.c +++ b/src/mtext.c @@ -93,9 +93,6 @@ #include "character.h" #include "mtext.h" #include "plist.h" -#ifdef HAVE_THAI_WORDSEG -#include "word-thai.h" -#endif static M17NObjectArray mtext_table; @@ -155,6 +152,11 @@ static MSymbol M_charbag; (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). */ @@ -242,7 +244,7 @@ insert (MText *mt1, int pos, MText *mt2, int from, int to) 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 @@ -256,7 +258,7 @@ insert (MText *mt1, int pos, MText *mt2, int from, int to) else if (mt1->format == MTEXT_FORMAT_US_ASCII) { if (mt2->format == MTEXT_FORMAT_UTF_8) - mt1->format = MTEXT_FORMAT_UTF_8; + 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); @@ -685,18 +687,12 @@ case_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2) /* Internal API */ -MCharTable *wordseg_func_table; - int mtext__init () { M17N_OBJECT_ADD_ARRAY (mtext_table, "M-text"); M_charbag = msymbol_as_managing_key (" charbag"); mtext_table.count = 0; - wordseg_func_table = mchartable (Mnil, NULL); -#ifdef HAVE_THAI_WORDSEG - mtext__word_thai_init (); -#endif return 0; } @@ -704,11 +700,7 @@ mtext__init () void mtext__fini (void) { -#ifdef HAVE_THAI_WORDSEG - mtext__word_thai_fini (); -#endif - M17N_OBJECT_UNREF (wordseg_func_table); - wordseg_func_table = NULL; + mtext__wseg_fini (); } @@ -905,6 +897,7 @@ mtext__from_data (const void *data, int nitems, enum MTextFormat 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; @@ -995,6 +988,7 @@ mtext__adjust_format (MText *mt, enum MTextFormat format) } } mt->format = format; + mt->coverage = FORMAT_COVERAGE (format); } @@ -1117,22 +1111,6 @@ mtext__eol (MText *mt, int pos) } } -typedef int (*MTextWordsegFunc) (MText *mt, int pos, int *from, int *to); - -int -mtext__word_segment (MText *mt, int pos, int *from, int *to) -{ - int c = mtext_ref_char (mt, pos); - MTextWordsegFunc func - = (MTextWordsegFunc) mchartable_lookup (wordseg_func_table, c); - - if (func) - return (func) (mt, pos, from, to); - *from = *to = pos; - return -1; -} - - /*** @} */ #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ @@ -1160,7 +1138,7 @@ const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32LE; 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 @@ -1168,13 +1146,13 @@ const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32LE; ´Ø¿ô mtext () ¤Ï¡¢Ä¹¤µ 0 ¤Î¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô - m17n_object_free () ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£ + m17n_object_unref () ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£ @latexonly \IPAlabel{mtext} @endlatexonly */ /*** @seealso - m17n_object_free () */ + m17n_object_unref () */ MText * mtext () @@ -1182,7 +1160,8 @@ 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; } @@ -1459,12 +1438,12 @@ mtext_set_char (MText *mt, int pos, int c) 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) - 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) { @@ -1642,19 +1621,7 @@ mtext_cat_char (MText *mt, int c) 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)); } /*=*/ @@ -1844,10 +1811,10 @@ mtext_ncpy (MText *mt1, MText *mt2, int n) (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 ¤ò¤Ä¤¯¤ë. @@ -1873,13 +1840,12 @@ mtext_ncpy (MText *mt1, MText *mt2, int n) 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; - if (from < to) - insert (new, 0, mt, from, to); + new->coverage = mt->coverage; + insert (new, 0, mt, from, to); return new; } @@ -2018,7 +1984,7 @@ mtext_del (MText *mt, int from, int to) /***ja @brief M-text ¤òÊ̤ΠM-text ¤ËÁÞÆþ¤¹¤ë. - ´Ø¿ô mtext_ins () ¤Ï M-text $MT1 ¤Î $POS ¤Î°ÌÃÖ¤Ë Ê̤ΠM-text $MT2 + ´Ø¿ô mtext_ins () ¤Ï M-text $MT1 ¤Î $POS ¤Î°ÌÃÖ¤ËÊ̤ΠM-text $MT2 ¤òÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $MT2 ¤ÎŤµÊ¬¤À¤±Áý¤¨¤ë¡£ÁÞÆþ¤ÎºÝ¡¢$MT2 ¤Î¥Æ¥­¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£ @@ -2028,10 +1994,10 @@ mtext_del (MText *mt, int from, int to) /*** @errors - @c MERROR_RANGE + @c MERROR_RANGE , @c MERROR_MTEXT @seealso - mtext_del () */ + mtext_del () , mtext_insert () */ int mtext_ins (MText *mt1, int pos, MText *mt2) @@ -2045,6 +2011,51 @@ mtext_ins (MText *mt1, int pos, MText *mt2) 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; +} /*=*/ @@ -2122,7 +2133,7 @@ mtext_ins_char (MText *mt, int pos, int c, int 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, @@ -2156,6 +2167,130 @@ mtext_ins_char (MText *mt, int pos, int c, int n) /*=*/ /***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 (exclusinve) with the sub-text + of M-text $MT2 between $FROM2 (inclusive) and $TO2 (exclusinve). + 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