1 /* mtext.c -- M-text module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 @brief M-text objects and API for them.
27 In the m17n library, text is represented as an object called @e
28 M-text rather than as a C-string (<tt>char *</tt> or <tt>unsigned
29 char *</tt>). An M-text is a sequence of characters whose length
30 is equals to or more than 0, and can be coined from various
31 character sources, e.g. C-strings, files, character codes, etc.
33 M-texts are more useful than C-strings in the following points.
35 @li M-texts can handle mixture of characters of various scripts,
36 including all Unicode characters and more. This is an
37 indispensable facility when handling multilingual text.
39 @li Each character in an M-text can have properties called @e text
40 @e properties. Text properties store various kinds of information
41 attached to parts of an M-text to provide application programs
42 with a unified view of those information. As rich information can
43 be stored in M-texts in the form of text properties, functions in
44 application programs can be simple.
46 In addition, the library provides many functions to manipulate an
47 M-text just the same way as a C-string. */
52 @brief M-text ¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
54 m17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢ C-string¡Ê<tt>char *</tt> ¤ä <tt>unsigned
55 char *</tt>¡Ë¤Ç¤Ï¤Ê¤¯ @e M-text ¤È¸Æ¤Ö¥ª¥Ö¥¸¥§¥¯¥È¤Ç¥Æ¥¥¹¥È¤òɽ¸½¤¹¤ë¡£
56 M-text ¤ÏŤµ 0 °Ê¾å¤Îʸ»úÎó¤Ç¤¢¤ê¡¢¼ï¡¹¤Îʸ»ú¥½¡¼¥¹¡Ê¤¿¤È¤¨¤Ð
57 C-string¡¢¥Õ¥¡¥¤¥ë¡¢Ê¸»ú¥³¡¼¥ÉÅù¡Ë¤«¤éºîÀ®¤Ç¤¤ë¡£
59 M-text ¤Ë¤Ï¡¢C-string ¤Ë¤Ê¤¤°Ê²¼¤ÎÆÃħ¤¬¤¢¤ë¡£
61 @li M-text ¤ÏÈó¾ï¤Ë¿¤¯¤Î¼ïÎà¤Îʸ»ú¤ò¡¢Æ±»þ¤Ë¡¢º®ºß¤µ¤»¤Æ¡¢Æ±Åù¤Ë
62 °·¤¦¤³¤È¤¬¤Ç¤¤ë¡£Unicode ¤ÎÁ´¤Æ¤Îʸ»ú¤Ï¤â¤Á¤í¤ó¡¢¤è¤ê¿¤¯¤Îʸ»ú¤Þ
63 ¤Ç°·¤¨¤ë¡£¤³¤ì¤Ï¿¸À¸ì¥Æ¥¥¹¥È¤ò°·¤¦¾å¤Ç¤Ïɬ¿Ü¤Îµ¡Ç½¤Ç¤¢¤ë¡£
65 @li M-text Æâ¤Î³Æʸ»ú¤Ï¡¢@e ¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£ ¤È¸Æ¤Ð¤ì¤ë¥×¥í¥Ñ¥Æ¥£
66 ¤ò»ý¤Ä¤³¤È¤¬¤Ç¤¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ë¤è¤Ã¤Æ¡¢¥Æ¥¥¹¥È¤Î³ÆÉô°Ì¤Ë
67 ´Ø¤¹¤ëÍÍ¡¹¤Ê¾ðÊó¤ò M-text Æâ¤ËÊÝ»ý¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î¤¿¤á¡¢¤½¤ì
68 ¤é¤Î¾ðÊó¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥àÆâ¤ÇÅý°ìŪ¤Ë°·¤¦¤³¤È¤¬¤Ç¤¤ë¡£
69 ¤Þ¤¿¡¢M-text ¼«ÂΤ¬ËÉ٤ʾðÊó¤ò»ý¤Ä¤¿¤á¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
70 ¥àÃæ¤Î³Æ´Ø¿ô¤ò´ÊÁDz½¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£
72 ¤µ¤é¤Ëm17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢ C-string ¤òÁàºî¤¹¤ë¤¿¤á¤ËÄ󶡤µ¤ì¤ë¼ï¡¹
73 ¤Î´Ø¿ô¤ÈƱÅù¤Î¤â¤Î¤ò M-text ¤òÁàºî¤¹¤ë¤¿¤á¤Ë¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£ */
77 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
78 /*** @addtogroup m17nInternal
88 #include "m17n-misc.h"
91 #include "character.h"
95 static M17NObjectArray mtext_table;
97 static MSymbol M_charbag;
99 #ifdef WORDS_BIGENDIAN
100 static enum MTextFormat default_utf_16 = MTEXT_FORMAT_UTF_16BE;
101 static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32BE;
103 static enum MTextFormat default_utf_16 = MTEXT_FORMAT_UTF_16LE;
104 static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32LE;
107 /** Increment character position CHAR_POS and unit position UNIT_POS
108 so that they point to the next character in M-text MT. No range
109 check for CHAR_POS and UNIT_POS. */
111 #define INC_POSITION(mt, char_pos, unit_pos) \
115 if ((mt)->format <= MTEXT_FORMAT_UTF_8) \
117 c = (mt)->data[(unit_pos)]; \
118 (unit_pos) += CHAR_UNITS_BY_HEAD_UTF8 (c); \
120 else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \
122 c = ((unsigned short *) ((mt)->data))[(unit_pos)]; \
124 if ((mt)->format != default_utf_16) \
126 (unit_pos) += CHAR_UNITS_BY_HEAD_UTF16 (c); \
134 /** Decrement character position CHAR_POS and unit position UNIT_POS
135 so that they point to the previous character in M-text MT. No
136 range check for CHAR_POS and UNIT_POS. */
138 #define DEC_POSITION(mt, char_pos, unit_pos) \
140 if ((mt)->format <= MTEXT_FORMAT_UTF_8) \
142 unsigned char *p1 = (mt)->data + (unit_pos); \
143 unsigned char *p0 = p1 - 1; \
145 while (! CHAR_HEAD_P (p0)) p0--; \
146 (unit_pos) -= (p1 - p0); \
148 else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \
150 int c = ((unsigned short *) ((mt)->data))[(unit_pos) - 1]; \
152 if ((mt)->format != default_utf_16) \
154 (unit_pos) -= 2 - (c < 0xD800 || c >= 0xE000); \
162 /* Compoare sub-texts in MT1 (range FROM1 and TO1) and MT2 (range
166 compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
168 if (mt1->format == mt2->format
169 && (mt1->format <= MTEXT_FORMAT_UTF_8))
171 unsigned char *p1, *pend1, *p2, *pend2;
172 int unit_bytes = UNIT_BYTES (mt1->format);
176 p1 = mt1->data + mtext__char_to_byte (mt1, from1) * unit_bytes;
177 pend1 = mt1->data + mtext__char_to_byte (mt1, to1) * unit_bytes;
179 p2 = mt2->data + mtext__char_to_byte (mt2, from2) * unit_bytes;
180 pend2 = mt2->data + mtext__char_to_byte (mt2, to2) * unit_bytes;
182 if (pend1 - p1 < pend2 - p2)
186 result = memcmp (p1, p2, nbytes);
189 return ((pend1 - p1) - (pend2 - p2));
191 for (; from1 < to1 && from2 < to2; from1++, from2++)
193 int c1 = mtext_ref_char (mt1, from1);
194 int c2 = mtext_ref_char (mt2, from2);
197 return (c1 > c2 ? 1 : -1);
199 return (from2 == to2 ? (from1 < to1) : -1);
203 /* Return how many units are required in UTF-8 to represent characters
204 between FROM and TO of MT. */
207 count_by_utf_8 (MText *mt, int from, int to)
211 for (n = 0; from < to; from++)
213 c = mtext_ref_char (mt, from);
214 n += CHAR_UNITS_UTF8 (c);
220 /* Return how many units are required in UTF-16 to represent
221 characters between FROM and TO of MT. */
224 count_by_utf_16 (MText *mt, int from, int to)
228 for (n = 0; from < to; from++)
230 c = mtext_ref_char (mt, from);
231 n += CHAR_UNITS_UTF16 (c);
237 /* Insert text between FROM and TO of MT2 at POS of MT1. */
240 insert (MText *mt1, int pos, MText *mt2, int from, int to)
242 int pos_unit = POS_CHAR_TO_BYTE (mt1, pos);
243 int from_unit = POS_CHAR_TO_BYTE (mt2, from);
244 int new_units = POS_CHAR_TO_BYTE (mt2, to) - from_unit;
247 if (mt1->nchars == 0)
248 mt1->format = mt2->format;
249 else if (mt1->format != mt2->format)
251 /* Be sure to make mt1->format sufficient to contain all
252 characters in mt2. */
253 if (mt1->format == MTEXT_FORMAT_UTF_8
254 || mt1->format == default_utf_32
255 || (mt1->format == default_utf_16
256 && mt2->format <= MTEXT_FORMAT_UTF_16BE
257 && mt2->format != MTEXT_FORMAT_UTF_8))
259 else if (mt1->format == MTEXT_FORMAT_US_ASCII)
261 if (mt2->format == MTEXT_FORMAT_UTF_8)
262 mt1->format = MTEXT_FORMAT_UTF_8;
263 else if (mt2->format == default_utf_16
264 || mt2->format == default_utf_32)
265 mtext__adjust_format (mt1, mt2->format);
267 mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
271 mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
272 pos_unit = POS_CHAR_TO_BYTE (mt1, pos);
276 unit_bytes = UNIT_BYTES (mt1->format);
278 if (mt1->format == mt2->format)
280 int pos_byte = pos_unit * unit_bytes;
281 int total_bytes = (mt1->nbytes + new_units) * unit_bytes;
282 int new_bytes = new_units * unit_bytes;
284 if (total_bytes + unit_bytes > mt1->allocated)
286 mt1->allocated = total_bytes + unit_bytes;
287 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
289 if (pos < mt1->nchars)
290 memmove (mt1->data + pos_byte + new_bytes, mt1->data + pos_byte,
291 (mt1->nbytes - pos_unit + 1) * unit_bytes);
292 memcpy (mt1->data + pos_byte, mt2->data + from_unit * unit_bytes,
295 else if (mt1->format == MTEXT_FORMAT_UTF_8)
298 int total_bytes, i, c;
300 new_units = count_by_utf_8 (mt2, from, to);
301 total_bytes = mt1->nbytes + new_units;
303 if (total_bytes + 1 > mt1->allocated)
305 mt1->allocated = total_bytes + 1;
306 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
308 p = mt1->data + pos_unit;
309 memmove (p + new_units, p, mt1->nbytes - pos_unit + 1);
310 for (i = from; i < to; i++)
312 c = mtext_ref_char (mt2, i);
313 p += CHAR_STRING_UTF8 (c, p);
316 else if (mt1->format == default_utf_16)
319 int total_bytes, i, c;
321 new_units = count_by_utf_16 (mt2, from, to);
322 total_bytes = (mt1->nbytes + new_units) * USHORT_SIZE;
324 if (total_bytes + USHORT_SIZE > mt1->allocated)
326 mt1->allocated = total_bytes + USHORT_SIZE;
327 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
329 p = (unsigned short *) mt1->data + pos_unit;
330 memmove (p + new_units, p,
331 (mt1->nbytes - pos_unit + 1) * USHORT_SIZE);
332 for (i = from; i < to; i++)
334 c = mtext_ref_char (mt2, i);
335 p += CHAR_STRING_UTF16 (c, p);
338 else /* default_utf_32 */
343 new_units = to - from;
344 total_bytes = (mt1->nbytes + new_units) * UINT_SIZE;
346 if (total_bytes + UINT_SIZE > mt1->allocated)
348 mt1->allocated = total_bytes + UINT_SIZE;
349 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
351 p = (unsigned *) mt1->data + pos_unit;
352 memmove (p + new_units, p,
353 (mt1->nbytes - pos_unit + 1) * UINT_SIZE);
354 for (i = from; i < to; i++)
355 *p++ = mtext_ref_char (mt2, i);
358 mtext__adjust_plist_for_insert
359 (mt1, pos, to - from,
360 mtext__copy_plist (mt2->plist, from, to, mt1, pos));
361 mt1->nchars += to - from;
362 mt1->nbytes += new_units;
363 if (mt1->cache_char_pos > pos)
365 mt1->cache_char_pos += to - from;
366 mt1->cache_byte_pos += new_units;
374 get_charbag (MText *mt)
376 MTextProperty *prop = mtext_get_property (mt, 0, M_charbag);
382 if (prop->end == mt->nchars)
383 return ((MCharTable *) prop->val);
384 mtext_detach_property (prop);
387 table = mchartable (Msymbol, (void *) 0);
388 for (i = mt->nchars - 1; i >= 0; i--)
389 mchartable_set (table, mtext_ref_char (mt, i), Mt);
390 prop = mtext_property (M_charbag, table, MTEXTPROP_VOLATILE_WEAK);
391 mtext_attach_property (mt, 0, mtext_nchars (mt), prop);
392 M17N_OBJECT_UNREF (prop);
397 /* span () : Number of consecutive chars starting at POS in MT1 that
398 are included (if NOT is Mnil) or not included (if NOT is Mt) in
402 span (MText *mt1, MText *mt2, int pos, MSymbol not)
404 int nchars = mtext_nchars (mt1);
405 MCharTable *table = get_charbag (mt2);
408 for (i = pos; i < nchars; i++)
409 if ((MSymbol) mchartable_lookup (table, mtext_ref_char (mt1, i)) == not)
416 count_utf_8_chars (void *data, int nitems)
418 unsigned char *p = (unsigned char *) data;
419 unsigned char *pend = p + nitems;
426 for (; p < pend && *p < 128; nchars++, p++);
429 if (! CHAR_HEAD_P_UTF8 (p))
431 n = CHAR_UNITS_BY_HEAD_UTF8 (*p);
434 for (i = 1; i < n; i++)
435 if (CHAR_HEAD_P_UTF8 (p + i))
444 count_utf_16_chars (void *data, int nitems, int swap)
446 unsigned short *p = (unsigned short *) data;
447 unsigned short *pend = p + nitems;
449 int prev_surrogate = 0;
451 for (; p < pend; p++)
459 if (c < 0xDC00 || c >= 0xE000)
481 find_char_forward (MText *mt, int from, int to, int c)
483 int from_byte = POS_CHAR_TO_BYTE (mt, from);
485 if (mt->format <= MTEXT_FORMAT_UTF_8)
487 unsigned char *p = mt->data + from_byte;
489 while (from < to && STRING_CHAR_ADVANCE_UTF8 (p) != c) from++;
491 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
493 unsigned short *p = (unsigned short *) (mt->data) + from_byte;
495 if (mt->format == default_utf_16)
496 while (from < to && STRING_CHAR_ADVANCE_UTF16 (p) != c) from++;
497 else if (c < 0x10000)
500 while (from < to && *p != c)
503 p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2;
506 else if (c < 0x110000)
508 int c1 = (c >> 10) + 0xD800;
509 int c2 = (c & 0x3FF) + 0xDC00;
513 while (from < to && (*p != c1 || p[1] != c2))
516 p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2;
524 unsigned *p = (unsigned *) (mt->data) + from_byte;
527 if (mt->format != default_utf_32)
529 while (from < to && *p++ != c1) from++;
532 return (from < to ? from : -1);
537 find_char_backward (MText *mt, int from, int to, int c)
539 int to_byte = POS_CHAR_TO_BYTE (mt, to);
541 if (mt->format <= MTEXT_FORMAT_UTF_8)
543 unsigned char *p = mt->data + to_byte;
547 for (p--; ! CHAR_HEAD_P (p); p--);
548 if (c == STRING_CHAR (p))
553 else if (mt->format <= MTEXT_FORMAT_UTF_16LE)
555 unsigned short *p = (unsigned short *) (mt->data) + to_byte;
557 if (mt->format == default_utf_16)
562 if (*p >= 0xDC00 && *p < 0xE000)
564 if (c == STRING_CHAR_UTF16 (p))
569 else if (c < 0x10000)
572 while (from < to && p[-1] != c)
575 p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2;
578 else if (c < 0x110000)
580 int c1 = (c >> 10) + 0xD800;
581 int c2 = (c & 0x3FF) + 0xDC00;
585 while (from < to && (p[-1] != c2 || p[-2] != c1))
588 p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2;
594 unsigned *p = (unsigned *) (mt->data) + to_byte;
597 if (mt->format != default_utf_32)
599 while (from < to && p[-1] != c1) to--, p--;
602 return (from < to ? to - 1 : -1);
607 free_mtext (void *object)
609 MText *mt = (MText *) object;
612 mtext__free_plist (mt);
613 if (mt->data && mt->allocated >= 0)
615 M17N_OBJECT_UNREGISTER (mtext_table, mt);
619 /** Structure for an iterator used in case-fold comparison. */
621 struct casecmp_iterator {
625 unsigned char *foldedp;
630 next_char_from_it (struct casecmp_iterator *it)
636 c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len);
640 c = mtext_ref_char (it->mt, it->pos);
641 c1 = (int) mchar_get_prop (c, Msimple_case_folding);
645 = (MText *) mchar_get_prop (c, Mcomplicated_case_folding);
646 it->foldedp = it->folded->data;
647 c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len);
657 advance_it (struct casecmp_iterator *it)
661 it->foldedp += it->folded_len;
662 if (it->foldedp == it->folded->data + it->folded->nbytes)
672 case_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
674 struct casecmp_iterator it1, it2;
676 it1.mt = mt1, it1.pos = from1, it1.folded = NULL;
677 it2.mt = mt2, it2.pos = from2, it2.folded = NULL;
679 while (it1.pos < to1 && it2.pos < to2)
681 int c1 = next_char_from_it (&it1);
682 int c2 = next_char_from_it (&it2);
685 return (c1 > c2 ? 1 : -1);
689 return (it2.pos == to2 ? (it1.pos < to1) : -1);
698 M_charbag = msymbol_as_managing_key (" charbag");
699 mtext_table.count = 0;
707 mdebug__report_object ("M-text", &mtext_table);
712 mtext__char_to_byte (MText *mt, int pos)
714 int char_pos, byte_pos;
717 if (pos < mt->cache_char_pos)
719 if (mt->cache_char_pos == mt->cache_byte_pos)
721 if (pos < mt->cache_char_pos - pos)
723 char_pos = byte_pos = 0;
728 char_pos = mt->cache_char_pos;
729 byte_pos = mt->cache_byte_pos;
735 if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos)
736 return (mt->cache_byte_pos + (pos - mt->cache_char_pos));
737 if (pos - mt->cache_char_pos < mt->nchars - pos)
739 char_pos = mt->cache_char_pos;
740 byte_pos = mt->cache_byte_pos;
745 char_pos = mt->nchars;
746 byte_pos = mt->nbytes;
751 while (char_pos < pos)
752 INC_POSITION (mt, char_pos, byte_pos);
754 while (char_pos > pos)
755 DEC_POSITION (mt, char_pos, byte_pos);
756 mt->cache_char_pos = char_pos;
757 mt->cache_byte_pos = byte_pos;
761 /* mtext__byte_to_char () */
764 mtext__byte_to_char (MText *mt, int pos_byte)
766 int char_pos, byte_pos;
769 if (pos_byte < mt->cache_byte_pos)
771 if (mt->cache_char_pos == mt->cache_byte_pos)
773 if (pos_byte < mt->cache_byte_pos - pos_byte)
775 char_pos = byte_pos = 0;
780 char_pos = mt->cache_char_pos;
781 byte_pos = mt->cache_byte_pos;
787 if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos)
788 return (mt->cache_char_pos + (pos_byte - mt->cache_byte_pos));
789 if (pos_byte - mt->cache_byte_pos < mt->nbytes - pos_byte)
791 char_pos = mt->cache_char_pos;
792 byte_pos = mt->cache_byte_pos;
797 char_pos = mt->nchars;
798 byte_pos = mt->nbytes;
803 while (byte_pos < pos_byte)
804 INC_POSITION (mt, char_pos, byte_pos);
806 while (byte_pos > pos_byte)
807 DEC_POSITION (mt, char_pos, byte_pos);
808 mt->cache_char_pos = char_pos;
809 mt->cache_byte_pos = byte_pos;
813 /* Estimated extra bytes that malloc will use for its own purpose on
814 each memory allocation. */
815 #define MALLOC_OVERHEAD 4
816 #define MALLOC_MININUM_BYTES 12
819 mtext__enlarge (MText *mt, int nbytes)
821 nbytes += MAX_UTF8_CHAR_BYTES;
822 if (mt->allocated >= nbytes)
824 if (nbytes < MALLOC_MININUM_BYTES)
825 nbytes = MALLOC_MININUM_BYTES;
826 while (mt->allocated < nbytes)
827 mt->allocated = mt->allocated * 2 + MALLOC_OVERHEAD;
828 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
832 mtext__takein (MText *mt, int nchars, int nbytes)
835 mtext__adjust_plist_for_insert (mt, mt->nchars, nchars, NULL);
836 mt->nchars += nchars;
837 mt->nbytes += nbytes;
838 mt->data[mt->nbytes] = 0;
844 mtext__cat_data (MText *mt, unsigned char *p, int nbytes,
845 enum MTextFormat format)
849 if (mt->format > MTEXT_FORMAT_UTF_8)
850 MERROR (MERROR_MTEXT, -1);
851 if (format == MTEXT_FORMAT_US_ASCII)
853 else if (format == MTEXT_FORMAT_UTF_8)
854 nchars = count_utf_8_chars (p, nbytes);
856 MERROR (MERROR_MTEXT, -1);
857 mtext__enlarge (mt, mtext_nbytes (mt) + nbytes + 1);
858 memcpy (MTEXT_DATA (mt) + mtext_nbytes (mt), p, nbytes);
859 mtext__takein (mt, nchars, nbytes);
864 mtext__from_data (void *data, int nitems, enum MTextFormat format,
868 int nchars, nbytes, unit_bytes;
870 if (format == MTEXT_FORMAT_US_ASCII)
872 char *p = (char *) data, *pend = p + nitems;
876 MERROR (MERROR_MTEXT, NULL);
877 nchars = nbytes = nitems;
880 else if (format == MTEXT_FORMAT_UTF_8)
882 if ((nchars = count_utf_8_chars (data, nitems)) < 0)
883 MERROR (MERROR_MTEXT, NULL);
887 else if (format <= MTEXT_FORMAT_UTF_16BE)
889 if ((nchars = count_utf_16_chars (data, nitems,
890 format != default_utf_16)) < 0)
891 MERROR (MERROR_MTEXT, NULL);
892 nbytes = USHORT_SIZE * nitems;
893 unit_bytes = USHORT_SIZE;
895 else /* MTEXT_FORMAT_UTF_32XX */
898 nbytes = UINT_SIZE * nitems;
899 unit_bytes = UINT_SIZE;
904 mt->allocated = need_copy ? nbytes + unit_bytes : -1;
909 MTABLE_MALLOC (mt->data, mt->allocated, MERROR_MTEXT);
910 memcpy (mt->data, data, nbytes);
911 mt->data[nbytes] = 0;
914 mt->data = (unsigned char *) data;
920 mtext__adjust_format (MText *mt, enum MTextFormat format)
927 case MTEXT_FORMAT_US_ASCII:
929 unsigned char *p = mt->data;
931 for (i = 0; i < mt->nchars; i++)
932 *p++ = mtext_ref_char (mt, i);
933 mt->nbytes = mt->nchars;
934 mt->cache_byte_pos = mt->cache_char_pos;
938 case MTEXT_FORMAT_UTF_8:
940 unsigned char *p0, *p1;
942 i = count_by_utf_8 (mt, 0, mt->nchars) + 1;
943 MTABLE_MALLOC (p0, i, MERROR_MTEXT);
945 for (i = 0, p1 = p0; i < mt->nchars; i++)
947 c = mtext_ref_char (mt, i);
948 p1 += CHAR_STRING_UTF8 (c, p1);
953 mt->nbytes = p1 - p0;
954 mt->cache_char_pos = mt->cache_byte_pos = 0;
959 if (format == default_utf_16)
961 unsigned short *p0, *p1;
963 i = (count_by_utf_16 (mt, 0, mt->nchars) + 1) * USHORT_SIZE;
964 MTABLE_MALLOC (p0, i, MERROR_MTEXT);
966 for (i = 0, p1 = p0; i < mt->nchars; i++)
968 c = mtext_ref_char (mt, i);
969 p1 += CHAR_STRING_UTF16 (c, p1);
973 mt->data = (unsigned char *) p0;
974 mt->nbytes = p1 - p0;
975 mt->cache_char_pos = mt->cache_byte_pos = 0;
982 mt->allocated = (mt->nchars + 1) * UINT_SIZE;
983 MTABLE_MALLOC (p, mt->allocated, MERROR_MTEXT);
984 for (i = 0; i < mt->nchars; i++)
985 p[i] = mtext_ref_char (mt, i);
988 mt->data = (unsigned char *) p;
989 mt->nbytes = mt->nchars;
990 mt->cache_byte_pos = mt->cache_char_pos;
997 /* Find the position of a character at the beginning of a line of
998 M-Text MT searching backward from POS. */
1001 mtext__bol (MText *mt, int pos)
1007 byte_pos = POS_CHAR_TO_BYTE (mt, pos);
1008 if (mt->format <= MTEXT_FORMAT_UTF_8)
1010 unsigned char *p = mt->data + byte_pos;
1015 while (p > mt->data && p[-1] != '\n')
1019 byte_pos = p - mt->data;
1020 return POS_BYTE_TO_CHAR (mt, byte_pos);
1022 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1024 unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
1025 unsigned short newline = mt->format == default_utf_16 ? 0x0A00 : 0x000A;
1027 if (p[-1] == newline)
1030 while (p > (unsigned short *) (mt->data) && p[-1] != newline)
1032 if (p == (unsigned short *) (mt->data))
1034 byte_pos = p - (unsigned short *) (mt->data);
1035 return POS_BYTE_TO_CHAR (mt, byte_pos);;
1039 unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
1040 unsigned newline = mt->format == default_utf_32 ? 0x0A000000 : 0x0000000A;
1042 if (p[-1] == newline)
1045 while (p > (unsigned *) (mt->data) && p[-1] != newline)
1052 /* Find the position of a character at the end of a line of M-Text MT
1053 searching forward from POS. */
1056 mtext__eol (MText *mt, int pos)
1060 if (pos == mt->nchars)
1062 byte_pos = POS_CHAR_TO_BYTE (mt, pos);
1063 if (mt->format <= MTEXT_FORMAT_UTF_8)
1065 unsigned char *p = mt->data + byte_pos;
1066 unsigned char *endp;
1071 endp = mt->data + mt->nbytes;
1072 while (p < endp && *p != '\n')
1076 byte_pos = p + 1 - mt->data;
1077 return POS_BYTE_TO_CHAR (mt, byte_pos);
1079 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1081 unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
1082 unsigned short *endp;
1083 unsigned short newline = mt->format == default_utf_16 ? 0x0A00 : 0x000A;
1088 endp = (unsigned short *) (mt->data) + mt->nbytes;
1089 while (p < endp && *p != newline)
1093 byte_pos = p + 1 - (unsigned short *) (mt->data);
1094 return POS_BYTE_TO_CHAR (mt, byte_pos);
1098 unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
1100 unsigned newline = mt->format == default_utf_32 ? 0x0A000000 : 0x0000000A;
1105 endp = (unsigned *) (mt->data) + mt->nbytes;
1106 while (p < endp && *p != newline)
1113 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1118 /*** @addtogroup m17nMtext */
1123 @brief Allocate a new M-text.
1125 The mtext () function allocates a new M-text of length 0 and
1126 returns a pointer to it. The allocated M-text will not be freed
1127 unless the user explicitly does so with the m17n_object_free ()
1131 @brief ¿·¤·¤¤M-text¤ò³ä¤êÅö¤Æ¤ë.
1133 ´Ø¿ô mtext () ¤Ï¡¢Ä¹¤µ 0 ¤Î¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¡¢¤½¤ì¤Ø¤Î¥Ý¥¤
1134 ¥ó¥¿¤òÊÖ¤¹¡£³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_free () ¤Ë
1135 ¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£
1137 @latexonly \IPAlabel{mtext} @endlatexonly */
1141 m17n_object_free () */
1148 M17N_OBJECT (mt, free_mtext, MERROR_MTEXT);
1149 mt->format = MTEXT_FORMAT_UTF_8;
1150 M17N_OBJECT_REGISTER (mtext_table, mt);
1155 @brief Allocate a new M-text with specified data.
1157 The mtext_from_data () function allocates a new M-text whose
1158 character sequence is specified by array $DATA of $NITEMS
1159 elements. $FORMAT specifies the format of $DATA.
1161 When $FORMAT is either #MTEXT_FORMAT_US_ASCII or
1162 #MTEXT_FORMAT_UTF_8, the contents of $DATA must be of the type @c
1163 unsigned @c char, and $NITEMS counts by byte.
1165 When $FORMAT is either #MTEXT_FORMAT_UTF_16LE or
1166 #MTEXT_FORMAT_UTF_16BE, the contents of $DATA must be of the type
1167 @c unsigned @c short, and $NITEMS counts by unsigned short.
1169 When $FORMAT is either #MTEXT_FORMAT_UTF_32LE or
1170 #MTEXT_FORMAT_UTF_32BE, the contents of $DATA must be of the type
1171 @c unsigned, and $NITEMS counts by unsigned.
1173 The character sequence of the M-text is not modifiable.
1174 The contents of $DATA must not be modified while the M-text is alive.
1176 The allocated M-text will not be freed unless the user explicitly
1177 does so with the m17n_object_free () function. Even in that case,
1181 If the operation was successful, mtext_from_data () returns a
1182 pointer to the allocated M-text. Otherwise it returns @c NULL and
1183 assigns an error code to the external variable #merror_code. */
1185 @brief »ØÄê¤Î¥Ç¡¼¥¿¤ò¸µ¤Ë¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë.
1187 ´Ø¿ô mtext_from_data () ¤Ï¡¢Í×ÁÇ¿ô $NITEMS ¤ÎÇÛÎó $DATA ¤Ç»ØÄꤵ¤ì
1188 ¤¿Ê¸»úÎó¤ò»ý¤Ä¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë¡£$FORMAT ¤Ï $DATA ¤Î¥Õ¥©¡¼
1191 $FORMAT ¤¬ #MTEXT_FORMAT_US_ASCII ¤« #MTEXT_FORMAT_UTF_8 ¤Ê¤é¤Ð¡¢
1192 $DATA ¤ÎÆâÍÆ¤Ï @c unsigned @c char ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¥Ð¥¤¥Èñ°Ì
1195 $FORMAT ¤¬ #MTEXT_FORMAT_UTF_16LE ¤« #MTEXT_FORMAT_UTF_16BE ¤Ê¤é¤Ð¡¢
1196 $DATA ¤ÎÆâÍÆ¤Ï @c unsigned @c short ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned
1199 $FORMAT ¤¬ #MTEXT_FORMAT_UTF_32LE ¤« #MTEXT_FORMAT_UTF_32BE ¤Ê¤é¤Ð¡¢
1200 $DATA ¤ÎÆâÍƤÏ@c unsigned ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned ñ°Ì¤Ç¤¢¤ë¡£
1202 ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Îʸ»úÎó¤ÏÊѹ¹¤Ç¤¤Ê¤¤¡£$DATA ¤ÎÆâÍƤÏ
1203 M-text ¤¬Í¸ú¤Ê´Ö¤ÏÊѹ¹¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1205 ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_free () ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶
1206 ¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£¤½¤Î¾ì¹ç¤Ç¤â $DATA ¤Ï²òÊü
1210 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_from_data () ¤Ï³ä¤êÅö¤Æ¤é¤ì¤¿M-text ¤Ø¤Î¥Ý
1211 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·³°ÉôÊÑ¿ô #merror_code ¤Ë
1212 ¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1219 mtext_from_data (void *data, int nitems, enum MTextFormat format)
1222 || format < MTEXT_FORMAT_US_ASCII || format >= MTEXT_FORMAT_MAX)
1223 MERROR (MERROR_MTEXT, NULL);
1224 return mtext__from_data (data, nitems, format, 0);
1230 @brief Number of characters in M-text.
1232 The mtext_len () function returns the number of characters in
1236 @brief M-text Ãæ¤Îʸ»ú¤Î¿ô.
1238 ´Ø¿ô mtext_len () ¤Ï M-text $MT Ãæ¤Îʸ»ú¤Î¿ô¤òÊÖ¤¹¡£
1240 @latexonly \IPAlabel{mtext_len} @endlatexonly */
1243 mtext_len (MText *mt)
1245 return (mt->nchars);
1251 @brief Return the character at the specified position in an M-text.
1253 The mtext_ref_char () function returns the character at $POS in
1254 M-text $MT. If an error is detected, it returns -1 and assigns an
1255 error code to the external variable #merror_code. */
1258 @brief M-text Ãæ¤Î»ØÄꤵ¤ì¤¿°ÌÃÖ¤Îʸ»ú¤òÊÖ¤¹.
1260 ´Ø¿ô mtext_ref_char () ¤Ï¡¢M-text $MT ¤Î°ÌÃÖ $POS ¤Îʸ»ú¤òÊÖ¤¹¡£
1261 ¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code
1262 ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1264 @latexonly \IPAlabel{mtext_ref_char} @endlatexonly */
1271 mtext_ref_char (MText *mt, int pos)
1275 M_CHECK_POS (mt, pos, -1);
1276 if (mt->format <= MTEXT_FORMAT_UTF_8)
1278 unsigned char *p = mt->data + POS_CHAR_TO_BYTE (mt, pos);
1280 c = STRING_CHAR_UTF8 (p);
1282 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1285 = (unsigned short *) (mt->data) + POS_CHAR_TO_BYTE (mt, pos);
1286 unsigned short p1[2];
1288 if (mt->format != default_utf_16)
1290 p1[0] = SWAP_16 (*p);
1291 if (p1[0] >= 0xD800 || p1[0] < 0xDC00)
1292 p1[1] = SWAP_16 (p[1]);
1295 c = STRING_CHAR_UTF16 (p);
1299 c = ((unsigned *) (mt->data))[pos];
1300 if (mt->format != default_utf_32)
1309 @brief Store a character into an M-text.
1311 The mtext_set_char () function sets character $C, which has no
1312 text properties, at $POS in M-text $MT.
1315 If the operation was successful, mtext_set_char () returns 0.
1316 Otherwise it returns -1 and assigns an error code to the external
1317 variable #merror_code. */
1320 @brief M-text ¤Ë°ìʸ»ú¤òÀßÄꤹ¤ë.
1322 ´Ø¿ô mtext_set_char () ¤Ï¡¢¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£Ìµ¤·¤Îʸ»ú $C ¤ò
1323 M-text $MT ¤Î°ÌÃÖ $POS ¤ËÀßÄꤹ¤ë¡£
1326 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mtext_set_char () ¤Ï 0 ¤òÊÖ¤¹¡£¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ
1327 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1329 @latexonly \IPAlabel{mtext_set_char} @endlatexonly */
1336 mtext_set_char (MText *mt, int pos, int c)
1339 int old_units, new_units;
1344 M_CHECK_POS (mt, pos, -1);
1345 M_CHECK_READONLY (mt, -1);
1347 mtext__adjust_plist_for_change (mt, pos, pos + 1);
1349 if (mt->format <= MTEXT_FORMAT_UTF_8)
1352 mt->format = MTEXT_FORMAT_UTF_8;
1354 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1357 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1358 else if (mt->format != default_utf_16)
1359 mtext__adjust_format (mt, default_utf_16);
1361 else if (mt->format != default_utf_32)
1362 mtext__adjust_format (mt, default_utf_32);
1364 unit_bytes = UNIT_BYTES (mt->format);
1365 pos_unit = POS_CHAR_TO_BYTE (mt, pos);
1366 p = mt->data + pos_unit * unit_bytes;
1367 old_units = CHAR_UNITS_AT (mt, p);
1368 new_units = CHAR_UNITS (c, mt->format);
1369 delta = new_units - old_units;
1373 if (mt->cache_char_pos > pos)
1374 mt->cache_byte_pos += delta;
1376 if ((mt->nbytes + delta + 1) * unit_bytes > mt->allocated)
1378 mt->allocated = (mt->nbytes + delta + 1) * unit_bytes;
1379 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1382 memmove (mt->data + (pos_unit + new_units) * unit_bytes,
1383 mt->data + (pos_unit + old_units) * unit_bytes,
1384 (mt->nbytes - pos_unit - old_units + 1) * unit_bytes);
1385 mt->nbytes += delta;
1386 mt->data[mt->nbytes * unit_bytes] = 0;
1390 case MTEXT_FORMAT_US_ASCII:
1391 mt->data[pos_unit] = c;
1393 case MTEXT_FORMAT_UTF_8:
1395 unsigned char *p = mt->data + pos_unit;
1396 CHAR_STRING_UTF8 (c, p);
1400 if (mt->format == default_utf_16)
1402 unsigned short *p = (unsigned short *) mt->data + pos_unit;
1404 CHAR_STRING_UTF16 (c, p);
1407 ((unsigned *) mt->data)[pos_unit] = c;
1415 @brief Append a character to an M-text.
1417 The mtext_cat_char () function appends character $C, which has no
1418 text properties, to the end of M-text $MT.
1421 This function returns a pointer to the resulting M-text $MT. If
1422 $C is an invalid character, it returns @c NULL. */
1425 @brief M-text ¤Ë°ìʸ»úÄɲ乤ë.
1427 ´Ø¿ô mtext_cat_char () ¤Ï¡¢¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£Ìµ¤·¤Îʸ»ú $C ¤ò
1428 M-text $MT ¤ÎËöÈø¤ËÄɲ乤롣
1431 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$C ¤¬Àµ¤·¤¤Ê¸
1432 »ú¤Ç¤Ê¤¤¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£ */
1436 mtext_cat (), mtext_ncat () */
1439 mtext_cat_char (MText *mt, int c)
1442 int unit_bytes = UNIT_BYTES (mt->format);
1444 M_CHECK_READONLY (mt, NULL);
1445 if (c < 0 || c > MCHAR_MAX)
1447 mtext__adjust_plist_for_insert (mt, mt->nchars, 1, NULL);
1450 && (mt->format == MTEXT_FORMAT_US_ASCII
1452 && (mt->format == MTEXT_FORMAT_UTF_16LE
1453 || mt->format == MTEXT_FORMAT_UTF_16BE))))
1456 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1459 else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
1461 if (mt->format != default_utf_32)
1462 mtext__adjust_format (mt, default_utf_32);
1464 else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
1466 if (mt->format != default_utf_16)
1467 mtext__adjust_format (mt, default_utf_16);
1470 nunits = CHAR_UNITS (c, mt->format);
1471 if ((mt->nbytes + nunits + 1) * unit_bytes > mt->allocated)
1473 mt->allocated = (mt->nbytes + nunits + 1) * unit_bytes;
1474 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1477 if (mt->format <= MTEXT_FORMAT_UTF_8)
1479 unsigned char *p = mt->data + mt->nbytes;
1480 p += CHAR_STRING_UTF8 (c, p);
1483 else if (mt->format == default_utf_16)
1485 unsigned short *p = (unsigned short *) mt->data + mt->nbytes;
1486 p += CHAR_STRING_UTF16 (c, p);
1491 unsigned *p = (unsigned *) mt->data + mt->nbytes;
1497 mt->nbytes += nunits;
1504 @brief Create a copy of an M-text.
1506 The mtext_dup () function creates a copy of M-text $MT while
1507 inheriting all the text properties of $MT.
1510 This function returns a pointer to the created copy. */
1513 @brief M-text ¤Î¥³¥Ô¡¼¤òºî¤ë.
1515 ´Ø¿ô mtext_dup () ¤Ï¡¢M-text $MT ¤Î¥³¥Ô¡¼¤òºî¤ë¡£$MT ¤Î¥Æ¥¥¹¥È¥×
1516 ¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
1519 ¤³¤Î´Ø¿ô¤Ïºî¤é¤ì¤¿¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1521 @latexonly \IPAlabel{mtext_dup} @endlatexonly */
1525 mtext_duplicate () */
1528 mtext_dup (MText *mt)
1530 MText *new = mtext ();
1531 int unit_bytes = UNIT_BYTES (mt->format);
1534 new->allocated = (mt->nbytes + 1) * unit_bytes;
1535 MTABLE_MALLOC (new->data, new->allocated, MERROR_MTEXT);
1536 memcpy (new->data, mt->data, new->allocated);
1538 new->plist = mtext__copy_plist (mt->plist, 0, mt->nchars, new, 0);
1545 @brief Append an M-text to another.
1547 The mtext_cat () function appends M-text $MT2 to the end of M-text
1548 $MT1 while inheriting all the text properties. $MT2 itself is not
1552 This function returns a pointer to the resulting M-text $MT1. */
1555 @brief 2¸Ä¤Î M-text¤òÏ¢·ë¤¹¤ë.
1557 ´Ø¿ô mtext_cat () ¤Ï¡¢ M-text $MT2 ¤ò M-text $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨
1558 ¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê
1562 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1564 @latexonly \IPAlabel{mtext_cat} @endlatexonly */
1568 mtext_ncat (), mtext_cat_char () */
1571 mtext_cat (MText *mt1, MText *mt2)
1573 M_CHECK_READONLY (mt1, NULL);
1575 return insert (mt1, mt1->nchars, mt2, 0, mt2->nchars);
1582 @brief Append a part of an M-text to another.
1584 The mtext_ncat () function appends the first $N characters of
1585 M-text $MT2 to the end of M-text $MT1 while inheriting all the
1586 text properties. If the length of $MT2 is less than $N, all
1587 characters are copied. $MT2 is not modified.
1590 If the operation was successful, mtext_ncat () returns a
1591 pointer to the resulting M-text $MT1. If an error is detected, it
1592 returns @c NULL and assigns an error code to the global variable
1597 @brief M-text ¤Î°ìÉô¤òÊ̤ΠM-text ¤ËÉղ乤ë.
1599 ´Ø¿ô mtext_ncat () ¤Ï¡¢M-text $MT2 ¤Î¤Ï¤¸¤á¤Î $N ʸ»ú¤ò M-text
1600 $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì
1601 ¤ë¡£$MT2 ¤ÎŤµ¤¬ $N °Ê²¼¤Ê¤é¤Ð¡¢$MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤¬Éղ䵤ì¤ë¡£
1602 $MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1605 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncat () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý
1606 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1607 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1609 @latexonly \IPAlabel{mtext_ncat} @endlatexonly */
1616 mtext_cat (), mtext_cat_char () */
1619 mtext_ncat (MText *mt1, MText *mt2, int n)
1621 M_CHECK_READONLY (mt1, NULL);
1623 MERROR (MERROR_RANGE, NULL);
1624 return insert (mt1, mt1->nchars, mt2, 0, mt2->nchars < n ? mt2->nchars : n);
1631 @brief Copy an M-text to another.
1633 The mtext_cpy () function copies M-text $MT2 to M-text $MT1 while
1634 inheriting all the text properties. The old text in $MT1 is
1635 overwritten and the length of $MT1 is extended if necessary. $MT2
1639 This function returns a pointer to the resulting M-text $MT1. */
1642 @brief M-text ¤òÊ̤ΠM-text ¤Ë¥³¥Ô¡¼¤¹¤ë.
1644 ´Ø¿ô mtext_cpy () ¤Ï M-text $MT2 ¤ò M-text $MT1 ¤Ë¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£
1645 $MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 ¤ÎŤµ¤ÏɬÍפ˱þ
1646 ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1649 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1651 @latexonly \IPAlabel{mtext_cpy} @endlatexonly */
1655 mtext_ncpy (), mtext_copy () */
1658 mtext_cpy (MText *mt1, MText *mt2)
1660 M_CHECK_READONLY (mt1, NULL);
1661 mtext_del (mt1, 0, mt1->nchars);
1662 return insert (mt1, 0, mt2, 0, mt2->nchars);
1668 @brief Copy the first some characters in an M-text to another.
1670 The mtext_ncpy () function copies the first $N characters of
1671 M-text $MT2 to M-text $MT1 while inheriting all the text
1672 properties. If the length of $MT2 is less than $N, all characters
1673 of $MT2 are copied. The old text in $MT1 is overwritten and the
1674 length of $MT1 is extended if necessary. $MT2 is not modified.
1677 If the operation was successful, mtext_ncpy () returns a pointer
1678 to the resulting M-text $MT1. If an error is detected, it returns
1679 @c NULL and assigns an error code to the global variable
1683 @brief M-text ¤Ë´Þ¤Þ¤ì¤ëºÇ½é¤Î²¿Ê¸»ú¤«¤ò¥³¥Ô¡¼¤¹¤ë.
1685 ´Ø¿ô mtext_ncpy () ¤Ï¡¢M-text $MT2 ¤ÎºÇ½é¤Î $N ʸ»ú¤ò M-text $MT1
1686 ¤Ë¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
1687 ¤â¤· $MT2 ¤ÎŤµ¤¬ $N ¤è¤ê¤â¾®¤µ¤±¤ì¤Ð $MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ò¥³¥Ô¡¼
1688 ¤¹¤ë¡£$MT1 ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1691 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncpy () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý
1692 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1693 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1695 @latexonly \IPAlabel{mtext_ncpy} @endlatexonly */
1702 mtext_cpy (), mtext_copy () */
1705 mtext_ncpy (MText *mt1, MText *mt2, int n)
1707 M_CHECK_READONLY (mt1, NULL);
1709 MERROR (MERROR_RANGE, NULL);
1710 mtext_del (mt1, 0, mt1->nchars);
1711 return insert (mt1, 0, mt2, 0, mt2->nchars < n ? mt2->nchars : n);
1717 @brief Create a new M-text from a part of an existing M-text.
1719 The mtext_duplicate () function creates a copy of sub-text of
1720 M-text $MT, starting at $FROM (inclusive) and ending at $TO
1721 (exclusive) while inheriting all the text properties of $MT. $MT
1722 itself is not modified.
1725 If the operation was successful, mtext_duplicate () returns a
1726 pointer to the created M-text. If an error is detected, it returns 0
1727 and assigns an error code to the external variable #merror_code. */
1730 @brief ´û¸¤Î M-text ¤Î°ìÉô¤«¤é¿·¤·¤¤ M-text ¤ò¤Ä¤¯¤ë.
1732 ´Ø¿ô mtext_duplicate () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO
1733 ¡Ê´Þ¤Þ¤Ê¤¤¡Ë¤Þ¤Ç¤ÎÉôʬ¤Î¥³¥Ô¡¼¤òºî¤ë¡£¤³¤Î¤È¤ $MT ¤Î¥Æ¥¥¹¥È¥×¥í
1734 ¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1737 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_duplicate () ¤Ïºî¤é¤ì¤¿ M-text ¤Ø¤Î¥Ý¥¤¥ó
1738 ¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1739 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1741 @latexonly \IPAlabel{mtext_duplicate} @endlatexonly */
1751 mtext_duplicate (MText *mt, int from, int to)
1755 M_CHECK_RANGE (mt, from, to, NULL, new);
1757 new->format = mt->format;
1758 return insert (new, 0, mt, from, to);
1764 @brief Copy characters in the specified range into an M-text.
1766 The mtext_copy () function copies the text between $FROM
1767 (inclusive) and $TO (exclusive) in M-text $MT2 to the region
1768 starting at $POS in M-text $MT1 while inheriting the text
1769 properties. The old text in $MT1 is overwritten and the length of
1770 $MT1 is extended if necessary. $MT2 is not modified.
1773 If the operation was successful, mtext_copy () returns a pointer
1774 to the modified $MT1. Otherwise, it returns @c NULL and assigns
1775 an error code to the external variable #merror_code. */
1778 @brief M-text ¤Ë»ØÄêÈϰϤÎʸ»ú¤ò¥³¥Ô¡¼¤¹¤ë.
1780 ´Ø¿ô mtext_copy () ¤Ï¡¢ M-text $MT2 ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO ¡Ê´Þ
1781 ¤Þ¤Ê¤¤¡Ë¤Þ¤Ç¤ÎÈϰϤΥƥ¥¹¥È¤ò M-text $MT1 ¤Î°ÌÃÖ $POS ¤«¤é¾å½ñ¤
1782 ¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 ¤ÎĹ
1783 ¤µ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1785 @latexonly \IPAlabel{mtext_copy} @endlatexonly
1788 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_copy () ¤ÏÊѹ¹¤µ¤ì¤¿ $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò
1789 ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼
1790 ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1797 mtext_cpy (), mtext_ncpy () */
1800 mtext_copy (MText *mt1, int pos, MText *mt2, int from, int to)
1802 M_CHECK_POS_X (mt1, pos, NULL);
1803 M_CHECK_READONLY (mt1, NULL);
1804 M_CHECK_RANGE_X (mt2, from, to, NULL);
1805 mtext_del (mt1, pos, mt1->nchars);
1806 return insert (mt1, pos, mt2, from, to);
1813 @brief Delete characters in the specified range destructively.
1815 The mtext_del () function deletes the characters in the range
1816 $FROM (inclusive) and $TO (exclusive) from M-text $MT
1817 destructively. As a result, the length of $MT shrinks by ($TO -
1821 If the operation was successful, mtext_del () returns 0.
1822 Otherwise, it returns -1 and assigns an error code to the external
1823 variable #merror_code. */
1826 @brief »ØÄêÈϰϤÎʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯.
1828 ´Ø¿ô mtext_del () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO ¡Ê´Þ¤Þ
1829 ¤Ê¤¤¡Ë¤Þ¤Ç¤Îʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯¡£·ë²ÌŪ¤Ë $MT ¤ÏŤµ¤¬ ($TO @c
1830 - $FROM) ¤À¤±½Ì¤à¤³¤È¤Ë¤Ê¤ë¡£
1833 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_del () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ
1834 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1844 mtext_del (MText *mt, int from, int to)
1846 int from_byte, to_byte;
1847 int unit_bytes = UNIT_BYTES (mt->format);
1849 M_CHECK_READONLY (mt, -1);
1850 M_CHECK_RANGE (mt, from, to, -1, 0);
1852 from_byte = POS_CHAR_TO_BYTE (mt, from);
1853 to_byte = POS_CHAR_TO_BYTE (mt, to);
1855 if (mt->cache_char_pos >= to)
1857 mt->cache_char_pos -= to - from;
1858 mt->cache_byte_pos -= to_byte - from_byte;
1860 else if (mt->cache_char_pos > from)
1862 mt->cache_char_pos -= from;
1863 mt->cache_byte_pos -= from_byte;
1866 mtext__adjust_plist_for_delete (mt, from, to - from);
1867 memmove (mt->data + from_byte * unit_bytes,
1868 mt->data + to_byte * unit_bytes,
1869 (mt->nbytes - to_byte + 1) * unit_bytes);
1870 mt->nchars -= (to - from);
1871 mt->nbytes -= (to_byte - from_byte);
1872 mt->cache_char_pos = from;
1873 mt->cache_byte_pos = from_byte;
1881 @brief Insert an M-text into another M-text.
1883 The mtext_ins () function inserts M-text $MT2 into M-text $MT1, at
1884 position $POS. As a result, $MT1 is lengthen by the length of
1885 $MT2. On insertion, all the text properties of $MT2 are
1886 inherited. The original $MT2 is not modified.
1889 If the operation was successful, mtext_ins () returns 0.
1890 Otherwise, it returns -1 and assigns an error code to the external
1891 variable #merror_code. */
1894 @brief M-text ¤òÊ̤ΠM-text ¤ËÁÞÆþ¤¹¤ë.
1896 ´Ø¿ô mtext_ins () ¤Ï M-text $MT1 ¤Î $POS ¤Î°ÌÃÖ¤Ë Ê̤ΠM-text $MT2
1897 ¤òÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $MT2 ¤ÎŤµÊ¬¤À¤±Áý¤¨¤ë¡£ÁÞÆþ¤Î
1898 ºÝ¡¢$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤½¤Î¤â¤Î¤ÏÊÑ
1902 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ
1903 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1913 mtext_ins (MText *mt1, int pos, MText *mt2)
1915 M_CHECK_READONLY (mt1, -1);
1916 M_CHECK_POS_X (mt1, pos, -1);
1918 if (mt2->nchars == 0)
1920 insert (mt1, pos, mt2, 0, mt2->nchars);
1928 @brief Insert a character into an M-text.
1930 The mtext_ins_char () function inserts $N copies of character $C
1931 into M-text $MT at position $POS. As a result, $MT is lengthen by
1935 If the operation was successful, mtext_ins () returns 0.
1936 Otherwise, it returns -1 and assigns an error code to the external
1937 variable #merror_code. */
1940 @brief M-text ¤Ëʸ»ú¤òÁÞÆþ¤¹¤ë.
1942 ´Ø¿ô mtext_ins_char () ¤Ï M-text $MT ¤Î $POS ¤Î°ÌÃÖ¤Ëʸ»ú $C ¤ò $N
1943 ¸ÄÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $N ¤À¤±Áý¤¨¤ë¡£
1946 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins_char () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1
1947 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1954 mtext_ins, mtext_del () */
1957 mtext_ins_char (MText *mt, int pos, int c, int n)
1960 int unit_bytes = UNIT_BYTES (mt->format);
1964 M_CHECK_READONLY (mt, -1);
1965 M_CHECK_POS_X (mt, pos, -1);
1966 if (c < 0 || c > MCHAR_MAX)
1967 MERROR (MERROR_MTEXT, -1);
1970 mtext__adjust_plist_for_insert (mt, pos, n, NULL);
1973 && (mt->format == MTEXT_FORMAT_US_ASCII
1974 || (c >= 0x10000 && (mt->format == MTEXT_FORMAT_UTF_16LE
1975 || mt->format == MTEXT_FORMAT_UTF_16BE))))
1977 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1980 else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
1982 if (mt->format != default_utf_32)
1983 mtext__adjust_format (mt, default_utf_32);
1985 else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
1987 if (mt->format != default_utf_16)
1988 mtext__adjust_format (mt, default_utf_16);
1991 nunits = CHAR_UNITS (c, mt->format);
1992 if ((mt->nbytes + nunits * n + 1) * unit_bytes > mt->allocated)
1994 mt->allocated = (mt->nbytes + nunits * n + 1) * unit_bytes;
1995 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1997 pos_unit = POS_CHAR_TO_BYTE (mt, pos);
1998 if (mt->cache_char_pos > pos)
2000 mt->cache_char_pos += n;
2001 mt->cache_byte_pos += nunits + n;
2003 memmove (mt->data + (pos_unit + nunits * n) * unit_bytes,
2004 mt->data + pos_unit * unit_bytes,
2005 (mt->nbytes - pos_unit + 1) * unit_bytes);
2006 if (mt->format <= MTEXT_FORMAT_UTF_8)
2008 unsigned char *p = mt->data + pos_unit;
2010 for (i = 0; i < n; i++)
2011 p += CHAR_STRING_UTF8 (c, p);
2013 else if (mt->format == default_utf_16)
2015 unsigned short *p = (unsigned short *) mt->data + pos_unit;
2017 for (i = 0; i < n; i++)
2018 p += CHAR_STRING_UTF16 (c, p);
2022 unsigned *p = (unsigned *) mt->data + pos_unit;
2024 for (i = 0; i < n; i++)
2028 mt->nbytes += nunits * n;
2035 @brief Search a character in an M-text.
2037 The mtext_character () function searches M-text $MT for character
2038 $C. If $FROM is less than $TO, the search begins at position $FROM
2039 and goes forward but does not exceed ($TO - 1). Otherwise, the search
2040 begins at position ($FROM - 1) and goes backward but does not
2041 exceed $TO. An invalid position specification is regarded as both
2042 $FROM and $TO being 0.
2045 If $C is found, mtext_character () returns the position of its
2046 first occurrence. Otherwise it returns -1 without changing the
2047 external variable #merror_code. If an error is detected, it returns -1 and
2048 assigns an error code to the external variable #merror_code. */
2051 @brief M-text Ãæ¤Çʸ»ú¤òõ¤¹.
2053 ´Ø¿ô mtext_character () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£¤â¤·
2054 $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ð¡¢Ãµº÷¤Ï°ÌÃÖ $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢ºÇÂç
2055 ($TO - 1) ¤Þ¤Ç¿Ê¤à¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð°ÌÃÖ ($FROM - 1) ¤«¤éÀèƬÊý¸þ¤Ø¡¢
2056 ºÇÂç $TO ¤Þ¤Ç¿Ê¤à¡£°ÌÃ֤λØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM ¤È $TO ¤Îξ
2057 Êý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
2060 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_character () ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2061 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code ¤òÊѹ¹¤»¤º¤Ë -1 ¤òÊÖ
2062 ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼
2063 ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
2067 mtext_chr(), mtext_rchr () */
2070 mtext_character (MText *mt, int from, int to, int c)
2074 /* We do not use M_CHECK_RANGE () because this function should
2075 not set merror_code. */
2076 if (from < 0 || to > mt->nchars)
2078 return find_char_forward (mt, from, to, c);
2083 if (to < 0 || from > mt->nchars)
2085 return find_char_backward (mt, to, from, c);
2093 @brief Return the position of the first occurrence of a character in an M-text.
2095 The mtext_chr () function searches M-text $MT for character $C.
2096 The search starts from the beginning of $MT and goes toward the end.
2099 If $C is found, mtext_chr () returns its position; otherwise it
2103 @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
2105 ´Ø¿ô mtext_chr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT ¤Î
2106 ÀèƬ¤«¤éËöÈøÊý¸þ¤Ë¿Ê¤à¡£
2109 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_chr () ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é
2110 ¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
2112 @latexonly \IPAlabel{mtext_chr} @endlatexonly */
2119 mtext_rchr (), mtext_character () */
2122 mtext_chr (MText *mt, int c)
2124 return find_char_forward (mt, 0, mt->nchars, c);
2130 @brief Return the position of the last occurrence of a character in an M-text.
2132 The mtext_rchr () function searches M-text $MT for character $C.
2133 The search starts from the end of $MT and goes backwardly toward the
2137 If $C is found, mtext_rchr () returns its position; otherwise it
2141 @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ¸å¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
2143 ´Ø¿ô mtext_rchr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT ¤Î
2144 ºÇ¸å¤«¤éÀèƬÊý¸þ¤Ø¤È¸å¸þ¤¤Ë¿Ê¤à¡£
2147 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_rchr () ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é
2148 ¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
2150 @latexonly \IPAlabel{mtext_rchr} @endlatexonly */
2157 mtext_chr (), mtext_character () */
2160 mtext_rchr (MText *mt, int c)
2162 return find_char_backward (mt, mt->nchars, 0, c);
2169 @brief Compare two M-texts character-by-character.
2171 The mtext_cmp () function compares M-texts $MT1 and $MT2 character
2175 This function returns 1, 0, or -1 if $MT1 is found greater than,
2176 equal to, or less than $MT2, respectively. Comparison is based on
2180 @brief Æó¤Ä¤Î M-text ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
2182 ´Ø¿ô mtext_cmp () ¤Ï¡¢ M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£
2185 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2186 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å
2189 @latexonly \IPAlabel{mtext_cmp} @endlatexonly */
2193 mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2194 mtext_compare (), mtext_case_compare () */
2197 mtext_cmp (MText *mt1, MText *mt2)
2199 return compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars);
2206 @brief Compare initial parts of two M-texts character-by-character.
2208 The mtext_ncmp () function is similar to mtext_cmp (), but
2209 compares at most $N characters from the beginning.
2212 This function returns 1, 0, or -1 if $MT1 is found greater than,
2213 equal to, or less than $MT2, respectively. */
2216 @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
2218 ´Ø¿ô mtext_ncmp () ¤Ï¡¢´Ø¿ô mtext_cmp () ƱÍͤΠM-text Ʊ»Î¤ÎÈæ³Ó
2219 ¤òÀèƬ¤«¤éºÇÂç $N ʸ»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
2222 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2223 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2225 @latexonly \IPAlabel{mtext_ncmp} @endlatexonly */
2229 mtext_cmp (), mtext_casecmp (), mtext_ncasecmp ()
2230 mtext_compare (), mtext_case_compare () */
2233 mtext_ncmp (MText *mt1, MText *mt2, int n)
2237 return compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n),
2238 mt2, 0, (mt2->nchars < n ? mt2->nchars : n));
2244 @brief Compare specified regions of two M-texts.
2246 The mtext_compare () function compares two M-texts $MT1 and $MT2,
2247 character-by-character. The compared regions are between $FROM1
2248 and $TO1 in $MT1 and $FROM2 to $TO2 in MT2. $FROM1 and $FROM2 are
2249 inclusive, $TO1 and $TO2 are exclusive. $FROM1 being equal to
2250 $TO1 (or $FROM2 being equal to $TO2) means an M-text of length
2251 zero. An invalid region specification is regarded as both $FROM1
2252 and $TO1 (or $FROM2 and $TO2) being 0.
2255 This function returns 1, 0, or -1 if $MT1 is found greater than,
2256 equal to, or less than $MT2, respectively. Comparison is based on
2260 @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿ÎΰèƱ»Î¤òÈæ³Ó¤¹¤ë.
2262 ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ
2263 ³Ó¤¹¤ë¡£Èæ³ÓÂоݤȤʤë¤Î¤Ï $MT1 ¤Ç¤Ï $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2
2264 ¤Ç¤Ï $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£$FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1
2265 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë
2266 ¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì
2267 ¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë ξÊý¤Ë 0 ¤¬»ØÄꤵ
2271 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2272 ¤Ð 1 ¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð
2277 mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2278 mtext_case_compare () */
2281 mtext_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
2283 if (from1 < 0 || from1 > to1 || to1 > mt1->nchars)
2286 if (from2 < 0 || from2 > to2 || to2 > mt2->nchars)
2289 return compare (mt1, from1, to1, mt2, from2, to2);
2295 @brief Search an M-text for a set of characters.
2297 The mtext_spn () function returns the length of the initial
2298 segment of M-text $MT1 that consists entirely of characters in
2302 @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2304 ´Ø¿ô mtext_spn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2 ¤Ë´Þ¤Þ
2305 ¤ì¤ëʸ»ú¤À¤±¤Ç¤Ç¤¤Æ¤¤¤ëÉôʬ¤ÎºÇÂ獵¤òÊÖ¤¹¡£
2307 @latexonly \IPAlabel{mtext_spn} @endlatexonly */
2314 mtext_spn (MText *mt, MText *accept)
2316 return span (mt, accept, 0, Mnil);
2322 @brief Search an M-text for the complement of a set of characters.
2324 The mtext_cspn () returns the length of the initial segment of
2325 M-text $MT1 that consists entirely of characters not in M-text $MT2. */
2328 @brief ¤¢¤ë½¸¹ç¤Ë°¤µ¤Ê¤¤Ê¸»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2330 ´Ø¿ô mtext_cspn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2 ¤Ë´Þ¤Þ
2331 ¤ì¤Ê¤¤Ê¸»ú¤À¤±¤Ç¤Ç¤¤Æ¤¤¤ëÉôʬ¤ÎºÇÂ獵¤òÊÖ¤¹¡£
2333 @latexonly \IPAlabel{mtext_cspn} @endlatexonly */
2340 mtext_cspn (MText *mt, MText *reject)
2342 return span (mt, reject, 0, Mt);
2348 @brief Search an M-text for any of a set of characters.
2350 The mtext_pbrk () function locates the first occurrence in M-text
2351 $MT1 of any of the characters in M-text $MT2.
2354 This function returns the position in $MT1 of the found character.
2355 If no such character is found, it returns -1. */
2358 @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤Î¤É¤ì¤«¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2360 ´Ø¿ô mtext_pbrk () ¤Ï¡¢M-text $MT1 Ãæ¤Ç M-text $MT2 ¤Î¤¤¤º¤ì¤«¤Îʸ
2361 »ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£
2364 ¸«¤Ä¤«¤Ã¤¿Ê¸»ú¤Î¡¢$MT1 Æâ¤Ë¤ª¤±¤ë½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¤â¤·¤½¤Î¤è¤¦¤Êʸ
2365 »ú¤¬¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2367 @latexonly \IPAlabel{mtext_pbrk} @endlatexonly */
2370 mtext_pbrk (MText *mt, MText *accept)
2372 int nchars = mtext_nchars (mt);
2373 int len = span (mt, accept, 0, Mt);
2375 return (len == nchars ? -1 : len);
2381 @brief Look for a token in an M-text.
2383 The mtext_tok () function searches a token that firstly occurs
2384 after position $POS in M-text $MT. Here, a token means a
2385 substring each of which does not appear in M-text $DELIM. Note
2386 that the type of $POS is not @c int but pointer to @c int.
2389 If a token is found, mtext_tok () copies the corresponding part of
2390 $MT and returns a pointer to the copy. In this case, $POS is set
2391 to the end of the found token. If no token is found, it returns
2392 @c NULL without changing the external variable #merror_code. If an
2393 error is detected, it returns @c NULL and assigns an error code
2394 to the external variable #merror_code. */
2397 @brief M-text Ãæ¤Î¥È¡¼¥¯¥ó¤òõ¤¹.
2399 ´Ø¿ô mtext_tok () ¤Ï¡¢M-text $MT ¤ÎÃæ¤Ç°ÌÃÖ $POS °Ê¹ßºÇ½é¤Ë¸½¤ì¤ë
2400 ¥È¡¼¥¯¥ó¤òõ¤¹¡£¤³¤³¤Ç¥È¡¼¥¯¥ó¤È¤Ï M-text $DELIM ¤ÎÃæ¤Ë¸½¤ï¤ì¤Ê¤¤
2401 ʸ»ú¤À¤±¤«¤é¤Ê¤ëÉôʬʸ»úÎó¤Ç¤¢¤ë¡£$POS ¤Î·¿¤¬ @c int ¤Ç¤Ï¤Ê¤¯¤Æ @c
2402 int ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤³¤È¤ËÃí°Õ¡£
2405 ¤â¤·¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤ì¤Ð mtext_tok ()¤Ï¤½¤Î¥È¡¼¥¯¥ó¤ËÁêÅö¤¹¤ëÉôʬ
2406 ¤Î $MT ¤ò¥³¥Ô¡¼¤·¡¢¤½¤Î¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢$POS ¤Ï
2407 ¸«¤Ä¤«¤Ã¤¿¥È¡¼¥¯¥ó¤Î½ªÃ¼¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿
2408 ¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code ¤òÊѤ¨¤º¤Ë @c NULL ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
2409 ¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢ÊÑÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤ò
2412 @latexonly \IPAlabel{mtext_tok} @endlatexonly */
2419 mtext_tok (MText *mt, MText *delim, int *pos)
2421 int nchars = mtext_nchars (mt);
2424 M_CHECK_POS (mt, *pos, NULL);
2427 Skip delimiters starting at POS in MT.
2428 Never do *pos += span(...), or you will change *pos
2429 even though no token is found.
2431 pos2 = *pos + span (mt, delim, *pos, Mnil);
2436 *pos = pos2 + span (mt, delim, pos2, Mt);
2437 return (insert (mtext (), 0, mt, pos2, *pos));
2443 @brief Locate an M-text in another.
2445 The mtext_text () function finds the first occurrence of M-text
2446 $MT2 in M-text $MT1 after the position $POS while ignoring
2447 difference of the text properties.
2450 If $MT2 is found in $MT1, mtext_text () returns the position of it
2451 first occurrence. Otherwise it returns -1. If $MT2 is empty, it
2455 @brief M-text Ãæ¤ÇÊ̤ΠM-text ¤òõ¤¹.
2457 ´Ø¿ô mtext_text () ¤Ï¡¢M-text $MT1 Ãæ¤Ç°ÌÃÖ $POS °Ê¹ß¤Ë¸½¤ï¤ì¤ë
2458 M-text $MT2 ¤ÎºÇ½é¤Î°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î°ã¤¤¤Ï̵»ë¤µ
2462 $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_text() ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2463 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
2465 @latexonly \IPAlabel{mtext_text} @endlatexonly */
2468 mtext_text (MText *mt1, int pos, MText *mt2)
2471 int pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
2472 int c = mtext_ref_char (mt2, 0);
2473 int nbytes1 = mtext_nbytes (mt1);
2474 int nbytes2 = mtext_nbytes (mt2);
2476 int use_memcmp = (mt1->format == mt2->format
2477 || (mt1->format < MTEXT_FORMAT_UTF_8
2478 && mt2->format == MTEXT_FORMAT_UTF_8));
2479 int unit_bytes = UNIT_BYTES (mt1->format);
2481 if (nbytes2 > pos_byte + nbytes1)
2483 pos_byte = nbytes1 - nbytes2;
2484 limit = POS_BYTE_TO_CHAR (mt1, pos_byte);
2488 if ((pos = mtext_character (mt1, from, limit, c)) < 0)
2490 pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
2492 ? ! memcmp (mt1->data + pos_byte * unit_bytes,
2493 mt2->data, nbytes2 * unit_bytes)
2494 : ! compare (mt1, pos, mt2->nchars, mt2, 0, mt2->nchars))
2502 @brief Locate an M-text in a specific range of another.
2504 The mtext_search () function searches for the first occurrence of
2505 M-text $MT2 in M-text $MT1 in the region $FROM and $TO while
2506 ignoring difference of the text properties. If $FROM is less than
2507 $TO, the forward search starts from $FROM, otherwise the backward
2508 search starts from $TO.
2511 If $MT2 is found in $MT1, mtext_search () returns the position of the
2512 first occurrence. Otherwise it returns -1. If $MT2 is empty, it
2516 @brief M-text Ãæ¤ÎÆÃÄê¤ÎÎΰè¤ÇÊ̤ΠM-text ¤òõ¤¹.
2518 ´Ø¿ô mtext_search () ¤Ï¡¢M-text $MT1 Ãæ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î´Ö¤Î
2519 Îΰè¤ÇM-text $MT2 ¤¬ºÇ½é¤Ë¸½¤ï¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£
2520 ¤Î°ã¤¤¤Ï̵»ë¤µ¤ì¤ë¡£¤â¤· $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ðõº÷¤Ï°ÌÃÖ
2521 $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð $TO ¤«¤éÀèƬÊý¸þ¤ØºÇÂç $TO ¤Þ
2525 $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_search() ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2526 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
2530 mtext_search (MText *mt1, int from, int to, MText *mt2)
2532 int c = mtext_ref_char (mt2, 0);
2534 int nbytes2 = mtext_nbytes (mt2);
2536 if (mt1->format > MTEXT_FORMAT_UTF_8
2537 || mt2->format > MTEXT_FORMAT_UTF_8)
2538 MERROR (MERROR_MTEXT, -1);
2542 to -= mtext_nchars (mt2);
2547 if ((from = find_char_forward (mt1, from, to, c)) < 0)
2549 from_byte = POS_CHAR_TO_BYTE (mt1, from);
2550 if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
2557 from -= mtext_nchars (mt2);
2562 if ((from = find_char_backward (mt1, from, to, c)) < 0)
2564 from_byte = POS_CHAR_TO_BYTE (mt1, from);
2565 if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
2577 @brief Compare two M-texts ignoring cases.
2579 The mtext_casecmp () function is similar to mtext_cmp (), but
2580 ignores cases on comparison.
2583 This function returns 1, 0, or -1 if $MT1 is found greater than,
2584 equal to, or less than $MT2, respectively. */
2587 @brief Æó¤Ä¤Î M-text ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2589 ´Ø¿ô mtext_casecmp () ¤Ï¡¢´Ø¿ô mtext_cmp () ƱÍͤΠM-text Ʊ»Î¤ÎÈæ
2590 ³Ó¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æ¹Ô¤Ê¤¦¡£
2593 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2594 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2596 @latexonly \IPAlabel{mtext_casecmp} @endlatexonly */
2600 mtext_cmp (), mtext_ncmp (), mtext_ncasecmp ()
2601 mtext_compare (), mtext_case_compare () */
2604 mtext_casecmp (MText *mt1, MText *mt2)
2606 return case_compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars);
2612 @brief Compare initial parts of two M-texts ignoring cases.
2614 The mtext_ncasecmp () function is similar to mtext_casecmp (), but
2615 compares at most $N characters from the beginning.
2618 This function returns 1, 0, or -1 if $MT1 is found greater than,
2619 equal to, or less than $MT2, respectively. */
2622 @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2624 ´Ø¿ô mtext_ncasecmp () ¤Ï¡¢´Ø¿ô mtext_casecmp () ƱÍͤΠM-text Ʊ
2625 »Î¤ÎÈæ³Ó¤òÀèƬ¤«¤éºÇÂç $N ʸ»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
2628 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2629 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2631 @latexonly \IPAlabel{mtext_ncasecmp} @endlatexonly */
2635 mtext_cmp (), mtext_casecmp (), mtext_casecmp ()
2636 mtext_compare (), mtext_case_compare () */
2639 mtext_ncasecmp (MText *mt1, MText *mt2, int n)
2643 return case_compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n),
2644 mt2, 0, (mt2->nchars < n ? mt2->nchars : n));
2650 @brief Compare specified regions of two M-texts ignoring cases.
2652 The mtext_case_compare () function compares two M-texts $MT1 and
2653 $MT2, character-by-character, ignoring cases. The compared
2654 regions are between $FROM1 and $TO1 in $MT1 and $FROM2 to $TO2 in
2655 MT2. $FROM1 and $FROM2 are inclusive, $TO1 and $TO2 are
2656 exclusive. $FROM1 being equal to $TO1 (or $FROM2 being equal to
2657 $TO2) means an M-text of length zero. An invalid region
2658 specification is regarded as both $FROM1 and $TO1 (or $FROM2 and
2662 This function returns 1, 0, or -1 if $MT1 is found greater than,
2663 equal to, or less than $MT2, respectively. Comparison is based on
2667 @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿Îΰè¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2669 ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 ¤ò¡¢Âçʸ»ú¡¿¾®
2670 ʸ»ú¤Î¶èÊ̤ò̵»ë¤·¤Æʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£Èæ³ÓÂоݤȤʤë¤Î¤Ï $MT1
2671 ¤Ç¤Ï $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2 ¤Ç¤Ï $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£
2672 $FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È
2673 $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text
2674 ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï
2675 $FROM2 ¤È $TO2 ¡ËξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
2678 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2679 ¤Ð1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð-1¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£
2681 @latexonly \IPAlabel{mtext_case_compare} @endlatexonly
2686 mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2690 mtext_case_compare (MText *mt1, int from1, int to1,
2691 MText *mt2, int from2, int to2)
2693 if (from1 < 0 || from1 > to1 || to1 > mt1->nchars)
2696 if (from2 < 0 || from2 > to2 || to2 > mt2->nchars)
2699 return case_compare (mt1, from1, to1, mt2, from2, to2);
2706 /*** @addtogroup m17nDebug */
2711 @brief Dump an M-text.
2713 The mdebug_dump_mtext () function prints the M-text $MT in a human
2714 readable way to the stderr. $INDENT specifies how many columns to
2715 indent the lines but the first one. If $FULLP is zero, this
2716 function prints only a character code sequence. Otherwise, it
2717 prints the internal byte sequence and text properties as well.
2720 This function returns $MT. */
2722 @brief M-text ¤ò¥À¥ó¥×¤¹¤ë.
2724 ´Ø¿ô mdebug_dump_mtext () ¤Ï M-text $MT ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
2725 ·Á¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£$FULLP
2726 ¤¬ 0 ¤Ê¤é¤Ð¡¢Ê¸»ú¥³¡¼¥ÉÎó¤À¤±¤ò°õºþ¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢ÆâÉô¥Ð¥¤
2727 ¥ÈÎó¤È¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤â°õºþ¤¹¤ë¡£
2730 ¤³¤Î´Ø¿ô¤Ï $MT ¤òÊÖ¤¹¡£ */
2733 mdebug_dump_mtext (MText *mt, int indent, int fullp)
2735 char *prefix = (char *) alloca (indent + 1);
2739 memset (prefix, 32, indent);
2744 fprintf (stderr, "\"");
2745 for (i = 0; i < mt->nbytes; i++)
2747 int c = mt->data[i];
2748 if (c >= ' ' && c < 127)
2749 fprintf (stderr, "%c", c);
2751 fprintf (stderr, "\\x%02X", c);
2753 fprintf (stderr, "\"");
2758 "(mtext (size %d %d %d) (cache %d %d)",
2759 mt->nchars, mt->nbytes, mt->allocated,
2760 mt->cache_char_pos, mt->cache_byte_pos);
2763 fprintf (stderr, "\n%s (bytes \"", prefix);
2764 for (i = 0; i < mt->nbytes; i++)
2765 fprintf (stderr, "\\x%02x", mt->data[i]);
2766 fprintf (stderr, "\")\n");
2767 fprintf (stderr, "%s (chars \"", prefix);
2769 for (i = 0; i < mt->nchars; i++)
2772 int c = STRING_CHAR_AND_BYTES (p, len);
2774 if (c >= ' ' && c < 127 && c != '\\' && c != '"')
2777 fprintf (stderr, "\\x%X", c);
2780 fprintf (stderr, "\")");
2783 fprintf (stderr, "\n%s ", prefix);
2784 dump_textplist (mt->plist, indent + 1);
2787 fprintf (stderr, ")");