I think you are right about the bug, but I think your patch does not completely fix it. This patch, which seems to work, should fix the bug completely by accessing the string only through its Lisp object pointer.
*** xdisp.c 08 Sep 2005 20:35:28 -0400 1.1050 --- xdisp.c 12 Sep 2005 06:18:48 -0400 *************** *** 15949,15955 **** { /* A string: output it and check for %-constructs within it. */ unsigned char c; ! const unsigned char *this, *lisp_string; if (!NILP (props) || risky) { --- 15949,15955 ---- { /* A string: output it and check for %-constructs within it. */ unsigned char c; ! int offset = 0; if (!NILP (props) || risky) { *************** *** 16007,16014 **** } } ! this = SDATA (elt); ! lisp_string = this; if (literal) { --- 16007,16013 ---- } } ! offset = 0; if (literal) { *************** *** 16031,16072 **** break; } while ((precision <= 0 || n < precision) ! && *this && (mode_line_target != MODE_LINE_DISPLAY || it->current_x < it->last_visible_x)) { ! const unsigned char *last = this; /* Advance to end of string or next format specifier. */ ! while ((c = *this++) != '\0' && c != '%') ; ! if (this - 1 != last) { int nchars, nbytes; /* Output to end of string or up to '%'. Field width is length of string. Don't output more than PRECISION allows us. */ ! --this; ! prec = c_string_width (last, this - last, precision - n, &nchars, &nbytes); switch (mode_line_target) { case MODE_LINE_NOPROP: case MODE_LINE_TITLE: ! n += store_mode_line_noprop (last, 0, prec); break; case MODE_LINE_STRING: { ! int bytepos = last - lisp_string; int charpos = string_byte_to_char (elt, bytepos); int endpos = (precision <= 0 ! ? string_byte_to_char (elt, ! this - lisp_string) : charpos + nchars); n += store_mode_line_string (NULL, --- 16030,16073 ---- break; } + /* Handle the non-literal case. */ + while ((precision <= 0 || n < precision) ! && SREF (elt, offset) != 0 && (mode_line_target != MODE_LINE_DISPLAY || it->current_x < it->last_visible_x)) { ! int last_offset = offset; /* Advance to end of string or next format specifier. */ ! while ((c = SREF (elt, offset++)) != '\0' && c != '%') ; ! if (offset - 1 != last_offset) { int nchars, nbytes; /* Output to end of string or up to '%'. Field width is length of string. Don't output more than PRECISION allows us. */ ! offset--; ! prec = c_string_width (SDATA (elt) + last_offset, ! offset - last_offset, precision - n, &nchars, &nbytes); switch (mode_line_target) { case MODE_LINE_NOPROP: case MODE_LINE_TITLE: ! n += store_mode_line_noprop (SDATA (elt) + last_offset, 0, prec); break; case MODE_LINE_STRING: { ! int bytepos = last_offset; int charpos = string_byte_to_char (elt, bytepos); int endpos = (precision <= 0 ! ? string_byte_to_char (elt, offset) : charpos + nchars); n += store_mode_line_string (NULL, *************** *** 16077,16083 **** break; case MODE_LINE_DISPLAY: { ! int bytepos = last - lisp_string; int charpos = string_byte_to_char (elt, bytepos); n += display_string (NULL, elt, Qnil, 0, charpos, it, 0, prec, 0, --- 16078,16084 ---- break; case MODE_LINE_DISPLAY: { ! int bytepos = last_offset; int charpos = string_byte_to_char (elt, bytepos); n += display_string (NULL, elt, Qnil, 0, charpos, it, 0, prec, 0, *************** *** 16088,16099 **** } else /* c == '%' */ { ! const unsigned char *percent_position = this; /* Get the specified minimum width. Zero means don't pad. */ field = 0; ! while ((c = *this++) >= '0' && c <= '9') field = field * 10 + c - '0'; /* Don't pad beyond the total padding allowed. */ --- 16089,16100 ---- } else /* c == '%' */ { ! int percent_position = offset; /* Get the specified minimum width. Zero means don't pad. */ field = 0; ! while ((c = SREF (elt, offset++)) >= '0' && c <= '9') field = field * 10 + c - '0'; /* Don't pad beyond the total padding allowed. */ *************** *** 16113,16119 **** int bytepos, charpos; unsigned char *spec; ! bytepos = percent_position - lisp_string; charpos = (STRING_MULTIBYTE (elt) ? string_byte_to_char (elt, bytepos) : bytepos); --- 16114,16120 ---- int bytepos, charpos; unsigned char *spec; ! bytepos = percent_position; charpos = (STRING_MULTIBYTE (elt) ? string_byte_to_char (elt, bytepos) : bytepos); _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel