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 ¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ë¤è¤Ã¤Æ¡¢¥Æ¥¥¹¥È¤Î³ÆÉô°Ì¤Ë´Ø¤¹¤ëÍÍ¡¹¤Ê¾ðÊó¤ò
68 M-text Æâ¤ËÊÝ»ý¤¹¤ë¤³¤È¤¬²Äǽ¤Ë¤Ê¤ë¡£
69 ¤½¤Î¤¿¤á¡¢¤½¤ì¤é¤Î¾ðÊó¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥àÆâ¤ÇÅý°ìŪ¤Ë°·¤¦¤³¤È¤¬²Äǽ¤Ë¤Ê¤ë¡£
71 ¼«ÂΤ¬ËÉ٤ʾðÊó¤ò»ý¤Ä¤¿¤á¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥àÃæ¤Î³Æ´Ø¿ô¤ò´ÊÁDz½¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£
73 ¤µ¤é¤Ëm17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢ C-string
74 ¤òÁàºî¤¹¤ë¤¿¤á¤ËÄ󶡤µ¤ì¤ë¼ï¡¹¤Î´Ø¿ô¤ÈƱÅù¤Î¤â¤Î¤ò M-text
75 ¤òÁàºî¤¹¤ë¤¿¤á¤Ë¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£ */
79 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
80 /*** @addtogroup m17nInternal
90 #include "m17n-misc.h"
93 #include "character.h"
97 static M17NObjectArray mtext_table;
99 static MSymbol M_charbag;
101 /** Increment character position CHAR_POS and unit position UNIT_POS
102 so that they point to the next character in M-text MT. No range
103 check for CHAR_POS and UNIT_POS. */
105 #define INC_POSITION(mt, char_pos, unit_pos) \
109 if ((mt)->format <= MTEXT_FORMAT_UTF_8) \
111 c = (mt)->data[(unit_pos)]; \
112 (unit_pos) += CHAR_UNITS_BY_HEAD_UTF8 (c); \
114 else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \
116 c = ((unsigned short *) ((mt)->data))[(unit_pos)]; \
118 if ((mt)->format != MTEXT_FORMAT_UTF_16) \
120 (unit_pos) += CHAR_UNITS_BY_HEAD_UTF16 (c); \
128 /** Decrement character position CHAR_POS and unit position UNIT_POS
129 so that they point to the previous character in M-text MT. No
130 range check for CHAR_POS and UNIT_POS. */
132 #define DEC_POSITION(mt, char_pos, unit_pos) \
134 if ((mt)->format <= MTEXT_FORMAT_UTF_8) \
136 unsigned char *p1 = (mt)->data + (unit_pos); \
137 unsigned char *p0 = p1 - 1; \
139 while (! CHAR_HEAD_P (p0)) p0--; \
140 (unit_pos) -= (p1 - p0); \
142 else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \
144 int c = ((unsigned short *) ((mt)->data))[(unit_pos) - 1]; \
146 if ((mt)->format != MTEXT_FORMAT_UTF_16) \
148 (unit_pos) -= 2 - (c < 0xD800 || c >= 0xE000); \
156 /* Compoare sub-texts in MT1 (range FROM1 and TO1) and MT2 (range
160 compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
162 if (mt1->format == mt2->format
163 && (mt1->format <= MTEXT_FORMAT_UTF_8))
165 unsigned char *p1, *pend1, *p2, *pend2;
166 int unit_bytes = UNIT_BYTES (mt1->format);
170 p1 = mt1->data + mtext__char_to_byte (mt1, from1) * unit_bytes;
171 pend1 = mt1->data + mtext__char_to_byte (mt1, to1) * unit_bytes;
173 p2 = mt2->data + mtext__char_to_byte (mt2, from2) * unit_bytes;
174 pend2 = mt2->data + mtext__char_to_byte (mt2, to2) * unit_bytes;
176 if (pend1 - p1 < pend2 - p2)
180 result = memcmp (p1, p2, nbytes);
183 return ((pend1 - p1) - (pend2 - p2));
185 for (; from1 < to1 && from2 < to2; from1++, from2++)
187 int c1 = mtext_ref_char (mt1, from1);
188 int c2 = mtext_ref_char (mt2, from2);
191 return (c1 > c2 ? 1 : -1);
193 return (from2 == to2 ? (from1 < to1) : -1);
197 /* Return how many units are required in UTF-8 to represent characters
198 between FROM and TO of MT. */
201 count_by_utf_8 (MText *mt, int from, int to)
205 for (n = 0; from < to; from++)
207 c = mtext_ref_char (mt, from);
208 n += CHAR_UNITS_UTF8 (c);
214 /* Return how many units are required in UTF-16 to represent
215 characters between FROM and TO of MT. */
218 count_by_utf_16 (MText *mt, int from, int to)
222 for (n = 0; from < to; from++)
224 c = mtext_ref_char (mt, from);
225 n += CHAR_UNITS_UTF16 (c);
231 /* Insert text between FROM and TO of MT2 at POS of MT1. */
234 insert (MText *mt1, int pos, MText *mt2, int from, int to)
236 int pos_unit = POS_CHAR_TO_BYTE (mt1, pos);
237 int from_unit = POS_CHAR_TO_BYTE (mt2, from);
238 int new_units = POS_CHAR_TO_BYTE (mt2, to) - from_unit;
241 if (mt1->nchars == 0)
242 mt1->format = mt2->format;
243 else if (mt1->format != mt2->format)
245 /* Be sure to make mt1->format sufficient to contain all
246 characters in mt2. */
247 if (mt1->format == MTEXT_FORMAT_UTF_8
248 || mt1->format == MTEXT_FORMAT_UTF_32
249 || (mt1->format == MTEXT_FORMAT_UTF_16
250 && mt2->format <= MTEXT_FORMAT_UTF_16BE
251 && mt2->format != MTEXT_FORMAT_UTF_8))
253 else if (mt1->format == MTEXT_FORMAT_US_ASCII)
255 if (mt2->format == MTEXT_FORMAT_UTF_8)
256 mt1->format = MTEXT_FORMAT_UTF_8;
257 else if (mt2->format == MTEXT_FORMAT_UTF_16
258 || mt2->format == MTEXT_FORMAT_UTF_32)
259 mtext__adjust_format (mt1, mt2->format);
261 mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
265 mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
266 pos_unit = POS_CHAR_TO_BYTE (mt1, pos);
270 unit_bytes = UNIT_BYTES (mt1->format);
272 if (mt1->format == mt2->format)
274 int pos_byte = pos_unit * unit_bytes;
275 int total_bytes = (mt1->nbytes + new_units) * unit_bytes;
276 int new_bytes = new_units * unit_bytes;
278 if (total_bytes + unit_bytes > mt1->allocated)
280 mt1->allocated = total_bytes + unit_bytes;
281 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
283 if (pos < mt1->nchars)
284 memmove (mt1->data + pos_byte + new_bytes, mt1->data + pos_byte,
285 (mt1->nbytes - pos_unit + 1) * unit_bytes);
286 memcpy (mt1->data + pos_byte, mt2->data + from_unit * unit_bytes,
289 else if (mt1->format == MTEXT_FORMAT_UTF_8)
292 int total_bytes, i, c;
294 new_units = count_by_utf_8 (mt2, from, to);
295 total_bytes = mt1->nbytes + new_units;
297 if (total_bytes + 1 > mt1->allocated)
299 mt1->allocated = total_bytes + 1;
300 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
302 p = mt1->data + pos_unit;
303 memmove (p + new_units, p, mt1->nbytes - pos_unit + 1);
304 for (i = from; i < to; i++)
306 c = mtext_ref_char (mt2, i);
307 p += CHAR_STRING_UTF8 (c, p);
310 else if (mt1->format == MTEXT_FORMAT_UTF_16)
313 int total_bytes, i, c;
315 new_units = count_by_utf_16 (mt2, from, to);
316 total_bytes = (mt1->nbytes + new_units) * USHORT_SIZE;
318 if (total_bytes + USHORT_SIZE > mt1->allocated)
320 mt1->allocated = total_bytes + USHORT_SIZE;
321 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
323 p = (unsigned short *) mt1->data + pos_unit;
324 memmove (p + new_units, p,
325 (mt1->nbytes - pos_unit + 1) * USHORT_SIZE);
326 for (i = from; i < to; i++)
328 c = mtext_ref_char (mt2, i);
329 p += CHAR_STRING_UTF16 (c, p);
332 else /* MTEXT_FORMAT_UTF_32 */
337 new_units = to - from;
338 total_bytes = (mt1->nbytes + new_units) * UINT_SIZE;
340 if (total_bytes + UINT_SIZE > mt1->allocated)
342 mt1->allocated = total_bytes + UINT_SIZE;
343 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
345 p = (unsigned *) mt1->data + pos_unit;
346 memmove (p + new_units, p,
347 (mt1->nbytes - pos_unit + 1) * UINT_SIZE);
348 for (i = from; i < to; i++)
349 *p++ = mtext_ref_char (mt2, i);
352 mtext__adjust_plist_for_insert
353 (mt1, pos, to - from,
354 mtext__copy_plist (mt2->plist, from, to, mt1, pos));
355 mt1->nchars += to - from;
356 mt1->nbytes += new_units;
357 if (mt1->cache_char_pos > pos)
359 mt1->cache_char_pos += to - from;
360 mt1->cache_byte_pos += new_units;
368 get_charbag (MText *mt)
370 MTextProperty *prop = mtext_get_property (mt, 0, M_charbag);
376 if (prop->end == mt->nchars)
377 return ((MCharTable *) prop->val);
378 mtext_detach_property (prop);
381 table = mchartable (Msymbol, (void *) 0);
382 for (i = mt->nchars - 1; i >= 0; i--)
383 mchartable_set (table, mtext_ref_char (mt, i), Mt);
384 prop = mtext_property (M_charbag, table, MTEXTPROP_VOLATILE_WEAK);
385 mtext_attach_property (mt, 0, mtext_nchars (mt), prop);
386 M17N_OBJECT_UNREF (prop);
391 /* span () : Number of consecutive chars starting at POS in MT1 that
392 are included (if NOT is Mnil) or not included (if NOT is Mt) in
396 span (MText *mt1, MText *mt2, int pos, MSymbol not)
398 int nchars = mtext_nchars (mt1);
399 MCharTable *table = get_charbag (mt2);
402 for (i = pos; i < nchars; i++)
403 if ((MSymbol) mchartable_lookup (table, mtext_ref_char (mt1, i)) == not)
410 count_utf_8_chars (const void *data, int nitems)
412 unsigned char *p = (unsigned char *) data;
413 unsigned char *pend = p + nitems;
420 for (; p < pend && *p < 128; nchars++, p++);
423 if (! CHAR_HEAD_P_UTF8 (p))
425 n = CHAR_UNITS_BY_HEAD_UTF8 (*p);
428 for (i = 1; i < n; i++)
429 if (CHAR_HEAD_P_UTF8 (p + i))
438 count_utf_16_chars (const void *data, int nitems, int swap)
440 unsigned short *p = (unsigned short *) data;
441 unsigned short *pend = p + nitems;
443 int prev_surrogate = 0;
445 for (; p < pend; p++)
453 if (c < 0xDC00 || c >= 0xE000)
454 /* Invalid surrogate */
459 if (c >= 0xD800 && c < 0xDC00)
471 find_char_forward (MText *mt, int from, int to, int c)
473 int from_byte = POS_CHAR_TO_BYTE (mt, from);
475 if (mt->format <= MTEXT_FORMAT_UTF_8)
477 unsigned char *p = mt->data + from_byte;
479 while (from < to && STRING_CHAR_ADVANCE_UTF8 (p) != c) from++;
481 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
483 unsigned short *p = (unsigned short *) (mt->data) + from_byte;
485 if (mt->format == MTEXT_FORMAT_UTF_16)
486 while (from < to && STRING_CHAR_ADVANCE_UTF16 (p) != c) from++;
487 else if (c < 0x10000)
490 while (from < to && *p != c)
493 p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2;
496 else if (c < 0x110000)
498 int c1 = (c >> 10) + 0xD800;
499 int c2 = (c & 0x3FF) + 0xDC00;
503 while (from < to && (*p != c1 || p[1] != c2))
506 p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2;
514 unsigned *p = (unsigned *) (mt->data) + from_byte;
517 if (mt->format != MTEXT_FORMAT_UTF_32)
519 while (from < to && *p++ != c1) from++;
522 return (from < to ? from : -1);
527 find_char_backward (MText *mt, int from, int to, int c)
529 int to_byte = POS_CHAR_TO_BYTE (mt, to);
531 if (mt->format <= MTEXT_FORMAT_UTF_8)
533 unsigned char *p = mt->data + to_byte;
537 for (p--; ! CHAR_HEAD_P (p); p--);
538 if (c == STRING_CHAR (p))
543 else if (mt->format <= MTEXT_FORMAT_UTF_16LE)
545 unsigned short *p = (unsigned short *) (mt->data) + to_byte;
547 if (mt->format == MTEXT_FORMAT_UTF_16)
552 if (*p >= 0xDC00 && *p < 0xE000)
554 if (c == STRING_CHAR_UTF16 (p))
559 else if (c < 0x10000)
562 while (from < to && p[-1] != c)
565 p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2;
568 else if (c < 0x110000)
570 int c1 = (c >> 10) + 0xD800;
571 int c2 = (c & 0x3FF) + 0xDC00;
575 while (from < to && (p[-1] != c2 || p[-2] != c1))
578 p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2;
584 unsigned *p = (unsigned *) (mt->data) + to_byte;
587 if (mt->format != MTEXT_FORMAT_UTF_32)
589 while (from < to && p[-1] != c1) to--, p--;
592 return (from < to ? to - 1 : -1);
597 free_mtext (void *object)
599 MText *mt = (MText *) object;
602 mtext__free_plist (mt);
603 if (mt->data && mt->allocated >= 0)
605 M17N_OBJECT_UNREGISTER (mtext_table, mt);
609 /** Structure for an iterator used in case-fold comparison. */
611 struct casecmp_iterator {
615 unsigned char *foldedp;
620 next_char_from_it (struct casecmp_iterator *it)
626 c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len);
630 c = mtext_ref_char (it->mt, it->pos);
631 c1 = (int) mchar_get_prop (c, Msimple_case_folding);
635 = (MText *) mchar_get_prop (c, Mcomplicated_case_folding);
636 it->foldedp = it->folded->data;
637 c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len);
647 advance_it (struct casecmp_iterator *it)
651 it->foldedp += it->folded_len;
652 if (it->foldedp == it->folded->data + it->folded->nbytes)
662 case_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
664 struct casecmp_iterator it1, it2;
666 it1.mt = mt1, it1.pos = from1, it1.folded = NULL;
667 it2.mt = mt2, it2.pos = from2, it2.folded = NULL;
669 while (it1.pos < to1 && it2.pos < to2)
671 int c1 = next_char_from_it (&it1);
672 int c2 = next_char_from_it (&it2);
675 return (c1 > c2 ? 1 : -1);
679 return (it2.pos == to2 ? (it1.pos < to1) : -1);
688 M_charbag = msymbol_as_managing_key (" charbag");
689 mtext_table.count = 0;
697 mdebug__report_object ("M-text", &mtext_table);
702 mtext__char_to_byte (MText *mt, int pos)
704 int char_pos, byte_pos;
707 if (pos < mt->cache_char_pos)
709 if (mt->cache_char_pos == mt->cache_byte_pos)
711 if (pos < mt->cache_char_pos - pos)
713 char_pos = byte_pos = 0;
718 char_pos = mt->cache_char_pos;
719 byte_pos = mt->cache_byte_pos;
725 if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos)
726 return (mt->cache_byte_pos + (pos - mt->cache_char_pos));
727 if (pos - mt->cache_char_pos < mt->nchars - pos)
729 char_pos = mt->cache_char_pos;
730 byte_pos = mt->cache_byte_pos;
735 char_pos = mt->nchars;
736 byte_pos = mt->nbytes;
741 while (char_pos < pos)
742 INC_POSITION (mt, char_pos, byte_pos);
744 while (char_pos > pos)
745 DEC_POSITION (mt, char_pos, byte_pos);
746 mt->cache_char_pos = char_pos;
747 mt->cache_byte_pos = byte_pos;
751 /* mtext__byte_to_char () */
754 mtext__byte_to_char (MText *mt, int pos_byte)
756 int char_pos, byte_pos;
759 if (pos_byte < mt->cache_byte_pos)
761 if (mt->cache_char_pos == mt->cache_byte_pos)
763 if (pos_byte < mt->cache_byte_pos - pos_byte)
765 char_pos = byte_pos = 0;
770 char_pos = mt->cache_char_pos;
771 byte_pos = mt->cache_byte_pos;
777 if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos)
778 return (mt->cache_char_pos + (pos_byte - mt->cache_byte_pos));
779 if (pos_byte - mt->cache_byte_pos < mt->nbytes - pos_byte)
781 char_pos = mt->cache_char_pos;
782 byte_pos = mt->cache_byte_pos;
787 char_pos = mt->nchars;
788 byte_pos = mt->nbytes;
793 while (byte_pos < pos_byte)
794 INC_POSITION (mt, char_pos, byte_pos);
796 while (byte_pos > pos_byte)
797 DEC_POSITION (mt, char_pos, byte_pos);
798 mt->cache_char_pos = char_pos;
799 mt->cache_byte_pos = byte_pos;
803 /* Estimated extra bytes that malloc will use for its own purpose on
804 each memory allocation. */
805 #define MALLOC_OVERHEAD 4
806 #define MALLOC_MININUM_BYTES 12
809 mtext__enlarge (MText *mt, int nbytes)
811 nbytes += MAX_UTF8_CHAR_BYTES;
812 if (mt->allocated >= nbytes)
814 if (nbytes < MALLOC_MININUM_BYTES)
815 nbytes = MALLOC_MININUM_BYTES;
816 while (mt->allocated < nbytes)
817 mt->allocated = mt->allocated * 2 + MALLOC_OVERHEAD;
818 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
822 mtext__takein (MText *mt, int nchars, int nbytes)
825 mtext__adjust_plist_for_insert (mt, mt->nchars, nchars, NULL);
826 mt->nchars += nchars;
827 mt->nbytes += nbytes;
828 mt->data[mt->nbytes] = 0;
834 mtext__cat_data (MText *mt, unsigned char *p, int nbytes,
835 enum MTextFormat format)
839 if (mt->format > MTEXT_FORMAT_UTF_8)
840 MERROR (MERROR_MTEXT, -1);
841 if (format == MTEXT_FORMAT_US_ASCII)
843 else if (format == MTEXT_FORMAT_UTF_8)
844 nchars = count_utf_8_chars (p, nbytes);
846 MERROR (MERROR_MTEXT, -1);
847 mtext__enlarge (mt, mtext_nbytes (mt) + nbytes + 1);
848 memcpy (MTEXT_DATA (mt) + mtext_nbytes (mt), p, nbytes);
849 mtext__takein (mt, nchars, nbytes);
854 mtext__from_data (const void *data, int nitems, enum MTextFormat format,
858 int nchars, nbytes, unit_bytes;
860 if (format == MTEXT_FORMAT_US_ASCII)
862 const char *p = (char *) data, *pend = p + nitems;
866 MERROR (MERROR_MTEXT, NULL);
867 nchars = nbytes = nitems;
870 else if (format == MTEXT_FORMAT_UTF_8)
872 if ((nchars = count_utf_8_chars (data, nitems)) < 0)
873 MERROR (MERROR_MTEXT, NULL);
877 else if (format <= MTEXT_FORMAT_UTF_16BE)
879 if ((nchars = count_utf_16_chars (data, nitems,
880 format != MTEXT_FORMAT_UTF_16)) < 0)
881 MERROR (MERROR_MTEXT, NULL);
882 nbytes = USHORT_SIZE * nitems;
883 unit_bytes = USHORT_SIZE;
885 else /* MTEXT_FORMAT_UTF_32XX */
888 nbytes = UINT_SIZE * nitems;
889 unit_bytes = UINT_SIZE;
894 mt->allocated = need_copy ? nbytes + unit_bytes : -1;
899 MTABLE_MALLOC (mt->data, mt->allocated, MERROR_MTEXT);
900 memcpy (mt->data, data, nbytes);
901 mt->data[nbytes] = 0;
904 mt->data = (unsigned char *) data;
910 mtext__adjust_format (MText *mt, enum MTextFormat format)
917 case MTEXT_FORMAT_US_ASCII:
919 unsigned char *p = mt->data;
921 for (i = 0; i < mt->nchars; i++)
922 *p++ = mtext_ref_char (mt, i);
923 mt->nbytes = mt->nchars;
924 mt->cache_byte_pos = mt->cache_char_pos;
928 case MTEXT_FORMAT_UTF_8:
930 unsigned char *p0, *p1;
932 i = count_by_utf_8 (mt, 0, mt->nchars) + 1;
933 MTABLE_MALLOC (p0, i, MERROR_MTEXT);
935 for (i = 0, p1 = p0; i < mt->nchars; i++)
937 c = mtext_ref_char (mt, i);
938 p1 += CHAR_STRING_UTF8 (c, p1);
943 mt->nbytes = p1 - p0;
944 mt->cache_char_pos = mt->cache_byte_pos = 0;
949 if (format == MTEXT_FORMAT_UTF_16)
951 unsigned short *p0, *p1;
953 i = (count_by_utf_16 (mt, 0, mt->nchars) + 1) * USHORT_SIZE;
954 MTABLE_MALLOC (p0, i, MERROR_MTEXT);
956 for (i = 0, p1 = p0; i < mt->nchars; i++)
958 c = mtext_ref_char (mt, i);
959 p1 += CHAR_STRING_UTF16 (c, p1);
963 mt->data = (unsigned char *) p0;
964 mt->nbytes = p1 - p0;
965 mt->cache_char_pos = mt->cache_byte_pos = 0;
972 mt->allocated = (mt->nchars + 1) * UINT_SIZE;
973 MTABLE_MALLOC (p, mt->allocated, MERROR_MTEXT);
974 for (i = 0; i < mt->nchars; i++)
975 p[i] = mtext_ref_char (mt, i);
978 mt->data = (unsigned char *) p;
979 mt->nbytes = mt->nchars;
980 mt->cache_byte_pos = mt->cache_char_pos;
987 /* Find the position of a character at the beginning of a line of
988 M-Text MT searching backward from POS. */
991 mtext__bol (MText *mt, int pos)
997 byte_pos = POS_CHAR_TO_BYTE (mt, pos);
998 if (mt->format <= MTEXT_FORMAT_UTF_8)
1000 unsigned char *p = mt->data + byte_pos;
1005 while (p > mt->data && p[-1] != '\n')
1009 byte_pos = p - mt->data;
1010 return POS_BYTE_TO_CHAR (mt, byte_pos);
1012 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1014 unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
1015 unsigned short newline = (mt->format == MTEXT_FORMAT_UTF_16
1018 if (p[-1] == newline)
1021 while (p > (unsigned short *) (mt->data) && p[-1] != newline)
1023 if (p == (unsigned short *) (mt->data))
1025 byte_pos = p - (unsigned short *) (mt->data);
1026 return POS_BYTE_TO_CHAR (mt, byte_pos);;
1030 unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
1031 unsigned newline = (mt->format == MTEXT_FORMAT_UTF_32
1032 ? 0x0A000000 : 0x0000000A);
1034 if (p[-1] == newline)
1037 while (p > (unsigned *) (mt->data) && p[-1] != newline)
1044 /* Find the position of a character at the end of a line of M-Text MT
1045 searching forward from POS. */
1048 mtext__eol (MText *mt, int pos)
1052 if (pos == mt->nchars)
1054 byte_pos = POS_CHAR_TO_BYTE (mt, pos);
1055 if (mt->format <= MTEXT_FORMAT_UTF_8)
1057 unsigned char *p = mt->data + byte_pos;
1058 unsigned char *endp;
1063 endp = mt->data + mt->nbytes;
1064 while (p < endp && *p != '\n')
1068 byte_pos = p + 1 - mt->data;
1069 return POS_BYTE_TO_CHAR (mt, byte_pos);
1071 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1073 unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
1074 unsigned short *endp;
1075 unsigned short newline = (mt->format == MTEXT_FORMAT_UTF_16
1081 endp = (unsigned short *) (mt->data) + mt->nbytes;
1082 while (p < endp && *p != newline)
1086 byte_pos = p + 1 - (unsigned short *) (mt->data);
1087 return POS_BYTE_TO_CHAR (mt, byte_pos);
1091 unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
1093 unsigned newline = (mt->format == MTEXT_FORMAT_UTF_32
1094 ? 0x0A000000 : 0x0000000A);
1099 endp = (unsigned *) (mt->data) + mt->nbytes;
1100 while (p < endp && *p != newline)
1107 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1112 #ifdef WORDS_BIGENDIAN
1113 const int MTEXT_FORMAT_UTF_16 = MTEXT_FORMAT_UTF_16BE;
1115 const int MTEXT_FORMAT_UTF_16 = MTEXT_FORMAT_UTF_16LE;
1118 #ifdef WORDS_BIGENDIAN
1119 const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32BE;
1121 const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32LE;
1124 /*** @addtogroup m17nMtext */
1129 @brief Allocate a new M-text.
1131 The mtext () function allocates a new M-text of length 0 and
1132 returns a pointer to it. The allocated M-text will not be freed
1133 unless the user explicitly does so with the m17n_object_free ()
1137 @brief ¿·¤·¤¤M-text¤ò³ä¤êÅö¤Æ¤ë.
1139 ´Ø¿ô mtext () ¤Ï¡¢Ä¹¤µ 0 ¤Î¿·¤·¤¤ M-text
1140 ¤ò³ä¤êÅö¤Æ¡¢¤½¤ì¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô
1141 m17n_object_free () ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£
1143 @latexonly \IPAlabel{mtext} @endlatexonly */
1147 m17n_object_free () */
1154 M17N_OBJECT (mt, free_mtext, MERROR_MTEXT);
1155 mt->format = MTEXT_FORMAT_UTF_8;
1156 M17N_OBJECT_REGISTER (mtext_table, mt);
1161 @brief Allocate a new M-text with specified data.
1163 The mtext_from_data () function allocates a new M-text whose
1164 character sequence is specified by array $DATA of $NITEMS
1165 elements. $FORMAT specifies the format of $DATA.
1167 When $FORMAT is either #MTEXT_FORMAT_US_ASCII or
1168 #MTEXT_FORMAT_UTF_8, the contents of $DATA must be of the type @c
1169 unsigned @c char, and $NITEMS counts by byte.
1171 When $FORMAT is either #MTEXT_FORMAT_UTF_16LE or
1172 #MTEXT_FORMAT_UTF_16BE, the contents of $DATA must be of the type
1173 @c unsigned @c short, and $NITEMS counts by unsigned short.
1175 When $FORMAT is either #MTEXT_FORMAT_UTF_32LE or
1176 #MTEXT_FORMAT_UTF_32BE, the contents of $DATA must be of the type
1177 @c unsigned, and $NITEMS counts by unsigned.
1179 The character sequence of the M-text is not modifiable.
1180 The contents of $DATA must not be modified while the M-text is alive.
1182 The allocated M-text will not be freed unless the user explicitly
1183 does so with the m17n_object_unref () function. Even in that case,
1187 If the operation was successful, mtext_from_data () returns a
1188 pointer to the allocated M-text. Otherwise it returns @c NULL and
1189 assigns an error code to the external variable #merror_code. */
1191 @brief »ØÄê¤Î¥Ç¡¼¥¿¤ò¸µ¤Ë¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë.
1193 ´Ø¿ô mtext_from_data () ¤Ï¡¢Í×ÁÇ¿ô $NITEMS ¤ÎÇÛÎó $DATA
1194 ¤Ç»ØÄꤵ¤ì¤¿Ê¸»úÎó¤ò»ý¤Ä¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë¡£$FORMAT ¤Ï $DATA
1195 ¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤ò¼¨¤¹¡£
1197 $FORMAT ¤¬ #MTEXT_FORMAT_US_ASCII ¤« #MTEXT_FORMAT_UTF_8 ¤Ê¤é¤Ð¡¢
1198 $DATA ¤ÎÆâÍÆ¤Ï @c unsigned @c char ·¿¤Ç¤¢¤ê¡¢$NITEMS
1199 ¤Ï¥Ð¥¤¥Èñ°Ì¤Çɽ¤µ¤ì¤Æ¤¤¤ë¡£
1201 $FORMAT ¤¬ #MTEXT_FORMAT_UTF_16LE ¤« #MTEXT_FORMAT_UTF_16BE ¤Ê¤é¤Ð¡¢
1202 $DATA ¤ÎÆâÍÆ¤Ï @c unsigned @c short ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned
1205 $FORMAT ¤¬ #MTEXT_FORMAT_UTF_32LE ¤« #MTEXT_FORMAT_UTF_32BE ¤Ê¤é¤Ð¡¢
1206 $DATA ¤ÎÆâÍƤÏ@c unsigned ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned ñ°Ì¤Ç¤¢¤ë¡£
1208 ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Îʸ»úÎó¤ÏÊѹ¹¤Ç¤¤Ê¤¤¡£$DATA ¤ÎÆâÍƤÏ
1209 M-text ¤¬Í¸ú¤Ê´Ö¤ÏÊѹ¹¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1211 ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_unref ()
1212 ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£¤½¤Î¾ì¹ç¤Ç¤â $DATA ¤Ï²òÊü¤µ¤ì¤Ê¤¤¡£
1215 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_from_data () ¤Ï³ä¤êÅö¤Æ¤é¤ì¤¿M-text
1216 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·³°ÉôÊÑ¿ô #merror_code
1217 ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1224 mtext_from_data (const void *data, int nitems, enum MTextFormat format)
1227 || format < MTEXT_FORMAT_US_ASCII || format >= MTEXT_FORMAT_MAX)
1228 MERROR (MERROR_MTEXT, NULL);
1229 return mtext__from_data (data, nitems, format, 0);
1235 @brief Number of characters in M-text.
1237 The mtext_len () function returns the number of characters in
1241 @brief M-text Ãæ¤Îʸ»ú¤Î¿ô.
1243 ´Ø¿ô mtext_len () ¤Ï M-text $MT Ãæ¤Îʸ»ú¤Î¿ô¤òÊÖ¤¹¡£
1245 @latexonly \IPAlabel{mtext_len} @endlatexonly */
1248 mtext_len (MText *mt)
1250 return (mt->nchars);
1256 @brief Return the character at the specified position in an M-text.
1258 The mtext_ref_char () function returns the character at $POS in
1259 M-text $MT. If an error is detected, it returns -1 and assigns an
1260 error code to the external variable #merror_code. */
1263 @brief M-text Ãæ¤Î»ØÄꤵ¤ì¤¿°ÌÃÖ¤Îʸ»ú¤òÊÖ¤¹.
1265 ´Ø¿ô mtext_ref_char () ¤Ï¡¢M-text $MT ¤Î°ÌÃÖ $POS
1266 ¤Îʸ»ú¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code
1267 ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1269 @latexonly \IPAlabel{mtext_ref_char} @endlatexonly */
1276 mtext_ref_char (MText *mt, int pos)
1280 M_CHECK_POS (mt, pos, -1);
1281 if (mt->format <= MTEXT_FORMAT_UTF_8)
1283 unsigned char *p = mt->data + POS_CHAR_TO_BYTE (mt, pos);
1285 c = STRING_CHAR_UTF8 (p);
1287 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1290 = (unsigned short *) (mt->data) + POS_CHAR_TO_BYTE (mt, pos);
1291 unsigned short p1[2];
1293 if (mt->format != MTEXT_FORMAT_UTF_16)
1295 p1[0] = SWAP_16 (*p);
1296 if (p1[0] >= 0xD800 || p1[0] < 0xDC00)
1297 p1[1] = SWAP_16 (p[1]);
1300 c = STRING_CHAR_UTF16 (p);
1304 c = ((unsigned *) (mt->data))[pos];
1305 if (mt->format != MTEXT_FORMAT_UTF_32)
1314 @brief Store a character into an M-text.
1316 The mtext_set_char () function sets character $C, which has no
1317 text properties, at $POS in M-text $MT.
1320 If the operation was successful, mtext_set_char () returns 0.
1321 Otherwise it returns -1 and assigns an error code to the external
1322 variable #merror_code. */
1325 @brief M-text ¤Ë°ìʸ»ú¤òÀßÄꤹ¤ë.
1327 ´Ø¿ô mtext_set_char () ¤Ï¡¢¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£Ìµ¤·¤Îʸ»ú $C ¤ò
1328 M-text $MT ¤Î°ÌÃÖ $POS ¤ËÀßÄꤹ¤ë¡£
1331 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mtext_set_char () ¤Ï 0 ¤òÊÖ¤¹¡£¼ºÇÔ¤¹¤ì¤Ð -1
1332 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1334 @latexonly \IPAlabel{mtext_set_char} @endlatexonly */
1341 mtext_set_char (MText *mt, int pos, int c)
1344 int old_units, new_units;
1349 M_CHECK_POS (mt, pos, -1);
1350 M_CHECK_READONLY (mt, -1);
1352 mtext__adjust_plist_for_change (mt, pos, pos + 1);
1354 if (mt->format <= MTEXT_FORMAT_UTF_8)
1357 mt->format = MTEXT_FORMAT_UTF_8;
1359 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1362 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1363 else if (mt->format != MTEXT_FORMAT_UTF_16)
1364 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
1366 else if (mt->format != MTEXT_FORMAT_UTF_32)
1367 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
1369 unit_bytes = UNIT_BYTES (mt->format);
1370 pos_unit = POS_CHAR_TO_BYTE (mt, pos);
1371 p = mt->data + pos_unit * unit_bytes;
1372 old_units = CHAR_UNITS_AT (mt, p);
1373 new_units = CHAR_UNITS (c, mt->format);
1374 delta = new_units - old_units;
1378 if (mt->cache_char_pos > pos)
1379 mt->cache_byte_pos += delta;
1381 if ((mt->nbytes + delta + 1) * unit_bytes > mt->allocated)
1383 mt->allocated = (mt->nbytes + delta + 1) * unit_bytes;
1384 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1387 memmove (mt->data + (pos_unit + new_units) * unit_bytes,
1388 mt->data + (pos_unit + old_units) * unit_bytes,
1389 (mt->nbytes - pos_unit - old_units + 1) * unit_bytes);
1390 mt->nbytes += delta;
1391 mt->data[mt->nbytes * unit_bytes] = 0;
1395 case MTEXT_FORMAT_US_ASCII:
1396 mt->data[pos_unit] = c;
1398 case MTEXT_FORMAT_UTF_8:
1400 unsigned char *p = mt->data + pos_unit;
1401 CHAR_STRING_UTF8 (c, p);
1405 if (mt->format == MTEXT_FORMAT_UTF_16)
1407 unsigned short *p = (unsigned short *) mt->data + pos_unit;
1409 CHAR_STRING_UTF16 (c, p);
1412 ((unsigned *) mt->data)[pos_unit] = c;
1420 @brief Append a character to an M-text.
1422 The mtext_cat_char () function appends character $C, which has no
1423 text properties, to the end of M-text $MT.
1426 This function returns a pointer to the resulting M-text $MT. If
1427 $C is an invalid character, it returns @c NULL. */
1430 @brief M-text ¤Ë°ìʸ»úÄɲ乤ë.
1432 ´Ø¿ô mtext_cat_char () ¤Ï¡¢¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£Ìµ¤·¤Îʸ»ú $C ¤ò
1433 M-text $MT ¤ÎËöÈø¤ËÄɲ乤롣
1436 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$C
1437 ¤¬Àµ¤·¤¤Ê¸»ú¤Ç¤Ê¤¤¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£ */
1441 mtext_cat (), mtext_ncat () */
1444 mtext_cat_char (MText *mt, int c)
1447 int unit_bytes = UNIT_BYTES (mt->format);
1449 M_CHECK_READONLY (mt, NULL);
1450 if (c < 0 || c > MCHAR_MAX)
1452 mtext__adjust_plist_for_insert (mt, mt->nchars, 1, NULL);
1455 && (mt->format == MTEXT_FORMAT_US_ASCII
1457 && (mt->format == MTEXT_FORMAT_UTF_16LE
1458 || mt->format == MTEXT_FORMAT_UTF_16BE))))
1461 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1464 else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
1466 if (mt->format != MTEXT_FORMAT_UTF_32)
1467 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
1469 else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
1471 if (mt->format != MTEXT_FORMAT_UTF_16)
1472 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
1475 nunits = CHAR_UNITS (c, mt->format);
1476 if ((mt->nbytes + nunits + 1) * unit_bytes > mt->allocated)
1478 mt->allocated = (mt->nbytes + nunits + 1) * unit_bytes;
1479 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1482 if (mt->format <= MTEXT_FORMAT_UTF_8)
1484 unsigned char *p = mt->data + mt->nbytes;
1485 p += CHAR_STRING_UTF8 (c, p);
1488 else if (mt->format == MTEXT_FORMAT_UTF_16)
1490 unsigned short *p = (unsigned short *) mt->data + mt->nbytes;
1491 p += CHAR_STRING_UTF16 (c, p);
1496 unsigned *p = (unsigned *) mt->data + mt->nbytes;
1502 mt->nbytes += nunits;
1509 @brief Create a copy of an M-text.
1511 The mtext_dup () function creates a copy of M-text $MT while
1512 inheriting all the text properties of $MT.
1515 This function returns a pointer to the created copy. */
1518 @brief M-text ¤Î¥³¥Ô¡¼¤òºî¤ë.
1520 ´Ø¿ô mtext_dup () ¤Ï¡¢M-text $MT ¤Î¥³¥Ô¡¼¤òºî¤ë¡£$MT
1521 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
1524 ¤³¤Î´Ø¿ô¤Ïºî¤é¤ì¤¿¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1526 @latexonly \IPAlabel{mtext_dup} @endlatexonly */
1530 mtext_duplicate () */
1533 mtext_dup (MText *mt)
1535 MText *new = mtext ();
1536 int unit_bytes = UNIT_BYTES (mt->format);
1541 new->allocated = (mt->nbytes + 1) * unit_bytes;
1542 MTABLE_MALLOC (new->data, new->allocated, MERROR_MTEXT);
1543 memcpy (new->data, mt->data, new->allocated);
1545 new->plist = mtext__copy_plist (mt->plist, 0, mt->nchars, new, 0);
1553 @brief Append an M-text to another.
1555 The mtext_cat () function appends M-text $MT2 to the end of M-text
1556 $MT1 while inheriting all the text properties. $MT2 itself is not
1560 This function returns a pointer to the resulting M-text $MT1. */
1563 @brief 2¸Ä¤Î M-text¤òÏ¢·ë¤¹¤ë.
1565 ´Ø¿ô mtext_cat () ¤Ï¡¢ M-text $MT2 ¤ò M-text $MT1
1566 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1569 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1571 @latexonly \IPAlabel{mtext_cat} @endlatexonly */
1575 mtext_ncat (), mtext_cat_char () */
1578 mtext_cat (MText *mt1, MText *mt2)
1580 M_CHECK_READONLY (mt1, NULL);
1582 if (mt2->nchars > 0)
1583 insert (mt1, mt1->nchars, mt2, 0, mt2->nchars);
1591 @brief Append a part of an M-text to another.
1593 The mtext_ncat () function appends the first $N characters of
1594 M-text $MT2 to the end of M-text $MT1 while inheriting all the
1595 text properties. If the length of $MT2 is less than $N, all
1596 characters are copied. $MT2 is not modified.
1599 If the operation was successful, mtext_ncat () returns a
1600 pointer to the resulting M-text $MT1. If an error is detected, it
1601 returns @c NULL and assigns an error code to the global variable
1605 @brief M-text ¤Î°ìÉô¤òÊ̤ΠM-text ¤ËÉղ乤ë.
1607 ´Ø¿ô mtext_ncat () ¤Ï¡¢M-text $MT2 ¤Î¤Ï¤¸¤á¤Î $N ʸ»ú¤ò M-text
1608 $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2
1609 ¤ÎŤµ¤¬ $N °Ê²¼¤Ê¤é¤Ð¡¢$MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤¬Éղ䵤ì¤ë¡£ $MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1612 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncat () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1
1613 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1614 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1616 @latexonly \IPAlabel{mtext_ncat} @endlatexonly */
1623 mtext_cat (), mtext_cat_char () */
1626 mtext_ncat (MText *mt1, MText *mt2, int n)
1628 M_CHECK_READONLY (mt1, NULL);
1630 MERROR (MERROR_RANGE, NULL);
1631 if (mt2->nchars > 0)
1632 insert (mt1, mt1->nchars, mt2, 0, mt2->nchars < n ? mt2->nchars : n);
1640 @brief Copy an M-text to another.
1642 The mtext_cpy () function copies M-text $MT2 to M-text $MT1 while
1643 inheriting all the text properties. The old text in $MT1 is
1644 overwritten and the length of $MT1 is extended if necessary. $MT2
1648 This function returns a pointer to the resulting M-text $MT1. */
1651 @brief M-text ¤òÊ̤ΠM-text ¤Ë¥³¥Ô¡¼¤¹¤ë.
1653 ´Ø¿ô mtext_cpy () ¤Ï M-text $MT2 ¤ò M-text $MT1 ¤Ë¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£
1654 $MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1
1655 ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1658 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1660 @latexonly \IPAlabel{mtext_cpy} @endlatexonly */
1664 mtext_ncpy (), mtext_copy () */
1667 mtext_cpy (MText *mt1, MText *mt2)
1669 M_CHECK_READONLY (mt1, NULL);
1670 mtext_del (mt1, 0, mt1->nchars);
1671 if (mt2->nchars > 0)
1672 insert (mt1, 0, mt2, 0, mt2->nchars);
1679 @brief Copy the first some characters in an M-text to another.
1681 The mtext_ncpy () function copies the first $N characters of
1682 M-text $MT2 to M-text $MT1 while inheriting all the text
1683 properties. If the length of $MT2 is less than $N, all characters
1684 of $MT2 are copied. The old text in $MT1 is overwritten and the
1685 length of $MT1 is extended if necessary. $MT2 is not modified.
1688 If the operation was successful, mtext_ncpy () returns a pointer
1689 to the resulting M-text $MT1. If an error is detected, it returns
1690 @c NULL and assigns an error code to the global variable
1694 @brief M-text ¤Ë´Þ¤Þ¤ì¤ëºÇ½é¤Î²¿Ê¸»ú¤«¤ò¥³¥Ô¡¼¤¹¤ë.
1696 ´Ø¿ô mtext_ncpy () ¤Ï¡¢M-text $MT2 ¤ÎºÇ½é¤Î $N ʸ»ú¤ò M-text $MT1
1697 ¤Ë¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£¤â¤· $MT2
1698 ¤ÎŤµ¤¬ $N ¤è¤ê¤â¾®¤µ¤±¤ì¤Ð $MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ò¥³¥Ô¡¼¤¹¤ë¡£$MT1
1699 ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1702 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncpy () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1
1703 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1704 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1706 @latexonly \IPAlabel{mtext_ncpy} @endlatexonly */
1713 mtext_cpy (), mtext_copy () */
1716 mtext_ncpy (MText *mt1, MText *mt2, int n)
1718 M_CHECK_READONLY (mt1, NULL);
1720 MERROR (MERROR_RANGE, NULL);
1721 mtext_del (mt1, 0, mt1->nchars);
1722 if (mt2->nchars > 0)
1723 insert (mt1, 0, mt2, 0, mt2->nchars < n ? mt2->nchars : n);
1730 @brief Create a new M-text from a part of an existing M-text.
1732 The mtext_duplicate () function creates a copy of sub-text of
1733 M-text $MT, starting at $FROM (inclusive) and ending at $TO
1734 (exclusive) while inheriting all the text properties of $MT. $MT
1735 itself is not modified.
1738 If the operation was successful, mtext_duplicate () returns a
1739 pointer to the created M-text. If an error is detected, it returns 0
1740 and assigns an error code to the external variable #merror_code. */
1743 @brief ´û¸¤Î M-text ¤Î°ìÉô¤«¤é¿·¤·¤¤ M-text ¤ò¤Ä¤¯¤ë.
1745 ´Ø¿ô mtext_duplicate () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê$FROM ¼«ÂΤâ´Þ¤à¡Ë¤«¤é
1746 $TO ¡Ê$TO ¼«ÂΤϴޤޤʤ¤¡Ë¤Þ¤Ç¤ÎÉôʬ¤Î¥³¥Ô¡¼¤òºî¤ë¡£¤³¤Î¤È¤ $MT
1747 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1750 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_duplicate () ¤Ïºî¤é¤ì¤¿ M-text
1751 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1752 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1754 @latexonly \IPAlabel{mtext_duplicate} @endlatexonly */
1764 mtext_duplicate (MText *mt, int from, int to)
1768 M_CHECK_RANGE_X (mt, from, to, NULL);
1770 new->format = mt->format;
1772 insert (new, 0, mt, from, to);
1779 @brief Copy characters in the specified range into an M-text.
1781 The mtext_copy () function copies the text between $FROM
1782 (inclusive) and $TO (exclusive) in M-text $MT2 to the region
1783 starting at $POS in M-text $MT1 while inheriting the text
1784 properties. The old text in $MT1 is overwritten and the length of
1785 $MT1 is extended if necessary. $MT2 is not modified.
1788 If the operation was successful, mtext_copy () returns a pointer
1789 to the modified $MT1. Otherwise, it returns @c NULL and assigns
1790 an error code to the external variable #merror_code. */
1793 @brief M-text ¤Ë»ØÄêÈϰϤÎʸ»ú¤ò¥³¥Ô¡¼¤¹¤ë.
1795 ´Ø¿ô mtext_copy () ¤Ï¡¢ M-text $MT2 ¤Î $FROM ¡Ê$FROM ¼«ÂΤâ´Þ¤à¡Ë¤«¤é
1796 $TO ¡Ê$TO ¼«ÂΤϴޤޤʤ¤¡Ë¤Þ¤Ç¤ÎÈϰϤΥƥ¥¹¥È¤ò M-text $MT1 ¤Î°ÌÃÖ $POS
1797 ¤«¤é¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1
1798 ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1800 @latexonly \IPAlabel{mtext_copy} @endlatexonly
1803 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_copy () ¤ÏÊѹ¹¤µ¤ì¤¿ $MT1
1804 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code
1805 ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1812 mtext_cpy (), mtext_ncpy () */
1815 mtext_copy (MText *mt1, int pos, MText *mt2, int from, int to)
1817 M_CHECK_POS_X (mt1, pos, NULL);
1818 M_CHECK_READONLY (mt1, NULL);
1819 M_CHECK_RANGE_X (mt2, from, to, NULL);
1820 mtext_del (mt1, pos, mt1->nchars);
1821 return insert (mt1, pos, mt2, from, to);
1828 @brief Delete characters in the specified range destructively.
1830 The mtext_del () function deletes the characters in the range
1831 $FROM (inclusive) and $TO (exclusive) from M-text $MT
1832 destructively. As a result, the length of $MT shrinks by ($TO -
1836 If the operation was successful, mtext_del () returns 0.
1837 Otherwise, it returns -1 and assigns an error code to the external
1838 variable #merror_code. */
1841 @brief »ØÄêÈϰϤÎʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯.
1843 ´Ø¿ô mtext_del () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê$FROM ¼«ÂΤâ´Þ¤à¡Ë¤«¤é $TO
1844 ¡Ê$TO ¼«ÂΤϴޤޤʤ¤¡Ë¤Þ¤Ç¤Îʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯¡£·ë²ÌŪ¤Ë $MT ¤ÏŤµ¤¬ ($TO @c
1845 - $FROM) ¤À¤±½Ì¤à¤³¤È¤Ë¤Ê¤ë¡£
1848 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_del () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1
1849 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1859 mtext_del (MText *mt, int from, int to)
1861 int from_byte, to_byte;
1862 int unit_bytes = UNIT_BYTES (mt->format);
1864 M_CHECK_READONLY (mt, -1);
1865 M_CHECK_RANGE (mt, from, to, -1, 0);
1867 from_byte = POS_CHAR_TO_BYTE (mt, from);
1868 to_byte = POS_CHAR_TO_BYTE (mt, to);
1870 if (mt->cache_char_pos >= to)
1872 mt->cache_char_pos -= to - from;
1873 mt->cache_byte_pos -= to_byte - from_byte;
1875 else if (mt->cache_char_pos > from)
1877 mt->cache_char_pos -= from;
1878 mt->cache_byte_pos -= from_byte;
1881 mtext__adjust_plist_for_delete (mt, from, to - from);
1882 memmove (mt->data + from_byte * unit_bytes,
1883 mt->data + to_byte * unit_bytes,
1884 (mt->nbytes - to_byte + 1) * unit_bytes);
1885 mt->nchars -= (to - from);
1886 mt->nbytes -= (to_byte - from_byte);
1887 mt->cache_char_pos = from;
1888 mt->cache_byte_pos = from_byte;
1896 @brief Insert an M-text into another M-text.
1898 The mtext_ins () function inserts M-text $MT2 into M-text $MT1, at
1899 position $POS. As a result, $MT1 is lengthen by the length of
1900 $MT2. On insertion, all the text properties of $MT2 are
1901 inherited. The original $MT2 is not modified.
1904 If the operation was successful, mtext_ins () returns 0.
1905 Otherwise, it returns -1 and assigns an error code to the external
1906 variable #merror_code. */
1909 @brief M-text ¤òÊ̤ΠM-text ¤ËÁÞÆþ¤¹¤ë.
1911 ´Ø¿ô mtext_ins () ¤Ï M-text $MT1 ¤Î $POS ¤Î°ÌÃÖ¤Ë Ê̤ΠM-text $MT2
1912 ¤òÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $MT2 ¤ÎŤµÊ¬¤À¤±Áý¤¨¤ë¡£ÁÞÆþ¤ÎºÝ¡¢$MT2
1913 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1916 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1
1917 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1927 mtext_ins (MText *mt1, int pos, MText *mt2)
1929 M_CHECK_READONLY (mt1, -1);
1930 M_CHECK_POS_X (mt1, pos, -1);
1932 if (mt2->nchars == 0)
1934 insert (mt1, pos, mt2, 0, mt2->nchars);
1942 @brief Insert a character into an M-text.
1944 The mtext_ins_char () function inserts $N copies of character $C
1945 into M-text $MT at position $POS. As a result, $MT is lengthen by
1949 If the operation was successful, mtext_ins () returns 0.
1950 Otherwise, it returns -1 and assigns an error code to the external
1951 variable #merror_code. */
1954 @brief M-text ¤Ëʸ»ú¤òÁÞÆþ¤¹¤ë.
1956 ´Ø¿ô mtext_ins_char () ¤Ï M-text $MT ¤Î $POS ¤Î°ÌÃÖ¤Ëʸ»ú $C ¤Î¥³¥Ô¡¼¤ò $N
1957 ¸ÄÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $N ¤À¤±Áý¤¨¤ë¡£
1960 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins_char () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1
1961 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1968 mtext_ins, mtext_del () */
1971 mtext_ins_char (MText *mt, int pos, int c, int n)
1974 int unit_bytes = UNIT_BYTES (mt->format);
1978 M_CHECK_READONLY (mt, -1);
1979 M_CHECK_POS_X (mt, pos, -1);
1980 if (c < 0 || c > MCHAR_MAX)
1981 MERROR (MERROR_MTEXT, -1);
1984 mtext__adjust_plist_for_insert (mt, pos, n, NULL);
1987 && (mt->format == MTEXT_FORMAT_US_ASCII
1988 || (c >= 0x10000 && (mt->format == MTEXT_FORMAT_UTF_16LE
1989 || mt->format == MTEXT_FORMAT_UTF_16BE))))
1991 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1994 else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
1996 if (mt->format != MTEXT_FORMAT_UTF_32)
1997 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
1999 else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
2001 if (mt->format != MTEXT_FORMAT_UTF_16)
2002 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
2005 nunits = CHAR_UNITS (c, mt->format);
2006 if ((mt->nbytes + nunits * n + 1) * unit_bytes > mt->allocated)
2008 mt->allocated = (mt->nbytes + nunits * n + 1) * unit_bytes;
2009 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
2011 pos_unit = POS_CHAR_TO_BYTE (mt, pos);
2012 if (mt->cache_char_pos > pos)
2014 mt->cache_char_pos += n;
2015 mt->cache_byte_pos += nunits + n;
2017 memmove (mt->data + (pos_unit + nunits * n) * unit_bytes,
2018 mt->data + pos_unit * unit_bytes,
2019 (mt->nbytes - pos_unit + 1) * unit_bytes);
2020 if (mt->format <= MTEXT_FORMAT_UTF_8)
2022 unsigned char *p = mt->data + pos_unit;
2024 for (i = 0; i < n; i++)
2025 p += CHAR_STRING_UTF8 (c, p);
2027 else if (mt->format == MTEXT_FORMAT_UTF_16)
2029 unsigned short *p = (unsigned short *) mt->data + pos_unit;
2031 for (i = 0; i < n; i++)
2032 p += CHAR_STRING_UTF16 (c, p);
2036 unsigned *p = (unsigned *) mt->data + pos_unit;
2038 for (i = 0; i < n; i++)
2042 mt->nbytes += nunits * n;
2049 @brief Search a character in an M-text.
2051 The mtext_character () function searches M-text $MT for character
2052 $C. If $FROM is less than $TO, the search begins at position $FROM
2053 and goes forward but does not exceed ($TO - 1). Otherwise, the search
2054 begins at position ($FROM - 1) and goes backward but does not
2055 exceed $TO. An invalid position specification is regarded as both
2056 $FROM and $TO being 0.
2059 If $C is found, mtext_character () returns the position of its
2060 first occurrence. Otherwise it returns -1 without changing the
2061 external variable #merror_code. If an error is detected, it returns -1 and
2062 assigns an error code to the external variable #merror_code. */
2065 @brief M-text Ãæ¤Çʸ»ú¤òõ¤¹.
2067 ´Ø¿ô mtext_character () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£¤â¤·
2068 $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ð¡¢Ãµº÷¤Ï°ÌÃÖ $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢ºÇÂç
2069 ($TO - 1) ¤Þ¤Ç¿Ê¤à¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð°ÌÃÖ ($FROM - 1) ¤«¤éÀèƬÊý¸þ¤Ø¡¢ºÇÂç
2070 $TO ¤Þ¤Ç¿Ê¤à¡£°ÌÃ֤λØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM ¤È $TO
2071 ¤ÎξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¤ß¤Ê¤¹¡£
2074 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_character ()
2075 ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code
2076 ¤òÊѹ¹¤»¤º¤Ë -1 ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
2077 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
2081 mtext_chr(), mtext_rchr () */
2084 mtext_character (MText *mt, int from, int to, int c)
2088 /* We do not use M_CHECK_RANGE () because this function should
2089 not set merror_code. */
2090 if (from < 0 || to > mt->nchars)
2092 return find_char_forward (mt, from, to, c);
2097 if (to < 0 || from > mt->nchars)
2099 return find_char_backward (mt, to, from, c);
2107 @brief Return the position of the first occurrence of a character in an M-text.
2109 The mtext_chr () function searches M-text $MT for character $C.
2110 The search starts from the beginning of $MT and goes toward the end.
2113 If $C is found, mtext_chr () returns its position; otherwise it
2117 @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
2119 ´Ø¿ô mtext_chr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT
2120 ¤ÎÀèƬ¤«¤éËöÈøÊý¸þ¤Ë¿Ê¤à¡£
2123 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_chr ()
2124 ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
2126 @latexonly \IPAlabel{mtext_chr} @endlatexonly */
2133 mtext_rchr (), mtext_character () */
2136 mtext_chr (MText *mt, int c)
2138 return find_char_forward (mt, 0, mt->nchars, c);
2144 @brief Return the position of the last occurrence of a character in an M-text.
2146 The mtext_rchr () function searches M-text $MT for character $C.
2147 The search starts from the end of $MT and goes backwardly toward the
2151 If $C is found, mtext_rchr () returns its position; otherwise it
2155 @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ¸å¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
2157 ´Ø¿ô mtext_rchr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT
2158 ¤ÎºÇ¸å¤«¤éÀèƬÊý¸þ¤Ø¤È¸å¸þ¤¤Ë¿Ê¤à¡£
2161 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_rchr ()
2162 ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
2164 @latexonly \IPAlabel{mtext_rchr} @endlatexonly */
2171 mtext_chr (), mtext_character () */
2174 mtext_rchr (MText *mt, int c)
2176 return find_char_backward (mt, mt->nchars, 0, c);
2183 @brief Compare two M-texts character-by-character.
2185 The mtext_cmp () function compares M-texts $MT1 and $MT2 character
2189 This function returns 1, 0, or -1 if $MT1 is found greater than,
2190 equal to, or less than $MT2, respectively. Comparison is based on
2194 @brief Æó¤Ä¤Î M-text ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
2196 ´Ø¿ô mtext_cmp () ¤Ï¡¢ M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£
2199 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì¤Ð
2200 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£
2202 @latexonly \IPAlabel{mtext_cmp} @endlatexonly */
2206 mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2207 mtext_compare (), mtext_case_compare () */
2210 mtext_cmp (MText *mt1, MText *mt2)
2212 return compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars);
2219 @brief Compare initial parts of two M-texts character-by-character.
2221 The mtext_ncmp () function is similar to mtext_cmp (), but
2222 compares at most $N characters from the beginning.
2225 This function returns 1, 0, or -1 if $MT1 is found greater than,
2226 equal to, or less than $MT2, respectively. */
2229 @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
2231 ´Ø¿ô mtext_ncmp () ¤Ï¡¢´Ø¿ô mtext_cmp () ƱÍͤΠM-text
2232 Ʊ»Î¤ÎÈæ³Ó¤òÀèƬ¤«¤éºÇÂç $N ʸ»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
2235 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì¤Ð
2236 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2238 @latexonly \IPAlabel{mtext_ncmp} @endlatexonly */
2242 mtext_cmp (), mtext_casecmp (), mtext_ncasecmp ()
2243 mtext_compare (), mtext_case_compare () */
2246 mtext_ncmp (MText *mt1, MText *mt2, int n)
2250 return compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n),
2251 mt2, 0, (mt2->nchars < n ? mt2->nchars : n));
2257 @brief Compare specified regions of two M-texts.
2259 The mtext_compare () function compares two M-texts $MT1 and $MT2,
2260 character-by-character. The compared regions are between $FROM1
2261 and $TO1 in $MT1 and $FROM2 to $TO2 in MT2. $FROM1 and $FROM2 are
2262 inclusive, $TO1 and $TO2 are exclusive. $FROM1 being equal to
2263 $TO1 (or $FROM2 being equal to $TO2) means an M-text of length
2264 zero. An invalid region specification is regarded as both $FROM1
2265 and $TO1 (or $FROM2 and $TO2) being 0.
2268 This function returns 1, 0, or -1 if $MT1 is found greater than,
2269 equal to, or less than $MT2, respectively. Comparison is based on
2273 @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿ÎΰèƱ»Î¤òÈæ³Ó¤¹¤ë.
2275 ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2
2276 ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£Èæ³Ó¤ÎÂÐ¾Ý¤Ï $MT1 ¤Î¤¦¤Á $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¤È¡¢$MT2
2277 ¤Î¤¦¤Á $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£$FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1
2278 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2
2279 ¡Ë¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢
2280 $FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë ξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¤ß¤Ê¤¹¡£
2283 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì¤Ð
2284 1 ¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£ */
2288 mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2289 mtext_case_compare () */
2292 mtext_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
2294 if (from1 < 0 || from1 > to1 || to1 > mt1->nchars)
2297 if (from2 < 0 || from2 > to2 || to2 > mt2->nchars)
2300 return compare (mt1, from1, to1, mt2, from2, to2);
2306 @brief Search an M-text for a set of characters.
2308 The mtext_spn () function returns the length of the initial
2309 segment of M-text $MT1 that consists entirely of characters in
2313 @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2315 ´Ø¿ô mtext_spn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬ¤«¤é M-text $MT2
2316 ¤Ë´Þ¤Þ¤ì¤ëʸ»ú¤À¤±¤Ç¤Ç¤¤Æ¤¤¤ëÉôʬ¤ÎŤµ¤òÊÖ¤¹¡£
2318 @latexonly \IPAlabel{mtext_spn} @endlatexonly */
2325 mtext_spn (MText *mt, MText *accept)
2327 return span (mt, accept, 0, Mnil);
2333 @brief Search an M-text for the complement of a set of characters.
2335 The mtext_cspn () returns the length of the initial segment of
2336 M-text $MT1 that consists entirely of characters not in M-text $MT2. */
2339 @brief ¤¢¤ë½¸¹ç¤Ë°¤µ¤Ê¤¤Ê¸»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2341 ´Ø¿ô mtext_cspn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2
2342 ¤Ë´Þ¤Þ¤ì¤Ê¤¤Ê¸»ú¤À¤±¤Ç¤Ç¤¤Æ¤¤¤ëÉôʬ¤ÎŤµ¤òÊÖ¤¹¡£
2344 @latexonly \IPAlabel{mtext_cspn} @endlatexonly */
2351 mtext_cspn (MText *mt, MText *reject)
2353 return span (mt, reject, 0, Mt);
2359 @brief Search an M-text for any of a set of characters.
2361 The mtext_pbrk () function locates the first occurrence in M-text
2362 $MT1 of any of the characters in M-text $MT2.
2365 This function returns the position in $MT1 of the found character.
2366 If no such character is found, it returns -1. */
2369 @brief ¤¢¤ë½¸¹ç¤Ë°¤¹Ê¸»ú¤ò M-text ¤ÎÃ椫¤éõ¤¹.
2371 ´Ø¿ô mtext_pbrk () ¤Ï¡¢M-text $MT1 Ãæ¤Ç M-text $MT2
2372 ¤Îʸ»ú¤Î¤É¤ì¤«¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£
2375 ¸«¤Ä¤«¤Ã¤¿Ê¸»ú¤Î¡¢$MT1
2376 Æâ¤Ë¤ª¤±¤ë½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¤â¤·¤½¤Î¤è¤¦¤Êʸ»ú¤¬¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2378 @latexonly \IPAlabel{mtext_pbrk} @endlatexonly */
2381 mtext_pbrk (MText *mt, MText *accept)
2383 int nchars = mtext_nchars (mt);
2384 int len = span (mt, accept, 0, Mt);
2386 return (len == nchars ? -1 : len);
2392 @brief Look for a token in an M-text.
2394 The mtext_tok () function searches a token that firstly occurs
2395 after position $POS in M-text $MT. Here, a token means a
2396 substring each of which does not appear in M-text $DELIM. Note
2397 that the type of $POS is not @c int but pointer to @c int.
2400 If a token is found, mtext_tok () copies the corresponding part of
2401 $MT and returns a pointer to the copy. In this case, $POS is set
2402 to the end of the found token. If no token is found, it returns
2403 @c NULL without changing the external variable #merror_code. If an
2404 error is detected, it returns @c NULL and assigns an error code
2405 to the external variable #merror_code. */
2408 @brief M-text Ãæ¤Î¥È¡¼¥¯¥ó¤òõ¤¹.
2410 ´Ø¿ô mtext_tok () ¤Ï¡¢M-text $MT ¤ÎÃæ¤Ç°ÌÃÖ $POS
2411 °Ê¹ßºÇ½é¤Ë¸½¤ì¤ë¥È¡¼¥¯¥ó¤òõ¤¹¡£¤³¤³¤Ç¥È¡¼¥¯¥ó¤È¤Ï M-text $DELIM
2412 ¤ÎÃæ¤Ë¸½¤ï¤ì¤Ê¤¤Ê¸»ú¤À¤±¤«¤é¤Ê¤ëÉôʬʸ»úÎó¤Ç¤¢¤ë¡£$POS ¤Î·¿¤¬ @c int ¤Ç¤Ï¤Ê¤¯¤Æ @c
2413 int ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤³¤È¤ËÃí°Õ¡£
2416 ¤â¤·¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤ì¤Ð mtext_tok ()¤Ï¤½¤Î¥È¡¼¥¯¥ó¤ËÁêÅö¤¹¤ëÉôʬ¤Î
2417 $MT ¤ò¥³¥Ô¡¼¤·¡¢¤½¤Î¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢$POS
2418 ¤Ï¸«¤Ä¤«¤Ã¤¿¥È¡¼¥¯¥ó¤Î½ªÃ¼¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï³°ÉôÊÑ¿ô
2419 #merror_code ¤òÊѤ¨¤º¤Ë @c NULL ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï
2420 @c NULL ¤òÊÖ¤·¡¢ÊÑÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
2422 @latexonly \IPAlabel{mtext_tok} @endlatexonly */
2429 mtext_tok (MText *mt, MText *delim, int *pos)
2431 int nchars = mtext_nchars (mt);
2434 M_CHECK_POS (mt, *pos, NULL);
2437 Skip delimiters starting at POS in MT.
2438 Never do *pos += span(...), or you will change *pos
2439 even though no token is found.
2441 pos2 = *pos + span (mt, delim, *pos, Mnil);
2446 *pos = pos2 + span (mt, delim, pos2, Mt);
2447 return (insert (mtext (), 0, mt, pos2, *pos));
2453 @brief Locate an M-text in another.
2455 The mtext_text () function finds the first occurrence of M-text
2456 $MT2 in M-text $MT1 after the position $POS while ignoring
2457 difference of the text properties.
2460 If $MT2 is found in $MT1, mtext_text () returns the position of it
2461 first occurrence. Otherwise it returns -1. If $MT2 is empty, it
2465 @brief M-text Ãæ¤ÇÊ̤ΠM-text ¤òõ¤¹.
2467 ´Ø¿ô mtext_text () ¤Ï¡¢M-text $MT1 Ãæ¤Ç°ÌÃÖ $POS °Ê¹ß¤Ë¸½¤ï¤ì¤ë
2468 M-text $MT2 ¤ÎºÇ½é¤Î°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î°ã¤¤¤Ï̵»ë¤µ¤ì¤ë¡£
2471 $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_text()
2472 ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
2474 @latexonly \IPAlabel{mtext_text} @endlatexonly */
2477 mtext_text (MText *mt1, int pos, MText *mt2)
2480 int pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
2481 int c = mtext_ref_char (mt2, 0);
2482 int nbytes1 = mtext_nbytes (mt1);
2483 int nbytes2 = mtext_nbytes (mt2);
2485 int use_memcmp = (mt1->format == mt2->format
2486 || (mt1->format < MTEXT_FORMAT_UTF_8
2487 && mt2->format == MTEXT_FORMAT_UTF_8));
2488 int unit_bytes = UNIT_BYTES (mt1->format);
2490 if (nbytes2 > pos_byte + nbytes1)
2492 pos_byte = nbytes1 - nbytes2;
2493 limit = POS_BYTE_TO_CHAR (mt1, pos_byte);
2497 if ((pos = mtext_character (mt1, from, limit, c)) < 0)
2499 pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
2501 ? ! memcmp (mt1->data + pos_byte * unit_bytes,
2502 mt2->data, nbytes2 * unit_bytes)
2503 : ! compare (mt1, pos, mt2->nchars, mt2, 0, mt2->nchars))
2511 @brief Locate an M-text in a specific range of another.
2513 The mtext_search () function searches for the first occurrence of
2514 M-text $MT2 in M-text $MT1 in the region $FROM and $TO while
2515 ignoring difference of the text properties. If $FROM is less than
2516 $TO, the forward search starts from $FROM, otherwise the backward
2517 search starts from $TO.
2520 If $MT2 is found in $MT1, mtext_search () returns the position of the
2521 first occurrence. Otherwise it returns -1. If $MT2 is empty, it
2525 @brief M-text Ãæ¤ÎÆÃÄê¤ÎÎΰè¤ÇÊ̤ΠM-text ¤òõ¤¹.
2527 ´Ø¿ô mtext_search () ¤Ï¡¢M-text $MT1 Ãæ¤Î $FROM ¤«¤é $TO
2528 ¤Þ¤Ç¤Î´Ö¤ÎÎΰè¤ÇM-text $MT2
2529 ¤¬ºÇ½é¤Ë¸½¤ï¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î°ã¤¤¤Ï̵»ë¤µ¤ì¤ë¡£¤â¤·
2530 $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ðõº÷¤Ï°ÌÃÖ $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð
2531 $TO ¤«¤éÀèƬÊý¸þ¤Ø¿Ê¤à¡£
2534 $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_search()
2535 ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
2539 mtext_search (MText *mt1, int from, int to, MText *mt2)
2541 int c = mtext_ref_char (mt2, 0);
2543 int nbytes2 = mtext_nbytes (mt2);
2545 if (mt1->format > MTEXT_FORMAT_UTF_8
2546 || mt2->format > MTEXT_FORMAT_UTF_8)
2547 MERROR (MERROR_MTEXT, -1);
2551 to -= mtext_nchars (mt2);
2556 if ((from = find_char_forward (mt1, from, to, c)) < 0)
2558 from_byte = POS_CHAR_TO_BYTE (mt1, from);
2559 if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
2566 from -= mtext_nchars (mt2);
2571 if ((from = find_char_backward (mt1, from, to, c)) < 0)
2573 from_byte = POS_CHAR_TO_BYTE (mt1, from);
2574 if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
2586 @brief Compare two M-texts ignoring cases.
2588 The mtext_casecmp () function is similar to mtext_cmp (), but
2589 ignores cases on comparison.
2592 This function returns 1, 0, or -1 if $MT1 is found greater than,
2593 equal to, or less than $MT2, respectively. */
2596 @brief Æó¤Ä¤Î M-text ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2598 ´Ø¿ô mtext_casecmp () ¤Ï¡¢´Ø¿ô mtext_cmp () ƱÍͤΠM-text
2599 Ʊ»Î¤ÎÈæ³Ó¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æ¹Ô¤Ê¤¦¡£
2602 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2
2603 ¤è¤êÂ礤±¤ì¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2605 @latexonly \IPAlabel{mtext_casecmp} @endlatexonly */
2609 mtext_cmp (), mtext_ncmp (), mtext_ncasecmp ()
2610 mtext_compare (), mtext_case_compare () */
2613 mtext_casecmp (MText *mt1, MText *mt2)
2615 return case_compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars);
2621 @brief Compare initial parts of two M-texts ignoring cases.
2623 The mtext_ncasecmp () function is similar to mtext_casecmp (), but
2624 compares at most $N characters from the beginning.
2627 This function returns 1, 0, or -1 if $MT1 is found greater than,
2628 equal to, or less than $MT2, respectively. */
2631 @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2633 ´Ø¿ô mtext_ncasecmp () ¤Ï¡¢´Ø¿ô mtext_casecmp () ƱÍͤΠM-text
2634 Ʊ»Î¤ÎÈæ³Ó¤òÀèƬ¤«¤éºÇÂç $N ʸ»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
2637 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2
2638 ¤è¤êÂ礤±¤ì¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2640 @latexonly \IPAlabel{mtext_ncasecmp} @endlatexonly */
2644 mtext_cmp (), mtext_casecmp (), mtext_casecmp ()
2645 mtext_compare (), mtext_case_compare () */
2648 mtext_ncasecmp (MText *mt1, MText *mt2, int n)
2652 return case_compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n),
2653 mt2, 0, (mt2->nchars < n ? mt2->nchars : n));
2659 @brief Compare specified regions of two M-texts ignoring cases.
2661 The mtext_case_compare () function compares two M-texts $MT1 and
2662 $MT2, character-by-character, ignoring cases. The compared
2663 regions are between $FROM1 and $TO1 in $MT1 and $FROM2 to $TO2 in
2664 MT2. $FROM1 and $FROM2 are inclusive, $TO1 and $TO2 are
2665 exclusive. $FROM1 being equal to $TO1 (or $FROM2 being equal to
2666 $TO2) means an M-text of length zero. An invalid region
2667 specification is regarded as both $FROM1 and $TO1 (or $FROM2 and
2671 This function returns 1, 0, or -1 if $MT1 is found greater than,
2672 equal to, or less than $MT2, respectively. Comparison is based on
2676 @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿Îΰè¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2678 ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2
2679 ¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£Èæ³Ó¤ÎÂÐ¾Ý¤Ï $MT1
2680 ¤Î $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2 ¤Î $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£
2681 $FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È $TO1
2682 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text
2683 ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï
2684 $FROM2 ¤È $TO2 ¡ËξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
2687 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì¤Ð
2688 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£
2690 @latexonly \IPAlabel{mtext_case_compare} @endlatexonly
2695 mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2699 mtext_case_compare (MText *mt1, int from1, int to1,
2700 MText *mt2, int from2, int to2)
2702 if (from1 < 0 || from1 > to1 || to1 > mt1->nchars)
2705 if (from2 < 0 || from2 > to2 || to2 > mt2->nchars)
2708 return case_compare (mt1, from1, to1, mt2, from2, to2);
2715 /*** @addtogroup m17nDebug */
2720 @brief Dump an M-text.
2722 The mdebug_dump_mtext () function prints the M-text $MT in a human
2723 readable way to the stderr. $INDENT specifies how many columns to
2724 indent the lines but the first one. If $FULLP is zero, this
2725 function prints only a character code sequence. Otherwise, it
2726 prints the internal byte sequence and text properties as well.
2729 This function returns $MT. */
2731 @brief M-text ¤ò¥À¥ó¥×¤¹¤ë.
2733 ´Ø¿ô mdebug_dump_mtext () ¤Ï M-text $MT ¤ò stderr
2734 ¤Ë¿Í´Ö¤Ë²ÄÆɤʷÁ¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£
2735 $FULLP ¤¬ 0 ¤Ê¤é¤Ð¡¢Ê¸»ú¥³¡¼¥ÉÎó¤À¤±¤ò°õºþ¤¹¤ë¡£
2736 ¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢ÆâÉô¥Ð¥¤¥ÈÎó¤È¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤â°õºþ¤¹¤ë¡£
2739 ¤³¤Î´Ø¿ô¤Ï $MT ¤òÊÖ¤¹¡£ */
2742 mdebug_dump_mtext (MText *mt, int indent, int fullp)
2744 char *prefix = (char *) alloca (indent + 1);
2748 memset (prefix, 32, indent);
2752 "(mtext (size %d %d %d) (cache %d %d)",
2753 mt->nchars, mt->nbytes, mt->allocated,
2754 mt->cache_char_pos, mt->cache_byte_pos);
2757 fprintf (stderr, " \"");
2758 for (i = 0; i < mt->nchars; i++)
2760 int c = mtext_ref_char (mt, i);
2761 if (c >= ' ' && c < 127)
2762 fprintf (stderr, "%c", c);
2764 fprintf (stderr, "\\x%02X", c);
2766 fprintf (stderr, "\"");
2768 else if (mt->nchars > 0)
2770 fprintf (stderr, "\n%s (bytes \"", prefix);
2771 for (i = 0; i < mt->nbytes; i++)
2772 fprintf (stderr, "\\x%02x", mt->data[i]);
2773 fprintf (stderr, "\")\n");
2774 fprintf (stderr, "%s (chars \"", prefix);
2776 for (i = 0; i < mt->nchars; i++)
2779 int c = STRING_CHAR_AND_BYTES (p, len);
2781 if (c >= ' ' && c < 127 && c != '\\' && c != '\"')
2784 fprintf (stderr, "\\x%X", c);
2787 fprintf (stderr, "\")");
2790 fprintf (stderr, "\n%s ", prefix);
2791 dump_textplist (mt->plist, indent + 1);
2794 fprintf (stderr, ")");