[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] Changes to emacs/src/editfns.c
From: |
Richard M. Stallman |
Subject: |
[Emacs-diffs] Changes to emacs/src/editfns.c |
Date: |
Tue, 08 Apr 2003 21:28:44 -0400 |
Index: emacs/src/editfns.c
diff -c emacs/src/editfns.c:1.353 emacs/src/editfns.c:1.354
*** emacs/src/editfns.c:1.353 Fri Apr 4 05:47:15 2003
--- emacs/src/editfns.c Tue Apr 8 21:28:44 2003
***************
*** 3201,3207 ****
register int n; /* The number of the next arg to substitute */
register int total; /* An estimate of the final length */
char *buf, *p;
! register unsigned char *format, *end;
int nchars;
/* Nonzero if the output should be a multibyte string,
which is true if any of the inputs is one. */
--- 3201,3207 ----
register int n; /* The number of the next arg to substitute */
register int total; /* An estimate of the final length */
char *buf, *p;
! register unsigned char *format, *end, *format_start;
int nchars;
/* Nonzero if the output should be a multibyte string,
which is true if any of the inputs is one. */
***************
*** 3220,3228 ****
int *precision = (int *) (alloca(nargs * sizeof (int)));
int longest_format;
Lisp_Object val;
struct info
{
! int start, end;
} *info = 0;
/* It should not be necessary to GCPRO ARGS, because
--- 3220,3239 ----
int *precision = (int *) (alloca(nargs * sizeof (int)));
int longest_format;
Lisp_Object val;
+ int arg_intervals = 0;
+
+ /* discarded[I] is 1 if byte I of the format
+ string was not copied into the output.
+ It is 2 if byte I was not the first byte of its character. */
+ char *discarded;
+
+ /* Each element records, for one argument,
+ the start and end bytepos in the output string,
+ and whether the argument is a string with intervals.
+ info[0] is unused. Unused elements have -1 for start. */
struct info
{
! int start, end, intervals;
} *info = 0;
/* It should not be necessary to GCPRO ARGS, because
***************
*** 3232,3243 ****
This is not always right; sometimes the result needs to be multibyte
because of an object that we will pass through prin1,
and in that case, we won't know it here. */
! for (n = 0; n < nargs; n++) {
! if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
! multibyte = 1;
! /* Piggyback on this loop to initialize precision[N]. */
! precision[n] = -1;
! }
CHECK_STRING (args[0]);
/* We may have to change "%S" to "%s". */
--- 3243,3255 ----
This is not always right; sometimes the result needs to be multibyte
because of an object that we will pass through prin1,
and in that case, we won't know it here. */
! for (n = 0; n < nargs; n++)
! {
! if (STRINGP (args[n]) && STRING_MULTIBYTE (args[n]))
! multibyte = 1;
! /* Piggyback on this loop to initialize precision[N]. */
! precision[n] = -1;
! }
CHECK_STRING (args[0]);
/* We may have to change "%S" to "%s". */
***************
*** 3248,3259 ****
--- 3260,3284 ----
retry:
format = SDATA (args[0]);
+ format_start = format;
end = format + SBYTES (args[0]);
longest_format = 0;
/* Make room in result for all the non-%-codes in the control string. */
total = 5 + CONVERTED_BYTE_SIZE (multibyte, args[0]);
+ /* Allocate the info and discarded tables. */
+ {
+ int nbytes = nargs * sizeof *info;
+ int i;
+ info = (struct info *) alloca (nbytes);
+ bzero (info, nbytes);
+ for (i = 0; i <= nargs; i++)
+ info[i].start = -1;
+ discarded = (char *) alloca (SBYTES (args[0]));
+ bzero (discarded, SBYTES (args[0]));
+ }
+
/* Add to TOTAL enough space to hold the converted arguments. */
n = 0;
***************
*** 3458,3463 ****
--- 3483,3489 ----
int negative = 0;
unsigned char *this_format_start = format;
+ discarded[format - format_start] = 1;
format++;
/* Process a numeric arg and skip it. */
***************
*** 3471,3477 ****
fixed. */
while ((*format >= '0' && *format <= '9')
|| *format == '-' || *format == ' ' || *format == '.')
! format++;
if (*format++ == '%')
{
--- 3497,3506 ----
fixed. */
while ((*format >= '0' && *format <= '9')
|| *format == '-' || *format == ' ' || *format == '.')
! {
! discarded[format - format_start] = 1;
! format++;
! }
if (*format++ == '%')
{
***************
*** 3482,3487 ****
--- 3511,3519 ----
++n;
+ discarded[format - format_start - 1] = 1;
+ info[n].start = nchars;
+
if (STRINGP (args[n]))
{
/* handle case (precision[n] >= 0) */
***************
*** 3541,3557 ****
/* If this argument has text properties, record where
in the result string it appears. */
if (STRING_INTERVALS (args[n]))
! {
! if (!info)
! {
! int nbytes = nargs * sizeof *info;
! info = (struct info *) alloca (nbytes);
! bzero (info, nbytes);
! }
!
! info[n].start = start;
! info[n].end = end;
! }
}
else if (INTEGERP (args[n]) || FLOATP (args[n]))
{
--- 3573,3579 ----
/* If this argument has text properties, record where
in the result string it appears. */
if (STRING_INTERVALS (args[n]))
! info[n].intervals = arg_intervals = 1;
}
else if (INTEGERP (args[n]) || FLOATP (args[n]))
{
***************
*** 3578,3583 ****
--- 3600,3607 ----
p += this_nchars;
nchars += this_nchars;
}
+
+ info[n].end = nchars;
}
else if (STRING_MULTIBYTE (args[0]))
{
***************
*** 3588,3594 ****
&& !CHAR_HEAD_P (*format))
maybe_combine_byte = 1;
*p++ = *format++;
! while (! CHAR_HEAD_P (*format)) *p++ = *format++;
nchars++;
}
else if (multibyte)
--- 3612,3622 ----
&& !CHAR_HEAD_P (*format))
maybe_combine_byte = 1;
*p++ = *format++;
! while (! CHAR_HEAD_P (*format))
! {
! discarded[format - format_start] = 2;
! *p++ = *format++;
! }
nchars++;
}
else if (multibyte)
***************
*** 3619,3625 ****
arguments has text properties, set up text properties of the
result string. */
! if (STRING_INTERVALS (args[0]) || info)
{
Lisp_Object len, new_len, props;
struct gcpro gcpro1;
--- 3647,3653 ----
arguments has text properties, set up text properties of the
result string. */
! if (STRING_INTERVALS (args[0]) || arg_intervals)
{
Lisp_Object len, new_len, props;
struct gcpro gcpro1;
***************
*** 3631,3645 ****
if (CONSP (props))
{
! new_len = make_number (SCHARS (val));
! extend_property_ranges (props, len, new_len);
add_text_properties_from_list (val, props, make_number (0));
}
/* Add text properties from arguments. */
! if (info)
for (n = 1; n < nargs; ++n)
! if (info[n].end)
{
len = make_number (SCHARS (args[n]));
new_len = make_number (info[n].end - info[n].start);
--- 3659,3733 ----
if (CONSP (props))
{
! int bytepos = 0, position = 0, translated = 0, argn = 1;
! Lisp_Object list;
!
! /* Adjust the bounds of each text property
! to the proper start and end in the output string. */
! /* We take advantage of the fact that the positions in PROPS
! are in increasing order, so that we can do (effectively)
! one scan through the position space of the format string.
!
! BYTEPOS is the byte position in the format string,
! POSITION is the untranslated char position in it,
! TRANSLATED is the translated char position in BUF,
! and ARGN is the number of the next arg we will come to. */
! for (list = props; CONSP (list); list = XCDR (list))
! {
! Lisp_Object item, pos;
!
! item = XCAR (list);
!
! /* First adjust the property start position. */
! pos = XINT (XCAR (item));
!
! /* Advance BYTEPOS, POSITION, TRANSLATED and ARGN
! up to this position. */
! for (; position < pos; bytepos++)
! {
! if (! discarded[bytepos])
! position++, translated++;
! else if (discarded[bytepos] == 1)
! {
! position++;
! if (translated == info[argn].start)
! {
! translated += info[argn].end - info[argn].start;
! argn++;
! }
! }
! }
!
! XSETCAR (item, make_number (translated));
!
! /* Likewise adjust the property end position. */
! pos = XINT (XCAR (XCDR (item)));
!
! for (; bytepos < pos; bytepos++)
! {
! if (! discarded[bytepos])
! position++, translated++;
! else if (discarded[bytepos] == 1)
! {
! position++;
! if (translated == info[argn].start)
! {
! translated += info[argn].end - info[argn].start;
! argn++;
! }
! }
! }
!
! XSETCAR (XCDR (item), make_number (translated));
! }
!
add_text_properties_from_list (val, props, make_number (0));
}
/* Add text properties from arguments. */
! if (arg_intervals)
for (n = 1; n < nargs; ++n)
! if (info[n].intervals)
{
len = make_number (SCHARS (args[n]));
new_len = make_number (info[n].end - info[n].start);