1 /* mtext.c -- M-text module.
2 Copyright (C) 2003, 2004
3 National Institute of Advanced Industrial Science and Technology (AIST)
4 Registration Number H15PRO112
6 This file is part of the m17n library.
8 The m17n library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public License
10 as published by the Free Software Foundation; either version 2.1 of
11 the License, or (at your option) any later version.
13 The m17n library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with the m17n library; if not, write to the Free
20 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 @brief M-text objects and API for them.
27 In the m17n library, text is represented as an object called @e
28 M-text rather than as a C-string (<tt>char *</tt> or <tt>unsigned
29 char *</tt>). An M-text is a sequence of characters whose length
30 is equals to or more than 0, and can be coined from various
31 character sources, e.g. C-strings, files, character codes, etc.
33 M-texts are more useful than C-strings in the following points.
35 @li M-texts can handle mixture of characters of various scripts,
36 including all Unicode characters and more. This is an
37 indispensable facility when handling multilingual text.
39 @li Each character in an M-text can have properties called @e text
40 @e properties. Text properties store various kinds of information
41 attached to parts of an M-text to provide application programs
42 with a unified view of those information. As rich information can
43 be stored in M-texts in the form of text properties, functions in
44 application programs can be simple.
46 In addition, the library provides many functions to manipulate an
47 M-text just the same way as a C-string. */
52 @brief M-text ¥ª¥Ö¥¸¥§¥¯¥È¤È¤½¤ì¤Ë´Ø¤¹¤ë API.
54 m17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢ C-string¡Ê<tt>char *</tt> ¤ä <tt>unsigned
55 char *</tt>¡Ë¤Ç¤Ï¤Ê¤¯ @e M-text ¤È¸Æ¤Ö¥ª¥Ö¥¸¥§¥¯¥È¤Ç¥Æ¥¥¹¥È¤òɽ¸½¤¹¤ë¡£
56 M-text ¤ÏŤµ 0 °Ê¾å¤Îʸ»úÎó¤Ç¤¢¤ê¡¢¼ï¡¹¤Îʸ»ú¥½¡¼¥¹¡Ê¤¿¤È¤¨¤Ð
57 C-string¡¢¥Õ¥¡¥¤¥ë¡¢Ê¸»ú¥³¡¼¥ÉÅù¡Ë¤«¤éºîÀ®¤Ç¤¤ë¡£
59 M-text ¤Ë¤Ï¡¢C-string ¤Ë¤Ê¤¤°Ê²¼¤ÎÆÃħ¤¬¤¢¤ë¡£
61 @li M-text ¤ÏÈó¾ï¤Ë¿¤¯¤Î¼ïÎà¤Îʸ»ú¤ò¡¢Æ±»þ¤Ë¡¢º®ºß¤µ¤»¤Æ¡¢Æ±Åù¤Ë
62 °·¤¦¤³¤È¤¬¤Ç¤¤ë¡£Unicode ¤ÎÁ´¤Æ¤Îʸ»ú¤Ï¤â¤Á¤í¤ó¡¢¤è¤ê¿¤¯¤Îʸ»ú¤Þ
63 ¤Ç°·¤¨¤ë¡£¤³¤ì¤Ï¿¸À¸ì¥Æ¥¥¹¥È¤ò°·¤¦¾å¤Ç¤Ïɬ¿Ü¤Îµ¡Ç½¤Ç¤¢¤ë¡£
65 @li M-text Æâ¤Î³Æʸ»ú¤Ï¡¢@e ¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£ ¤È¸Æ¤Ð¤ì¤ë¥×¥í¥Ñ¥Æ¥£
66 ¤ò»ý¤Ä¤³¤È¤¬¤Ç¤¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ë¤è¤Ã¤Æ¡¢¥Æ¥¥¹¥È¤Î³ÆÉô°Ì¤Ë
67 ´Ø¤¹¤ëÍÍ¡¹¤Ê¾ðÊó¤ò M-text Æâ¤ËÊÝ»ý¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£¤½¤Î¤¿¤á¡¢¤½¤ì
68 ¤é¤Î¾ðÊó¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥àÆâ¤ÇÅý°ìŪ¤Ë°·¤¦¤³¤È¤¬¤Ç¤¤ë¡£
69 ¤Þ¤¿¡¢M-text ¼«ÂΤ¬ËÉ٤ʾðÊó¤ò»ý¤Ä¤¿¤á¡¢¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é
70 ¥àÃæ¤Î³Æ´Ø¿ô¤ò´ÊÁDz½¤¹¤ë¤³¤È¤¬¤Ç¤¤ë¡£
72 ¤µ¤é¤Ëm17n ¥é¥¤¥Ö¥é¥ê¤Ï¡¢ C-string ¤òÁàºî¤¹¤ë¤¿¤á¤ËÄ󶡤µ¤ì¤ë¼ï¡¹
73 ¤Î´Ø¿ô¤ÈƱÅù¤Î¤â¤Î¤ò M-text ¤òÁàºî¤¹¤ë¤¿¤á¤Ë¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤ë¡£ */
77 #if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
78 /*** @addtogroup m17nInternal
88 #include "m17n-misc.h"
91 #include "character.h"
95 static M17NObjectArray mtext_table;
97 static MSymbol M_charbag;
99 #ifdef WORDS_BIGENDIAN
100 static enum MTextFormat default_utf_16 = MTEXT_FORMAT_UTF_16BE;
101 static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32BE;
103 static enum MTextFormat default_utf_16 = MTEXT_FORMAT_UTF_16LE;
104 static enum MTextFormat default_utf_32 = MTEXT_FORMAT_UTF_32LE;
107 /** Increment character position CHAR_POS and unit position UNIT_POS
108 so that they point to the next character in M-text MT. No range
109 check for CHAR_POS and UNIT_POS. */
111 #define INC_POSITION(mt, char_pos, unit_pos) \
115 if ((mt)->format <= MTEXT_FORMAT_UTF_8) \
117 c = (mt)->data[(unit_pos)]; \
118 (unit_pos) += CHAR_UNITS_BY_HEAD_UTF8 (c); \
120 else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \
122 c = ((unsigned short *) ((mt)->data))[(unit_pos)]; \
124 if ((mt)->format != default_utf_16) \
126 (unit_pos) += CHAR_UNITS_BY_HEAD_UTF16 (c); \
134 /** Decrement character position CHAR_POS and unit position UNIT_POS
135 so that they point to the previous character in M-text MT. No
136 range check for CHAR_POS and UNIT_POS. */
138 #define DEC_POSITION(mt, char_pos, unit_pos) \
140 if ((mt)->format <= MTEXT_FORMAT_UTF_8) \
142 unsigned char *p1 = (mt)->data + (unit_pos); \
143 unsigned char *p0 = p1 - 1; \
145 while (! CHAR_HEAD_P (p0)) p0--; \
146 (unit_pos) -= (p1 - p0); \
148 else if ((mt)->format <= MTEXT_FORMAT_UTF_16BE) \
150 int c = ((unsigned short *) ((mt)->data))[(unit_pos) - 1]; \
152 if ((mt)->format != default_utf_16) \
154 (unit_pos) -= 2 - (c < 0xD800 || c >= 0xE000); \
162 /* Compoare sub-texts in MT1 (range FROM1 and TO1) and MT2 (range
166 compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
168 if (mt1->format == mt2->format
169 && (mt1->format <= MTEXT_FORMAT_UTF_8))
171 unsigned char *p1, *pend1, *p2, *pend2;
172 int unit_bytes = UNIT_BYTES (mt1->format);
176 p1 = mt1->data + mtext__char_to_byte (mt1, from1) * unit_bytes;
177 pend1 = mt1->data + mtext__char_to_byte (mt1, to1) * unit_bytes;
179 p2 = mt2->data + mtext__char_to_byte (mt2, from2) * unit_bytes;
180 pend2 = mt2->data + mtext__char_to_byte (mt2, to2) * unit_bytes;
182 if (pend1 - p1 < pend2 - p2)
186 result = memcmp (p1, p2, nbytes);
189 return ((pend1 - p1) - (pend2 - p2));
191 for (; from1 < to1 && from2 < to2; from1++, from2++)
193 int c1 = mtext_ref_char (mt1, from1);
194 int c2 = mtext_ref_char (mt2, from2);
197 return (c1 > c2 ? 1 : -1);
199 return (from2 == to2 ? (from1 < to1) : -1);
203 /* Return how many units are required in UTF-8 to represent characters
204 between FROM and TO of MT. */
207 count_by_utf_8 (MText *mt, int from, int to)
211 for (n = 0; from < to; from++)
213 c = mtext_ref_char (mt, from);
214 n += CHAR_UNITS_UTF8 (c);
220 /* Return how many units are required in UTF-16 to represent
221 characters between FROM and TO of MT. */
224 count_by_utf_16 (MText *mt, int from, int to)
228 for (n = 0; from < to; from++)
230 c = mtext_ref_char (mt, from);
231 n += CHAR_UNITS_UTF16 (c);
237 /* Insert text between FROM and TO of MT2 at POS of MT1. */
240 insert (MText *mt1, int pos, MText *mt2, int from, int to)
242 int pos_unit = POS_CHAR_TO_BYTE (mt1, pos);
243 int from_unit = POS_CHAR_TO_BYTE (mt2, from);
244 int new_units = POS_CHAR_TO_BYTE (mt2, to) - from_unit;
247 if (mt1->nchars == 0)
248 mt1->format = mt2->format;
249 else if (mt1->format != mt2->format)
251 /* Be sure to make mt1->format sufficient to contain all
252 characters in mt2. */
253 if (mt1->format == MTEXT_FORMAT_UTF_8
254 || mt1->format == default_utf_32
255 || (mt1->format == default_utf_16
256 && mt2->format <= MTEXT_FORMAT_UTF_16BE
257 && mt2->format != MTEXT_FORMAT_UTF_8))
259 else if (mt1->format == MTEXT_FORMAT_US_ASCII)
261 if (mt2->format == MTEXT_FORMAT_UTF_8)
262 mt1->format = MTEXT_FORMAT_UTF_8;
263 else if (mt2->format == default_utf_16
264 || mt2->format == default_utf_32)
265 mtext__adjust_format (mt1, mt2->format);
267 mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
271 mtext__adjust_format (mt1, MTEXT_FORMAT_UTF_8);
272 pos_unit = POS_CHAR_TO_BYTE (mt1, pos);
276 unit_bytes = UNIT_BYTES (mt1->format);
278 if (mt1->format == mt2->format)
280 int pos_byte = pos_unit * unit_bytes;
281 int total_bytes = (mt1->nbytes + new_units) * unit_bytes;
282 int new_bytes = new_units * unit_bytes;
284 if (total_bytes + unit_bytes > mt1->allocated)
286 mt1->allocated = total_bytes + unit_bytes;
287 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
289 if (pos < mt1->nchars)
290 memmove (mt1->data + pos_byte + new_bytes, mt1->data + pos_byte,
291 (mt1->nbytes - pos_unit + 1) * unit_bytes);
292 memcpy (mt1->data + pos_byte, mt2->data + from_unit * unit_bytes,
295 else if (mt1->format == MTEXT_FORMAT_UTF_8)
298 int total_bytes, i, c;
300 new_units = count_by_utf_8 (mt2, from, to);
301 total_bytes = mt1->nbytes + new_units;
303 if (total_bytes + 1 > mt1->allocated)
305 mt1->allocated = total_bytes + 1;
306 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
308 p = mt1->data + pos_unit;
309 memmove (p + new_units, p, mt1->nbytes - pos_unit + 1);
310 for (i = from; i < to; i++)
312 c = mtext_ref_char (mt2, i);
313 p += CHAR_STRING_UTF8 (c, p);
316 else if (mt1->format == default_utf_16)
319 int total_bytes, i, c;
321 new_units = count_by_utf_16 (mt2, from, to);
322 total_bytes = (mt1->nbytes + new_units) * USHORT_SIZE;
324 if (total_bytes + USHORT_SIZE > mt1->allocated)
326 mt1->allocated = total_bytes + USHORT_SIZE;
327 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
329 p = (unsigned short *) mt1->data + pos_unit;
330 memmove (p + new_units, p,
331 (mt1->nbytes - pos_unit + 1) * USHORT_SIZE);
332 for (i = from; i < to; i++)
334 c = mtext_ref_char (mt2, i);
335 p += CHAR_STRING_UTF16 (c, p);
338 else /* default_utf_32 */
343 new_units = to - from;
344 total_bytes = (mt1->nbytes + new_units) * UINT_SIZE;
346 if (total_bytes + UINT_SIZE > mt1->allocated)
348 mt1->allocated = total_bytes + UINT_SIZE;
349 MTABLE_REALLOC (mt1->data, mt1->allocated, MERROR_MTEXT);
351 p = (unsigned *) mt1->data + pos_unit;
352 memmove (p + new_units, p,
353 (mt1->nbytes - pos_unit + 1) * UINT_SIZE);
354 for (i = from; i < to; i++)
355 *p++ = mtext_ref_char (mt2, i);
358 mtext__adjust_plist_for_insert
359 (mt1, pos, to - from,
360 mtext__copy_plist (mt2->plist, from, to, mt1, pos));
361 mt1->nchars += to - from;
362 mt1->nbytes += new_units;
363 if (mt1->cache_char_pos > pos)
365 mt1->cache_char_pos += to - from;
366 mt1->cache_byte_pos += new_units;
374 get_charbag (MText *mt)
376 MTextProperty *prop = mtext_get_property (mt, 0, M_charbag);
382 if (prop->end == mt->nchars)
383 return ((MCharTable *) prop->val);
384 mtext_detach_property (prop);
387 table = mchartable (Msymbol, (void *) 0);
388 for (i = mt->nchars - 1; i >= 0; i--)
389 mchartable_set (table, mtext_ref_char (mt, i), Mt);
390 prop = mtext_property (M_charbag, table, MTEXTPROP_VOLATILE_WEAK);
391 mtext_attach_property (mt, 0, mtext_nchars (mt), prop);
392 M17N_OBJECT_UNREF (prop);
397 /* span () : Number of consecutive chars starting at POS in MT1 that
398 are included (if NOT is Mnil) or not included (if NOT is Mt) in
402 span (MText *mt1, MText *mt2, int pos, MSymbol not)
404 int nchars = mtext_nchars (mt1);
405 MCharTable *table = get_charbag (mt2);
408 for (i = pos; i < nchars; i++)
409 if ((MSymbol) mchartable_lookup (table, mtext_ref_char (mt1, i)) == not)
416 count_utf_8_chars (const void *data, int nitems)
418 unsigned char *p = (unsigned char *) data;
419 unsigned char *pend = p + nitems;
426 for (; p < pend && *p < 128; nchars++, p++);
429 if (! CHAR_HEAD_P_UTF8 (p))
431 n = CHAR_UNITS_BY_HEAD_UTF8 (*p);
434 for (i = 1; i < n; i++)
435 if (CHAR_HEAD_P_UTF8 (p + i))
444 count_utf_16_chars (const void *data, int nitems, int swap)
446 unsigned short *p = (unsigned short *) data;
447 unsigned short *pend = p + nitems;
449 int prev_surrogate = 0;
451 for (; p < pend; p++)
459 if (c < 0xDC00 || c >= 0xE000)
481 find_char_forward (MText *mt, int from, int to, int c)
483 int from_byte = POS_CHAR_TO_BYTE (mt, from);
485 if (mt->format <= MTEXT_FORMAT_UTF_8)
487 unsigned char *p = mt->data + from_byte;
489 while (from < to && STRING_CHAR_ADVANCE_UTF8 (p) != c) from++;
491 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
493 unsigned short *p = (unsigned short *) (mt->data) + from_byte;
495 if (mt->format == default_utf_16)
496 while (from < to && STRING_CHAR_ADVANCE_UTF16 (p) != c) from++;
497 else if (c < 0x10000)
500 while (from < to && *p != c)
503 p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2;
506 else if (c < 0x110000)
508 int c1 = (c >> 10) + 0xD800;
509 int c2 = (c & 0x3FF) + 0xDC00;
513 while (from < to && (*p != c1 || p[1] != c2))
516 p += ((*p & 0xFF) < 0xD8 || (*p & 0xFF) >= 0xE0) ? 1 : 2;
524 unsigned *p = (unsigned *) (mt->data) + from_byte;
527 if (mt->format != default_utf_32)
529 while (from < to && *p++ != c1) from++;
532 return (from < to ? from : -1);
537 find_char_backward (MText *mt, int from, int to, int c)
539 int to_byte = POS_CHAR_TO_BYTE (mt, to);
541 if (mt->format <= MTEXT_FORMAT_UTF_8)
543 unsigned char *p = mt->data + to_byte;
547 for (p--; ! CHAR_HEAD_P (p); p--);
548 if (c == STRING_CHAR (p))
553 else if (mt->format <= MTEXT_FORMAT_UTF_16LE)
555 unsigned short *p = (unsigned short *) (mt->data) + to_byte;
557 if (mt->format == default_utf_16)
562 if (*p >= 0xDC00 && *p < 0xE000)
564 if (c == STRING_CHAR_UTF16 (p))
569 else if (c < 0x10000)
572 while (from < to && p[-1] != c)
575 p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2;
578 else if (c < 0x110000)
580 int c1 = (c >> 10) + 0xD800;
581 int c2 = (c & 0x3FF) + 0xDC00;
585 while (from < to && (p[-1] != c2 || p[-2] != c1))
588 p -= ((p[-1] & 0xFF) < 0xD8 || (p[-1] & 0xFF) >= 0xE0) ? 1 : 2;
594 unsigned *p = (unsigned *) (mt->data) + to_byte;
597 if (mt->format != default_utf_32)
599 while (from < to && p[-1] != c1) to--, p--;
602 return (from < to ? to - 1 : -1);
607 free_mtext (void *object)
609 MText *mt = (MText *) object;
612 mtext__free_plist (mt);
613 if (mt->data && mt->allocated >= 0)
615 M17N_OBJECT_UNREGISTER (mtext_table, mt);
619 /** Structure for an iterator used in case-fold comparison. */
621 struct casecmp_iterator {
625 unsigned char *foldedp;
630 next_char_from_it (struct casecmp_iterator *it)
636 c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len);
640 c = mtext_ref_char (it->mt, it->pos);
641 c1 = (int) mchar_get_prop (c, Msimple_case_folding);
645 = (MText *) mchar_get_prop (c, Mcomplicated_case_folding);
646 it->foldedp = it->folded->data;
647 c = STRING_CHAR_AND_BYTES (it->foldedp, it->folded_len);
657 advance_it (struct casecmp_iterator *it)
661 it->foldedp += it->folded_len;
662 if (it->foldedp == it->folded->data + it->folded->nbytes)
672 case_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
674 struct casecmp_iterator it1, it2;
676 it1.mt = mt1, it1.pos = from1, it1.folded = NULL;
677 it2.mt = mt2, it2.pos = from2, it2.folded = NULL;
679 while (it1.pos < to1 && it2.pos < to2)
681 int c1 = next_char_from_it (&it1);
682 int c2 = next_char_from_it (&it2);
685 return (c1 > c2 ? 1 : -1);
689 return (it2.pos == to2 ? (it1.pos < to1) : -1);
698 M_charbag = msymbol_as_managing_key (" charbag");
699 mtext_table.count = 0;
707 mdebug__report_object ("M-text", &mtext_table);
712 mtext__char_to_byte (MText *mt, int pos)
714 int char_pos, byte_pos;
717 if (pos < mt->cache_char_pos)
719 if (mt->cache_char_pos == mt->cache_byte_pos)
721 if (pos < mt->cache_char_pos - pos)
723 char_pos = byte_pos = 0;
728 char_pos = mt->cache_char_pos;
729 byte_pos = mt->cache_byte_pos;
735 if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos)
736 return (mt->cache_byte_pos + (pos - mt->cache_char_pos));
737 if (pos - mt->cache_char_pos < mt->nchars - pos)
739 char_pos = mt->cache_char_pos;
740 byte_pos = mt->cache_byte_pos;
745 char_pos = mt->nchars;
746 byte_pos = mt->nbytes;
751 while (char_pos < pos)
752 INC_POSITION (mt, char_pos, byte_pos);
754 while (char_pos > pos)
755 DEC_POSITION (mt, char_pos, byte_pos);
756 mt->cache_char_pos = char_pos;
757 mt->cache_byte_pos = byte_pos;
761 /* mtext__byte_to_char () */
764 mtext__byte_to_char (MText *mt, int pos_byte)
766 int char_pos, byte_pos;
769 if (pos_byte < mt->cache_byte_pos)
771 if (mt->cache_char_pos == mt->cache_byte_pos)
773 if (pos_byte < mt->cache_byte_pos - pos_byte)
775 char_pos = byte_pos = 0;
780 char_pos = mt->cache_char_pos;
781 byte_pos = mt->cache_byte_pos;
787 if (mt->nchars - mt->cache_char_pos == mt->nbytes - mt->cache_byte_pos)
788 return (mt->cache_char_pos + (pos_byte - mt->cache_byte_pos));
789 if (pos_byte - mt->cache_byte_pos < mt->nbytes - pos_byte)
791 char_pos = mt->cache_char_pos;
792 byte_pos = mt->cache_byte_pos;
797 char_pos = mt->nchars;
798 byte_pos = mt->nbytes;
803 while (byte_pos < pos_byte)
804 INC_POSITION (mt, char_pos, byte_pos);
806 while (byte_pos > pos_byte)
807 DEC_POSITION (mt, char_pos, byte_pos);
808 mt->cache_char_pos = char_pos;
809 mt->cache_byte_pos = byte_pos;
813 /* Estimated extra bytes that malloc will use for its own purpose on
814 each memory allocation. */
815 #define MALLOC_OVERHEAD 4
816 #define MALLOC_MININUM_BYTES 12
819 mtext__enlarge (MText *mt, int nbytes)
821 nbytes += MAX_UTF8_CHAR_BYTES;
822 if (mt->allocated >= nbytes)
824 if (nbytes < MALLOC_MININUM_BYTES)
825 nbytes = MALLOC_MININUM_BYTES;
826 while (mt->allocated < nbytes)
827 mt->allocated = mt->allocated * 2 + MALLOC_OVERHEAD;
828 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
832 mtext__takein (MText *mt, int nchars, int nbytes)
835 mtext__adjust_plist_for_insert (mt, mt->nchars, nchars, NULL);
836 mt->nchars += nchars;
837 mt->nbytes += nbytes;
838 mt->data[mt->nbytes] = 0;
844 mtext__cat_data (MText *mt, unsigned char *p, int nbytes,
845 enum MTextFormat format)
849 if (mt->format > MTEXT_FORMAT_UTF_8)
850 MERROR (MERROR_MTEXT, -1);
851 if (format == MTEXT_FORMAT_US_ASCII)
853 else if (format == MTEXT_FORMAT_UTF_8)
854 nchars = count_utf_8_chars (p, nbytes);
856 MERROR (MERROR_MTEXT, -1);
857 mtext__enlarge (mt, mtext_nbytes (mt) + nbytes + 1);
858 memcpy (MTEXT_DATA (mt) + mtext_nbytes (mt), p, nbytes);
859 mtext__takein (mt, nchars, nbytes);
864 mtext__from_data (const void *data, int nitems, enum MTextFormat format,
868 int nchars, nbytes, unit_bytes;
870 if (format == MTEXT_FORMAT_US_ASCII)
872 const char *p = (char *) data, *pend = p + nitems;
876 MERROR (MERROR_MTEXT, NULL);
877 nchars = nbytes = nitems;
880 else if (format == MTEXT_FORMAT_UTF_8)
882 if ((nchars = count_utf_8_chars (data, nitems)) < 0)
883 MERROR (MERROR_MTEXT, NULL);
887 else if (format <= MTEXT_FORMAT_UTF_16BE)
889 if ((nchars = count_utf_16_chars (data, nitems,
890 format != default_utf_16)) < 0)
891 MERROR (MERROR_MTEXT, NULL);
892 nbytes = USHORT_SIZE * nitems;
893 unit_bytes = USHORT_SIZE;
895 else /* MTEXT_FORMAT_UTF_32XX */
898 nbytes = UINT_SIZE * nitems;
899 unit_bytes = UINT_SIZE;
904 mt->allocated = need_copy ? nbytes + unit_bytes : -1;
909 MTABLE_MALLOC (mt->data, mt->allocated, MERROR_MTEXT);
910 memcpy (mt->data, data, nbytes);
911 mt->data[nbytes] = 0;
914 mt->data = (unsigned char *) data;
920 mtext__adjust_format (MText *mt, enum MTextFormat format)
927 case MTEXT_FORMAT_US_ASCII:
929 unsigned char *p = mt->data;
931 for (i = 0; i < mt->nchars; i++)
932 *p++ = mtext_ref_char (mt, i);
933 mt->nbytes = mt->nchars;
934 mt->cache_byte_pos = mt->cache_char_pos;
938 case MTEXT_FORMAT_UTF_8:
940 unsigned char *p0, *p1;
942 i = count_by_utf_8 (mt, 0, mt->nchars) + 1;
943 MTABLE_MALLOC (p0, i, MERROR_MTEXT);
945 for (i = 0, p1 = p0; i < mt->nchars; i++)
947 c = mtext_ref_char (mt, i);
948 p1 += CHAR_STRING_UTF8 (c, p1);
953 mt->nbytes = p1 - p0;
954 mt->cache_char_pos = mt->cache_byte_pos = 0;
959 if (format == default_utf_16)
961 unsigned short *p0, *p1;
963 i = (count_by_utf_16 (mt, 0, mt->nchars) + 1) * USHORT_SIZE;
964 MTABLE_MALLOC (p0, i, MERROR_MTEXT);
966 for (i = 0, p1 = p0; i < mt->nchars; i++)
968 c = mtext_ref_char (mt, i);
969 p1 += CHAR_STRING_UTF16 (c, p1);
973 mt->data = (unsigned char *) p0;
974 mt->nbytes = p1 - p0;
975 mt->cache_char_pos = mt->cache_byte_pos = 0;
982 mt->allocated = (mt->nchars + 1) * UINT_SIZE;
983 MTABLE_MALLOC (p, mt->allocated, MERROR_MTEXT);
984 for (i = 0; i < mt->nchars; i++)
985 p[i] = mtext_ref_char (mt, i);
988 mt->data = (unsigned char *) p;
989 mt->nbytes = mt->nchars;
990 mt->cache_byte_pos = mt->cache_char_pos;
997 /* Find the position of a character at the beginning of a line of
998 M-Text MT searching backward from POS. */
1001 mtext__bol (MText *mt, int pos)
1007 byte_pos = POS_CHAR_TO_BYTE (mt, pos);
1008 if (mt->format <= MTEXT_FORMAT_UTF_8)
1010 unsigned char *p = mt->data + byte_pos;
1015 while (p > mt->data && p[-1] != '\n')
1019 byte_pos = p - mt->data;
1020 return POS_BYTE_TO_CHAR (mt, byte_pos);
1022 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1024 unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
1025 unsigned short newline = mt->format == default_utf_16 ? 0x0A00 : 0x000A;
1027 if (p[-1] == newline)
1030 while (p > (unsigned short *) (mt->data) && p[-1] != newline)
1032 if (p == (unsigned short *) (mt->data))
1034 byte_pos = p - (unsigned short *) (mt->data);
1035 return POS_BYTE_TO_CHAR (mt, byte_pos);;
1039 unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
1040 unsigned newline = mt->format == default_utf_32 ? 0x0A000000 : 0x0000000A;
1042 if (p[-1] == newline)
1045 while (p > (unsigned *) (mt->data) && p[-1] != newline)
1052 /* Find the position of a character at the end of a line of M-Text MT
1053 searching forward from POS. */
1056 mtext__eol (MText *mt, int pos)
1060 if (pos == mt->nchars)
1062 byte_pos = POS_CHAR_TO_BYTE (mt, pos);
1063 if (mt->format <= MTEXT_FORMAT_UTF_8)
1065 unsigned char *p = mt->data + byte_pos;
1066 unsigned char *endp;
1071 endp = mt->data + mt->nbytes;
1072 while (p < endp && *p != '\n')
1076 byte_pos = p + 1 - mt->data;
1077 return POS_BYTE_TO_CHAR (mt, byte_pos);
1079 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1081 unsigned short *p = ((unsigned short *) (mt->data)) + byte_pos;
1082 unsigned short *endp;
1083 unsigned short newline = mt->format == default_utf_16 ? 0x0A00 : 0x000A;
1088 endp = (unsigned short *) (mt->data) + mt->nbytes;
1089 while (p < endp && *p != newline)
1093 byte_pos = p + 1 - (unsigned short *) (mt->data);
1094 return POS_BYTE_TO_CHAR (mt, byte_pos);
1098 unsigned *p = ((unsigned *) (mt->data)) + byte_pos;
1100 unsigned newline = mt->format == default_utf_32 ? 0x0A000000 : 0x0000000A;
1105 endp = (unsigned *) (mt->data) + mt->nbytes;
1106 while (p < endp && *p != newline)
1113 #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
1118 /*** @addtogroup m17nMtext */
1123 @brief Allocate a new M-text.
1125 The mtext () function allocates a new M-text of length 0 and
1126 returns a pointer to it. The allocated M-text will not be freed
1127 unless the user explicitly does so with the m17n_object_free ()
1131 @brief ¿·¤·¤¤M-text¤ò³ä¤êÅö¤Æ¤ë.
1133 ´Ø¿ô mtext () ¤Ï¡¢Ä¹¤µ 0 ¤Î¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¡¢¤½¤ì¤Ø¤Î¥Ý¥¤
1134 ¥ó¥¿¤òÊÖ¤¹¡£³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_free () ¤Ë
1135 ¤è¤Ã¤Æ¥æ¡¼¥¶¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£
1137 @latexonly \IPAlabel{mtext} @endlatexonly */
1141 m17n_object_free () */
1148 M17N_OBJECT (mt, free_mtext, MERROR_MTEXT);
1149 mt->format = MTEXT_FORMAT_UTF_8;
1150 M17N_OBJECT_REGISTER (mtext_table, mt);
1155 @brief Allocate a new M-text with specified data.
1157 The mtext_from_data () function allocates a new M-text whose
1158 character sequence is specified by array $DATA of $NITEMS
1159 elements. $FORMAT specifies the format of $DATA.
1161 When $FORMAT is either #MTEXT_FORMAT_US_ASCII or
1162 #MTEXT_FORMAT_UTF_8, the contents of $DATA must be of the type @c
1163 unsigned @c char, and $NITEMS counts by byte.
1165 When $FORMAT is either #MTEXT_FORMAT_UTF_16LE or
1166 #MTEXT_FORMAT_UTF_16BE, the contents of $DATA must be of the type
1167 @c unsigned @c short, and $NITEMS counts by unsigned short.
1169 When $FORMAT is either #MTEXT_FORMAT_UTF_32LE or
1170 #MTEXT_FORMAT_UTF_32BE, the contents of $DATA must be of the type
1171 @c unsigned, and $NITEMS counts by unsigned.
1173 The character sequence of the M-text is not modifiable.
1174 The contents of $DATA must not be modified while the M-text is alive.
1176 The allocated M-text will not be freed unless the user explicitly
1177 does so with the m17n_object_free () function. Even in that case,
1181 If the operation was successful, mtext_from_data () returns a
1182 pointer to the allocated M-text. Otherwise it returns @c NULL and
1183 assigns an error code to the external variable #merror_code. */
1185 @brief »ØÄê¤Î¥Ç¡¼¥¿¤ò¸µ¤Ë¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë.
1187 ´Ø¿ô mtext_from_data () ¤Ï¡¢Í×ÁÇ¿ô $NITEMS ¤ÎÇÛÎó $DATA ¤Ç»ØÄꤵ¤ì
1188 ¤¿Ê¸»úÎó¤ò»ý¤Ä¿·¤·¤¤ M-text ¤ò³ä¤êÅö¤Æ¤ë¡£$FORMAT ¤Ï $DATA ¤Î¥Õ¥©¡¼
1191 $FORMAT ¤¬ #MTEXT_FORMAT_US_ASCII ¤« #MTEXT_FORMAT_UTF_8 ¤Ê¤é¤Ð¡¢
1192 $DATA ¤ÎÆâÍÆ¤Ï @c unsigned @c char ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï¥Ð¥¤¥Èñ°Ì
1195 $FORMAT ¤¬ #MTEXT_FORMAT_UTF_16LE ¤« #MTEXT_FORMAT_UTF_16BE ¤Ê¤é¤Ð¡¢
1196 $DATA ¤ÎÆâÍÆ¤Ï @c unsigned @c short ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned
1199 $FORMAT ¤¬ #MTEXT_FORMAT_UTF_32LE ¤« #MTEXT_FORMAT_UTF_32BE ¤Ê¤é¤Ð¡¢
1200 $DATA ¤ÎÆâÍƤÏ@c unsigned ·¿¤Ç¤¢¤ê¡¢$NITEMS ¤Ï unsigned ñ°Ì¤Ç¤¢¤ë¡£
1202 ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Îʸ»úÎó¤ÏÊѹ¹¤Ç¤¤Ê¤¤¡£$DATA ¤ÎÆâÍƤÏ
1203 M-text ¤¬Í¸ú¤Ê´Ö¤ÏÊѹ¹¤·¤Æ¤Ï¤Ê¤é¤Ê¤¤¡£
1205 ³ä¤êÅö¤Æ¤é¤ì¤¿ M-text ¤Ï¡¢´Ø¿ô m17n_object_free () ¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶
1206 ¤¬ÌÀ¼¨Åª¤Ë¹Ô¤Ê¤ï¤Ê¤¤¸Â¤ê¡¢²òÊü¤µ¤ì¤Ê¤¤¡£¤½¤Î¾ì¹ç¤Ç¤â $DATA ¤Ï²òÊü
1210 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_from_data () ¤Ï³ä¤êÅö¤Æ¤é¤ì¤¿M-text ¤Ø¤Î¥Ý
1211 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·³°ÉôÊÑ¿ô #merror_code ¤Ë
1212 ¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1219 mtext_from_data (const void *data, int nitems, enum MTextFormat format)
1222 || format < MTEXT_FORMAT_US_ASCII || format >= MTEXT_FORMAT_MAX)
1223 MERROR (MERROR_MTEXT, NULL);
1224 return mtext__from_data (data, nitems, format, 0);
1230 @brief Number of characters in M-text.
1232 The mtext_len () function returns the number of characters in
1236 @brief M-text Ãæ¤Îʸ»ú¤Î¿ô.
1238 ´Ø¿ô mtext_len () ¤Ï M-text $MT Ãæ¤Îʸ»ú¤Î¿ô¤òÊÖ¤¹¡£
1240 @latexonly \IPAlabel{mtext_len} @endlatexonly */
1243 mtext_len (MText *mt)
1245 return (mt->nchars);
1251 @brief Return the character at the specified position in an M-text.
1253 The mtext_ref_char () function returns the character at $POS in
1254 M-text $MT. If an error is detected, it returns -1 and assigns an
1255 error code to the external variable #merror_code. */
1258 @brief M-text Ãæ¤Î»ØÄꤵ¤ì¤¿°ÌÃÖ¤Îʸ»ú¤òÊÖ¤¹.
1260 ´Ø¿ô mtext_ref_char () ¤Ï¡¢M-text $MT ¤Î°ÌÃÖ $POS ¤Îʸ»ú¤òÊÖ¤¹¡£
1261 ¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code
1262 ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1264 @latexonly \IPAlabel{mtext_ref_char} @endlatexonly */
1271 mtext_ref_char (MText *mt, int pos)
1275 M_CHECK_POS (mt, pos, -1);
1276 if (mt->format <= MTEXT_FORMAT_UTF_8)
1278 unsigned char *p = mt->data + POS_CHAR_TO_BYTE (mt, pos);
1280 c = STRING_CHAR_UTF8 (p);
1282 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1285 = (unsigned short *) (mt->data) + POS_CHAR_TO_BYTE (mt, pos);
1286 unsigned short p1[2];
1288 if (mt->format != default_utf_16)
1290 p1[0] = SWAP_16 (*p);
1291 if (p1[0] >= 0xD800 || p1[0] < 0xDC00)
1292 p1[1] = SWAP_16 (p[1]);
1295 c = STRING_CHAR_UTF16 (p);
1299 c = ((unsigned *) (mt->data))[pos];
1300 if (mt->format != default_utf_32)
1309 @brief Store a character into an M-text.
1311 The mtext_set_char () function sets character $C, which has no
1312 text properties, at $POS in M-text $MT.
1315 If the operation was successful, mtext_set_char () returns 0.
1316 Otherwise it returns -1 and assigns an error code to the external
1317 variable #merror_code. */
1320 @brief M-text ¤Ë°ìʸ»ú¤òÀßÄꤹ¤ë.
1322 ´Ø¿ô mtext_set_char () ¤Ï¡¢¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£Ìµ¤·¤Îʸ»ú $C ¤ò
1323 M-text $MT ¤Î°ÌÃÖ $POS ¤ËÀßÄꤹ¤ë¡£
1326 ½èÍý¤ËÀ®¸ù¤¹¤ì¤Ð mtext_set_char () ¤Ï 0 ¤òÊÖ¤¹¡£¼ºÇÔ¤¹¤ì¤Ð -1 ¤òÊÖ
1327 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1329 @latexonly \IPAlabel{mtext_set_char} @endlatexonly */
1336 mtext_set_char (MText *mt, int pos, int c)
1339 int old_units, new_units;
1344 M_CHECK_POS (mt, pos, -1);
1345 M_CHECK_READONLY (mt, -1);
1347 mtext__adjust_plist_for_change (mt, pos, pos + 1);
1349 if (mt->format <= MTEXT_FORMAT_UTF_8)
1352 mt->format = MTEXT_FORMAT_UTF_8;
1354 else if (mt->format <= MTEXT_FORMAT_UTF_16BE)
1357 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1358 else if (mt->format != default_utf_16)
1359 mtext__adjust_format (mt, default_utf_16);
1361 else if (mt->format != default_utf_32)
1362 mtext__adjust_format (mt, default_utf_32);
1364 unit_bytes = UNIT_BYTES (mt->format);
1365 pos_unit = POS_CHAR_TO_BYTE (mt, pos);
1366 p = mt->data + pos_unit * unit_bytes;
1367 old_units = CHAR_UNITS_AT (mt, p);
1368 new_units = CHAR_UNITS (c, mt->format);
1369 delta = new_units - old_units;
1373 if (mt->cache_char_pos > pos)
1374 mt->cache_byte_pos += delta;
1376 if ((mt->nbytes + delta + 1) * unit_bytes > mt->allocated)
1378 mt->allocated = (mt->nbytes + delta + 1) * unit_bytes;
1379 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1382 memmove (mt->data + (pos_unit + new_units) * unit_bytes,
1383 mt->data + (pos_unit + old_units) * unit_bytes,
1384 (mt->nbytes - pos_unit - old_units + 1) * unit_bytes);
1385 mt->nbytes += delta;
1386 mt->data[mt->nbytes * unit_bytes] = 0;
1390 case MTEXT_FORMAT_US_ASCII:
1391 mt->data[pos_unit] = c;
1393 case MTEXT_FORMAT_UTF_8:
1395 unsigned char *p = mt->data + pos_unit;
1396 CHAR_STRING_UTF8 (c, p);
1400 if (mt->format == default_utf_16)
1402 unsigned short *p = (unsigned short *) mt->data + pos_unit;
1404 CHAR_STRING_UTF16 (c, p);
1407 ((unsigned *) mt->data)[pos_unit] = c;
1415 @brief Append a character to an M-text.
1417 The mtext_cat_char () function appends character $C, which has no
1418 text properties, to the end of M-text $MT.
1421 This function returns a pointer to the resulting M-text $MT. If
1422 $C is an invalid character, it returns @c NULL. */
1425 @brief M-text ¤Ë°ìʸ»úÄɲ乤ë.
1427 ´Ø¿ô mtext_cat_char () ¤Ï¡¢¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£Ìµ¤·¤Îʸ»ú $C ¤ò
1428 M-text $MT ¤ÎËöÈø¤ËÄɲ乤롣
1431 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£$C ¤¬Àµ¤·¤¤Ê¸
1432 »ú¤Ç¤Ê¤¤¾ì¹ç¤Ë¤Ï @c NULL ¤òÊÖ¤¹¡£ */
1436 mtext_cat (), mtext_ncat () */
1439 mtext_cat_char (MText *mt, int c)
1442 int unit_bytes = UNIT_BYTES (mt->format);
1444 M_CHECK_READONLY (mt, NULL);
1445 if (c < 0 || c > MCHAR_MAX)
1447 mtext__adjust_plist_for_insert (mt, mt->nchars, 1, NULL);
1450 && (mt->format == MTEXT_FORMAT_US_ASCII
1452 && (mt->format == MTEXT_FORMAT_UTF_16LE
1453 || mt->format == MTEXT_FORMAT_UTF_16BE))))
1456 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1459 else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
1461 if (mt->format != default_utf_32)
1462 mtext__adjust_format (mt, default_utf_32);
1464 else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
1466 if (mt->format != default_utf_16)
1467 mtext__adjust_format (mt, default_utf_16);
1470 nunits = CHAR_UNITS (c, mt->format);
1471 if ((mt->nbytes + nunits + 1) * unit_bytes > mt->allocated)
1473 mt->allocated = (mt->nbytes + nunits + 1) * unit_bytes;
1474 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
1477 if (mt->format <= MTEXT_FORMAT_UTF_8)
1479 unsigned char *p = mt->data + mt->nbytes;
1480 p += CHAR_STRING_UTF8 (c, p);
1483 else if (mt->format == default_utf_16)
1485 unsigned short *p = (unsigned short *) mt->data + mt->nbytes;
1486 p += CHAR_STRING_UTF16 (c, p);
1491 unsigned *p = (unsigned *) mt->data + mt->nbytes;
1497 mt->nbytes += nunits;
1504 @brief Create a copy of an M-text.
1506 The mtext_dup () function creates a copy of M-text $MT while
1507 inheriting all the text properties of $MT.
1510 This function returns a pointer to the created copy. */
1513 @brief M-text ¤Î¥³¥Ô¡¼¤òºî¤ë.
1515 ´Ø¿ô mtext_dup () ¤Ï¡¢M-text $MT ¤Î¥³¥Ô¡¼¤òºî¤ë¡£$MT ¤Î¥Æ¥¥¹¥È¥×
1516 ¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
1519 ¤³¤Î´Ø¿ô¤Ïºî¤é¤ì¤¿¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1521 @latexonly \IPAlabel{mtext_dup} @endlatexonly */
1525 mtext_duplicate () */
1528 mtext_dup (MText *mt)
1530 MText *new = mtext ();
1531 int unit_bytes = UNIT_BYTES (mt->format);
1536 new->allocated = (mt->nbytes + 1) * unit_bytes;
1537 MTABLE_MALLOC (new->data, new->allocated, MERROR_MTEXT);
1538 memcpy (new->data, mt->data, new->allocated);
1540 new->plist = mtext__copy_plist (mt->plist, 0, mt->nchars, new, 0);
1548 @brief Append an M-text to another.
1550 The mtext_cat () function appends M-text $MT2 to the end of M-text
1551 $MT1 while inheriting all the text properties. $MT2 itself is not
1555 This function returns a pointer to the resulting M-text $MT1. */
1558 @brief 2¸Ä¤Î M-text¤òÏ¢·ë¤¹¤ë.
1560 ´Ø¿ô mtext_cat () ¤Ï¡¢ M-text $MT2 ¤ò M-text $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨
1561 ¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê
1565 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1567 @latexonly \IPAlabel{mtext_cat} @endlatexonly */
1571 mtext_ncat (), mtext_cat_char () */
1574 mtext_cat (MText *mt1, MText *mt2)
1576 M_CHECK_READONLY (mt1, NULL);
1578 if (mt2->nchars > 0)
1579 insert (mt1, mt1->nchars, mt2, 0, mt2->nchars);
1587 @brief Append a part of an M-text to another.
1589 The mtext_ncat () function appends the first $N characters of
1590 M-text $MT2 to the end of M-text $MT1 while inheriting all the
1591 text properties. If the length of $MT2 is less than $N, all
1592 characters are copied. $MT2 is not modified.
1595 If the operation was successful, mtext_ncat () returns a
1596 pointer to the resulting M-text $MT1. If an error is detected, it
1597 returns @c NULL and assigns an error code to the global variable
1602 @brief M-text ¤Î°ìÉô¤òÊ̤ΠM-text ¤ËÉղ乤ë.
1604 ´Ø¿ô mtext_ncat () ¤Ï¡¢M-text $MT2 ¤Î¤Ï¤¸¤á¤Î $N ʸ»ú¤ò M-text
1605 $MT1 ¤ÎËöÈø¤ËÉÕ¤±²Ã¤¨¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì
1606 ¤ë¡£$MT2 ¤ÎŤµ¤¬ $N °Ê²¼¤Ê¤é¤Ð¡¢$MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤¬Éղ䵤ì¤ë¡£
1607 $MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1610 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncat () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý
1611 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1612 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1614 @latexonly \IPAlabel{mtext_ncat} @endlatexonly */
1621 mtext_cat (), mtext_cat_char () */
1624 mtext_ncat (MText *mt1, MText *mt2, int n)
1626 M_CHECK_READONLY (mt1, NULL);
1628 MERROR (MERROR_RANGE, NULL);
1629 if (mt2->nchars > 0)
1630 insert (mt1, mt1->nchars, mt2, 0, mt2->nchars < n ? mt2->nchars : n);
1638 @brief Copy an M-text to another.
1640 The mtext_cpy () function copies M-text $MT2 to M-text $MT1 while
1641 inheriting all the text properties. The old text in $MT1 is
1642 overwritten and the length of $MT1 is extended if necessary. $MT2
1646 This function returns a pointer to the resulting M-text $MT1. */
1649 @brief M-text ¤òÊ̤ΠM-text ¤Ë¥³¥Ô¡¼¤¹¤ë.
1651 ´Ø¿ô mtext_cpy () ¤Ï M-text $MT2 ¤ò M-text $MT1 ¤Ë¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£
1652 $MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 ¤ÎŤµ¤ÏɬÍפ˱þ
1653 ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1656 ¤³¤Î´Ø¿ô¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£
1658 @latexonly \IPAlabel{mtext_cpy} @endlatexonly */
1662 mtext_ncpy (), mtext_copy () */
1665 mtext_cpy (MText *mt1, MText *mt2)
1667 M_CHECK_READONLY (mt1, NULL);
1668 mtext_del (mt1, 0, mt1->nchars);
1669 if (mt2->nchars > 0)
1670 insert (mt1, 0, mt2, 0, mt2->nchars);
1677 @brief Copy the first some characters in an M-text to another.
1679 The mtext_ncpy () function copies the first $N characters of
1680 M-text $MT2 to M-text $MT1 while inheriting all the text
1681 properties. If the length of $MT2 is less than $N, all characters
1682 of $MT2 are copied. The old text in $MT1 is overwritten and the
1683 length of $MT1 is extended if necessary. $MT2 is not modified.
1686 If the operation was successful, mtext_ncpy () returns a pointer
1687 to the resulting M-text $MT1. If an error is detected, it returns
1688 @c NULL and assigns an error code to the global variable
1692 @brief M-text ¤Ë´Þ¤Þ¤ì¤ëºÇ½é¤Î²¿Ê¸»ú¤«¤ò¥³¥Ô¡¼¤¹¤ë.
1694 ´Ø¿ô mtext_ncpy () ¤Ï¡¢M-text $MT2 ¤ÎºÇ½é¤Î $N ʸ»ú¤ò M-text $MT1
1695 ¤Ë¾å½ñ¤¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£
1696 ¤â¤· $MT2 ¤ÎŤµ¤¬ $N ¤è¤ê¤â¾®¤µ¤±¤ì¤Ð $MT2 ¤Î¤¹¤Ù¤Æ¤Îʸ»ú¤ò¥³¥Ô¡¼
1697 ¤¹¤ë¡£$MT1 ¤ÎŤµ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1700 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_ncpy () ¤ÏÊѹ¹¤µ¤ì¤¿ M-text $MT1 ¤Ø¤Î¥Ý
1701 ¥¤¥ó¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1702 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1704 @latexonly \IPAlabel{mtext_ncpy} @endlatexonly */
1711 mtext_cpy (), mtext_copy () */
1714 mtext_ncpy (MText *mt1, MText *mt2, int n)
1716 M_CHECK_READONLY (mt1, NULL);
1718 MERROR (MERROR_RANGE, NULL);
1719 mtext_del (mt1, 0, mt1->nchars);
1720 if (mt2->nchars > 0)
1721 insert (mt1, 0, mt2, 0, mt2->nchars < n ? mt2->nchars : n);
1728 @brief Create a new M-text from a part of an existing M-text.
1730 The mtext_duplicate () function creates a copy of sub-text of
1731 M-text $MT, starting at $FROM (inclusive) and ending at $TO
1732 (exclusive) while inheriting all the text properties of $MT. $MT
1733 itself is not modified.
1736 If the operation was successful, mtext_duplicate () returns a
1737 pointer to the created M-text. If an error is detected, it returns 0
1738 and assigns an error code to the external variable #merror_code. */
1741 @brief ´û¸¤Î M-text ¤Î°ìÉô¤«¤é¿·¤·¤¤ M-text ¤ò¤Ä¤¯¤ë.
1743 ´Ø¿ô mtext_duplicate () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO
1744 ¡Ê´Þ¤Þ¤Ê¤¤¡Ë¤Þ¤Ç¤ÎÉôʬ¤Î¥³¥Ô¡¼¤òºî¤ë¡£¤³¤Î¤È¤ $MT ¤Î¥Æ¥¥¹¥È¥×¥í
1745 ¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT ¤½¤Î¤â¤Î¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1748 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð¡¢mtext_duplicate () ¤Ïºî¤é¤ì¤¿ M-text ¤Ø¤Î¥Ý¥¤¥ó
1749 ¥¿¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô
1750 #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£
1752 @latexonly \IPAlabel{mtext_duplicate} @endlatexonly */
1762 mtext_duplicate (MText *mt, int from, int to)
1766 M_CHECK_RANGE_X (mt, from, to, NULL);
1768 new->format = mt->format;
1770 insert (new, 0, mt, from, to);
1777 @brief Copy characters in the specified range into an M-text.
1779 The mtext_copy () function copies the text between $FROM
1780 (inclusive) and $TO (exclusive) in M-text $MT2 to the region
1781 starting at $POS in M-text $MT1 while inheriting the text
1782 properties. The old text in $MT1 is overwritten and the length of
1783 $MT1 is extended if necessary. $MT2 is not modified.
1786 If the operation was successful, mtext_copy () returns a pointer
1787 to the modified $MT1. Otherwise, it returns @c NULL and assigns
1788 an error code to the external variable #merror_code. */
1791 @brief M-text ¤Ë»ØÄêÈϰϤÎʸ»ú¤ò¥³¥Ô¡¼¤¹¤ë.
1793 ´Ø¿ô mtext_copy () ¤Ï¡¢ M-text $MT2 ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO ¡Ê´Þ
1794 ¤Þ¤Ê¤¤¡Ë¤Þ¤Ç¤ÎÈϰϤΥƥ¥¹¥È¤ò M-text $MT1 ¤Î°ÌÃÖ $POS ¤«¤é¾å½ñ¤
1795 ¥³¥Ô¡¼¤¹¤ë¡£$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT1 ¤ÎĹ
1796 ¤µ¤ÏɬÍפ˱þ¤¸¤Æ¿¤Ð¤µ¤ì¤ë¡£$MT2 ¤ÏÊѹ¹¤µ¤ì¤Ê¤¤¡£
1798 @latexonly \IPAlabel{mtext_copy} @endlatexonly
1801 ½èÍý¤¬À®¸ù¤·¤¿¾ì¹ç¡¢mtext_copy () ¤ÏÊѹ¹¤µ¤ì¤¿ $MT1 ¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò
1802 ÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð @c NULL ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼
1803 ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1810 mtext_cpy (), mtext_ncpy () */
1813 mtext_copy (MText *mt1, int pos, MText *mt2, int from, int to)
1815 M_CHECK_POS_X (mt1, pos, NULL);
1816 M_CHECK_READONLY (mt1, NULL);
1817 M_CHECK_RANGE_X (mt2, from, to, NULL);
1818 mtext_del (mt1, pos, mt1->nchars);
1819 return insert (mt1, pos, mt2, from, to);
1826 @brief Delete characters in the specified range destructively.
1828 The mtext_del () function deletes the characters in the range
1829 $FROM (inclusive) and $TO (exclusive) from M-text $MT
1830 destructively. As a result, the length of $MT shrinks by ($TO -
1834 If the operation was successful, mtext_del () returns 0.
1835 Otherwise, it returns -1 and assigns an error code to the external
1836 variable #merror_code. */
1839 @brief »ØÄêÈϰϤÎʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯.
1841 ´Ø¿ô mtext_del () ¤Ï¡¢M-text $MT ¤Î $FROM ¡Ê´Þ¤à¡Ë¤«¤é $TO ¡Ê´Þ¤Þ
1842 ¤Ê¤¤¡Ë¤Þ¤Ç¤Îʸ»ú¤òÇ˲õŪ¤Ë¼è¤ê½ü¤¯¡£·ë²ÌŪ¤Ë $MT ¤ÏŤµ¤¬ ($TO @c
1843 - $FROM) ¤À¤±½Ì¤à¤³¤È¤Ë¤Ê¤ë¡£
1846 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_del () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ
1847 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1857 mtext_del (MText *mt, int from, int to)
1859 int from_byte, to_byte;
1860 int unit_bytes = UNIT_BYTES (mt->format);
1862 M_CHECK_READONLY (mt, -1);
1863 M_CHECK_RANGE (mt, from, to, -1, 0);
1865 from_byte = POS_CHAR_TO_BYTE (mt, from);
1866 to_byte = POS_CHAR_TO_BYTE (mt, to);
1868 if (mt->cache_char_pos >= to)
1870 mt->cache_char_pos -= to - from;
1871 mt->cache_byte_pos -= to_byte - from_byte;
1873 else if (mt->cache_char_pos > from)
1875 mt->cache_char_pos -= from;
1876 mt->cache_byte_pos -= from_byte;
1879 mtext__adjust_plist_for_delete (mt, from, to - from);
1880 memmove (mt->data + from_byte * unit_bytes,
1881 mt->data + to_byte * unit_bytes,
1882 (mt->nbytes - to_byte + 1) * unit_bytes);
1883 mt->nchars -= (to - from);
1884 mt->nbytes -= (to_byte - from_byte);
1885 mt->cache_char_pos = from;
1886 mt->cache_byte_pos = from_byte;
1894 @brief Insert an M-text into another M-text.
1896 The mtext_ins () function inserts M-text $MT2 into M-text $MT1, at
1897 position $POS. As a result, $MT1 is lengthen by the length of
1898 $MT2. On insertion, all the text properties of $MT2 are
1899 inherited. The original $MT2 is not modified.
1902 If the operation was successful, mtext_ins () returns 0.
1903 Otherwise, it returns -1 and assigns an error code to the external
1904 variable #merror_code. */
1907 @brief M-text ¤òÊ̤ΠM-text ¤ËÁÞÆþ¤¹¤ë.
1909 ´Ø¿ô mtext_ins () ¤Ï M-text $MT1 ¤Î $POS ¤Î°ÌÃÖ¤Ë Ê̤ΠM-text $MT2
1910 ¤òÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $MT2 ¤ÎŤµÊ¬¤À¤±Áý¤¨¤ë¡£ÁÞÆþ¤Î
1911 ºÝ¡¢$MT2 ¤Î¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Ï¤¹¤Ù¤Æ·Ñ¾µ¤µ¤ì¤ë¡£$MT2 ¤½¤Î¤â¤Î¤ÏÊÑ
1915 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1 ¤òÊÖ
1916 ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1926 mtext_ins (MText *mt1, int pos, MText *mt2)
1928 M_CHECK_READONLY (mt1, -1);
1929 M_CHECK_POS_X (mt1, pos, -1);
1931 if (mt2->nchars == 0)
1933 insert (mt1, pos, mt2, 0, mt2->nchars);
1941 @brief Insert a character into an M-text.
1943 The mtext_ins_char () function inserts $N copies of character $C
1944 into M-text $MT at position $POS. As a result, $MT is lengthen by
1948 If the operation was successful, mtext_ins () returns 0.
1949 Otherwise, it returns -1 and assigns an error code to the external
1950 variable #merror_code. */
1953 @brief M-text ¤Ëʸ»ú¤òÁÞÆþ¤¹¤ë.
1955 ´Ø¿ô mtext_ins_char () ¤Ï M-text $MT ¤Î $POS ¤Î°ÌÃÖ¤Ëʸ»ú $C ¤ò $N
1956 ¸ÄÁÞÆþ¤¹¤ë¡£¤³¤Î·ë²Ì $MT1 ¤ÎŤµ¤Ï $N ¤À¤±Áý¤¨¤ë¡£
1959 ½èÍý¤¬À®¸ù¤¹¤ì¤Ð mtext_ins_char () ¤Ï 0 ¤òÊÖ¤¹¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð -1
1960 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
1967 mtext_ins, mtext_del () */
1970 mtext_ins_char (MText *mt, int pos, int c, int n)
1973 int unit_bytes = UNIT_BYTES (mt->format);
1977 M_CHECK_READONLY (mt, -1);
1978 M_CHECK_POS_X (mt, pos, -1);
1979 if (c < 0 || c > MCHAR_MAX)
1980 MERROR (MERROR_MTEXT, -1);
1983 mtext__adjust_plist_for_insert (mt, pos, n, NULL);
1986 && (mt->format == MTEXT_FORMAT_US_ASCII
1987 || (c >= 0x10000 && (mt->format == MTEXT_FORMAT_UTF_16LE
1988 || mt->format == MTEXT_FORMAT_UTF_16BE))))
1990 mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
1993 else if (mt->format >= MTEXT_FORMAT_UTF_32LE)
1995 if (mt->format != default_utf_32)
1996 mtext__adjust_format (mt, default_utf_32);
1998 else if (mt->format >= MTEXT_FORMAT_UTF_16LE)
2000 if (mt->format != default_utf_16)
2001 mtext__adjust_format (mt, default_utf_16);
2004 nunits = CHAR_UNITS (c, mt->format);
2005 if ((mt->nbytes + nunits * n + 1) * unit_bytes > mt->allocated)
2007 mt->allocated = (mt->nbytes + nunits * n + 1) * unit_bytes;
2008 MTABLE_REALLOC (mt->data, mt->allocated, MERROR_MTEXT);
2010 pos_unit = POS_CHAR_TO_BYTE (mt, pos);
2011 if (mt->cache_char_pos > pos)
2013 mt->cache_char_pos += n;
2014 mt->cache_byte_pos += nunits + n;
2016 memmove (mt->data + (pos_unit + nunits * n) * unit_bytes,
2017 mt->data + pos_unit * unit_bytes,
2018 (mt->nbytes - pos_unit + 1) * unit_bytes);
2019 if (mt->format <= MTEXT_FORMAT_UTF_8)
2021 unsigned char *p = mt->data + pos_unit;
2023 for (i = 0; i < n; i++)
2024 p += CHAR_STRING_UTF8 (c, p);
2026 else if (mt->format == default_utf_16)
2028 unsigned short *p = (unsigned short *) mt->data + pos_unit;
2030 for (i = 0; i < n; i++)
2031 p += CHAR_STRING_UTF16 (c, p);
2035 unsigned *p = (unsigned *) mt->data + pos_unit;
2037 for (i = 0; i < n; i++)
2041 mt->nbytes += nunits * n;
2048 @brief Search a character in an M-text.
2050 The mtext_character () function searches M-text $MT for character
2051 $C. If $FROM is less than $TO, the search begins at position $FROM
2052 and goes forward but does not exceed ($TO - 1). Otherwise, the search
2053 begins at position ($FROM - 1) and goes backward but does not
2054 exceed $TO. An invalid position specification is regarded as both
2055 $FROM and $TO being 0.
2058 If $C is found, mtext_character () returns the position of its
2059 first occurrence. Otherwise it returns -1 without changing the
2060 external variable #merror_code. If an error is detected, it returns -1 and
2061 assigns an error code to the external variable #merror_code. */
2064 @brief M-text Ãæ¤Çʸ»ú¤òõ¤¹.
2066 ´Ø¿ô mtext_character () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£¤â¤·
2067 $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ð¡¢Ãµº÷¤Ï°ÌÃÖ $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢ºÇÂç
2068 ($TO - 1) ¤Þ¤Ç¿Ê¤à¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð°ÌÃÖ ($FROM - 1) ¤«¤éÀèƬÊý¸þ¤Ø¡¢
2069 ºÇÂç $TO ¤Þ¤Ç¿Ê¤à¡£°ÌÃ֤λØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM ¤È $TO ¤Îξ
2070 Êý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
2073 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_character () ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2074 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code ¤òÊѹ¹¤»¤º¤Ë -1 ¤òÊÖ
2075 ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð¤µ¤ì¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤·¡¢³°ÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼
2076 ¥³¡¼¥É¤òÀßÄꤹ¤ë¡£ */
2080 mtext_chr(), mtext_rchr () */
2083 mtext_character (MText *mt, int from, int to, int c)
2087 /* We do not use M_CHECK_RANGE () because this function should
2088 not set merror_code. */
2089 if (from < 0 || to > mt->nchars)
2091 return find_char_forward (mt, from, to, c);
2096 if (to < 0 || from > mt->nchars)
2098 return find_char_backward (mt, to, from, c);
2106 @brief Return the position of the first occurrence of a character in an M-text.
2108 The mtext_chr () function searches M-text $MT for character $C.
2109 The search starts from the beginning of $MT and goes toward the end.
2112 If $C is found, mtext_chr () returns its position; otherwise it
2116 @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
2118 ´Ø¿ô mtext_chr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT ¤Î
2119 ÀèƬ¤«¤éËöÈøÊý¸þ¤Ë¿Ê¤à¡£
2122 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_chr () ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é
2123 ¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
2125 @latexonly \IPAlabel{mtext_chr} @endlatexonly */
2132 mtext_rchr (), mtext_character () */
2135 mtext_chr (MText *mt, int c)
2137 return find_char_forward (mt, 0, mt->nchars, c);
2143 @brief Return the position of the last occurrence of a character in an M-text.
2145 The mtext_rchr () function searches M-text $MT for character $C.
2146 The search starts from the end of $MT and goes backwardly toward the
2150 If $C is found, mtext_rchr () returns its position; otherwise it
2154 @brief M-text Ãæ¤Ç»ØÄꤵ¤ì¤¿Ê¸»ú¤¬ºÇ¸å¤Ë¸½¤ì¤ë°ÌÃÖ¤òÊÖ¤¹.
2156 ´Ø¿ô mtext_rchr () ¤Ï M-text $MT Ãæ¤Çʸ»ú $C ¤òõ¤¹¡£Ãµº÷¤Ï $MT ¤Î
2157 ºÇ¸å¤«¤éÀèƬÊý¸þ¤Ø¤È¸å¸þ¤¤Ë¿Ê¤à¡£
2160 ¤â¤· $C ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_rchr () ¤Ï¤½¤Î½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¸«¤Ä¤«¤é
2161 ¤Ê¤«¤Ã¤¿¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£
2163 @latexonly \IPAlabel{mtext_rchr} @endlatexonly */
2170 mtext_chr (), mtext_character () */
2173 mtext_rchr (MText *mt, int c)
2175 return find_char_backward (mt, mt->nchars, 0, c);
2182 @brief Compare two M-texts character-by-character.
2184 The mtext_cmp () function compares M-texts $MT1 and $MT2 character
2188 This function returns 1, 0, or -1 if $MT1 is found greater than,
2189 equal to, or less than $MT2, respectively. Comparison is based on
2193 @brief Æó¤Ä¤Î M-text ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë.
2195 ´Ø¿ô mtext_cmp () ¤Ï¡¢ M-text $MT1 ¤È $MT2 ¤òʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£
2198 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2199 ¤Ð 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 ¤¬»ØÄꤵ
2284 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2285 ¤Ð 1 ¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð
2290 mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2291 mtext_case_compare () */
2294 mtext_compare (MText *mt1, int from1, int to1, MText *mt2, int from2, int to2)
2296 if (from1 < 0 || from1 > to1 || to1 > mt1->nchars)
2299 if (from2 < 0 || from2 > to2 || to2 > mt2->nchars)
2302 return compare (mt1, from1, to1, mt2, from2, to2);
2308 @brief Search an M-text for a set of characters.
2310 The mtext_spn () function returns the length of the initial
2311 segment of M-text $MT1 that consists entirely of characters in
2315 @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2317 ´Ø¿ô mtext_spn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2 ¤Ë´Þ¤Þ
2318 ¤ì¤ëʸ»ú¤À¤±¤Ç¤Ç¤¤Æ¤¤¤ëÉôʬ¤ÎºÇÂ獵¤òÊÖ¤¹¡£
2320 @latexonly \IPAlabel{mtext_spn} @endlatexonly */
2327 mtext_spn (MText *mt, MText *accept)
2329 return span (mt, accept, 0, Mnil);
2335 @brief Search an M-text for the complement of a set of characters.
2337 The mtext_cspn () returns the length of the initial segment of
2338 M-text $MT1 that consists entirely of characters not in M-text $MT2. */
2341 @brief ¤¢¤ë½¸¹ç¤Ë°¤µ¤Ê¤¤Ê¸»ú¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2343 ´Ø¿ô mtext_cspn () ¤Ï¡¢M-text $MT1 ¤ÎÀèƬÉôʬ¤Ç M-text $MT2 ¤Ë´Þ¤Þ
2344 ¤ì¤Ê¤¤Ê¸»ú¤À¤±¤Ç¤Ç¤¤Æ¤¤¤ëÉôʬ¤ÎºÇÂ獵¤òÊÖ¤¹¡£
2346 @latexonly \IPAlabel{mtext_cspn} @endlatexonly */
2353 mtext_cspn (MText *mt, MText *reject)
2355 return span (mt, reject, 0, Mt);
2361 @brief Search an M-text for any of a set of characters.
2363 The mtext_pbrk () function locates the first occurrence in M-text
2364 $MT1 of any of the characters in M-text $MT2.
2367 This function returns the position in $MT1 of the found character.
2368 If no such character is found, it returns -1. */
2371 @brief ¤¢¤ë½¸¹ç¤Îʸ»ú¤Î¤É¤ì¤«¤ò M-text ¤ÎÃæ¤Çõ¤¹.
2373 ´Ø¿ô mtext_pbrk () ¤Ï¡¢M-text $MT1 Ãæ¤Ç M-text $MT2 ¤Î¤¤¤º¤ì¤«¤Îʸ
2374 »ú¤¬ºÇ½é¤Ë¸½¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£
2377 ¸«¤Ä¤«¤Ã¤¿Ê¸»ú¤Î¡¢$MT1 Æâ¤Ë¤ª¤±¤ë½Ð¸½°ÌÃÖ¤òÊÖ¤¹¡£¤â¤·¤½¤Î¤è¤¦¤Êʸ
2378 »ú¤¬¤Ê¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2380 @latexonly \IPAlabel{mtext_pbrk} @endlatexonly */
2383 mtext_pbrk (MText *mt, MText *accept)
2385 int nchars = mtext_nchars (mt);
2386 int len = span (mt, accept, 0, Mt);
2388 return (len == nchars ? -1 : len);
2394 @brief Look for a token in an M-text.
2396 The mtext_tok () function searches a token that firstly occurs
2397 after position $POS in M-text $MT. Here, a token means a
2398 substring each of which does not appear in M-text $DELIM. Note
2399 that the type of $POS is not @c int but pointer to @c int.
2402 If a token is found, mtext_tok () copies the corresponding part of
2403 $MT and returns a pointer to the copy. In this case, $POS is set
2404 to the end of the found token. If no token is found, it returns
2405 @c NULL without changing the external variable #merror_code. If an
2406 error is detected, it returns @c NULL and assigns an error code
2407 to the external variable #merror_code. */
2410 @brief M-text Ãæ¤Î¥È¡¼¥¯¥ó¤òõ¤¹.
2412 ´Ø¿ô mtext_tok () ¤Ï¡¢M-text $MT ¤ÎÃæ¤Ç°ÌÃÖ $POS °Ê¹ßºÇ½é¤Ë¸½¤ì¤ë
2413 ¥È¡¼¥¯¥ó¤òõ¤¹¡£¤³¤³¤Ç¥È¡¼¥¯¥ó¤È¤Ï M-text $DELIM ¤ÎÃæ¤Ë¸½¤ï¤ì¤Ê¤¤
2414 ʸ»ú¤À¤±¤«¤é¤Ê¤ëÉôʬʸ»úÎó¤Ç¤¢¤ë¡£$POS ¤Î·¿¤¬ @c int ¤Ç¤Ï¤Ê¤¯¤Æ @c
2415 int ¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¤³¤È¤ËÃí°Õ¡£
2418 ¤â¤·¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤ì¤Ð mtext_tok ()¤Ï¤½¤Î¥È¡¼¥¯¥ó¤ËÁêÅö¤¹¤ëÉôʬ
2419 ¤Î $MT ¤ò¥³¥Ô¡¼¤·¡¢¤½¤Î¥³¥Ô¡¼¤Ø¤Î¥Ý¥¤¥ó¥¿¤òÊÖ¤¹¡£¤³¤Î¾ì¹ç¡¢$POS ¤Ï
2420 ¸«¤Ä¤«¤Ã¤¿¥È¡¼¥¯¥ó¤Î½ªÃ¼¤Ë¥»¥Ã¥È¤µ¤ì¤ë¡£¥È¡¼¥¯¥ó¤¬¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿
2421 ¾ì¹ç¤Ï³°ÉôÊÑ¿ô #merror_code ¤òÊѤ¨¤º¤Ë @c NULL ¤òÊÖ¤¹¡£¥¨¥é¡¼¤¬¸¡½Ð
2422 ¤µ¤ì¤¿¾ì¹ç¤Ï @c NULL ¤òÊÖ¤·¡¢ÊÑÉôÊÑ¿ô #merror_code ¤Ë¥¨¥é¡¼¥³¡¼¥É¤ò
2425 @latexonly \IPAlabel{mtext_tok} @endlatexonly */
2432 mtext_tok (MText *mt, MText *delim, int *pos)
2434 int nchars = mtext_nchars (mt);
2437 M_CHECK_POS (mt, *pos, NULL);
2440 Skip delimiters starting at POS in MT.
2441 Never do *pos += span(...), or you will change *pos
2442 even though no token is found.
2444 pos2 = *pos + span (mt, delim, *pos, Mnil);
2449 *pos = pos2 + span (mt, delim, pos2, Mt);
2450 return (insert (mtext (), 0, mt, pos2, *pos));
2456 @brief Locate an M-text in another.
2458 The mtext_text () function finds the first occurrence of M-text
2459 $MT2 in M-text $MT1 after the position $POS while ignoring
2460 difference of the text properties.
2463 If $MT2 is found in $MT1, mtext_text () returns the position of it
2464 first occurrence. Otherwise it returns -1. If $MT2 is empty, it
2468 @brief M-text Ãæ¤ÇÊ̤ΠM-text ¤òõ¤¹.
2470 ´Ø¿ô mtext_text () ¤Ï¡¢M-text $MT1 Ãæ¤Ç°ÌÃÖ $POS °Ê¹ß¤Ë¸½¤ï¤ì¤ë
2471 M-text $MT2 ¤ÎºÇ½é¤Î°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤Î°ã¤¤¤Ï̵»ë¤µ
2475 $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_text() ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2476 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
2478 @latexonly \IPAlabel{mtext_text} @endlatexonly */
2481 mtext_text (MText *mt1, int pos, MText *mt2)
2484 int pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
2485 int c = mtext_ref_char (mt2, 0);
2486 int nbytes1 = mtext_nbytes (mt1);
2487 int nbytes2 = mtext_nbytes (mt2);
2489 int use_memcmp = (mt1->format == mt2->format
2490 || (mt1->format < MTEXT_FORMAT_UTF_8
2491 && mt2->format == MTEXT_FORMAT_UTF_8));
2492 int unit_bytes = UNIT_BYTES (mt1->format);
2494 if (nbytes2 > pos_byte + nbytes1)
2496 pos_byte = nbytes1 - nbytes2;
2497 limit = POS_BYTE_TO_CHAR (mt1, pos_byte);
2501 if ((pos = mtext_character (mt1, from, limit, c)) < 0)
2503 pos_byte = POS_CHAR_TO_BYTE (mt1, pos);
2505 ? ! memcmp (mt1->data + pos_byte * unit_bytes,
2506 mt2->data, nbytes2 * unit_bytes)
2507 : ! compare (mt1, pos, mt2->nchars, mt2, 0, mt2->nchars))
2515 @brief Locate an M-text in a specific range of another.
2517 The mtext_search () function searches for the first occurrence of
2518 M-text $MT2 in M-text $MT1 in the region $FROM and $TO while
2519 ignoring difference of the text properties. If $FROM is less than
2520 $TO, the forward search starts from $FROM, otherwise the backward
2521 search starts from $TO.
2524 If $MT2 is found in $MT1, mtext_search () returns the position of the
2525 first occurrence. Otherwise it returns -1. If $MT2 is empty, it
2529 @brief M-text Ãæ¤ÎÆÃÄê¤ÎÎΰè¤ÇÊ̤ΠM-text ¤òõ¤¹.
2531 ´Ø¿ô mtext_search () ¤Ï¡¢M-text $MT1 Ãæ¤Î $FROM ¤«¤é $TO ¤Þ¤Ç¤Î´Ö¤Î
2532 Îΰè¤ÇM-text $MT2 ¤¬ºÇ½é¤Ë¸½¤ï¤ì¤ë°ÌÃÖ¤òÄ´¤Ù¤ë¡£¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£
2533 ¤Î°ã¤¤¤Ï̵»ë¤µ¤ì¤ë¡£¤â¤· $FROM ¤¬ $TO ¤è¤ê¾®¤µ¤±¤ì¤Ðõº÷¤Ï°ÌÃÖ
2534 $FROM ¤«¤éËöÈøÊý¸þ¤Ø¡¢¤½¤¦¤Ç¤Ê¤±¤ì¤Ð $TO ¤«¤éÀèƬÊý¸þ¤ØºÇÂç $TO ¤Þ
2538 $MT1 Ãæ¤Ë $MT2 ¤¬¸«¤Ä¤«¤ì¤Ð¡¢mtext_search() ¤Ï¤½¤ÎºÇ½é¤Î½Ð¸½°ÌÃÖ¤òÊÖ
2539 ¤¹¡£¸«¤Ä¤«¤é¤Ê¤¤¾ì¹ç¤Ï -1 ¤òÊÖ¤¹¡£¤â¤· $MT2 ¤¬¶õ¤Ê¤é¤Ð 0 ¤òÊÖ¤¹¡£
2543 mtext_search (MText *mt1, int from, int to, MText *mt2)
2545 int c = mtext_ref_char (mt2, 0);
2547 int nbytes2 = mtext_nbytes (mt2);
2549 if (mt1->format > MTEXT_FORMAT_UTF_8
2550 || mt2->format > MTEXT_FORMAT_UTF_8)
2551 MERROR (MERROR_MTEXT, -1);
2555 to -= mtext_nchars (mt2);
2560 if ((from = find_char_forward (mt1, from, to, c)) < 0)
2562 from_byte = POS_CHAR_TO_BYTE (mt1, from);
2563 if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
2570 from -= mtext_nchars (mt2);
2575 if ((from = find_char_backward (mt1, from, to, c)) < 0)
2577 from_byte = POS_CHAR_TO_BYTE (mt1, from);
2578 if (! memcmp (mt1->data + from_byte, mt2->data, nbytes2))
2590 @brief Compare two M-texts ignoring cases.
2592 The mtext_casecmp () function is similar to mtext_cmp (), but
2593 ignores cases on comparison.
2596 This function returns 1, 0, or -1 if $MT1 is found greater than,
2597 equal to, or less than $MT2, respectively. */
2600 @brief Æó¤Ä¤Î M-text ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2602 ´Ø¿ô mtext_casecmp () ¤Ï¡¢´Ø¿ô mtext_cmp () ƱÍͤΠM-text Ʊ»Î¤ÎÈæ
2603 ³Ó¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤Æ¹Ô¤Ê¤¦¡£
2606 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2607 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2609 @latexonly \IPAlabel{mtext_casecmp} @endlatexonly */
2613 mtext_cmp (), mtext_ncmp (), mtext_ncasecmp ()
2614 mtext_compare (), mtext_case_compare () */
2617 mtext_casecmp (MText *mt1, MText *mt2)
2619 return case_compare (mt1, 0, mt1->nchars, mt2, 0, mt2->nchars);
2625 @brief Compare initial parts of two M-texts ignoring cases.
2627 The mtext_ncasecmp () function is similar to mtext_casecmp (), but
2628 compares at most $N characters from the beginning.
2631 This function returns 1, 0, or -1 if $MT1 is found greater than,
2632 equal to, or less than $MT2, respectively. */
2635 @brief Æó¤Ä¤Î M-text ¤ÎÀèƬÉôʬ¤òÂçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2637 ´Ø¿ô mtext_ncasecmp () ¤Ï¡¢´Ø¿ô mtext_casecmp () ƱÍͤΠM-text Ʊ
2638 »Î¤ÎÈæ³Ó¤òÀèƬ¤«¤éºÇÂç $N ʸ»ú¤Þ¤Ç¤Ë´Ø¤·¤Æ¹Ô¤Ê¤¦¡£
2641 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð 0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2642 ¤Ð 1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð -1 ¤òÊÖ¤¹¡£
2644 @latexonly \IPAlabel{mtext_ncasecmp} @endlatexonly */
2648 mtext_cmp (), mtext_casecmp (), mtext_casecmp ()
2649 mtext_compare (), mtext_case_compare () */
2652 mtext_ncasecmp (MText *mt1, MText *mt2, int n)
2656 return case_compare (mt1, 0, (mt1->nchars < n ? mt1->nchars : n),
2657 mt2, 0, (mt2->nchars < n ? mt2->nchars : n));
2663 @brief Compare specified regions of two M-texts ignoring cases.
2665 The mtext_case_compare () function compares two M-texts $MT1 and
2666 $MT2, character-by-character, ignoring cases. The compared
2667 regions are between $FROM1 and $TO1 in $MT1 and $FROM2 to $TO2 in
2668 MT2. $FROM1 and $FROM2 are inclusive, $TO1 and $TO2 are
2669 exclusive. $FROM1 being equal to $TO1 (or $FROM2 being equal to
2670 $TO2) means an M-text of length zero. An invalid region
2671 specification is regarded as both $FROM1 and $TO1 (or $FROM2 and
2675 This function returns 1, 0, or -1 if $MT1 is found greater than,
2676 equal to, or less than $MT2, respectively. Comparison is based on
2680 @brief Æó¤Ä¤Î M-text ¤Î»ØÄꤷ¤¿Îΰè¤ò¡¢Âçʸ»ú¡¿¾®Ê¸»ú¤Î¶èÊ̤ò̵»ë¤·¤ÆÈæ³Ó¤¹¤ë.
2682 ´Ø¿ô mtext_compare () ¤ÏÆó¤Ä¤Î M-text $MT1 ¤È $MT2 ¤ò¡¢Âçʸ»ú¡¿¾®
2683 ʸ»ú¤Î¶èÊ̤ò̵»ë¤·¤Æʸ»úñ°Ì¤ÇÈæ³Ó¤¹¤ë¡£Èæ³ÓÂоݤȤʤë¤Î¤Ï $MT1
2684 ¤Ç¤Ï $FROM1 ¤«¤é $TO1 ¤Þ¤Ç¡¢$MT2 ¤Ç¤Ï $FROM2 ¤«¤é $TO2 ¤Þ¤Ç¤Ç¤¢¤ë¡£
2685 $FROM1 ¤È $FROM2 ¤Ï´Þ¤Þ¤ì¡¢$TO1 ¤È $TO2 ¤Ï´Þ¤Þ¤ì¤Ê¤¤¡£$FROM1 ¤È
2686 $TO1 ¡Ê¤¢¤ë¤¤¤Ï $FROM2 ¤È $TO2 ¡Ë¤¬Åù¤·¤¤¾ì¹ç¤ÏŤµ¥¼¥í¤Î M-text
2687 ¤ò°ÕÌ£¤¹¤ë¡£ÈÏ°Ï»ØÄê¤Ë¸í¤ê¤¬¤¢¤ë¾ì¹ç¤Ï¡¢$FROM1 ¤È $TO1 ¡Ê¤¢¤ë¤¤¤Ï
2688 $FROM2 ¤È $TO2 ¡ËξÊý¤Ë 0 ¤¬»ØÄꤵ¤ì¤¿¤â¤Î¤È¸«¤Ê¤¹¡£
2691 ¤³¤Î´Ø¿ô¤Ï¡¢$MT1 ¤È $MT2 ¤¬Åù¤·¤±¤ì¤Ð0¡¢$MT1 ¤¬ $MT2 ¤è¤êÂ礤±¤ì
2692 ¤Ð1¡¢$MT1 ¤¬ $MT2 ¤è¤ê¾®¤µ¤±¤ì¤Ð-1¤òÊÖ¤¹¡£Èæ³Ó¤Ïʸ»ú¥³¡¼¥É¤Ë´ð¤Å¤¯¡£
2694 @latexonly \IPAlabel{mtext_case_compare} @endlatexonly
2699 mtext_cmp (), mtext_ncmp (), mtext_casecmp (), mtext_ncasecmp (),
2703 mtext_case_compare (MText *mt1, int from1, int to1,
2704 MText *mt2, int from2, int to2)
2706 if (from1 < 0 || from1 > to1 || to1 > mt1->nchars)
2709 if (from2 < 0 || from2 > to2 || to2 > mt2->nchars)
2712 return case_compare (mt1, from1, to1, mt2, from2, to2);
2719 /*** @addtogroup m17nDebug */
2724 @brief Dump an M-text.
2726 The mdebug_dump_mtext () function prints the M-text $MT in a human
2727 readable way to the stderr. $INDENT specifies how many columns to
2728 indent the lines but the first one. If $FULLP is zero, this
2729 function prints only a character code sequence. Otherwise, it
2730 prints the internal byte sequence and text properties as well.
2733 This function returns $MT. */
2735 @brief M-text ¤ò¥À¥ó¥×¤¹¤ë.
2737 ´Ø¿ô mdebug_dump_mtext () ¤Ï M-text $MT ¤ò stderr ¤Ë¿Í´Ö¤Ë²ÄÆɤÊ
2738 ·Á¤Ç°õºþ¤¹¤ë¡£ $INDENT ¤Ï£²¹ÔÌܰʹߤΥ¤¥ó¥Ç¥ó¥È¤ò»ØÄꤹ¤ë¡£$FULLP
2739 ¤¬ 0 ¤Ê¤é¤Ð¡¢Ê¸»ú¥³¡¼¥ÉÎó¤À¤±¤ò°õºþ¤¹¤ë¡£¤½¤¦¤Ç¤Ê¤±¤ì¤Ð¡¢ÆâÉô¥Ð¥¤
2740 ¥ÈÎó¤È¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤â°õºþ¤¹¤ë¡£
2743 ¤³¤Î´Ø¿ô¤Ï $MT ¤òÊÖ¤¹¡£ */
2746 mdebug_dump_mtext (MText *mt, int indent, int fullp)
2748 char *prefix = (char *) alloca (indent + 1);
2752 memset (prefix, 32, indent);
2756 "(mtext (size %d %d %d) (cache %d %d)",
2757 mt->nchars, mt->nbytes, mt->allocated,
2758 mt->cache_char_pos, mt->cache_byte_pos);
2761 fprintf (stderr, " \"");
2762 for (i = 0; i < mt->nchars; i++)
2764 int c = mtext_ref_char (mt, i);
2765 if (c >= ' ' && c < 127)
2766 fprintf (stderr, "%c", c);
2768 fprintf (stderr, "\\x%02X", c);
2770 fprintf (stderr, "\"");
2772 else if (mt->nchars > 0)
2774 fprintf (stderr, "\n%s (bytes \"", prefix);
2775 for (i = 0; i < mt->nbytes; i++)
2776 fprintf (stderr, "\\x%02x", mt->data[i]);
2777 fprintf (stderr, "\")\n");
2778 fprintf (stderr, "%s (chars \"", prefix);
2780 for (i = 0; i < mt->nchars; i++)
2783 int c = STRING_CHAR_AND_BYTES (p, len);
2785 if (c >= ' ' && c < 127 && c != '\\' && c != '\"')
2788 fprintf (stderr, "\\x%X", c);
2791 fprintf (stderr, "\")");
2794 fprintf (stderr, "\n%s ", prefix);
2795 dump_textplist (mt->plist, indent + 1);
2798 fprintf (stderr, ")");