Mercurial > emacs
changeset 62929:4929fb0b87a7
(mode_line_noprop_buf, mode_line_noprop_buf_end)
(mode_line_noprop_ptr): Rename from frame_title_*.
(store_mode_line_noprop_char): Rename from store_frame_title_char.
(store_mode_line_noprop): Rename from store_frame_title.
(mode_line_target): New enum to specify current output target
for mode line formatting.
(display_mode_element): Test it rather than frame_title_ptr and
mode_line_string_list to determine where output should go.
(mode_line_proptrans_alist, mode_line_string_alist): Make static.
(Vmode_line_unwind_vector): New variable.
(format_mode_line_unwind_data, unwind_format_mode_line): New
functions for unwind protection in mode line formatting.
(x_consider_frame_title): Use them and new local var 'title_start'
to support nested calls to format-mode-line. Set mode_line_target
to MODE_LINE_TITLE.
(Fformat_mode_line): Use them and new local var 'string_start' to
support nested calls to format-mode-line. Set mode_line_target to
MODE_LINE_NOPROP or MODE_LINE_STRING. Don't trim trailing dashes.
(decode_mode_spec): Don't make infinite number of trailing dashes
for MODE_LINE_NOPROP and MODE_LINE_STRING targets.
(syms_of_xdisp): Initialize and staticpro mode_line_string_face,
mode_line_string_face_prop, and Vmode_line_unwind_vector.
(init_xdisp): Initialize mode_line_noprop_ptr to start of _buf.
Initialize mode_line_target to MODE_LINE_DISPLAY.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Tue, 31 May 2005 15:00:44 +0000 |
parents | 8470359e501c |
children | 79a7e032005c |
files | src/xdisp.c |
diffstat | 1 files changed, 277 insertions(+), 183 deletions(-) [+] |
line wrap: on
line diff
--- a/src/xdisp.c Tue May 31 15:00:23 2005 +0000 +++ b/src/xdisp.c Tue May 31 15:00:44 2005 +0000 @@ -843,8 +843,8 @@ struct text_pos)); static void reconsider_clip_changes P_ ((struct window *, struct buffer *)); static int text_outside_line_unchanged_p P_ ((struct window *, int, int)); -static void store_frame_title_char P_ ((char)); -static int store_frame_title P_ ((const unsigned char *, int, int)); +static void store_mode_line_noprop_char P_ ((char)); +static int store_mode_line_noprop P_ ((const unsigned char *, int, int)); static void x_consider_frame_title P_ ((Lisp_Object)); static void handle_stop P_ ((struct it *)); static int tool_bar_lines_needed P_ ((struct frame *)); @@ -8159,52 +8159,123 @@ /*********************************************************************** - Frame Titles + Mode Lines and Frame Titles ***********************************************************************/ - -/* The frame title buffering code is also used by Fformat_mode_line. - So it is not conditioned by HAVE_WINDOW_SYSTEM. */ - -/* A buffer for constructing frame titles in it; allocated from the - heap in init_xdisp and resized as needed in store_frame_title_char. */ - -static char *frame_title_buf; +/* A buffer for constructing non-propertized mode-line strings and + frame titles in it; allocated from the heap in init_xdisp and + resized as needed in store_mode_line_noprop_char. */ + +static char *mode_line_noprop_buf; /* The buffer's end, and a current output position in it. */ -static char *frame_title_buf_end; -static char *frame_title_ptr; - - -/* Store a single character C for the frame title in frame_title_buf. - Re-allocate frame_title_buf if necessary. */ +static char *mode_line_noprop_buf_end; +static char *mode_line_noprop_ptr; + +static enum { + MODE_LINE_DISPLAY = 0, + MODE_LINE_TITLE, + MODE_LINE_NOPROP, + MODE_LINE_STRING +} mode_line_target; + +/* Alist that caches the results of :propertize. + Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */ +static Lisp_Object mode_line_proptrans_alist; + +/* List of strings making up the mode-line. */ +static Lisp_Object mode_line_string_list; + +/* Base face property when building propertized mode line string. */ +static Lisp_Object mode_line_string_face; +static Lisp_Object mode_line_string_face_prop; + + +/* Unwind data for mode line strings */ + +static Lisp_Object Vmode_line_unwind_vector; + +static Lisp_Object +format_mode_line_unwind_data (obuf) + struct buffer *obuf; +{ + int i = 0; + Lisp_Object vector; + + /* Reduce consing by keeping one vector in + Vwith_echo_area_save_vector. */ + vector = Vmode_line_unwind_vector; + Vmode_line_unwind_vector = Qnil; + + if (NILP (vector)) + vector = Fmake_vector (make_number (7), Qnil); + + AREF (vector, 0) = make_number (mode_line_target); + AREF (vector, 1) = make_number (mode_line_noprop_ptr - mode_line_noprop_buf); + AREF (vector, 2) = mode_line_string_list; + AREF (vector, 3) = mode_line_proptrans_alist; + AREF (vector, 4) = mode_line_string_face; + AREF (vector, 5) = mode_line_string_face_prop; + + if (obuf) + XSETBUFFER (AREF (vector, 6), obuf); + else + AREF (vector, 6) = Qnil; + + return vector; +} + +static Lisp_Object +unwind_format_mode_line (vector) + Lisp_Object vector; +{ + mode_line_target = XINT (AREF (vector, 0)); + mode_line_noprop_ptr = mode_line_noprop_buf + XINT (AREF (vector, 1)); + mode_line_string_list = AREF (vector, 2); + mode_line_proptrans_alist = AREF (vector, 3); + mode_line_string_face = AREF (vector, 4); + mode_line_string_face_prop = AREF (vector, 5); + + if (!NILP (AREF (vector, 6))) + { + set_buffer_internal_1 (XBUFFER (AREF (vector, 6))); + AREF (vector, 6) = Qnil; + } + + Vmode_line_unwind_vector = vector; + return Qnil; +} + + +/* Store a single character C for the frame title in mode_line_noprop_buf. + Re-allocate mode_line_noprop_buf if necessary. */ static void #ifdef PROTOTYPES -store_frame_title_char (char c) +store_mode_line_noprop_char (char c) #else -store_frame_title_char (c) +store_mode_line_noprop_char (c) char c; #endif { /* If output position has reached the end of the allocated buffer, double the buffer's size. */ - if (frame_title_ptr == frame_title_buf_end) - { - int len = frame_title_ptr - frame_title_buf; - int new_size = 2 * len * sizeof *frame_title_buf; - frame_title_buf = (char *) xrealloc (frame_title_buf, new_size); - frame_title_buf_end = frame_title_buf + new_size; - frame_title_ptr = frame_title_buf + len; - } - - *frame_title_ptr++ = c; -} - - -/* Store part of a frame title in frame_title_buf, beginning at - frame_title_ptr. STR is the string to store. Do not copy + if (mode_line_noprop_ptr == mode_line_noprop_buf_end) + { + int len = mode_line_noprop_ptr - mode_line_noprop_buf; + int new_size = 2 * len * sizeof *mode_line_noprop_buf; + mode_line_noprop_buf = (char *) xrealloc (mode_line_noprop_buf, new_size); + mode_line_noprop_buf_end = mode_line_noprop_buf + new_size; + mode_line_noprop_ptr = mode_line_noprop_buf + len; + } + + *mode_line_noprop_ptr++ = c; +} + + +/* Store part of a frame title in mode_line_noprop_buf, beginning at + mode_line_noprop_ptr. STR is the string to store. Do not copy characters that yield more columns than PRECISION; PRECISION <= 0 means copy the whole string. Pad with spaces until FIELD_WIDTH number of characters have been copied; FIELD_WIDTH <= 0 means don't @@ -8212,7 +8283,7 @@ frame title. */ static int -store_frame_title (str, field_width, precision) +store_mode_line_noprop (str, field_width, precision) const unsigned char *str; int field_width, precision; { @@ -8223,19 +8294,23 @@ nbytes = strlen (str); n += c_string_width (str, nbytes, precision, &dummy, &nbytes); while (nbytes--) - store_frame_title_char (*str++); + store_mode_line_noprop_char (*str++); /* Fill up with spaces until FIELD_WIDTH reached. */ while (field_width > 0 && n < field_width) { - store_frame_title_char (' '); + store_mode_line_noprop_char (' '); ++n; } return n; } +/*********************************************************************** + Frame Titles + ***********************************************************************/ + #ifdef HAVE_WINDOW_SYSTEM /* Set the title of FRAME, if it has changed. The title format is @@ -8255,9 +8330,10 @@ /* Do we have more than one visible frame on this X display? */ Lisp_Object tail; Lisp_Object fmt; - struct buffer *obuf; + char *title_start; int len; struct it it; + int count = SPECPDL_INDEX (); for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail)) { @@ -8276,18 +8352,22 @@ multiple_frames = CONSP (tail); /* Switch to the buffer of selected window of the frame. Set up - frame_title_ptr so that display_mode_element will output into it; + mode_line_noprop_ptr so that display_mode_element will output into it; then display the title. */ - obuf = current_buffer; + record_unwind_protect (unwind_format_mode_line, + format_mode_line_unwind_data (current_buffer)); + set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer)); fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; - frame_title_ptr = frame_title_buf; + + mode_line_target = MODE_LINE_TITLE; + title_start = mode_line_noprop_ptr; init_iterator (&it, XWINDOW (f->selected_window), -1, -1, NULL, DEFAULT_FACE_ID); display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0); - len = frame_title_ptr - frame_title_buf; - frame_title_ptr = NULL; - set_buffer_internal_1 (obuf); + len = mode_line_noprop_ptr - title_start; + + unbind_to (count, Qnil); /* Set the title only if it's changed. This avoids consing in the common case where it hasn't. (If it turns out that we've @@ -8296,8 +8376,8 @@ higher level than this.) */ if (! STRINGP (f->name) || SBYTES (f->name) != len - || bcmp (frame_title_buf, SDATA (f->name), len) != 0) - x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil); + || bcmp (title_start, SDATA (f->name), len) != 0) + x_implicitly_set_name (f, make_string (title_start, len), Qnil); } } @@ -15631,18 +15711,6 @@ return it.glyph_row->height; } -/* Alist that caches the results of :propertize. - Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */ -Lisp_Object mode_line_proptrans_alist; - -/* List of strings making up the mode-line. */ -Lisp_Object mode_line_string_list; - -/* Base face property when building propertized mode line string. */ -static Lisp_Object mode_line_string_face; -static Lisp_Object mode_line_string_face_prop; - - /* Contribute ELT to the mode line for window IT->w. How it translates into text depends on its data type. @@ -15663,8 +15731,9 @@ If RISKY is nonzero, remove (disregard) any properties in any string we encounter, and ignore :eval and :propertize. - If the global variable `frame_title_ptr' is non-NULL, then the output - is passed to `store_frame_title' instead of `display_string'. */ + The global variable `mode_line_target' determines whether the + output is passed to `store_mode_line_noprop', + `store_mode_line_string', or `display_string'. */ static int display_mode_element (it, depth, field_width, precision, elt, props, risky) @@ -15753,21 +15822,27 @@ if (literal) { prec = precision - n; - if (frame_title_ptr) - n += store_frame_title (SDATA (elt), -1, prec); - else if (!NILP (mode_line_string_list)) - n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil); - else - n += display_string (NULL, elt, Qnil, 0, 0, it, - 0, prec, 0, STRING_MULTIBYTE (elt)); + switch (mode_line_target) + { + case MODE_LINE_NOPROP: + case MODE_LINE_TITLE: + n += store_mode_line_noprop (SDATA (elt), -1, prec); + break; + case MODE_LINE_STRING: + n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil); + break; + case MODE_LINE_DISPLAY: + n += display_string (NULL, elt, Qnil, 0, 0, it, + 0, prec, 0, STRING_MULTIBYTE (elt)); + break; + } break; } while ((precision <= 0 || n < precision) && *this - && (frame_title_ptr - || !NILP (mode_line_string_list) + && (mode_line_target != MODE_LINE_DISPLAY || it->current_x < it->last_visible_x)) { const unsigned char *last = this; @@ -15788,29 +15863,36 @@ prec = c_string_width (last, this - last, precision - n, &nchars, &nbytes); - if (frame_title_ptr) - n += store_frame_title (last, 0, prec); - else if (!NILP (mode_line_string_list)) + switch (mode_line_target) { - 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, - Fsubstring (elt, make_number (charpos), - make_number (endpos)), - 0, 0, 0, Qnil); - } - else - { - 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, - STRING_MULTIBYTE (elt)); + 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, + Fsubstring (elt, make_number (charpos), + make_number (endpos)), + 0, 0, 0, Qnil); + } + 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, + STRING_MULTIBYTE (elt)); + } + break; } } else /* c == '%' */ @@ -15848,44 +15930,51 @@ spec = decode_mode_spec (it->w, c, field, prec, &multibyte); - if (frame_title_ptr) - n += store_frame_title (spec, field, prec); - else if (!NILP (mode_line_string_list)) - { - int len = strlen (spec); - Lisp_Object tem = make_string (spec, len); - props = Ftext_properties_at (make_number (charpos), elt); - /* Should only keep face property in props */ - n += store_mode_line_string (NULL, tem, 0, field, prec, props); - } - else + switch (mode_line_target) { - int nglyphs_before, nwritten; - - nglyphs_before = it->glyph_row->used[TEXT_AREA]; - nwritten = display_string (spec, Qnil, elt, - charpos, 0, it, - field, prec, 0, - multibyte); - - /* Assign to the glyphs written above the - string where the `%x' came from, position - of the `%'. */ - if (nwritten > 0) - { - struct glyph *glyph - = (it->glyph_row->glyphs[TEXT_AREA] - + nglyphs_before); - int i; - - for (i = 0; i < nwritten; ++i) - { - glyph[i].object = elt; - glyph[i].charpos = charpos; - } - - n += nwritten; - } + case MODE_LINE_NOPROP: + case MODE_LINE_TITLE: + n += store_mode_line_noprop (spec, field, prec); + break; + case MODE_LINE_STRING: + { + int len = strlen (spec); + Lisp_Object tem = make_string (spec, len); + props = Ftext_properties_at (make_number (charpos), elt); + /* Should only keep face property in props */ + n += store_mode_line_string (NULL, tem, 0, field, prec, props); + } + break; + case MODE_LINE_DISPLAY: + { + int nglyphs_before, nwritten; + + nglyphs_before = it->glyph_row->used[TEXT_AREA]; + nwritten = display_string (spec, Qnil, elt, + charpos, 0, it, + field, prec, 0, + multibyte); + + /* Assign to the glyphs written above the + string where the `%x' came from, position + of the `%'. */ + if (nwritten > 0) + { + struct glyph *glyph + = (it->glyph_row->glyphs[TEXT_AREA] + + nglyphs_before); + int i; + + for (i = 0; i < nwritten; ++i) + { + glyph[i].object = elt; + glyph[i].charpos = charpos; + } + + n += nwritten; + } + } + break; } } else /* c == 0 */ @@ -16056,13 +16145,20 @@ /* Pad to FIELD_WIDTH. */ if (field_width > 0 && n < field_width) { - if (frame_title_ptr) - n += store_frame_title ("", field_width - n, 0); - else if (!NILP (mode_line_string_list)) - n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil); - else - n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n, - 0, 0, 0); + switch (mode_line_target) + { + case MODE_LINE_NOPROP: + case MODE_LINE_TITLE: + n += store_mode_line_noprop ("", field_width - n, 0); + break; + case MODE_LINE_STRING: + n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil); + break; + case MODE_LINE_DISPLAY: + n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n, + 0, 0, 0); + break; + } } return n; @@ -16194,6 +16290,9 @@ struct buffer *old_buffer = NULL; int face_id = -1; int no_props = INTEGERP (face); + int count = SPECPDL_INDEX (); + Lisp_Object str; + char *string_start = NULL; if (NILP (window)) window = selected_window; @@ -16221,64 +16320,52 @@ face_id = DEFAULT_FACE_ID; if (XBUFFER (buffer) != current_buffer) - { - old_buffer = current_buffer; - set_buffer_internal_1 (XBUFFER (buffer)); - } + old_buffer = current_buffer; + + record_unwind_protect (unwind_format_mode_line, + format_mode_line_unwind_data (old_buffer)); + + if (old_buffer) + set_buffer_internal_1 (XBUFFER (buffer)); init_iterator (&it, w, -1, -1, NULL, face_id); - if (!no_props) - { + if (no_props) + { + mode_line_target = MODE_LINE_NOPROP; + mode_line_string_face_prop = Qnil; + mode_line_string_list = Qnil; + string_start = mode_line_noprop_ptr; + } + else + { + mode_line_target = MODE_LINE_STRING; + mode_line_string_list = Qnil; mode_line_string_face = face; mode_line_string_face_prop = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil))); - /* We need a dummy last element in mode_line_string_list to - indicate we are building the propertized mode-line string. - Using mode_line_string_face_prop here GC protects it. */ - mode_line_string_list - = Fcons (mode_line_string_face_prop, Qnil); - frame_title_ptr = NULL; - } - else - { - mode_line_string_face_prop = Qnil; - mode_line_string_list = Qnil; - frame_title_ptr = frame_title_buf; + string_start = NULL; } push_frame_kboard (it.f); display_mode_element (&it, 0, 0, 0, format, Qnil, 0); pop_frame_kboard (); - if (old_buffer) - set_buffer_internal_1 (old_buffer); - - if (!no_props) - { - Lisp_Object str; + if (no_props) + { + len = mode_line_noprop_ptr - string_start; + str = make_string (string_start, len); + } + else + { mode_line_string_list = Fnreverse (mode_line_string_list); - str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list), + str = Fmapconcat (intern ("identity"), mode_line_string_list, make_string ("", 0)); - mode_line_string_face_prop = Qnil; - mode_line_string_list = Qnil; - return str; - } - - len = frame_title_ptr - frame_title_buf; - if (len > 0 && frame_title_ptr[-1] == '-') - { - /* Mode lines typically ends with numerous dashes; reduce to two dashes. */ - while (frame_title_ptr > frame_title_buf && *--frame_title_ptr == '-') - ; - frame_title_ptr += 3; /* restore last non-dash + two dashes */ - if (len > frame_title_ptr - frame_title_buf) - len = frame_title_ptr - frame_title_buf; - } - - frame_title_ptr = NULL; - return make_string (frame_title_buf, len); + } + + unbind_to (count, Qnil); + return str; } /* Write a null-terminated, right justified decimal representation of @@ -16596,7 +16683,8 @@ register int i; /* Let lots_of_dashes be a string of infinite length. */ - if (!NILP (mode_line_string_list)) + if (mode_line_target == MODE_LINE_NOPROP || + mode_line_target == MODE_LINE_STRING) return "--"; if (field_width <= 0 || field_width > sizeof (lots_of_dashes)) @@ -22689,9 +22777,14 @@ mode_line_proptrans_alist = Qnil; staticpro (&mode_line_proptrans_alist); - mode_line_string_list = Qnil; staticpro (&mode_line_string_list); + mode_line_string_face = Qnil; + staticpro (&mode_line_string_face); + mode_line_string_face_prop = Qnil; + staticpro (&mode_line_string_face_prop); + Vmode_line_unwind_vector = Qnil; + staticpro (&Vmode_line_unwind_vector); help_echo_string = Qnil; staticpro (&help_echo_string); @@ -23041,9 +23134,10 @@ /* Allocate the buffer for frame titles. Also used for `format-mode-line'. */ int size = 100; - frame_title_buf = (char *) xmalloc (size); - frame_title_buf_end = frame_title_buf + size; - frame_title_ptr = NULL; + mode_line_noprop_buf = (char *) xmalloc (size); + mode_line_noprop_buf_end = mode_line_noprop_buf + size; + mode_line_noprop_ptr = mode_line_noprop_buf; + mode_line_target = MODE_LINE_DISPLAY; } help_echo_showing_p = 0;