aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKenichi Handa1999-07-28 02:10:51 +0000
committerKenichi Handa1999-07-28 02:10:51 +0000
commit2d6115c83512590cda68e4a7911a82f30bf431e1 (patch)
tree608e3e411fc02b5e0c96ba4b9d5a42c7a92c268e /src
parentbe8a72f4245bbd4a5282e8c45a613b1d9ae7ac0e (diff)
downloademacs-2d6115c83512590cda68e4a7911a82f30bf431e1.tar.gz
emacs-2d6115c83512590cda68e4a7911a82f30bf431e1.zip
(count_combining): New function.
(struct textproc_rec): New structure. (concat): Copy text properties correctly when byte combining occurs.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c110
1 files changed, 81 insertions, 29 deletions
diff --git a/src/fns.c b/src/fns.c
index 554db983413..a1926e78e88 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -516,6 +516,37 @@ with the original.")
516 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0); 516 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
517} 517}
518 518
519/* In string STR of length LEN, see if bytes before STR[I] combine
520 with bytes after STR[I] to form a single character. If so, return
521 the number of bytes after STR[I] which combine in this way.
522 Otherwize, return 0. */
523
524static int
525count_combining (str, len, i)
526 unsigned char *str;
527 int len, i;
528{
529 int j = i - 1;
530
531 if (i == 0 || i == len || CHAR_HEAD_P (str[i]))
532 return 0;
533 while (j >= 0 && !CHAR_HEAD_P (str[j])) j--;
534 if (j < 0 || ! BASE_LEADING_CODE_P (str[j]))
535 return 0;
536 j = i + 1;
537 while (j < len && ! CHAR_HEAD_P (str[j])) j++;
538 return j - i;
539}
540
541/* This structure holds information of an argument of `concat' that is
542 a string and has text properties to be copied. */
543struct textproc_rec
544{
545 int argnum; /* refer to ARGS (arguments of `concat') */
546 int from; /* refer to ARGS[argnum] (argument string) */
547 int to; /* refer to VAL (the target string) */
548};
549
519static Lisp_Object 550static Lisp_Object
520concat (nargs, args, target_type, last_special) 551concat (nargs, args, target_type, last_special)
521 int nargs; 552 int nargs;
@@ -534,11 +565,14 @@ concat (nargs, args, target_type, last_special)
534 Lisp_Object last_tail; 565 Lisp_Object last_tail;
535 Lisp_Object prev; 566 Lisp_Object prev;
536 int some_multibyte; 567 int some_multibyte;
537 /* When we make a multibyte string, we must pay attention to the 568 /* When we make a multibyte string, we can't copy text properties
538 byte combining problem, i.e., a byte may be combined with a 569 while concatinating each string because the length of resulting
539 multibyte charcter of the previous string. This flag tells if we 570 string can't be decided until we finish the whole concatination.
540 must consider such a situation or not. */ 571 So, we record strings that have text properties to be copied
541 int maybe_combine_byte; 572 here, and copy the text properties after the concatination. */
573 struct textproc_rec *textprocs;
574 /* Number of elments in textprocs. */
575 int num_textprocs = 0;
542 576
543 /* In append, the last arg isn't treated like the others */ 577 /* In append, the last arg isn't treated like the others */
544 if (last_special && nargs > 0) 578 if (last_special && nargs > 0)
@@ -642,13 +676,15 @@ concat (nargs, args, target_type, last_special)
642 676
643 /* Copy the contents of the args into the result. */ 677 /* Copy the contents of the args into the result. */
644 if (CONSP (val)) 678 if (CONSP (val))
645 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */ 679 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
646 else 680 else
647 toindex = 0, toindex_byte = 0; 681 toindex = 0, toindex_byte = 0;
648 682
649 prev = Qnil; 683 prev = Qnil;
684 if (STRINGP (val))
685 textprocs
686 = (struct textproc_rec *) alloca (sizeof (struct textproc_rec) * nargs);
650 687
651 maybe_combine_byte = 0;
652 for (argnum = 0; argnum < nargs; argnum++) 688 for (argnum = 0; argnum < nargs; argnum++)
653 { 689 {
654 Lisp_Object thislen; 690 Lisp_Object thislen;
@@ -660,29 +696,40 @@ concat (nargs, args, target_type, last_special)
660 if (!CONSP (this)) 696 if (!CONSP (this))
661 thislen = Flength (this), thisleni = XINT (thislen); 697 thislen = Flength (this), thisleni = XINT (thislen);
662 698
663 if (STRINGP (this) && STRINGP (val)
664 && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
665 copy_text_properties (make_number (0), thislen, this,
666 make_number (toindex), val, Qnil);
667
668 /* Between strings of the same kind, copy fast. */ 699 /* Between strings of the same kind, copy fast. */
669 if (STRINGP (this) && STRINGP (val) 700 if (STRINGP (this) && STRINGP (val)
670 && STRING_MULTIBYTE (this) == some_multibyte) 701 && STRING_MULTIBYTE (this) == some_multibyte)
671 { 702 {
672 int thislen_byte = STRING_BYTES (XSTRING (this)); 703 int thislen_byte = STRING_BYTES (XSTRING (this));
704 int combined;
705
673 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte, 706 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
674 STRING_BYTES (XSTRING (this))); 707 STRING_BYTES (XSTRING (this)));
675 if (some_multibyte 708 combined = (some_multibyte && toindex_byte > 0
676 && toindex_byte > 0 709 ? count_combining (XSTRING (val)->data,
677 && !ASCII_BYTE_P (XSTRING (val)->data[toindex_byte - 1]) 710 toindex_byte + thislen_byte,
678 && !CHAR_HEAD_P (XSTRING (this)->data[0])) 711 toindex_byte)
679 maybe_combine_byte = 1; 712 : 0);
713 if (! NULL_INTERVAL_P (XSTRING (this)->intervals))
714 {
715 textprocs[num_textprocs].argnum = argnum;
716 /* We ignore text properties on characters being combined. */
717 textprocs[num_textprocs].from = combined;
718 textprocs[num_textprocs++].to = toindex;
719 }
680 toindex_byte += thislen_byte; 720 toindex_byte += thislen_byte;
681 toindex += thisleni; 721 toindex += thisleni - combined;
722 XSTRING (val)->size -= combined;
682 } 723 }
683 /* Copy a single-byte string to a multibyte string. */ 724 /* Copy a single-byte string to a multibyte string. */
684 else if (STRINGP (this) && STRINGP (val)) 725 else if (STRINGP (this) && STRINGP (val))
685 { 726 {
727 if (! NULL_INTERVAL_P (XSTRING (this)->intervals))
728 {
729 textprocs[num_textprocs].argnum = argnum;
730 textprocs[num_textprocs].from = 0;
731 textprocs[num_textprocs++].to = toindex;
732 }
686 toindex_byte += copy_text (XSTRING (this)->data, 733 toindex_byte += copy_text (XSTRING (this)->data,
687 XSTRING (val)->data + toindex_byte, 734 XSTRING (val)->data + toindex_byte,
688 XSTRING (this)->size, 0, 1); 735 XSTRING (this)->size, 0, 1);
@@ -752,13 +799,14 @@ concat (nargs, args, target_type, last_special)
752 CHECK_NUMBER (elt, 0); 799 CHECK_NUMBER (elt, 0);
753 if (SINGLE_BYTE_CHAR_P (XINT (elt))) 800 if (SINGLE_BYTE_CHAR_P (XINT (elt)))
754 { 801 {
802 XSTRING (val)->data[toindex_byte++] = XINT (elt);
755 if (some_multibyte 803 if (some_multibyte
756 && toindex_byte > 0 804 && toindex_byte > 0
757 && !ASCII_BYTE_P (XSTRING (val)->data[toindex_byte - 1]) 805 && count_combining (XSTRING (val)->data,
758 && !CHAR_HEAD_P (XINT (elt))) 806 toindex_byte, toindex_byte - 1))
759 maybe_combine_byte = 1; 807 XSTRING (val)->size--;
760 XSTRING (val)->data[toindex_byte++] = XINT (elt); 808 else
761 toindex++; 809 toindex++;
762 } 810 }
763 else 811 else
764 /* If we have any multibyte characters, 812 /* If we have any multibyte characters,
@@ -781,12 +829,16 @@ concat (nargs, args, target_type, last_special)
781 if (!NILP (prev)) 829 if (!NILP (prev))
782 XCONS (prev)->cdr = last_tail; 830 XCONS (prev)->cdr = last_tail;
783 831
784 if (maybe_combine_byte) 832 if (num_textprocs > 0)
785 /* Character counter of the multibyte string VAL may be wrong 833 {
786 because of byte combining problem. We must re-calculate it. */ 834 for (argnum = 0; argnum < num_textprocs; argnum++)
787 XSTRING (val)->size = multibyte_chars_in_text (XSTRING (val)->data, 835 {
788 XSTRING (val)->size_byte); 836 this = args[textprocs[argnum].argnum];
789 837 copy_text_properties (make_number (textprocs[argnum].from),
838 XSTRING (this)->size, this,
839 make_number (textprocs[argnum].to), val, Qnil);
840 }
841 }
790 return val; 842 return val;
791} 843}
792 844