From 1435c819752eac490286d7507b4a26ab1706627d Mon Sep 17 00:00:00 2001 From: handa Date: Thu, 1 Sep 2005 01:26:12 +0000 Subject: [PATCH] (FORMAT_COVERAGE): New macro. (insert): Copy mt2->coverage. (mtext__from_data): Initialize mt->coverage. (mtext__adjust_format): Update mt->coverage. (mtext): Initialize mt->coverage. (mtext_set_char): Adjust args to mtext__adjust_plist_for_change. Update mt->coverage if necessary. (mtext_duplicate): Copy mt->coverage. (mtext_insert, mtext_replace): New functions. --- src/mtext.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 151 insertions(+), 14 deletions(-) diff --git a/src/mtext.c b/src/mtext.c index cbe2412..8821a31 100644 --- a/src/mtext.c +++ b/src/mtext.c @@ -155,6 +155,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 +247,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 +261,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); @@ -905,6 +910,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 +1001,7 @@ mtext__adjust_format (MText *mt, enum MTextFormat format) } } mt->format = format; + mt->coverage = FORMAT_COVERAGE (format); } @@ -1182,7 +1189,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 +1467,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) { @@ -1844,10 +1852,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 +1881,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; } @@ -2045,6 +2052,31 @@ 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. */ + +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; +} /*=*/ @@ -2156,6 +2188,111 @@ 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. */ + +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 -- 1.7.10.4