aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1998-01-09 22:41:43 +0000
committerRichard M. Stallman1998-01-09 22:41:43 +0000
commitea35ce3d99adfbe260d32b6f30c7ec0b0895219a (patch)
treef09a52667e10dc0edcdb03a4da053fffc215fcb9 /src
parent1f24f4fdd2b7203aa75728a4437cb0520a8e6877 (diff)
downloademacs-ea35ce3d99adfbe260d32b6f30c7ec0b0895219a.tar.gz
emacs-ea35ce3d99adfbe260d32b6f30c7ec0b0895219a.zip
(map_char_table): Unconditionally consider non-ASCII charsets.
(Fsubstring): Use make_multibyte_string. (concat, Fsubstring, internal_equal, mapcar1): Distinguish bytes and chars when indexing strings. (Fstring_equal, Fstring_lessp): Likewise. (substring_both): New function. (string_make_multibyte, string_make_unibyte): New functions. (string_char_to_byte, string_byte_to_char): New functions.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c454
1 files changed, 339 insertions, 115 deletions
diff --git a/src/fns.c b/src/fns.c
index bab53aa44fd..c1e29b82e96 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -178,7 +178,7 @@ which is at least the number of distinct elements.")
178} 178}
179 179
180DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0, 180DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
181 "T if two strings have identical contents.\n\ 181 "Return t if two strings have identical contents.\n\
182Case is significant, but text properties are ignored.\n\ 182Case is significant, but text properties are ignored.\n\
183Symbols are also allowed; their print names are used instead.") 183Symbols are also allowed; their print names are used instead.")
184 (s1, s2) 184 (s1, s2)
@@ -191,14 +191,15 @@ Symbols are also allowed; their print names are used instead.")
191 CHECK_STRING (s1, 0); 191 CHECK_STRING (s1, 0);
192 CHECK_STRING (s2, 1); 192 CHECK_STRING (s2, 1);
193 193
194 if (XSTRING (s1)->size != XSTRING (s2)->size || 194 if (XSTRING (s1)->size != XSTRING (s2)->size
195 bcmp (XSTRING (s1)->data, XSTRING (s2)->data, XSTRING (s1)->size)) 195 || XSTRING (s1)->size_byte != XSTRING (s2)->size_byte
196 || bcmp (XSTRING (s1)->data, XSTRING (s2)->data, XSTRING (s1)->size_byte))
196 return Qnil; 197 return Qnil;
197 return Qt; 198 return Qt;
198} 199}
199 200
200DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0, 201DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
201 "T if first arg string is less than second in lexicographic order.\n\ 202 "Return t if first arg string is less than second in lexicographic order.\n\
202Case is significant.\n\ 203Case is significant.\n\
203Symbols are also allowed; their print names are used instead.") 204Symbols are also allowed; their print names are used instead.")
204 (s1, s2) 205 (s1, s2)
@@ -217,16 +218,16 @@ Symbols are also allowed; their print names are used instead.")
217 218
218 p1 = XSTRING (s1)->data; 219 p1 = XSTRING (s1)->data;
219 p2 = XSTRING (s2)->data; 220 p2 = XSTRING (s2)->data;
220 end = XSTRING (s1)->size; 221 end = XSTRING (s1)->size_byte;
221 if (end > XSTRING (s2)->size) 222 if (end > XSTRING (s2)->size_byte)
222 end = XSTRING (s2)->size; 223 end = XSTRING (s2)->size_byte;
223 224
224 for (i = 0; i < end; i++) 225 for (i = 0; i < end; i++)
225 { 226 {
226 if (p1[i] != p2[i]) 227 if (p1[i] != p2[i])
227 return p1[i] < p2[i] ? Qt : Qnil; 228 return p1[i] < p2[i] ? Qt : Qnil;
228 } 229 }
229 return i < XSTRING (s2)->size ? Qt : Qnil; 230 return i < XSTRING (s2)->size_byte ? Qt : Qnil;
230} 231}
231 232
232static Lisp_Object concat (); 233static Lisp_Object concat ();
@@ -379,14 +380,16 @@ concat (nargs, args, target_type, last_special)
379 int last_special; 380 int last_special;
380{ 381{
381 Lisp_Object val; 382 Lisp_Object val;
382 Lisp_Object len;
383 register Lisp_Object tail; 383 register Lisp_Object tail;
384 register Lisp_Object this; 384 register Lisp_Object this;
385 int toindex; 385 int toindex;
386 register int leni; 386 int toindex_byte;
387 register int result_len;
388 register int result_len_byte;
387 register int argnum; 389 register int argnum;
388 Lisp_Object last_tail; 390 Lisp_Object last_tail;
389 Lisp_Object prev; 391 Lisp_Object prev;
392 int some_multibyte;
390 393
391 /* In append, the last arg isn't treated like the others */ 394 /* In append, the last arg isn't treated like the others */
392 if (last_special && nargs > 0) 395 if (last_special && nargs > 0)
@@ -397,6 +400,7 @@ concat (nargs, args, target_type, last_special)
397 else 400 else
398 last_tail = Qnil; 401 last_tail = Qnil;
399 402
403 /* Canonicalize each argument. */
400 for (argnum = 0; argnum < nargs; argnum++) 404 for (argnum = 0; argnum < nargs; argnum++)
401 { 405 {
402 this = args[argnum]; 406 this = args[argnum];
@@ -410,56 +414,77 @@ concat (nargs, args, target_type, last_special)
410 } 414 }
411 } 415 }
412 416
413 for (argnum = 0, leni = 0; argnum < nargs; argnum++) 417 /* Compute total length in chars of arguments in RESULT_LEN.
418 If desired output is a string, also compute length in bytes
419 in RESULT_LEN_BYTE, and determine in SOME_MULTIBYTE
420 whether the result should be a multibyte string. */
421 result_len_byte = 0;
422 result_len = 0;
423 some_multibyte = 0;
424 for (argnum = 0; argnum < nargs; argnum++)
414 { 425 {
426 int len;
415 this = args[argnum]; 427 this = args[argnum];
416 len = Flength (this); 428 len = XFASTINT (Flength (this));
417 if ((VECTORP (this) || CONSP (this)) && target_type == Lisp_String) 429 if (target_type == Lisp_String)
418
419 { 430 {
420 /* We must pay attention to a multibyte character which 431 /* We must pay attention to a multibyte character which
421 takes more than one byte in string. */ 432 takes more than one byte in string. */
422 int i; 433 int i;
423 Lisp_Object ch; 434 Lisp_Object ch;
435 int this_len_byte;
424 436
425 if (VECTORP (this)) 437 if (VECTORP (this))
426 for (i = 0; i < XFASTINT (len); i++) 438 for (i = 0; i < len; i++)
427 { 439 {
428 ch = XVECTOR (this)->contents[i]; 440 ch = XVECTOR (this)->contents[i];
429 if (! INTEGERP (ch)) 441 if (! INTEGERP (ch))
430 wrong_type_argument (Qintegerp, ch); 442 wrong_type_argument (Qintegerp, ch);
431 leni += XFASTINT (Fchar_bytes (ch)); 443 this_len_byte = XFASTINT (Fchar_bytes (ch));
444 result_len_byte += this_len_byte;
445 if (this_len_byte > 1)
446 some_multibyte = 1;
432 } 447 }
433 else 448 else if (CONSP (this))
434 for (; CONSP (this); this = XCONS (this)->cdr) 449 for (; CONSP (this); this = XCONS (this)->cdr)
435 { 450 {
436 ch = XCONS (this)->car; 451 ch = XCONS (this)->car;
437 if (! INTEGERP (ch)) 452 if (! INTEGERP (ch))
438 wrong_type_argument (Qintegerp, ch); 453 wrong_type_argument (Qintegerp, ch);
439 leni += XFASTINT (Fchar_bytes (ch)); 454 this_len_byte = XFASTINT (Fchar_bytes (ch));
455 result_len_byte += this_len_byte;
456 if (this_len_byte > 1)
457 some_multibyte = 1;
440 } 458 }
459 else
460 {
461 result_len_byte += XSTRING (this)->size_byte;
462 if (STRING_MULTIBYTE (this))
463 some_multibyte = 1;
464 }
441 } 465 }
442 else 466
443 leni += XFASTINT (len); 467 result_len += len;
444 } 468 }
445 469
446 XSETFASTINT (len, leni); 470 /* In `append', if all but last arg are nil, return last arg. */
471 if (target_type == Lisp_Cons && EQ (val, Qnil))
472 return last_tail;
447 473
474 /* Create the output object. */
448 if (target_type == Lisp_Cons) 475 if (target_type == Lisp_Cons)
449 val = Fmake_list (len, Qnil); 476 val = Fmake_list (make_number (result_len), Qnil);
450 else if (target_type == Lisp_Vectorlike) 477 else if (target_type == Lisp_Vectorlike)
451 val = Fmake_vector (len, Qnil); 478 val = Fmake_vector (make_number (result_len), Qnil);
452 else 479 else
453 val = Fmake_string (len, len); 480 val = make_uninit_multibyte_string (result_len, result_len_byte);
454 481
455 /* In append, if all but last arg are nil, return last arg */
456 if (target_type == Lisp_Cons && EQ (val, Qnil))
457 return last_tail;
458 482
483 /* Copy the contents of the args into the result. */
459 if (CONSP (val)) 484 if (CONSP (val))
460 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */ 485 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
461 else 486 else
462 toindex = 0; 487 toindex = 0, toindex_byte = 0;
463 488
464 prev = Qnil; 489 prev = Qnil;
465 490
@@ -468,6 +493,7 @@ concat (nargs, args, target_type, last_special)
468 Lisp_Object thislen; 493 Lisp_Object thislen;
469 int thisleni; 494 int thisleni;
470 register unsigned int thisindex = 0; 495 register unsigned int thisindex = 0;
496 register unsigned int thisindex_byte = 0;
471 497
472 this = args[argnum]; 498 this = args[argnum];
473 if (!CONSP (this)) 499 if (!CONSP (this))
@@ -475,71 +501,106 @@ concat (nargs, args, target_type, last_special)
475 501
476 if (STRINGP (this) && STRINGP (val) 502 if (STRINGP (this) && STRINGP (val)
477 && ! NULL_INTERVAL_P (XSTRING (this)->intervals)) 503 && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
478 { 504 copy_text_properties (make_number (0), thislen, this,
479 copy_text_properties (make_number (0), thislen, this, 505 make_number (toindex), val, Qnil);
480 make_number (toindex), val, Qnil);
481 }
482 506
483 while (1) 507 /* Between strings of the same kind, copy fast. */
508 if (STRINGP (this) && STRINGP (val)
509 && STRING_MULTIBYTE (this) == some_multibyte)
484 { 510 {
485 register Lisp_Object elt; 511 int thislen_byte = XSTRING (this)->size_byte;
486 512 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
487 /* Fetch next element of `this' arg into `elt', or break if 513 XSTRING (this)->size_byte);
488 `this' is exhausted. */ 514 toindex_byte += thislen_byte;
489 if (NILP (this)) break; 515 toindex += thisleni;
490 if (CONSP (this)) 516 }
491 elt = XCONS (this)->car, this = XCONS (this)->cdr; 517 else
492 else 518 /* Copy element by element. */
493 { 519 while (1)
494 if (thisindex >= thisleni) break; 520 {
495 if (STRINGP (this)) 521 register Lisp_Object elt;
496 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]); 522
497 else if (BOOL_VECTOR_P (this)) 523 /* Fetch next element of `this' arg into `elt', or break if
498 { 524 `this' is exhausted. */
499 int size_in_chars 525 if (NILP (this)) break;
500 = ((XBOOL_VECTOR (this)->size + BITS_PER_CHAR - 1) 526 if (CONSP (this))
501 / BITS_PER_CHAR); 527 elt = XCONS (this)->car, this = XCONS (this)->cdr;
502 int byte; 528 else
503 byte = XBOOL_VECTOR (val)->data[thisindex / BITS_PER_CHAR]; 529 {
504 if (byte & (1 << (thisindex % BITS_PER_CHAR))) 530 if (thisindex >= thisleni) break;
505 elt = Qt; 531 if (STRINGP (this))
506 else 532 {
507 elt = Qnil; 533 if (STRING_MULTIBYTE (this))
508 } 534 {
509 else 535 int c;
510 elt = XVECTOR (this)->contents[thisindex++]; 536 FETCH_STRING_CHAR_ADVANCE (c, this,
511 } 537 thisindex,
538 thisindex_byte);
539 XSETFASTINT (elt, c);
540 }
541 else
542 {
543 unsigned char c;
544 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
545 if (some_multibyte && XINT (elt) >= 0200
546 && XINT (elt) < 0400)
547 {
548 c = XINT (elt);
549 copy_text (&c, &c, 1, 0, 1);
550 XSETINT (elt, c);
551 }
552 }
553 }
554 else if (BOOL_VECTOR_P (this))
555 {
556 int size_in_chars
557 = ((XBOOL_VECTOR (this)->size + BITS_PER_CHAR - 1)
558 / BITS_PER_CHAR);
559 int byte;
560 byte = XBOOL_VECTOR (val)->data[thisindex / BITS_PER_CHAR];
561 if (byte & (1 << (thisindex % BITS_PER_CHAR)))
562 elt = Qt;
563 else
564 elt = Qnil;
565 }
566 else
567 elt = XVECTOR (this)->contents[thisindex++];
568 }
512 569
513 /* Store into result */ 570 /* Store this element into the result. */
514 if (toindex < 0) 571 if (toindex < 0)
515 {
516 XCONS (tail)->car = elt;
517 prev = tail;
518 tail = XCONS (tail)->cdr;
519 }
520 else if (VECTORP (val))
521 XVECTOR (val)->contents[toindex++] = elt;
522 else
523 {
524 while (!INTEGERP (elt))
525 elt = wrong_type_argument (Qintegerp, elt);
526 { 572 {
527 int c = XINT (elt); 573 XCONS (tail)->car = elt;
528 unsigned char work[4], *str; 574 prev = tail;
529 int i = CHAR_STRING (c, work, str); 575 tail = XCONS (tail)->cdr;
530
531#ifdef MASSC_REGISTER_BUG
532 /* Even removing all "register"s doesn't disable this bug!
533 Nothing simpler than this seems to work. */
534 unsigned char *p = & XSTRING (val)->data[toindex];
535 bcopy (str, p, i);
536#else
537 bcopy (str, & XSTRING (val)->data[toindex], i);
538#endif
539 toindex += i;
540 } 576 }
541 } 577 else if (VECTORP (val))
542 } 578 XVECTOR (val)->contents[toindex++] = elt;
579 else
580 {
581 CHECK_NUMBER (elt, 0);
582 if (SINGLE_BYTE_CHAR_P (XINT (elt)))
583 {
584 XSTRING (val)->data[toindex++] = XINT (elt);
585 toindex_byte++;
586 }
587 else
588 /* If we have any multibyte characters,
589 we already decided to make a multibyte string. */
590 {
591 int c = XINT (elt);
592 unsigned char work[4], *str;
593 int i = CHAR_STRING (c, work, str);
594
595 /* P exists as a variable
596 to avoid a bug on the Masscomp C compiler. */
597 unsigned char *p = & XSTRING (val)->data[toindex_byte];
598 bcopy (str, p, i);
599 toindex_byte += i;
600 toindex++;
601 }
602 }
603 }
543 } 604 }
544 if (!NILP (prev)) 605 if (!NILP (prev))
545 XCONS (prev)->cdr = last_tail; 606 XCONS (prev)->cdr = last_tail;
@@ -547,6 +608,90 @@ concat (nargs, args, target_type, last_special)
547 return val; 608 return val;
548} 609}
549 610
611/* Return the character index corresponding to CHAR_INDEX in STRING. */
612
613int
614string_char_to_byte (string, char_index)
615 Lisp_Object string;
616 int char_index;
617{
618 int i = 0, i_byte = 0;
619
620 if (! STRING_MULTIBYTE (string))
621 return char_index;
622
623 while (i < char_index)
624 {
625 int c;
626 FETCH_STRING_CHAR_ADVANCE (c, string, i, i_byte);
627 }
628
629 return i_byte;
630}
631
632/* Return the character index corresponding to BYTE_INDEX in STRING. */
633
634int
635string_byte_to_char (string, byte_index)
636 Lisp_Object string;
637 int byte_index;
638{
639 int i = 0, i_byte = 0;
640
641 if (! STRING_MULTIBYTE (string))
642 return byte_index;
643
644 while (i_byte < byte_index)
645 {
646 int c;
647 FETCH_STRING_CHAR_ADVANCE (c, string, i, i_byte);
648 }
649
650 return i;
651}
652
653/* Convert STRING to a multibyte string.
654 Single-byte characters 0200 through 0377 are converted
655 by adding nonascii_insert_offset to each. */
656
657Lisp_Object
658string_make_multibyte (string)
659 Lisp_Object string;
660{
661 unsigned char *buf;
662 int nbytes;
663
664 if (STRING_MULTIBYTE (string))
665 return string;
666
667 nbytes = count_size_as_multibyte (XSTRING (string)->data,
668 XSTRING (string)->size);
669 buf = (unsigned char *) alloca (nbytes);
670 copy_text (XSTRING (string)->data, buf, XSTRING (string)->size_byte,
671 0, 1);
672
673 return make_multibyte_string (buf, XSTRING (string)->size, nbytes);
674}
675
676/* Convert STRING to a single-byte string. */
677
678Lisp_Object
679string_make_unibyte (string)
680 Lisp_Object string;
681{
682 unsigned char *buf;
683
684 if (! STRING_MULTIBYTE (string))
685 return string;
686
687 buf = (unsigned char *) alloca (XSTRING (string)->size);
688
689 copy_text (XSTRING (string)->data, buf, XSTRING (string)->size_byte,
690 1, 0);
691
692 return make_unibyte_string (buf, XSTRING (string)->size);
693}
694
550DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0, 695DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
551 "Return a copy of ALIST.\n\ 696 "Return a copy of ALIST.\n\
552This is an alist which represents the same mapping from objects to objects,\n\ 697This is an alist which represents the same mapping from objects to objects,\n\
@@ -586,6 +731,9 @@ This function allows vectors as well as strings.")
586{ 731{
587 Lisp_Object res; 732 Lisp_Object res;
588 int size; 733 int size;
734 int size_byte;
735 int from_char, to_char;
736 int from_byte, to_byte;
589 737
590 if (! (STRINGP (string) || VECTORP (string))) 738 if (! (STRINGP (string) || VECTORP (string)))
591 wrong_type_argument (Qarrayp, string); 739 wrong_type_argument (Qarrayp, string);
@@ -593,32 +741,89 @@ This function allows vectors as well as strings.")
593 CHECK_NUMBER (from, 1); 741 CHECK_NUMBER (from, 1);
594 742
595 if (STRINGP (string)) 743 if (STRINGP (string))
596 size = XSTRING (string)->size; 744 {
745 size = XSTRING (string)->size;
746 size_byte = XSTRING (string)->size_byte;
747 }
597 else 748 else
598 size = XVECTOR (string)->size; 749 size = XVECTOR (string)->size;
599 750
600 if (NILP (to)) 751 if (NILP (to))
601 XSETINT (to, size); 752 {
753 to_char = size;
754 to_byte = size_byte;
755 }
602 else 756 else
603 CHECK_NUMBER (to, 2); 757 {
758 CHECK_NUMBER (to, 2);
759
760 to_char = XINT (to);
761 if (to_char < 0)
762 to_char += size;
763
764 if (STRINGP (string))
765 to_byte = string_char_to_byte (string, to_char);
766 }
767
768 from_char = XINT (from);
769 if (from_char < 0)
770 from_char += size;
771 if (STRINGP (string))
772 from_byte = string_char_to_byte (string, from_char);
604 773
605 if (XINT (from) < 0) 774 if (!(0 <= from_char && from_char <= to_char && to_char <= size))
606 XSETINT (from, XINT (from) + size); 775 args_out_of_range_3 (string, make_number (from_char),
607 if (XINT (to) < 0) 776 make_number (to_char));
608 XSETINT (to, XINT (to) + size);
609 if (!(0 <= XINT (from) && XINT (from) <= XINT (to)
610 && XINT (to) <= size))
611 args_out_of_range_3 (string, from, to);
612 777
613 if (STRINGP (string)) 778 if (STRINGP (string))
614 { 779 {
615 res = make_string (XSTRING (string)->data + XINT (from), 780 res = make_multibyte_string (XSTRING (string)->data + from_byte,
616 XINT (to) - XINT (from)); 781 to_char - from_char, to_byte - from_byte);
782 copy_text_properties (from_char, to_char, string,
783 make_number (0), res, Qnil);
784 }
785 else
786 res = Fvector (to_char - from_char,
787 XVECTOR (string)->contents + from_char);
788
789 return res;
790}
791
792/* Extract a substring of STRING, giving start and end positions
793 both in characters and in bytes. */
794
795Lisp_Object
796substring_both (string, from, from_byte, to, to_byte)
797 Lisp_Object string;
798 int from, from_byte, to, to_byte;
799{
800 Lisp_Object res;
801 int size;
802 int size_byte;
803
804 if (! (STRINGP (string) || VECTORP (string)))
805 wrong_type_argument (Qarrayp, string);
806
807 if (STRINGP (string))
808 {
809 size = XSTRING (string)->size;
810 size_byte = XSTRING (string)->size_byte;
811 }
812 else
813 size = XVECTOR (string)->size;
814
815 if (!(0 <= from && from <= to && to <= size))
816 args_out_of_range_3 (string, make_number (from), make_number (to));
817
818 if (STRINGP (string))
819 {
820 res = make_multibyte_string (XSTRING (string)->data + from_byte,
821 to - from, to_byte - from_byte);
617 copy_text_properties (from, to, string, make_number (0), res, Qnil); 822 copy_text_properties (from, to, string, make_number (0), res, Qnil);
618 } 823 }
619 else 824 else
620 res = Fvector (XINT (to) - XINT (from), 825 res = Fvector (to - from,
621 XVECTOR (string)->contents + XINT (from)); 826 XVECTOR (string)->contents + from);
622 827
623 return res; 828 return res;
624} 829}
@@ -1081,7 +1286,7 @@ It can be retrieved with `(get SYMBOL PROPNAME)'.")
1081} 1286}
1082 1287
1083DEFUN ("equal", Fequal, Sequal, 2, 2, 0, 1288DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
1084 "T if two Lisp objects have similar structure and contents.\n\ 1289 "Return t if two Lisp objects have similar structure and contents.\n\
1085They must have the same data type.\n\ 1290They must have the same data type.\n\
1086Conses are compared by comparing the cars and the cdrs.\n\ 1291Conses are compared by comparing the cars and the cdrs.\n\
1087Vectors and strings are compared element by element.\n\ 1292Vectors and strings are compared element by element.\n\
@@ -1191,8 +1396,10 @@ internal_equal (o1, o2, depth)
1191 case Lisp_String: 1396 case Lisp_String:
1192 if (XSTRING (o1)->size != XSTRING (o2)->size) 1397 if (XSTRING (o1)->size != XSTRING (o2)->size)
1193 return 0; 1398 return 0;
1399 if (XSTRING (o1)->size_byte != XSTRING (o2)->size_byte)
1400 return 0;
1194 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data, 1401 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
1195 XSTRING (o1)->size)) 1402 XSTRING (o1)->size_byte))
1196 return 0; 1403 return 0;
1197 return 1; 1404 return 1;
1198 } 1405 }
@@ -1250,7 +1457,7 @@ ARRAY is a vector, string, char-table, or bool-vector.")
1250 } 1457 }
1251 return array; 1458 return array;
1252} 1459}
1253 1460
1254DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype, 1461DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
1255 1, 1, 0, 1462 1, 1, 0,
1256 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.") 1463 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
@@ -1332,7 +1539,7 @@ DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
1332 1539
1333 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value; 1540 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
1334} 1541}
1335 1542
1336DEFUN ("char-table-range", Fchar_table_range, Schar_table_range, 1543DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
1337 2, 2, 0, 1544 2, 2, 0,
1338 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\ 1545 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
@@ -1454,7 +1661,6 @@ See also the documentation of make-char.")
1454 XCHAR_TABLE (char_table)->contents[code1] = value; 1661 XCHAR_TABLE (char_table)->contents[code1] = value;
1455 return value; 1662 return value;
1456} 1663}
1457
1458 1664
1459/* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each 1665/* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
1460 character or group of characters that share a value. 1666 character or group of characters that share a value.
@@ -1483,8 +1689,11 @@ map_char_table (c_function, function, subtable, arg, depth, indices)
1483 else 1689 else
1484 call2 (function, make_number (i), elt); 1690 call2 (function, make_number (i), elt);
1485 } 1691 }
1692#if 0 /* If the char table has entries for higher characters,
1693 we should report them. */
1486 if (NILP (current_buffer->enable_multibyte_characters)) 1694 if (NILP (current_buffer->enable_multibyte_characters))
1487 return; 1695 return;
1696#endif
1488 to = CHAR_TABLE_ORDINARY_SLOTS; 1697 to = CHAR_TABLE_ORDINARY_SLOTS;
1489 } 1698 }
1490 else 1699 else
@@ -1597,9 +1806,9 @@ Only the last argument is not altered, and need not be a list.")
1597} 1806}
1598 1807
1599/* This is the guts of all mapping functions. 1808/* This is the guts of all mapping functions.
1600 Apply fn to each element of seq, one by one, 1809 Apply FN to each element of SEQ, one by one,
1601 storing the results into elements of vals, a C vector of Lisp_Objects. 1810 storing the results into elements of VALS, a C vector of Lisp_Objects.
1602 leni is the length of vals, which should also be the length of seq. */ 1811 LENI is the length of VALS, which should also be the length of SEQ. */
1603 1812
1604static void 1813static void
1605mapcar1 (leni, vals, fn, seq) 1814mapcar1 (leni, vals, fn, seq)
@@ -1630,14 +1839,29 @@ mapcar1 (leni, vals, fn, seq)
1630 vals[i] = call1 (fn, dummy); 1839 vals[i] = call1 (fn, dummy);
1631 } 1840 }
1632 } 1841 }
1633 else if (STRINGP (seq)) 1842 else if (STRINGP (seq) && ! STRING_MULTIBYTE (seq))
1634 { 1843 {
1844 /* Single-byte string. */
1635 for (i = 0; i < leni; i++) 1845 for (i = 0; i < leni; i++)
1636 { 1846 {
1637 XSETFASTINT (dummy, XSTRING (seq)->data[i]); 1847 XSETFASTINT (dummy, XSTRING (seq)->data[i]);
1638 vals[i] = call1 (fn, dummy); 1848 vals[i] = call1 (fn, dummy);
1639 } 1849 }
1640 } 1850 }
1851 else if (STRINGP (seq))
1852 {
1853 /* Multi-byte string. */
1854 int len_byte = XSTRING (seq)->size_byte;
1855 int i_byte;
1856
1857 for (i = 0, i_byte = 0; i < leni;)
1858 {
1859 int c;
1860 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte)
1861 XSETFASTINT (dummy, c);
1862 vals[i] = call1 (fn, dummy);
1863 }
1864 }
1641 else /* Must be a list, since Flength did not get an error */ 1865 else /* Must be a list, since Flength did not get an error */
1642 { 1866 {
1643 tail = seq; 1867 tail = seq;
@@ -1752,7 +1976,7 @@ Also accepts Space to mean yes, or Delete to mean no.")
1752#endif /* HAVE_MENUS */ 1976#endif /* HAVE_MENUS */
1753 cursor_in_echo_area = 1; 1977 cursor_in_echo_area = 1;
1754 choose_minibuf_frame (); 1978 choose_minibuf_frame ();
1755 message_nolog ("%s(y or n) ", XSTRING (xprompt)->data); 1979 message_with_string ("%s(y or n) ", xprompt, 0);
1756 1980
1757 if (minibuffer_auto_raise) 1981 if (minibuffer_auto_raise)
1758 { 1982 {
@@ -1815,8 +2039,8 @@ Also accepts Space to mean yes, or Delete to mean no.")
1815 if (! noninteractive) 2039 if (! noninteractive)
1816 { 2040 {
1817 cursor_in_echo_area = -1; 2041 cursor_in_echo_area = -1;
1818 message_nolog ("%s(y or n) %c", 2042 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
1819 XSTRING (xprompt)->data, answer ? 'y' : 'n'); 2043 xprompt, 0);
1820 } 2044 }
1821 2045
1822 unbind_to (count, Qnil); 2046 unbind_to (count, Qnil);