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 /** Increment character position CHAR_POS and unit position UNIT_POS
100 so that they point to the next character in M-text MT. No range
101 check for CHAR_POS and UNIT_POS. */
103 #define INC_POSITION(mt, char_pos, unit_pos) \
107 if ((mt)->format <= MTEXT_FORMAT_UTF_8) \
109 c = (mt)->data[(unit_pos)]; \
110 (unit_pos) += CHAR_UNITS_BY_HEAD_UTF8 (c); \
112 else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \
114 c = ((unsigned short *) ((mt)->data))[(unit_pos)]; \
116 if ((mt)->format != MTEXT_FORMAT_UTF_16) \
118 (unit_pos) += CHAR_UNITS_BY_HEAD_UTF16 (c); \
126 /** Decrement character position CHAR_POS and unit position UNIT_POS
127 so that they point to the previous character in M-text MT. No
128 range check for CHAR_POS and UNIT_POS. */
130 #define DEC_POSITION(mt, char_pos, unit_pos) \
132 if ((mt)->format <= MTEXT_FORMAT_UTF_8) \
134 unsigned char *p1 = (mt)->data + (unit_pos); \
135 unsigned char *p0 = p1 - 1; \
137 while (! CHAR_HEAD_P (p0)) p0--; \
138 (unit_pos) -= (p1 - p0); \
140 else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \
142 int c = ((unsigned short *) ((mt)->data))[(unit_pos) - 1]; \
144 if ((mt)->format != MTEXT_FORMAT_UTF_16) \
146 (unit_pos) -= 2 - (c < 0xD800 || c >= 0xE000); \
154 /* Compoare sub-texts in MT1 (range FROM1 and TO1) and MT2 (range
158 compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
160 if (mt1->format == mt2->format
161 && (mt1->format <= MTEXT_FORMAT_UTF_8))
163 unsigned char *p1, *pend1, *p2, *pend2;
164 int unit_bytes = UNIT_BYTES (mt1->format);
168 p1 = mt1->data + mtext__char_to_byte (mt1, from1) * unit_bytes;
169 pend1 = mt1->data + mtext__char_to_byte (mt1, to1) * unit_bytes;
171 p2 = mt2->data + mtext__char_to_byte (mt2, from2) * unit_bytes;
172 pend2 = mt2->data + mtext__char_to_byte (mt2, to2) * unit_bytes;
174 if (pend1 - p1 < pend2 - p2)
178 result = memcmp (p1, p2, nbytes);
181 return ((pend1 - p1) - (pend2 - p2));
183 for (; from1 < to1 && from2 < to2; from1++, from2++)
185 int c1 = mtext_ref_char (mt1, from1);
186 int c2 = mtext_ref_char (mt2, from2);
189 return (c1 > c2 ? 1 : -1);
191 return (from2 == to2 ? (from1 < to1) : -1);
195 /* Return how many units are required in UTF-8 to represent characters
196 between FROM and TO of MT. */
199 count_by_utf_8 (MText *mt, int from, int to)
203 for (n = 0; from < to; from++)
205 c = mtext_ref_char (mt, from);
206 n += CHAR_UNITS_UTF8 (c);
212 /* Return how many units are required in UTF-16 to represent
213 characters between FROM and TO of MT. */
216 count_by_utf_16 (MText *mt, int from, int to)
220 for (n = 0; from < to; from++)
222 c = mtext_ref_char (mt, from);
223 n += CHAR_UNITS_UTF16 (c);
229 /* Insert text between FROM and TO of MT2 at POS of MT1. */
232 insert (MText *mt1, int pos, MText *mt2, int from, int to)
234 int pos_unit = POS_CHAR_TO_BYTE (mt1, pos);
235 int from_unit = POS_CHAR_TO_BYTE (mt2, from);
236 int new_units = POS_CHAR_TO_BYTE (mt2, to) - from_unit;
239 if (mt1->nchars == 0)
240 mt1->format = mt2->format;
241 else if (mt1->format != mt2->format)
243 /* Be sure to make mt1->format sufficient to contain all
244 characters in mt2. */
245 if (mt1->format == MTEXT_FORMAT_UTF_8
246 || mt1->format == MTEXT_FORMAT_UTF_32
247 || (mt1->format == MTEXT_FORMAT_UTF_16
248 && mt2->format <= MTEXT_FORMAT_UTF_16BE
249 && mt2->format != MTEXT_FORMAT_UTF_8))
251 else if (mt1->format == MTEXT_FORMAT_US_ASCII)
253 if (mt2->format == MTEXT_FORMAT_UTF_8)
254 mt1->format = MTEXT_FORMAT_UTF_8;
255 else if (mt2->format == MTEXT_FORMAT_UTF_16
256 || mt2->format == MTEXT_FORMAT_UTF_32)
257 mtext__adjust_format (mt1, mt2->format);
259 mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
263 mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
264 pos_unit = POS_CHAR_TO_BYTE (mt1, pos);
268 unit_bytes = UNIT_BYTES (mt1->format);
270 if (mt1->format == mt2->format)
272 int pos_byte = pos_unit * unit_bytes;
273 int total_bytes = (mt1->nbytes + new_units) * unit_bytes;
274 int new_bytes = new_units * unit_bytes;
276 if (total_bytes + unit_bytes > mt1->allocated)
278 mt1->allocated = total_bytes + unit_bytes;
279 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
281 if (pos < mt1->nchars)
282 memmove (mt1->data + pos_byte + new_bytes, mt1->data + pos_byte,
283 (mt1->nbytes - pos_unit + 1) * unit_bytes);
284 memcpy (mt1->data + pos_byte, mt2->data + from_unit * unit_bytes,
287 else if (mt1->format == MTEXT_FORMAT_UTF_8)
290 int total_bytes, i, c;
292 new_units = count_by_utf_8 (mt2, from, to);
293 total_bytes = mt1->nbytes + new_units;
295 if (total_bytes + 1 > mt1->allocated)
297 mt1->allocated = total_bytes + 1;
298 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
300 p = mt1->data + pos_unit;
301 memmove (p + new_units, p, mt1->nbytes - pos_unit + 1);
302 for (i = from; i < to; i++)
304 c = mtext_ref_char (mt2, i);
305 p += CHAR_STRING_UTF8 (c, p);
308 else if (mt1->format == MTEXT_FORMAT_UTF_16)
311 int total_bytes, i, c;
313 new_units = count_by_utf_16 (mt2, from, to);
314 total_bytes = (mt1->nbytes + new_units) * USHORT_SIZE;
316 if (total_bytes + USHORT_SIZE > mt1->allocated)
318 mt1->allocated = total_bytes + USHORT_SIZE;
319 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
321 p = (unsigned short *) mt1->data + pos_unit;
322 memmove (p + new_units, p,
323 (mt1->nbytes - pos_unit + 1) * USHORT_SIZE);
324 for (i = from; i < to; i++)
326 c = mtext_ref_char (mt2, i);
327 p += CHAR_STRING_UTF16 (c, p);
330 else /* MTEXT_FORMAT_UTF_32 */
335 new_units = to - from;
336 total_bytes = (mt1->nbytes + new_units) * UINT_SIZE;
338 if (total_bytes + UINT_SIZE > mt1->allocated)
340 mt1->allocated = total_bytes + UINT_SIZE;
341 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
343 p = (unsigned *) mt1->data + pos_unit;
344 memmove (p + new_units, p,
345 (mt1->nbytes - pos_unit + 1) * UINT_SIZE);
346 for (i = from; i < to; i++)
347 *p++ = mtext_ref_char (mt2, i);
350 mtext__adjust_plist_for_insert
351 (mt1, pos, to - from,
352 mtext__copy_plist (mt2->plist, from, to, mt1, pos));
353 mt1->nchars += to - from;
354 mt1->nbytes += new_units;
355 if (mt1->cache_char_pos > pos)
357 mt1->cache_char_pos += to - from;
358 mt1->cache_byte_pos += new_units;
366 get_charbag (MText *mt)
368 MTextProperty *prop = mtext_get_property (mt, 0, M_charbag);
374 if (prop->end == mt->nchars)
375 return ((MCharTable *) prop->val);
376 mtext_detach_property (prop);
379 table = mchartable (Msymbol, (void *) 0);
380 for (i = mt->nchars - 1; i >= 0; i--)
381 mchartable_set (table, mtext_ref_char (mt, i), Mt);
382 prop = mtext_property (M_charbag, table, MTEXTPROP_VOLATILE_WEAK);
383 mtext_attach_property (mt, 0, mtext_nchars (mt), prop);
384 M17N_OBJECT_UNREF (prop);
389 /* span () : Number of consecutive chars starting at POS in MT1 that
390 are included (if NOT is Mnil) or not included (if NOT is Mt) in
394 span (MText *mt1, MText *mt2, int pos, MSymbol not)
396 int nchars = mtext_nchars (mt1);
397 MCharTable *table = get_charbag (mt2);
400 for (i = pos; i < nchars; i++)
401 if ((MSymbol) mchartable_lookup (table, mtext_ref_char (mt1, i)) == not)
408 count_utf_8_chars (const void *data, int nitems)
410 unsigned char *p = (unsigned char *) data;
411 unsigned char *pend = p + nitems;
418 for (; p < pend && *p < 128; nchars++, p++);
421 if (! CHAR_HEAD_P_UTF8 (p))
423 n = CHAR_UNITS_BY_HEAD_UTF8 (*p);
426 for (i = 1; i < n; i++)
427 if (CHAR_HEAD_P_UTF8 (p + i))
436 count_utf_16_chars (const void *data, int nitems, int swap)
438 unsigned short *p = (unsigned short *) data;
439 unsigned short *pend = p + nitems;
441 int prev_surrogate = 0;
443 for (; p < pend; p++)
451 if (c < 0xDC00 || c >= 0xE000)
452 /* Invalid surrogate */
457 if (c >= 0xD800 && c < 0xDC00)
469 find_char_forward (MText *mt, int from, int to, int c)
471 int from_byte = POS_CHAR_TO_BYTE (mt, from);
473 if (mt->format <= MTEXT_FORMAT_UTF_8)
475 unsigned char *p = mt->data + from_byte;
477 while (from < to && STRING_CHAR_ADVANCE_UTF8 (p) != c) from++;
479 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
481 unsigned short *p = (unsigned short *) (mt->data) + from_byte;
483 if (mt->format == MTEXT_FORMAT_UTF_16)
484 while (from < to && STRING_CHAR_ADVANCE_UTF16 (p) != c) from++;
485 else if (c < 0x10000)
488 while (from < to && *p != c)
491 p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2;
494 else if (c < 0x110000)
496 int c1 = (c >> 10) + 0xD800;
497 int c2 = (c & 0x3FF) + 0xDC00;
501 while (from < to && (*p != c1 || p[1] != c2))
504 p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2;
512 unsigned *p = (unsigned *) (mt->data) + from_byte;
515 if (mt->format != MTEXT_FORMAT_UTF_32)
517 while (from < to && *p++ != c1) from++;
520 return (from < to ? from : -1);
525 find_char_backward (MText *mt, int from, int to, int c)
527 int to_byte = POS_CHAR_TO_BYTE (mt, to);
529 if (mt->format <= MTEXT_FORMAT_UTF_8)
531 unsigned char *p = mt->data + to_byte;
535 for (p--; ! CHAR_HEAD_P (p); p--);
536 if (c == STRING_CHAR (p))
541 else if (mt->format <= MTEXT_FORMAT_UTF_16LE)
543 unsigned short *p = (unsigned short *) (mt->data) + to_byte;
545 if (mt->format == MTEXT_FORMAT_UTF_16)
550 if (*p >= 0xDC00 && *p < 0xE000)
552 if (c == STRING_CHAR_UTF16 (p))
557 else if (c < 0x10000)
560 while (from < to && p[-1] != c)
563 p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2;
566 else if (c < 0x110000)
568 int c1 = (c >> 10) + 0xD800;
569 int c2 = (c & 0x3FF) + 0xDC00;
573 while (from < to && (p[-1] != c2 || p[-2] != c1))
576 p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2;
582 unsigned *p = (unsigned *) (mt->data) + to_byte;
585 if (mt->format != MTEXT_FORMAT_UTF_32)
587 while (from < to && p[-1] != c1) to--, p--;
590 return (from < to ? to - 1 : -1);
595 free_mtext (void *object)
597 MText *mt = (MText *) object;
600 mtext__free_plist (mt);
601 if (mt->data && mt->allocated >= 0)
603 M17N_OBJECT_UNREGISTER (mtext_table, mt);
607 /** Structure for an iterator used in case-fold comparison. */
609 struct casecmp_iterator {
613 unsigned char *foldedp;
618 next_char_from_it (struct casecmp_iterator *it)
624 c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len);
628 c = mtext_ref_char (it->mt, it->pos);
629 c1 = (int) mchar_get_prop (c, Msimple_case_folding);
633 = (MText *) mchar_get_prop (c, Mcomplicated_case_folding);
634 it->foldedp = it->folded->data;
635 c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len);
645 advance_it (struct casecmp_iterator *it)
649 it->foldedp += it->folded_len;
650 if (it->foldedp == it->folded->data + it->folded->nbytes)
660 case_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
662 struct casecmp_iterator it1, it2;
664 it1.mt = mt1, it1.pos = from1, it1.folded = NULL;
665 it2.mt = mt2, it2.pos = from2, it2.folded = NULL;
667 while (it1.pos < to1 && it2.pos < to2)
669 int c1 = next_char_from_it (&it1);
670 int c2 = next_char_from_it (&it2);
673 return (c1 > c2 ? 1 : -1);
677 return (it2.pos == to2 ? (it1.pos < to1) : -1);
686 M_charbag = msymbol_as_managing_key (" charbag");
687 mtext_table.count = 0;
695 mdebug__report_object ("M-text", &mtext_table);
700 mtext__char_to_byte (MText *mt, int pos)
702 int char_pos, byte_pos;
705 if (pos < mt->cache_char_pos)
707 if (mt->cache_char_pos == mt->cache_byte_pos)
709 if (pos < mt->cache_char_pos - pos)
711 char_pos = byte_pos = 0;
716 char_pos = mt->cache_char_pos;
717 byte_pos = mt->cache_byte_pos;
723 if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos)
724 return (mt->cache_byte_pos + (pos - mt->cache_char_pos));
725 if (pos - mt->cache_char_pos < mt->nchars - pos)
727 char_pos = mt->cache_char_pos;
728 byte_pos = mt->cache_byte_pos;
733 char_pos = mt->nchars;
734 byte_pos = mt->nbytes;
739 while (char_pos < pos)
740 INC_POSITION (mt, char_pos, byte_pos);
742 while (char_pos > pos)
743 DEC_POSITION (mt, char_pos, byte_pos);
744 mt->cache_char_pos = char_pos;
745 mt->cache_byte_pos = byte_pos;
749 /* mtext__byte_to_char () */
752 mtext__byte_to_char (MText *mt, int pos_byte)
754 int char_pos, byte_pos;
757 if (pos_byte < mt->cache_byte_pos)
759 if (mt->cache_char_pos == mt->cache_byte_pos)
761 if (pos_byte < mt->cache_byte_pos - pos_byte)
763 char_pos = byte_pos = 0;
768 char_pos = mt->cache_char_pos;
769 byte_pos = mt->cache_byte_pos;
775 if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos)
776 return (mt->cache_char_pos + (pos_byte - mt->cache_byte_pos));
777 if (pos_byte - mt->cache_byte_pos < mt->nbytes - pos_byte)
779 char_pos = mt->cache_char_pos;
780 byte_pos = mt->cache_byte_pos;
785 char_pos = mt->nchars;
786 byte_pos = mt->nbytes;
791 while (byte_pos < pos_byte)
792 INC_POSITION (mt, char_pos, byte_pos);
794 while (byte_pos > pos_byte)
795 DEC_POSITION (mt, char_pos, byte_pos);
796 mt->cache_char_pos = char_pos;
797 mt->cache_byte_pos = byte_pos;
801 /* Estimated extra bytes that malloc will use for its own purpose on
802 each memory allocation. */
803 #define MALLOC_OVERHEAD 4
804 #define MALLOC_MININUM_BYTES 12
807 mtext__enlarge (MText *mt, int nbytes)
809 nbytes += MAX_UTF8_CHAR_BYTES;
810 if (mt->allocated >= nbytes)
812 if (nbytes < MALLOC_MININUM_BYTES)
813 nbytes = MALLOC_MININUM_BYTES;
814 while (mt->allocated < nbytes)
815 mt->allocated = mt->allocated * 2 + MALLOC_OVERHEAD;
816 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
820 mtext__takein (MText *mt, int nchars, int nbytes)
823 mtext__adjust_plist_for_insert (mt, mt->nchars, nchars, NULL);
824 mt->nchars += nchars;
825 mt->nbytes += nbytes;
826 mt->data[mt->nbytes] = 0;
832 mtext__cat_data (MText *mt, unsigned char *p, int nbytes,
833 enum MTextFormat format)
837 if (mt->format > MTEXT_FORMAT_UTF_8)
838 MERROR (MERROR_MTEXT, -1);
839 if (format == MTEXT_FORMAT_US_ASCII)
841 else if (format == MTEXT_FORMAT_UTF_8)
842 nchars = count_utf_8_chars (p, nbytes);
844 MERROR (MERROR_MTEXT, -1);
845 mtext__enlarge (mt, mtext_nbytes (mt) + nbytes + 1);
846 memcpy (MTEXT_DATA (mt) + mtext_nbytes (mt), p, nbytes);
847 mtext__takein (mt, nchars, nbytes);
852 mtext__from_data (const void *data, int nitems, enum MTextFormat format,
856 int nchars, nbytes, unit_bytes;
858 if (format == MTEXT_FORMAT_US_ASCII)
860 const char *p = (char *) data, *pend = p + nitems;
864 MERROR (MERROR_MTEXT, NULL);
865 nchars = nbytes = nitems;
868 else if (format == MTEXT_FORMAT_UTF_8)
870 if ((nchars = count_utf_8_chars (data, nitems)) < 0)
871 MERROR (MERROR_MTEXT, NULL);
875 else if (format <= MTEXT_FORMAT_UTF_16BE)
877 if ((nchars = count_utf_16_chars (data, nitems,
878 format != MTEXT_FORMAT_UTF_16)) < 0)
879 MERROR (MERROR_MTEXT, NULL);
880 nbytes = USHORT_SIZE * nitems;
881 unit_bytes = USHORT_SIZE;
883 else /* MTEXT_FORMAT_UTF_32XX */
886 nbytes = UINT_SIZE * nitems;
887 unit_bytes = UINT_SIZE;
892 mt->allocated = need_copy ? nbytes + unit_bytes : -1;
897 MTABLE_MALLOC (mt->data, mt->allocated, MERROR_MTEXT);
898 memcpy (mt->data, data, nbytes);
899 mt->data[nbytes] = 0;
902 mt->data = (unsigned char *) data;
908 mtext__adjust_format (MText *mt, enum MTextFormat format)
915 case MTEXT_FORMAT_US_ASCII:
917 unsigned char *p = mt->data;
919 for (i = 0; i < mt->nchars; i++)
920 *p++ = mtext_ref_char (mt, i);
921 mt->nbytes = mt->nchars;
922 mt->cache_byte_pos = mt->cache_char_pos;
926 case MTEXT_FORMAT_UTF_8:
928 unsigned char *p0, *p1;
930 i = count_by_utf_8 (mt, 0, mt->nchars) + 1;
931 MTABLE_MALLOC (p0, i, MERROR_MTEXT);
933 for (i = 0, p1 = p0; i < mt->nchars; i++)
935 c = mtext_ref_char (mt, i);
936 p1 += CHAR_STRING_UTF8 (c, p1);
941 mt->nbytes = p1 - p0;
942 mt->cache_char_pos = mt->cache_byte_pos = 0;
947 if (format == MTEXT_FORMAT_UTF_16)
949 unsigned short *p0, *p1;
951 i = (count_by_utf_16 (mt, 0, mt->nchars) + 1) * USHORT_SIZE;
952 MTABLE_MALLOC (p0, i, MERROR_MTEXT);
954 for (i = 0, p1 = p0; i < mt->nchars; i++)
956 c = mtext_ref_char (mt, i);
957 p1 += CHAR_STRING_UTF16 (c, p1);
961 mt->data = (unsigned char *) p0;
962 mt->nbytes = p1 - p0;
963 mt->cache_char_pos = mt->cache_byte_pos = 0;
970 mt->allocated = (mt->nchars + 1) * UINT_SIZE;
971 MTABLE_MALLOC (p, mt->allocated, MERROR_MTEXT);
972 for (i = 0; i < mt->nchars; i++)
973 p[i] = mtext_ref_char (mt, i);
976 mt->data = (unsigned char *) p;
977 mt->nbytes = mt->nchars;
978 mt->cache_byte_pos = mt->cache_char_pos;
985 /* Find the position of a character at the beginning of a line of
986 M-Text MT searching backward from POS. */
989 mtext__bol (MText *mt, int pos)
995 byte_pos = POS_CHAR_TO_BYTE (mt, pos);
996 if (mt->format <= MTEXT_FORMAT_UTF_8)
998 unsigned char *p = mt->data + byte_pos;
1003 while (p > mt->data && p[-1] != '\n')
1007 byte_pos = p - mt->data;
1008 return POS_BYTE_TO_CHAR (mt, byte_pos);
1010 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1012 unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
1013 unsigned short newline = (mt->format == MTEXT_FORMAT_UTF_16
1016 if (p[-1] == newline)
1019 while (p > (unsigned short *) (mt->data) && p[-1] != newline)
1021 if (p == (unsigned short *) (mt->data))
1023 byte_pos = p - (unsigned short *) (mt->data);
1024 return POS_BYTE_TO_CHAR (mt, byte_pos);;
1028 unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
1029 unsigned newline = (mt->format == MTEXT_FORMAT_UTF_32
1030 ? 0x0A000000 : 0x0000000A);
1032 if (p[-1] == newline)
1035 while (p > (unsigned *) (mt->data) && p[-1] != newline)
1042 /* Find the position of a character at the end of a line of M-Text MT
1043 searching forward from POS. */
1046 mtext__eol (MText *mt, int pos)
1050 if (pos == mt->nchars)
1052 byte_pos = POS_CHAR_TO_BYTE (mt, pos);
1053 if (mt->format <= MTEXT_FORMAT_UTF_8)
1055 unsigned char *p = mt->data + byte_pos;
1056 unsigned char *endp;
1061 endp = mt->data + mt->nbytes;
1062 while (p < endp && *p != '\n')
1066 byte_pos = p + 1 - mt->data;
1067 return POS_BYTE_TO_CHAR (mt, byte_pos);
1069 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1071 unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
1072 unsigned short *endp;
1073 unsigned short newline = (mt->format == MTEXT_FORMAT_UTF_16
1079 endp = (unsigned short *) (mt->data) + mt->nbytes;
1080 while (p < endp && *p != newline)
1084 byte_pos = p + 1 - (unsigned short *) (mt->data);
1085 return POS_BYTE_TO_CHAR (mt, byte_pos);
1089 unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
1091 unsigned newline = (mt->format == MTEXT_FORMAT_UTF_32
1092 ? 0x0A000000 : 0x0000000A);
1097 endp = (unsigned *) (mt->data) + mt->nbytes;
1098 while (p < endp && *p != newline)
1105 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1110 #ifdef WORDS_BIGENDIAN
1111 const int MTEXT_FORMAT_UTF_16 = MTEXT_FORMAT_UTF_16BE;
1113 const int MTEXT_FORMAT_UTF_16 = MTEXT_FORMAT_UTF_16LE;
1116 #ifdef WORDS_BIGENDIAN
1117 const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32BE;
1119 const int MTEXT_FORMAT_UTF_32 = MTEXT_FORMAT_UTF_32LE;
1122 /*** @addtogroup m17nMtext */
1127 @brief Allocate a new M-text.
1129 The mtext () function allocates a new M-text of length 0 and
1130 returns a pointer to it. The allocated M-text will not be freed
1131 unless the user explicitly does so with the m17n_object_free ()
1135 @brief ¿·¤·¤¤M-text¤ò³ä¤êÅö¤Æ¤ë.
1137 ´Ø¿ô mtext () ¤Ï¡¢Ä¹¤µ 0 ¤Î¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¡¢¤½¤ì¤Ø¤Î¥Ý¥¤
1138 ¥ó¥¿¤òÊÖ¤¹¡£³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_free () ¤Ë
1139 ¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£
1141 @latexonly \IPAlabel{mtext} @endlatexonly */
1145 m17n_object_free () */
1152 M17N_OBJECT (mt, free_mtext, MERROR_MTEXT);
1153 mt->format = MTEXT_FORMAT_UTF_8;
1154 M17N_OBJECT_REGISTER (mtext_table, mt);
1159 @brief Allocate a new M-text with specified data.
1161 The mtext_from_data () function allocates a new M-text whose
1162 character sequence is specified by array $DATA of $NITEMS
1163 elements. $FORMAT specifies the format of $DATA.
1165 When $FORMAT is either #MTEXT_FORMAT_US_ASCII or
1166 #MTEXT_FORMAT_UTF_8, the contents of $DATA must be of the type @c
1167 unsigned @c char, and $NITEMS counts by byte.
1169 When $FORMAT is either #MTEXT_FORMAT_UTF_16LE or
1170 #MTEXT_FORMAT_UTF_16BE, the contents of $DATA must be of the type
1171 @c unsigned @c short, and $NITEMS counts by unsigned short.
1173 When $FORMAT is either #MTEXT_FORMAT_UTF_32LE or
1174 #MTEXT_FORMAT_UTF_32BE, the contents of $DATA must be of the type
1175 @c unsigned, and $NITEMS counts by unsigned.
1177 The character sequence of the M-text is not modifiable.
1178 The contents of $DATA must not be modified while the M-text is alive.
1180 The allocated M-text will not be freed unless the user explicitly
1181 does so with the m17n_object_unref () function. Even in that case,
1185 If the operation was successful, mtext_from_data () returns a
1186 pointer to the allocated M-text. Otherwise it returns @c NULL and
1187 assigns an error code to the external variable #merror_code. */
1189 @brief »ØÄê¤Î¥Ç¡¼¥¿¤ò¸µ¤Ë¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë.
1191 ´Ø¿ô mtext_from_data () ¤Ï¡¢Í×ÁÇ¿ô $NITEMS ¤ÎÇÛÎó $DATA ¤Ç»ØÄꤵ¤ì
1192 ¤¿Ê¸»úÎó¤ò»ý¤Ä¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë¡£$FORMAT ¤Ï $DATA ¤Î¥Õ¥©¡¼
1195 $FORMAT ¤¬ #MTEXT_FORMAT_US_ASCII ¤« #MTEXT_FORMAT_UTF_8 ¤Ê¤é¤Ð¡¢
1196 $DATA ¤ÎÆâÍÆ¤Ï @c unsigned @c char ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¥Ð¥¤¥Èñ°Ì
1199 $FORMAT ¤¬ #MTEXT_FORMAT_UTF_16LE ¤« #MTEXT_FORMAT_UTF_16BE ¤Ê¤é¤Ð¡¢
1200 $DATA ¤ÎÆâÍÆ¤Ï @c unsigned @c short ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned
1203 $FORMAT ¤¬ #MTEXT_FORMAT_UTF_32LE ¤« #MTEXT_FORMAT_UTF_32BE ¤Ê¤é¤Ð¡¢
1204 $DATA ¤ÎÆâÍƤÏ@c unsigned ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned ñ°Ì¤Ç¤¢¤ë¡£
1206 ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Îʸ»úÎó¤ÏÊѹ¹¤Ç¤¤Ê¤¤¡£$DATA ¤ÎÆâÍƤÏ
1207 M-text ¤¬Í¸ú¤Ê´Ö¤ÏÊѹ¹¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1209 ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_unref () ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶
1210 ¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£¤½¤Î¾ì¹ç¤Ç¤â $DATA ¤Ï²òÊü
1214 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_from_data () ¤Ï³ä¤êÅö¤Æ¤é¤ì¤¿M-text ¤Ø¤Î¥Ý
1215 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·³°ÉôÊÑ¿ô #merror_code ¤Ë
1216 ¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1223 mtext_from_data (const void *data, int nitems, enum MTextFormat format)
1226 || format < MTEXT_FORMAT_US_ASCII || format >= MTEXT_FORMAT_MAX)
1227 MERROR (MERROR_MTEXT, NULL);
1228 return mtext__from_data (data, nitems, format, 0);
1234 @brief Number of characters in M-text.
1236 The mtext_len () function returns the number of characters in
1240 @brief M-text Ãæ¤Îʸ»ú¤Î¿ô.
1242 ´Ø¿ô mtext_len () ¤Ï M-text $MT Ãæ¤Îʸ»ú¤Î¿ô¤òÊÖ¤¹¡£
1244 @latexonly \IPAlabel{mtext_len} @endlatexonly */
1247 mtext_len (MText *mt)
1249 return (mt->nchars);
1255 @brief Return the character at the specified position in an M-text.
1257 The mtext_ref_char () function returns the character at $POS in
1258 M-text $MT. If an error is detected, it returns -1 and assigns an
1259 error code to the external variable #merror_code. */
1262 @brief M-text Ãæ¤Î»ØÄꤵ¤ì¤¿°ÌÃÖ¤Îʸ»ú¤òÊÖ¤¹.
1264 ´Ø¿ô mtext_ref_char () ¤Ï¡¢M-text $MT ¤Î°ÌÃÖ $POS ¤Îʸ»ú¤òÊÖ¤¹¡£
1265 ¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code
1266 ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1268 @latexonly \IPAlabel{mtext_ref_char} @endlatexonly */
1275 mtext_ref_char (MText *mt, int pos)
1279 M_CHECK_POS (mt, pos, -1);
1280 if (mt->format <= MTEXT_FORMAT_UTF_8)
1282 unsigned char *p = mt->data + POS_CHAR_TO_BYTE (mt, pos);
1284 c = STRING_CHAR_UTF8 (p);
1286 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1289 = (unsigned short *) (mt->data) + POS_CHAR_TO_BYTE (mt, pos);
1290 unsigned short p1[2];
1292 if (mt->format != MTEXT_FORMAT_UTF_16)
1294 p1[0] = SWAP_16 (*p);
1295 if (p1[0] >= 0xD800 || p1[0] < 0xDC00)
1296 p1[1] = SWAP_16 (p[1]);
1299 c = STRING_CHAR_UTF16 (p);
1303 c = ((unsigned *) (mt->data))[pos];
1304 if (mt->format != MTEXT_FORMAT_UTF_32)
1313 @brief Store a character into an M-text.
1315 The mtext_set_char () function sets character $C, which has no
1316 text properties, at $POS in M-text $MT.
1319 If the operation was successful, mtext_set_char () returns 0.
1320 Otherwise it returns -1 and assigns an error code to the external
1321 variable #merror_code. */
1324 @brief M-text ¤Ë°ìʸ»ú¤òÀßÄꤹ¤ë.
1326 ´Ø¿ô mtext_set_char () ¤Ï¡¢¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£Ìµ¤·¤Îʸ»ú $C ¤ò
1327 M-text $MT ¤Î°ÌÃÖ $POS ¤ËÀßÄꤹ¤ë¡£
1330 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mtext_set_char () ¤Ï 0 ¤òÊÖ¤¹¡£¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ
1331 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1333 @latexonly \IPAlabel{mtext_set_char} @endlatexonly */
1340 mtext_set_char (MText *mt, int pos, int c)
1343 int old_units, new_units;
1348 M_CHECK_POS (mt, pos, -1);
1349 M_CHECK_READONLY (mt, -1);
1351 mtext__adjust_plist_for_change (mt, pos, pos + 1);
1353 if (mt->format <= MTEXT_FORMAT_UTF_8)
1356 mt->format = MTEXT_FORMAT_UTF_8;
1358 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1361 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1362 else if (mt->format != MTEXT_FORMAT_UTF_16)
1363 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
1365 else if (mt->format != MTEXT_FORMAT_UTF_32)
1366 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
1368 unit_bytes = UNIT_BYTES (mt->format);
1369 pos_unit = POS_CHAR_TO_BYTE (mt, pos);
1370 p = mt->data + pos_unit * unit_bytes;
1371 old_units = CHAR_UNITS_AT (mt, p);
1372 new_units = CHAR_UNITS (c, mt->format);
1373 delta = new_units - old_units;
1377 if (mt->cache_char_pos > pos)
1378 mt->cache_byte_pos += delta;
1380 if ((mt->nbytes + delta + 1) * unit_bytes > mt->allocated)
1382 mt->allocated = (mt->nbytes + delta + 1) * unit_bytes;
1383 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1386 memmove (mt->data + (pos_unit + new_units) * unit_bytes,
1387 mt->data + (pos_unit + old_units) * unit_bytes,
1388 (mt->nbytes - pos_unit - old_units + 1) * unit_bytes);
1389 mt->nbytes += delta;
1390 mt->data[mt->nbytes * unit_bytes] = 0;
1394 case MTEXT_FORMAT_US_ASCII:
1395 mt->data[pos_unit] = c;
1397 case MTEXT_FORMAT_UTF_8:
1399 unsigned char *p = mt->data + pos_unit;
1400 CHAR_STRING_UTF8 (c, p);
1404 if (mt->format == MTEXT_FORMAT_UTF_16)
1406 unsigned short *p = (unsigned short *) mt->data + pos_unit;
1408 CHAR_STRING_UTF16 (c, p);
1411 ((unsigned *) mt->data)[pos_unit] = c;
1419 @brief Append a character to an M-text.
1421 The mtext_cat_char () function appends character $C, which has no
1422 text properties, to the end of M-text $MT.
1425 This function returns a pointer to the resulting M-text $MT. If
1426 $C is an invalid character, it returns @c NULL. */
1429 @brief M-text ¤Ë°ìʸ»úÄɲ乤ë.
1431 ´Ø¿ô mtext_cat_char () ¤Ï¡¢¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£Ìµ¤·¤Îʸ»ú $C ¤ò
1432 M-text $MT ¤ÎËöÈø¤ËÄɲ乤롣
1435 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$C ¤¬Àµ¤·¤¤Ê¸
1436 »ú¤Ç¤Ê¤¤¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£ */
1440 mtext_cat (), mtext_ncat () */
1443 mtext_cat_char (MText *mt, int c)
1446 int unit_bytes = UNIT_BYTES (mt->format);
1448 M_CHECK_READONLY (mt, NULL);
1449 if (c < 0 || c > MCHAR_MAX)
1451 mtext__adjust_plist_for_insert (mt, mt->nchars, 1, NULL);
1454 && (mt->format == MTEXT_FORMAT_US_ASCII
1456 && (mt->format == MTEXT_FORMAT_UTF_16LE
1457 || mt->format == MTEXT_FORMAT_UTF_16BE))))
1460 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1463 else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
1465 if (mt->format != MTEXT_FORMAT_UTF_32)
1466 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
1468 else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
1470 if (mt->format != MTEXT_FORMAT_UTF_16)
1471 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
1474 nunits = CHAR_UNITS (c, mt->format);
1475 if ((mt->nbytes + nunits + 1) * unit_bytes > mt->allocated)
1477 mt->allocated = (mt->nbytes + nunits + 1) * unit_bytes;
1478 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1481 if (mt->format <= MTEXT_FORMAT_UTF_8)
1483 unsigned char *p = mt->data + mt->nbytes;
1484 p += CHAR_STRING_UTF8 (c, p);
1487 else if (mt->format == MTEXT_FORMAT_UTF_16)
1489 unsigned short *p = (unsigned short *) mt->data + mt->nbytes;
1490 p += CHAR_STRING_UTF16 (c, p);
1495 unsigned *p = (unsigned *) mt->data + mt->nbytes;
1501 mt->nbytes += nunits;
1508 @brief Create a copy of an M-text.
1510 The mtext_dup () function creates a copy of M-text $MT while
1511 inheriting all the text properties of $MT.
1514 This function returns a pointer to the created copy. */
1517 @brief M-text ¤Î¥³¥Ô¡¼¤òºî¤ë.
1519 ´Ø¿ô mtext_dup () ¤Ï¡¢M-text $MT ¤Î¥³¥Ô¡¼¤òºî¤ë¡£$MT ¤Î¥Æ¥¥¹¥È¥×
1520 ¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
1523 ¤³¤Î´Ø¿ô¤Ïºî¤é¤ì¤¿¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1525 @latexonly \IPAlabel{mtext_dup} @endlatexonly */
1529 mtext_duplicate () */
1532 mtext_dup (MText *mt)
1534 MText *new = mtext ();
1535 int unit_bytes = UNIT_BYTES (mt->format);
1540 new->allocated = (mt->nbytes + 1) * unit_bytes;
1541 MTABLE_MALLOC (new->data, new->allocated, MERROR_MTEXT);
1542 memcpy (new->data, mt->data, new->allocated);
1544 new->plist = mtext__copy_plist (mt->plist, 0, mt->nchars, new, 0);
1552 @brief Append an M-text to another.
1554 The mtext_cat () function appends M-text $MT2 to the end of M-text
1555 $MT1 while inheriting all the text properties. $MT2 itself is not
1559 This function returns a pointer to the resulting M-text $MT1. */
1562 @brief 2¸Ä¤Î M-text¤òÏ¢·ë¤¹¤ë.
1564 ´Ø¿ô mtext_cat () ¤Ï¡¢ M-text $MT2 ¤ò M-text $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨
1565 ¤ë¡£$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
1606 @brief M-text ¤Î°ìÉô¤òÊ̤ΠM-text ¤ËÉղ乤ë.
1608 ´Ø¿ô mtext_ncat () ¤Ï¡¢M-text $MT2 ¤Î¤Ï¤¸¤á¤Î $N ʸ»ú¤ò M-text
1609 $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì
1610 ¤ë¡£$MT2 ¤ÎŤµ¤¬ $N °Ê²¼¤Ê¤é¤Ð¡¢$MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤¬Éղ䵤ì¤ë¡£
1611 $MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1614 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncat () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý
1615 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1616 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1618 @latexonly \IPAlabel{mtext_ncat} @endlatexonly */
1625 mtext_cat (), mtext_cat_char () */
1628 mtext_ncat (MText *mt1, MText *mt2, int n)
1630 M_CHECK_READONLY (mt1, NULL);
1632 MERROR (MERROR_RANGE, NULL);
1633 if (mt2->nchars > 0)
1634 insert (mt1, mt1->nchars, mt2, 0, mt2->nchars < n ? mt2->nchars : n);
1642 @brief Copy an M-text to another.
1644 The mtext_cpy () function copies M-text $MT2 to M-text $MT1 while
1645 inheriting all the text properties. The old text in $MT1 is
1646 overwritten and the length of $MT1 is extended if necessary. $MT2
1650 This function returns a pointer to the resulting M-text $MT1. */
1653 @brief M-text ¤òÊ̤ΠM-text ¤Ë¥³¥Ô¡¼¤¹¤ë.
1655 ´Ø¿ô mtext_cpy () ¤Ï M-text $MT2 ¤ò M-text $MT1 ¤Ë¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£
1656 $MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 ¤ÎŤµ¤ÏɬÍפ˱þ
1657 ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1660 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1662 @latexonly \IPAlabel{mtext_cpy} @endlatexonly */
1666 mtext_ncpy (), mtext_copy () */
1669 mtext_cpy (MText *mt1, MText *mt2)
1671 M_CHECK_READONLY (mt1, NULL);
1672 mtext_del (mt1, 0, mt1->nchars);
1673 if (mt2->nchars > 0)
1674 insert (mt1, 0, mt2, 0, mt2->nchars);
1681 @brief Copy the first some characters in an M-text to another.
1683 The mtext_ncpy () function copies the first $N characters of
1684 M-text $MT2 to M-text $MT1 while inheriting all the text
1685 properties. If the length of $MT2 is less than $N, all characters
1686 of $MT2 are copied. The old text in $MT1 is overwritten and the
1687 length of $MT1 is extended if necessary. $MT2 is not modified.
1690 If the operation was successful, mtext_ncpy () returns a pointer
1691 to the resulting M-text $MT1. If an error is detected, it returns
1692 @c NULL and assigns an error code to the global variable
1696 @brief M-text ¤Ë´Þ¤Þ¤ì¤ëºÇ½é¤Î²¿Ê¸»ú¤«¤ò¥³¥Ô¡¼¤¹¤ë.
1698 ´Ø¿ô mtext_ncpy () ¤Ï¡¢M-text $MT2 ¤ÎºÇ½é¤Î $N ʸ»ú¤ò M-text $MT1
1699 ¤Ë¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
1700 ¤â¤· $MT2 ¤ÎŤµ¤¬ $N ¤è¤ê¤â¾®¤µ¤±¤ì¤Ð $MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ò¥³¥Ô¡¼
1701 ¤¹¤ë¡£$MT1 ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1704 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncpy () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý
1705 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1706 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1708 @latexonly \IPAlabel{mtext_ncpy} @endlatexonly */
1715 mtext_cpy (), mtext_copy () */
1718 mtext_ncpy (MText *mt1, MText *mt2, int n)
1720 M_CHECK_READONLY (mt1, NULL);
1722 MERROR (MERROR_RANGE, NULL);
1723 mtext_del (mt1, 0, mt1->nchars);
1724 if (mt2->nchars > 0)
1725 insert (mt1, 0, mt2, 0, mt2->nchars < n ? mt2->nchars : n);
1732 @brief Create a new M-text from a part of an existing M-text.
1734 The mtext_duplicate () function creates a copy of sub-text of
1735 M-text $MT, starting at $FROM (inclusive) and ending at $TO
1736 (exclusive) while inheriting all the text properties of $MT. $MT
1737 itself is not modified.
1740 If the operation was successful, mtext_duplicate () returns a
1741 pointer to the created M-text. If an error is detected, it returns 0
1742 and assigns an error code to the external variable #merror_code. */
1745 @brief ´û¸¤Î M-text ¤Î°ìÉô¤«¤é¿·¤·¤¤ M-text ¤ò¤Ä¤¯¤ë.
1747 ´Ø¿ô mtext_duplicate () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO
1748 ¡Ê´Þ¤Þ¤Ê¤¤¡Ë¤Þ¤Ç¤ÎÉôʬ¤Î¥³¥Ô¡¼¤òºî¤ë¡£¤³¤Î¤È¤ $MT ¤Î¥Æ¥¥¹¥È¥×¥í
1749 ¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1752 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_duplicate () ¤Ïºî¤é¤ì¤¿ M-text ¤Ø¤Î¥Ý¥¤¥ó
1753 ¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1754 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1756 @latexonly \IPAlabel{mtext_duplicate} @endlatexonly */
1766 mtext_duplicate (MText *mt, int from, int to)
1770 M_CHECK_RANGE_X (mt, from, to, NULL);
1772 new->format = mt->format;
1774 insert (new, 0, mt, from, to);
1781 @brief Copy characters in the specified range into an M-text.
1783 The mtext_copy () function copies the text between $FROM
1784 (inclusive) and $TO (exclusive) in M-text $MT2 to the region
1785 starting at $POS in M-text $MT1 while inheriting the text
1786 properties. The old text in $MT1 is overwritten and the length of
1787 $MT1 is extended if necessary. $MT2 is not modified.
1790 If the operation was successful, mtext_copy () returns a pointer
1791 to the modified $MT1. Otherwise, it returns @c NULL and assigns
1792 an error code to the external variable #merror_code. */
1795 @brief M-text ¤Ë»ØÄêÈϰϤÎʸ»ú¤ò¥³¥Ô¡¼¤¹¤ë.
1797 ´Ø¿ô mtext_copy () ¤Ï¡¢ M-text $MT2 ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO ¡Ê´Þ
1798 ¤Þ¤Ê¤¤¡Ë¤Þ¤Ç¤ÎÈϰϤΥƥ¥¹¥È¤ò M-text $MT1 ¤Î°ÌÃÖ $POS ¤«¤é¾å½ñ¤
1799 ¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 ¤ÎĹ
1800 ¤µ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1802 @latexonly \IPAlabel{mtext_copy} @endlatexonly
1805 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_copy () ¤ÏÊѹ¹¤µ¤ì¤¿ $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò
1806 ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼
1807 ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1814 mtext_cpy (), mtext_ncpy () */
1817 mtext_copy (MText *mt1, int pos, MText *mt2, int from, int to)
1819 M_CHECK_POS_X (mt1, pos, NULL);
1820 M_CHECK_READONLY (mt1, NULL);
1821 M_CHECK_RANGE_X (mt2, from, to, NULL);
1822 mtext_del (mt1, pos, mt1->nchars);
1823 return insert (mt1, pos, mt2, from, to);
1830 @brief Delete characters in the specified range destructively.
1832 The mtext_del () function deletes the characters in the range
1833 $FROM (inclusive) and $TO (exclusive) from M-text $MT
1834 destructively. As a result, the length of $MT shrinks by ($TO -
1838 If the operation was successful, mtext_del () returns 0.
1839 Otherwise, it returns -1 and assigns an error code to the external
1840 variable #merror_code. */
1843 @brief »ØÄêÈϰϤÎʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯.
1845 ´Ø¿ô mtext_del () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO ¡Ê´Þ¤Þ
1846 ¤Ê¤¤¡Ë¤Þ¤Ç¤Îʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯¡£·ë²ÌŪ¤Ë $MT ¤ÏŤµ¤¬ ($TO @c
1847 - $FROM) ¤À¤±½Ì¤à¤³¤È¤Ë¤Ê¤ë¡£
1850 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_del () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ
1851 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1861 mtext_del (MText *mt, int from, int to)
1863 int from_byte, to_byte;
1864 int unit_bytes = UNIT_BYTES (mt->format);
1866 M_CHECK_READONLY (mt, -1);
1867 M_CHECK_RANGE (mt, from, to, -1, 0);
1869 from_byte = POS_CHAR_TO_BYTE (mt, from);
1870 to_byte = POS_CHAR_TO_BYTE (mt, to);
1872 if (mt->cache_char_pos >= to)
1874 mt->cache_char_pos -= to - from;
1875 mt->cache_byte_pos -= to_byte - from_byte;
1877 else if (mt->cache_char_pos > from)
1879 mt->cache_char_pos -= from;
1880 mt->cache_byte_pos -= from_byte;
1883 mtext__adjust_plist_for_delete (mt, from, to - from);
1884 memmove (mt->data + from_byte * unit_bytes,
1885 mt->data + to_byte * unit_bytes,
1886 (mt->nbytes - to_byte + 1) * unit_bytes);
1887 mt->nchars -= (to - from);
1888 mt->nbytes -= (to_byte - from_byte);
1889 mt->cache_char_pos = from;
1890 mt->cache_byte_pos = from_byte;
1898 @brief Insert an M-text into another M-text.
1900 The mtext_ins () function inserts M-text $MT2 into M-text $MT1, at
1901 position $POS. As a result, $MT1 is lengthen by the length of
1902 $MT2. On insertion, all the text properties of $MT2 are
1903 inherited. The original $MT2 is not modified.
1906 If the operation was successful, mtext_ins () returns 0.
1907 Otherwise, it returns -1 and assigns an error code to the external
1908 variable #merror_code. */
1911 @brief M-text ¤òÊ̤ΠM-text ¤ËÁÞÆþ¤¹¤ë.
1913 ´Ø¿ô mtext_ins () ¤Ï M-text $MT1 ¤Î $POS ¤Î°ÌÃÖ¤Ë Ê̤ΠM-text $MT2
1914 ¤òÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $MT2 ¤ÎŤµÊ¬¤À¤±Áý¤¨¤ë¡£ÁÞÆþ¤Î
1915 ºÝ¡¢$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤½¤Î¤â¤Î¤ÏÊÑ
1919 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ
1920 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1930 mtext_ins (MText *mt1, int pos, MText *mt2)
1932 M_CHECK_READONLY (mt1, -1);
1933 M_CHECK_POS_X (mt1, pos, -1);
1935 if (mt2->nchars == 0)
1937 insert (mt1, pos, mt2, 0, mt2->nchars);
1945 @brief Insert a character into an M-text.
1947 The mtext_ins_char () function inserts $N copies of character $C
1948 into M-text $MT at position $POS. As a result, $MT is lengthen by
1952 If the operation was successful, mtext_ins () returns 0.
1953 Otherwise, it returns -1 and assigns an error code to the external
1954 variable #merror_code. */
1957 @brief M-text ¤Ëʸ»ú¤òÁÞÆþ¤¹¤ë.
1959 ´Ø¿ô mtext_ins_char () ¤Ï M-text $MT ¤Î $POS ¤Î°ÌÃÖ¤Ëʸ»ú $C ¤ò $N
1960 ¸ÄÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $N ¤À¤±Áý¤¨¤ë¡£
1963 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins_char () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1
1964 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1971 mtext_ins, mtext_del () */
1974 mtext_ins_char (MText *mt, int pos, int c, int n)
1977 int unit_bytes = UNIT_BYTES (mt->format);
1981 M_CHECK_READONLY (mt, -1);
1982 M_CHECK_POS_X (mt, pos, -1);
1983 if (c < 0 || c > MCHAR_MAX)
1984 MERROR (MERROR_MTEXT, -1);
1987 mtext__adjust_plist_for_insert (mt, pos, n, NULL);
1990 && (mt->format == MTEXT_FORMAT_US_ASCII
1991 || (c >= 0x10000 && (mt->format == MTEXT_FORMAT_UTF_16LE
1992 || mt->format == MTEXT_FORMAT_UTF_16BE))))
1994 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1997 else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
1999 if (mt->format != MTEXT_FORMAT_UTF_32)
2000 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_32);
2002 else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
2004 if (mt->format != MTEXT_FORMAT_UTF_16)
2005 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_16);
2008 nunits = CHAR_UNITS (c, mt->format);
2009 if ((mt->nbytes + nunits * n + 1) * unit_bytes > mt->allocated)
2011 mt->allocated = (mt->nbytes + nunits * n + 1) * unit_bytes;
2012 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
2014 pos_unit = POS_CHAR_TO_BYTE (mt, pos);
2015 if (mt->cache_char_pos > pos)
2017 mt->cache_char_pos += n;
2018 mt->cache_byte_pos += nunits + n;
2020 memmove (mt->data + (pos_unit + nunits * n) * unit_bytes,
2021 mt->data + pos_unit * unit_bytes,
2022 (mt->nbytes - pos_unit + 1) * unit_bytes);
2023 if (mt->format <= MTEXT_FORMAT_UTF_8)
2025 unsigned char *p = mt->data + pos_unit;
2027 for (i = 0; i < n; i++)
2028 p += CHAR_STRING_UTF8 (c, p);
2030 else if (mt->format == MTEXT_FORMAT_UTF_16)
2032 unsigned short *p = (unsigned short *) mt->data + pos_unit;
2034 for (i = 0; i < n; i++)
2035 p += CHAR_STRING_UTF16 (c, p);
2039 unsigned *p = (unsigned *) mt->data + pos_unit;
2041 for (i = 0; i < n; i++)
2045 mt->nbytes += nunits * n;
2052 @brief Search a character in an M-text.
2054 The mtext_character () function searches M-text $MT for character
2055 $C. If $FROM is less than $TO, the search begins at position $FROM
2056 and goes forward but does not exceed ($TO - 1). Otherwise, the search
2057 begins at position ($FROM - 1) and goes backward but does not
2058 exceed $TO. An invalid position specification is regarded as both
2059 $FROM and $TO being 0.
2062 If $C is found, mtext_character () returns the position of its
2063 first occurrence. Otherwise it returns -1 without changing the
2064 external variable #merror_code. If an error is detected, it returns -1 and
2065 assigns an error code to the external variable #merror_code. */
2068 @brief M-text Ãæ¤Çʸ»ú¤òõ¤¹.
2070 ´Ø¿ô mtext_character () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£¤â¤·
2071 $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ð¡¢Ãµº÷¤Ï°ÌÃÖ $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢ºÇÂç
2072 ($TO - 1) ¤Þ¤Ç¿Ê¤à¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð°ÌÃÖ ($FROM - 1) ¤«¤éÀèƬÊý¸þ¤Ø¡¢
2073 ºÇÂç $TO ¤Þ¤Ç¿Ê¤à¡£°ÌÃ֤λØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM ¤È $TO ¤Îξ
2074 Êý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
2077 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_character () ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2078 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code ¤òÊѹ¹¤»¤º¤Ë -1 ¤òÊÖ
2079 ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼
2080 ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
2084 mtext_chr(), mtext_rchr () */
2087 mtext_character (MText *mt, int from, int to, int c)
2091 /* We do not use M_CHECK_RANGE () because this function should
2092 not set merror_code. */
2093 if (from < 0 || to > mt->nchars)
2095 return find_char_forward (mt, from, to, c);
2100 if (to < 0 || from > mt->nchars)
2102 return find_char_backward (mt, to, from, c);
2110 @brief Return the position of the first occurrence of a character in an M-text.
2112 The mtext_chr () function searches M-text $MT for character $C.
2113 The search starts from the beginning of $MT and goes toward the end.
2116 If $C is found, mtext_chr () returns its position; otherwise it
2120 @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
2122 ´Ø¿ô mtext_chr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT ¤Î
2123 ÀèƬ¤«¤éËöÈøÊý¸þ¤Ë¿Ê¤à¡£
2126 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_chr () ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é
2127 ¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
2129 @latexonly \IPAlabel{mtext_chr} @endlatexonly */
2136 mtext_rchr (), mtext_character () */
2139 mtext_chr (MText *mt, int c)
2141 return find_char_forward (mt, 0, mt->nchars, c);
2147 @brief Return the position of the last occurrence of a character in an M-text.
2149 The mtext_rchr () function searches M-text $MT for character $C.
2150 The search starts from the end of $MT and goes backwardly toward the
2154 If $C is found, mtext_rchr () returns its position; otherwise it
2158 @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ¸å¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
2160 ´Ø¿ô mtext_rchr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT ¤Î
2161 ºÇ¸å¤«¤éÀèƬÊý¸þ¤Ø¤È¸å¸þ¤¤Ë¿Ê¤à¡£
2164 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_rchr () ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é
2165 ¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
2167 @latexonly \IPAlabel{mtext_rchr} @endlatexonly */
2174 mtext_chr (), mtext_character () */
2177 mtext_rchr (MText *mt, int c)
2179 return find_char_backward (mt, mt->nchars, 0, c);
2186 @brief Compare two M-texts character-by-character.
2188 The mtext_cmp () function compares M-texts $MT1 and $MT2 character
2192 This function returns 1, 0, or -1 if $MT1 is found greater than,
2193 equal to, or less than $MT2, respectively. Comparison is based on
2197 @brief Æó¤Ä¤Î M-text ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
2199 ´Ø¿ô mtext_cmp () ¤Ï¡¢ M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£
2202 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2203 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å
2206 @latexonly \IPAlabel{mtext_cmp} @endlatexonly */
2210 mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2211 mtext_compare (), mtext_case_compare () */
2214 mtext_cmp (MText *mt1, MText *mt2)
2216 return compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars);
2223 @brief Compare initial parts of two M-texts character-by-character.
2225 The mtext_ncmp () function is similar to mtext_cmp (), but
2226 compares at most $N characters from the beginning.
2229 This function returns 1, 0, or -1 if $MT1 is found greater than,
2230 equal to, or less than $MT2, respectively. */
2233 @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
2235 ´Ø¿ô mtext_ncmp () ¤Ï¡¢´Ø¿ô mtext_cmp () ƱÍͤΠM-text Ʊ»Î¤ÎÈæ³Ó
2236 ¤òÀèƬ¤«¤éºÇÂç $N ʸ»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
2239 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2240 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2242 @latexonly \IPAlabel{mtext_ncmp} @endlatexonly */
2246 mtext_cmp (), mtext_casecmp (), mtext_ncasecmp ()
2247 mtext_compare (), mtext_case_compare () */
2250 mtext_ncmp (MText *mt1, MText *mt2, int n)
2254 return compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n),
2255 mt2, 0, (mt2->nchars < n ? mt2->nchars : n));
2261 @brief Compare specified regions of two M-texts.
2263 The mtext_compare () function compares two M-texts $MT1 and $MT2,
2264 character-by-character. The compared regions are between $FROM1
2265 and $TO1 in $MT1 and $FROM2 to $TO2 in MT2. $FROM1 and $FROM2 are
2266 inclusive, $TO1 and $TO2 are exclusive. $FROM1 being equal to
2267 $TO1 (or $FROM2 being equal to $TO2) means an M-text of length
2268 zero. An invalid region specification is regarded as both $FROM1
2269 and $TO1 (or $FROM2 and $TO2) being 0.
2272 This function returns 1, 0, or -1 if $MT1 is found greater than,
2273 equal to, or less than $MT2, respectively. Comparison is based on
2277 @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿ÎΰèƱ»Î¤òÈæ³Ó¤¹¤ë.
2279 ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ
2280 ³Ó¤¹¤ë¡£Èæ³ÓÂоݤȤʤë¤Î¤Ï $MT1 ¤Ç¤Ï $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2
2281 ¤Ç¤Ï $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£$FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1
2282 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë
2283 ¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì
2284 ¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë ξÊý¤Ë 0 ¤¬»ØÄꤵ
2288 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2289 ¤Ð 1 ¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð
2294 mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2295 mtext_case_compare () */
2298 mtext_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
2300 if (from1 < 0 || from1 > to1 || to1 > mt1->nchars)
2303 if (from2 < 0 || from2 > to2 || to2 > mt2->nchars)
2306 return compare (mt1, from1, to1, mt2, from2, to2);
2312 @brief Search an M-text for a set of characters.
2314 The mtext_spn () function returns the length of the initial
2315 segment of M-text $MT1 that consists entirely of characters in
2319 @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2321 ´Ø¿ô mtext_spn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2 ¤Ë´Þ¤Þ
2322 ¤ì¤ëʸ»ú¤À¤±¤Ç¤Ç¤¤Æ¤¤¤ëÉôʬ¤ÎºÇÂ獵¤òÊÖ¤¹¡£
2324 @latexonly \IPAlabel{mtext_spn} @endlatexonly */
2331 mtext_spn (MText *mt, MText *accept)
2333 return span (mt, accept, 0, Mnil);
2339 @brief Search an M-text for the complement of a set of characters.
2341 The mtext_cspn () returns the length of the initial segment of
2342 M-text $MT1 that consists entirely of characters not in M-text $MT2. */
2345 @brief ¤¢¤ë½¸¹ç¤Ë°¤µ¤Ê¤¤Ê¸»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2347 ´Ø¿ô mtext_cspn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2 ¤Ë´Þ¤Þ
2348 ¤ì¤Ê¤¤Ê¸»ú¤À¤±¤Ç¤Ç¤¤Æ¤¤¤ëÉôʬ¤ÎºÇÂ獵¤òÊÖ¤¹¡£
2350 @latexonly \IPAlabel{mtext_cspn} @endlatexonly */
2357 mtext_cspn (MText *mt, MText *reject)
2359 return span (mt, reject, 0, Mt);
2365 @brief Search an M-text for any of a set of characters.
2367 The mtext_pbrk () function locates the first occurrence in M-text
2368 $MT1 of any of the characters in M-text $MT2.
2371 This function returns the position in $MT1 of the found character.
2372 If no such character is found, it returns -1. */
2375 @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤Î¤É¤ì¤«¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2377 ´Ø¿ô mtext_pbrk () ¤Ï¡¢M-text $MT1 Ãæ¤Ç M-text $MT2 ¤Î¤¤¤º¤ì¤«¤Îʸ
2378 »ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£
2381 ¸«¤Ä¤«¤Ã¤¿Ê¸»ú¤Î¡¢$MT1 Æâ¤Ë¤ª¤±¤ë½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¤â¤·¤½¤Î¤è¤¦¤Êʸ
2382 »ú¤¬¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2384 @latexonly \IPAlabel{mtext_pbrk} @endlatexonly */
2387 mtext_pbrk (MText *mt, MText *accept)
2389 int nchars = mtext_nchars (mt);
2390 int len = span (mt, accept, 0, Mt);
2392 return (len == nchars ? -1 : len);
2398 @brief Look for a token in an M-text.
2400 The mtext_tok () function searches a token that firstly occurs
2401 after position $POS in M-text $MT. Here, a token means a
2402 substring each of which does not appear in M-text $DELIM. Note
2403 that the type of $POS is not @c int but pointer to @c int.
2406 If a token is found, mtext_tok () copies the corresponding part of
2407 $MT and returns a pointer to the copy. In this case, $POS is set
2408 to the end of the found token. If no token is found, it returns
2409 @c NULL without changing the external variable #merror_code. If an
2410 error is detected, it returns @c NULL and assigns an error code
2411 to the external variable #merror_code. */
2414 @brief M-text Ãæ¤Î¥È¡¼¥¯¥ó¤òõ¤¹.
2416 ´Ø¿ô mtext_tok () ¤Ï¡¢M-text $MT ¤ÎÃæ¤Ç°ÌÃÖ $POS °Ê¹ßºÇ½é¤Ë¸½¤ì¤ë
2417 ¥È¡¼¥¯¥ó¤òõ¤¹¡£¤³¤³¤Ç¥È¡¼¥¯¥ó¤È¤Ï M-text $DELIM ¤ÎÃæ¤Ë¸½¤ï¤ì¤Ê¤¤
2418 ʸ»ú¤À¤±¤«¤é¤Ê¤ëÉôʬʸ»úÎó¤Ç¤¢¤ë¡£$POS ¤Î·¿¤¬ @c int ¤Ç¤Ï¤Ê¤¯¤Æ @c
2419 int ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤³¤È¤ËÃí°Õ¡£
2422 ¤â¤·¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤ì¤Ð mtext_tok ()¤Ï¤½¤Î¥È¡¼¥¯¥ó¤ËÁêÅö¤¹¤ëÉôʬ
2423 ¤Î $MT ¤ò¥³¥Ô¡¼¤·¡¢¤½¤Î¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢$POS ¤Ï
2424 ¸«¤Ä¤«¤Ã¤¿¥È¡¼¥¯¥ó¤Î½ªÃ¼¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿
2425 ¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code ¤òÊѤ¨¤º¤Ë @c NULL ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
2426 ¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢ÊÑÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤ò
2429 @latexonly \IPAlabel{mtext_tok} @endlatexonly */
2436 mtext_tok (MText *mt, MText *delim, int *pos)
2438 int nchars = mtext_nchars (mt);
2441 M_CHECK_POS (mt, *pos, NULL);
2444 Skip delimiters starting at POS in MT.
2445 Never do *pos += span(...), or you will change *pos
2446 even though no token is found.
2448 pos2 = *pos + span (mt, delim, *pos, Mnil);
2453 *pos = pos2 + span (mt, delim, pos2, Mt);
2454 return (insert (mtext (), 0, mt, pos2, *pos));
2460 @brief Locate an M-text in another.
2462 The mtext_text () function finds the first occurrence of M-text
2463 $MT2 in M-text $MT1 after the position $POS while ignoring
2464 difference of the text properties.
2467 If $MT2 is found in $MT1, mtext_text () returns the position of it
2468 first occurrence. Otherwise it returns -1. If $MT2 is empty, it
2472 @brief M-text Ãæ¤ÇÊ̤ΠM-text ¤òõ¤¹.
2474 ´Ø¿ô mtext_text () ¤Ï¡¢M-text $MT1 Ãæ¤Ç°ÌÃÖ $POS °Ê¹ß¤Ë¸½¤ï¤ì¤ë
2475 M-text $MT2 ¤ÎºÇ½é¤Î°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î°ã¤¤¤Ï̵»ë¤µ
2479 $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_text() ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2480 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
2482 @latexonly \IPAlabel{mtext_text} @endlatexonly */
2485 mtext_text (MText *mt1, int pos, MText *mt2)
2488 int pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
2489 int c = mtext_ref_char (mt2, 0);
2490 int nbytes1 = mtext_nbytes (mt1);
2491 int nbytes2 = mtext_nbytes (mt2);
2493 int use_memcmp = (mt1->format == mt2->format
2494 || (mt1->format < MTEXT_FORMAT_UTF_8
2495 && mt2->format == MTEXT_FORMAT_UTF_8));
2496 int unit_bytes = UNIT_BYTES (mt1->format);
2498 if (nbytes2 > pos_byte + nbytes1)
2500 pos_byte = nbytes1 - nbytes2;
2501 limit = POS_BYTE_TO_CHAR (mt1, pos_byte);
2505 if ((pos = mtext_character (mt1, from, limit, c)) < 0)
2507 pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
2509 ? ! memcmp (mt1->data + pos_byte * unit_bytes,
2510 mt2->data, nbytes2 * unit_bytes)
2511 : ! compare (mt1, pos, mt2->nchars, mt2, 0, mt2->nchars))
2519 @brief Locate an M-text in a specific range of another.
2521 The mtext_search () function searches for the first occurrence of
2522 M-text $MT2 in M-text $MT1 in the region $FROM and $TO while
2523 ignoring difference of the text properties. If $FROM is less than
2524 $TO, the forward search starts from $FROM, otherwise the backward
2525 search starts from $TO.
2528 If $MT2 is found in $MT1, mtext_search () returns the position of the
2529 first occurrence. Otherwise it returns -1. If $MT2 is empty, it
2533 @brief M-text Ãæ¤ÎÆÃÄê¤ÎÎΰè¤ÇÊ̤ΠM-text ¤òõ¤¹.
2535 ´Ø¿ô mtext_search () ¤Ï¡¢M-text $MT1 Ãæ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î´Ö¤Î
2536 Îΰè¤ÇM-text $MT2 ¤¬ºÇ½é¤Ë¸½¤ï¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£
2537 ¤Î°ã¤¤¤Ï̵»ë¤µ¤ì¤ë¡£¤â¤· $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ðõº÷¤Ï°ÌÃÖ
2538 $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð $TO ¤«¤éÀèƬÊý¸þ¤ØºÇÂç $TO ¤Þ
2542 $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_search() ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2543 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
2547 mtext_search (MText *mt1, int from, int to, MText *mt2)
2549 int c = mtext_ref_char (mt2, 0);
2551 int nbytes2 = mtext_nbytes (mt2);
2553 if (mt1->format > MTEXT_FORMAT_UTF_8
2554 || mt2->format > MTEXT_FORMAT_UTF_8)
2555 MERROR (MERROR_MTEXT, -1);
2559 to -= mtext_nchars (mt2);
2564 if ((from = find_char_forward (mt1, from, to, c)) < 0)
2566 from_byte = POS_CHAR_TO_BYTE (mt1, from);
2567 if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
2574 from -= mtext_nchars (mt2);
2579 if ((from = find_char_backward (mt1, from, to, c)) < 0)
2581 from_byte = POS_CHAR_TO_BYTE (mt1, from);
2582 if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
2594 @brief Compare two M-texts ignoring cases.
2596 The mtext_casecmp () function is similar to mtext_cmp (), but
2597 ignores cases on comparison.
2600 This function returns 1, 0, or -1 if $MT1 is found greater than,
2601 equal to, or less than $MT2, respectively. */
2604 @brief Æó¤Ä¤Î M-text ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2606 ´Ø¿ô mtext_casecmp () ¤Ï¡¢´Ø¿ô mtext_cmp () ƱÍͤΠM-text Ʊ»Î¤ÎÈæ
2607 ³Ó¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æ¹Ô¤Ê¤¦¡£
2610 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2611 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2613 @latexonly \IPAlabel{mtext_casecmp} @endlatexonly */
2617 mtext_cmp (), mtext_ncmp (), mtext_ncasecmp ()
2618 mtext_compare (), mtext_case_compare () */
2621 mtext_casecmp (MText *mt1, MText *mt2)
2623 return case_compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars);
2629 @brief Compare initial parts of two M-texts ignoring cases.
2631 The mtext_ncasecmp () function is similar to mtext_casecmp (), but
2632 compares at most $N characters from the beginning.
2635 This function returns 1, 0, or -1 if $MT1 is found greater than,
2636 equal to, or less than $MT2, respectively. */
2639 @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2641 ´Ø¿ô mtext_ncasecmp () ¤Ï¡¢´Ø¿ô mtext_casecmp () ƱÍͤΠM-text Ʊ
2642 »Î¤ÎÈæ³Ó¤òÀèƬ¤«¤éºÇÂç $N ʸ»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
2645 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2646 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2648 @latexonly \IPAlabel{mtext_ncasecmp} @endlatexonly */
2652 mtext_cmp (), mtext_casecmp (), mtext_casecmp ()
2653 mtext_compare (), mtext_case_compare () */
2656 mtext_ncasecmp (MText *mt1, MText *mt2, int n)
2660 return case_compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n),
2661 mt2, 0, (mt2->nchars < n ? mt2->nchars : n));
2667 @brief Compare specified regions of two M-texts ignoring cases.
2669 The mtext_case_compare () function compares two M-texts $MT1 and
2670 $MT2, character-by-character, ignoring cases. The compared
2671 regions are between $FROM1 and $TO1 in $MT1 and $FROM2 to $TO2 in
2672 MT2. $FROM1 and $FROM2 are inclusive, $TO1 and $TO2 are
2673 exclusive. $FROM1 being equal to $TO1 (or $FROM2 being equal to
2674 $TO2) means an M-text of length zero. An invalid region
2675 specification is regarded as both $FROM1 and $TO1 (or $FROM2 and
2679 This function returns 1, 0, or -1 if $MT1 is found greater than,
2680 equal to, or less than $MT2, respectively. Comparison is based on
2684 @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿Îΰè¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2686 ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 ¤ò¡¢Âçʸ»ú¡¿¾®
2687 ʸ»ú¤Î¶èÊ̤ò̵»ë¤·¤Æʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£Èæ³ÓÂоݤȤʤë¤Î¤Ï $MT1
2688 ¤Ç¤Ï $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2 ¤Ç¤Ï $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£
2689 $FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È
2690 $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text
2691 ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï
2692 $FROM2 ¤È $TO2 ¡ËξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
2695 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2696 ¤Ð1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð-1¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£
2698 @latexonly \IPAlabel{mtext_case_compare} @endlatexonly
2703 mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2707 mtext_case_compare (MText *mt1, int from1, int to1,
2708 MText *mt2, int from2, int to2)
2710 if (from1 < 0 || from1 > to1 || to1 > mt1->nchars)
2713 if (from2 < 0 || from2 > to2 || to2 > mt2->nchars)
2716 return case_compare (mt1, from1, to1, mt2, from2, to2);
2723 /*** @addtogroup m17nDebug */
2728 @brief Dump an M-text.
2730 The mdebug_dump_mtext () function prints the M-text $MT in a human
2731 readable way to the stderr. $INDENT specifies how many columns to
2732 indent the lines but the first one. If $FULLP is zero, this
2733 function prints only a character code sequence. Otherwise, it
2734 prints the internal byte sequence and text properties as well.
2737 This function returns $MT. */
2739 @brief M-text ¤ò¥À¥ó¥×¤¹¤ë.
2741 ´Ø¿ô mdebug_dump_mtext () ¤Ï M-text $MT ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
2742 ·Á¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£$FULLP
2743 ¤¬ 0 ¤Ê¤é¤Ð¡¢Ê¸»ú¥³¡¼¥ÉÎó¤À¤±¤ò°õºþ¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢ÆâÉô¥Ð¥¤
2744 ¥ÈÎó¤È¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤â°õºþ¤¹¤ë¡£
2747 ¤³¤Î´Ø¿ô¤Ï $MT ¤òÊÖ¤¹¡£ */
2750 mdebug_dump_mtext (MText *mt, int indent, int fullp)
2752 char *prefix = (char *) alloca (indent + 1);
2756 memset (prefix, 32, indent);
2760 "(mtext (size %d %d %d) (cache %d %d)",
2761 mt->nchars, mt->nbytes, mt->allocated,
2762 mt->cache_char_pos, mt->cache_byte_pos);
2765 fprintf (stderr, " \"");
2766 for (i = 0; i < mt->nchars; i++)
2768 int c = mtext_ref_char (mt, i);
2769 if (c >= ' ' && c < 127)
2770 fprintf (stderr, "%c", c);
2772 fprintf (stderr, "\\x%02X", c);
2774 fprintf (stderr, "\"");
2776 else if (mt->nchars > 0)
2778 fprintf (stderr, "\n%s (bytes \"", prefix);
2779 for (i = 0; i < mt->nbytes; i++)
2780 fprintf (stderr, "\\x%02x", mt->data[i]);
2781 fprintf (stderr, "\")\n");
2782 fprintf (stderr, "%s (chars \"", prefix);
2784 for (i = 0; i < mt->nchars; i++)
2787 int c = STRING_CHAR_AND_BYTES (p, len);
2789 if (c >= ' ' && c < 127 && c != '\\' && c != '\"')
2792 fprintf (stderr, "\\x%X", c);
2795 fprintf (stderr, "\")");
2798 fprintf (stderr, "\n%s ", prefix);
2799 dump_textplist (mt->plist, indent + 1);
2802 fprintf (stderr, ")");