aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKim F. Storm2005-05-31 15:00:44 +0000
committerKim F. Storm2005-05-31 15:00:44 +0000
commit4c0e4b80fed124ec8324fb5a224a505c50daa3ef (patch)
tree699c39b032c0b407daf0615c8f3f92116918d862 /src
parent13cc7d614dd85382228c20b6e70ee8f9f1e28978 (diff)
downloademacs-4c0e4b80fed124ec8324fb5a224a505c50daa3ef.tar.gz
emacs-4c0e4b80fed124ec8324fb5a224a505c50daa3ef.zip
(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.
Diffstat (limited to 'src')
-rw-r--r--src/xdisp.c432
1 files changed, 263 insertions, 169 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index b20c4815abc..167b4afadaa 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -843,8 +843,8 @@ static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
843 struct text_pos)); 843 struct text_pos));
844static void reconsider_clip_changes P_ ((struct window *, struct buffer *)); 844static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
845static int text_outside_line_unchanged_p P_ ((struct window *, int, int)); 845static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
846static void store_frame_title_char P_ ((char)); 846static void store_mode_line_noprop_char P_ ((char));
847static int store_frame_title P_ ((const unsigned char *, int, int)); 847static int store_mode_line_noprop P_ ((const unsigned char *, int, int));
848static void x_consider_frame_title P_ ((Lisp_Object)); 848static void x_consider_frame_title P_ ((Lisp_Object));
849static void handle_stop P_ ((struct it *)); 849static void handle_stop P_ ((struct it *));
850static int tool_bar_lines_needed P_ ((struct frame *)); 850static int tool_bar_lines_needed P_ ((struct frame *));
@@ -8159,52 +8159,123 @@ echo_area_display (update_frame_p)
8159 8159
8160 8160
8161/*********************************************************************** 8161/***********************************************************************
8162 Frame Titles 8162 Mode Lines and Frame Titles
8163 ***********************************************************************/ 8163 ***********************************************************************/
8164 8164
8165/* A buffer for constructing non-propertized mode-line strings and
8166 frame titles in it; allocated from the heap in init_xdisp and
8167 resized as needed in store_mode_line_noprop_char. */
8165 8168
8166/* The frame title buffering code is also used by Fformat_mode_line. 8169static char *mode_line_noprop_buf;
8167 So it is not conditioned by HAVE_WINDOW_SYSTEM. */
8168 8170
8169/* A buffer for constructing frame titles in it; allocated from the 8171/* The buffer's end, and a current output position in it. */
8170 heap in init_xdisp and resized as needed in store_frame_title_char. */
8171 8172
8172static char *frame_title_buf; 8173static char *mode_line_noprop_buf_end;
8174static char *mode_line_noprop_ptr;
8173 8175
8174/* The buffer's end, and a current output position in it. */ 8176static enum {
8177 MODE_LINE_DISPLAY = 0,
8178 MODE_LINE_TITLE,
8179 MODE_LINE_NOPROP,
8180 MODE_LINE_STRING
8181} mode_line_target;
8182
8183/* Alist that caches the results of :propertize.
8184 Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */
8185static Lisp_Object mode_line_proptrans_alist;
8186
8187/* List of strings making up the mode-line. */
8188static Lisp_Object mode_line_string_list;
8189
8190/* Base face property when building propertized mode line string. */
8191static Lisp_Object mode_line_string_face;
8192static Lisp_Object mode_line_string_face_prop;
8193
8194
8195/* Unwind data for mode line strings */
8196
8197static Lisp_Object Vmode_line_unwind_vector;
8198
8199static Lisp_Object
8200format_mode_line_unwind_data (obuf)
8201 struct buffer *obuf;
8202{
8203 int i = 0;
8204 Lisp_Object vector;
8205
8206 /* Reduce consing by keeping one vector in
8207 Vwith_echo_area_save_vector. */
8208 vector = Vmode_line_unwind_vector;
8209 Vmode_line_unwind_vector = Qnil;
8210
8211 if (NILP (vector))
8212 vector = Fmake_vector (make_number (7), Qnil);
8213
8214 AREF (vector, 0) = make_number (mode_line_target);
8215 AREF (vector, 1) = make_number (mode_line_noprop_ptr - mode_line_noprop_buf);
8216 AREF (vector, 2) = mode_line_string_list;
8217 AREF (vector, 3) = mode_line_proptrans_alist;
8218 AREF (vector, 4) = mode_line_string_face;
8219 AREF (vector, 5) = mode_line_string_face_prop;
8220
8221 if (obuf)
8222 XSETBUFFER (AREF (vector, 6), obuf);
8223 else
8224 AREF (vector, 6) = Qnil;
8225
8226 return vector;
8227}
8228
8229static Lisp_Object
8230unwind_format_mode_line (vector)
8231 Lisp_Object vector;
8232{
8233 mode_line_target = XINT (AREF (vector, 0));
8234 mode_line_noprop_ptr = mode_line_noprop_buf + XINT (AREF (vector, 1));
8235 mode_line_string_list = AREF (vector, 2);
8236 mode_line_proptrans_alist = AREF (vector, 3);
8237 mode_line_string_face = AREF (vector, 4);
8238 mode_line_string_face_prop = AREF (vector, 5);
8175 8239
8176static char *frame_title_buf_end; 8240 if (!NILP (AREF (vector, 6)))
8177static char *frame_title_ptr; 8241 {
8242 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
8243 AREF (vector, 6) = Qnil;
8244 }
8178 8245
8246 Vmode_line_unwind_vector = vector;
8247 return Qnil;
8248}
8179 8249
8180/* Store a single character C for the frame title in frame_title_buf. 8250
8181 Re-allocate frame_title_buf if necessary. */ 8251/* Store a single character C for the frame title in mode_line_noprop_buf.
8252 Re-allocate mode_line_noprop_buf if necessary. */
8182 8253
8183static void 8254static void
8184#ifdef PROTOTYPES 8255#ifdef PROTOTYPES
8185store_frame_title_char (char c) 8256store_mode_line_noprop_char (char c)
8186#else 8257#else
8187store_frame_title_char (c) 8258store_mode_line_noprop_char (c)
8188 char c; 8259 char c;
8189#endif 8260#endif
8190{ 8261{
8191 /* If output position has reached the end of the allocated buffer, 8262 /* If output position has reached the end of the allocated buffer,
8192 double the buffer's size. */ 8263 double the buffer's size. */
8193 if (frame_title_ptr == frame_title_buf_end) 8264 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
8194 { 8265 {
8195 int len = frame_title_ptr - frame_title_buf; 8266 int len = mode_line_noprop_ptr - mode_line_noprop_buf;
8196 int new_size = 2 * len * sizeof *frame_title_buf; 8267 int new_size = 2 * len * sizeof *mode_line_noprop_buf;
8197 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size); 8268 mode_line_noprop_buf = (char *) xrealloc (mode_line_noprop_buf, new_size);
8198 frame_title_buf_end = frame_title_buf + new_size; 8269 mode_line_noprop_buf_end = mode_line_noprop_buf + new_size;
8199 frame_title_ptr = frame_title_buf + len; 8270 mode_line_noprop_ptr = mode_line_noprop_buf + len;
8200 } 8271 }
8201 8272
8202 *frame_title_ptr++ = c; 8273 *mode_line_noprop_ptr++ = c;
8203} 8274}
8204 8275
8205 8276
8206/* Store part of a frame title in frame_title_buf, beginning at 8277/* Store part of a frame title in mode_line_noprop_buf, beginning at
8207 frame_title_ptr. STR is the string to store. Do not copy 8278 mode_line_noprop_ptr. STR is the string to store. Do not copy
8208 characters that yield more columns than PRECISION; PRECISION <= 0 8279 characters that yield more columns than PRECISION; PRECISION <= 0
8209 means copy the whole string. Pad with spaces until FIELD_WIDTH 8280 means copy the whole string. Pad with spaces until FIELD_WIDTH
8210 number of characters have been copied; FIELD_WIDTH <= 0 means don't 8281 number of characters have been copied; FIELD_WIDTH <= 0 means don't
@@ -8212,7 +8283,7 @@ store_frame_title_char (c)
8212 frame title. */ 8283 frame title. */
8213 8284
8214static int 8285static int
8215store_frame_title (str, field_width, precision) 8286store_mode_line_noprop (str, field_width, precision)
8216 const unsigned char *str; 8287 const unsigned char *str;
8217 int field_width, precision; 8288 int field_width, precision;
8218{ 8289{
@@ -8223,19 +8294,23 @@ store_frame_title (str, field_width, precision)
8223 nbytes = strlen (str); 8294 nbytes = strlen (str);
8224 n += c_string_width (str, nbytes, precision, &dummy, &nbytes); 8295 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
8225 while (nbytes--) 8296 while (nbytes--)
8226 store_frame_title_char (*str++); 8297 store_mode_line_noprop_char (*str++);
8227 8298
8228 /* Fill up with spaces until FIELD_WIDTH reached. */ 8299 /* Fill up with spaces until FIELD_WIDTH reached. */
8229 while (field_width > 0 8300 while (field_width > 0
8230 && n < field_width) 8301 && n < field_width)
8231 { 8302 {
8232 store_frame_title_char (' '); 8303 store_mode_line_noprop_char (' ');
8233 ++n; 8304 ++n;
8234 } 8305 }
8235 8306
8236 return n; 8307 return n;
8237} 8308}
8238 8309
8310/***********************************************************************
8311 Frame Titles
8312 ***********************************************************************/
8313
8239#ifdef HAVE_WINDOW_SYSTEM 8314#ifdef HAVE_WINDOW_SYSTEM
8240 8315
8241/* Set the title of FRAME, if it has changed. The title format is 8316/* Set the title of FRAME, if it has changed. The title format is
@@ -8255,9 +8330,10 @@ x_consider_frame_title (frame)
8255 /* Do we have more than one visible frame on this X display? */ 8330 /* Do we have more than one visible frame on this X display? */
8256 Lisp_Object tail; 8331 Lisp_Object tail;
8257 Lisp_Object fmt; 8332 Lisp_Object fmt;
8258 struct buffer *obuf; 8333 char *title_start;
8259 int len; 8334 int len;
8260 struct it it; 8335 struct it it;
8336 int count = SPECPDL_INDEX ();
8261 8337
8262 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail)) 8338 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
8263 { 8339 {
@@ -8276,18 +8352,22 @@ x_consider_frame_title (frame)
8276 multiple_frames = CONSP (tail); 8352 multiple_frames = CONSP (tail);
8277 8353
8278 /* Switch to the buffer of selected window of the frame. Set up 8354 /* Switch to the buffer of selected window of the frame. Set up
8279 frame_title_ptr so that display_mode_element will output into it; 8355 mode_line_noprop_ptr so that display_mode_element will output into it;
8280 then display the title. */ 8356 then display the title. */
8281 obuf = current_buffer; 8357 record_unwind_protect (unwind_format_mode_line,
8358 format_mode_line_unwind_data (current_buffer));
8359
8282 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer)); 8360 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
8283 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; 8361 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
8284 frame_title_ptr = frame_title_buf; 8362
8363 mode_line_target = MODE_LINE_TITLE;
8364 title_start = mode_line_noprop_ptr;
8285 init_iterator (&it, XWINDOW (f->selected_window), -1, -1, 8365 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
8286 NULL, DEFAULT_FACE_ID); 8366 NULL, DEFAULT_FACE_ID);
8287 display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0); 8367 display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
8288 len = frame_title_ptr - frame_title_buf; 8368 len = mode_line_noprop_ptr - title_start;
8289 frame_title_ptr = NULL; 8369
8290 set_buffer_internal_1 (obuf); 8370 unbind_to (count, Qnil);
8291 8371
8292 /* Set the title only if it's changed. This avoids consing in 8372 /* Set the title only if it's changed. This avoids consing in
8293 the common case where it hasn't. (If it turns out that we've 8373 the common case where it hasn't. (If it turns out that we've
@@ -8296,8 +8376,8 @@ x_consider_frame_title (frame)
8296 higher level than this.) */ 8376 higher level than this.) */
8297 if (! STRINGP (f->name) 8377 if (! STRINGP (f->name)
8298 || SBYTES (f->name) != len 8378 || SBYTES (f->name) != len
8299 || bcmp (frame_title_buf, SDATA (f->name), len) != 0) 8379 || bcmp (title_start, SDATA (f->name), len) != 0)
8300 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil); 8380 x_implicitly_set_name (f, make_string (title_start, len), Qnil);
8301 } 8381 }
8302} 8382}
8303 8383
@@ -15631,18 +15711,6 @@ display_mode_line (w, face_id, format)
15631 return it.glyph_row->height; 15711 return it.glyph_row->height;
15632} 15712}
15633 15713
15634/* Alist that caches the results of :propertize.
15635 Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */
15636Lisp_Object mode_line_proptrans_alist;
15637
15638/* List of strings making up the mode-line. */
15639Lisp_Object mode_line_string_list;
15640
15641/* Base face property when building propertized mode line string. */
15642static Lisp_Object mode_line_string_face;
15643static Lisp_Object mode_line_string_face_prop;
15644
15645
15646/* Contribute ELT to the mode line for window IT->w. How it 15714/* Contribute ELT to the mode line for window IT->w. How it
15647 translates into text depends on its data type. 15715 translates into text depends on its data type.
15648 15716
@@ -15663,8 +15731,9 @@ static Lisp_Object mode_line_string_face_prop;
15663 If RISKY is nonzero, remove (disregard) any properties in any string 15731 If RISKY is nonzero, remove (disregard) any properties in any string
15664 we encounter, and ignore :eval and :propertize. 15732 we encounter, and ignore :eval and :propertize.
15665 15733
15666 If the global variable `frame_title_ptr' is non-NULL, then the output 15734 The global variable `mode_line_target' determines whether the
15667 is passed to `store_frame_title' instead of `display_string'. */ 15735 output is passed to `store_mode_line_noprop',
15736 `store_mode_line_string', or `display_string'. */
15668 15737
15669static int 15738static int
15670display_mode_element (it, depth, field_width, precision, elt, props, risky) 15739display_mode_element (it, depth, field_width, precision, elt, props, risky)
@@ -15753,21 +15822,27 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
15753 if (literal) 15822 if (literal)
15754 { 15823 {
15755 prec = precision - n; 15824 prec = precision - n;
15756 if (frame_title_ptr) 15825 switch (mode_line_target)
15757 n += store_frame_title (SDATA (elt), -1, prec); 15826 {
15758 else if (!NILP (mode_line_string_list)) 15827 case MODE_LINE_NOPROP:
15759 n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil); 15828 case MODE_LINE_TITLE:
15760 else 15829 n += store_mode_line_noprop (SDATA (elt), -1, prec);
15761 n += display_string (NULL, elt, Qnil, 0, 0, it, 15830 break;
15762 0, prec, 0, STRING_MULTIBYTE (elt)); 15831 case MODE_LINE_STRING:
15832 n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
15833 break;
15834 case MODE_LINE_DISPLAY:
15835 n += display_string (NULL, elt, Qnil, 0, 0, it,
15836 0, prec, 0, STRING_MULTIBYTE (elt));
15837 break;
15838 }
15763 15839
15764 break; 15840 break;
15765 } 15841 }
15766 15842
15767 while ((precision <= 0 || n < precision) 15843 while ((precision <= 0 || n < precision)
15768 && *this 15844 && *this
15769 && (frame_title_ptr 15845 && (mode_line_target != MODE_LINE_DISPLAY
15770 || !NILP (mode_line_string_list)
15771 || it->current_x < it->last_visible_x)) 15846 || it->current_x < it->last_visible_x))
15772 { 15847 {
15773 const unsigned char *last = this; 15848 const unsigned char *last = this;
@@ -15788,29 +15863,36 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
15788 prec = c_string_width (last, this - last, precision - n, 15863 prec = c_string_width (last, this - last, precision - n,
15789 &nchars, &nbytes); 15864 &nchars, &nbytes);
15790 15865
15791 if (frame_title_ptr) 15866 switch (mode_line_target)
15792 n += store_frame_title (last, 0, prec);
15793 else if (!NILP (mode_line_string_list))
15794 {
15795 int bytepos = last - lisp_string;
15796 int charpos = string_byte_to_char (elt, bytepos);
15797 int endpos = (precision <= 0
15798 ? string_byte_to_char (elt,
15799 this - lisp_string)
15800 : charpos + nchars);
15801
15802 n += store_mode_line_string (NULL,
15803 Fsubstring (elt, make_number (charpos),
15804 make_number (endpos)),
15805 0, 0, 0, Qnil);
15806 }
15807 else
15808 { 15867 {
15809 int bytepos = last - lisp_string; 15868 case MODE_LINE_NOPROP:
15810 int charpos = string_byte_to_char (elt, bytepos); 15869 case MODE_LINE_TITLE:
15811 n += display_string (NULL, elt, Qnil, 0, charpos, 15870 n += store_mode_line_noprop (last, 0, prec);
15812 it, 0, prec, 0, 15871 break;
15813 STRING_MULTIBYTE (elt)); 15872 case MODE_LINE_STRING:
15873 {
15874 int bytepos = last - lisp_string;
15875 int charpos = string_byte_to_char (elt, bytepos);
15876 int endpos = (precision <= 0
15877 ? string_byte_to_char (elt,
15878 this - lisp_string)
15879 : charpos + nchars);
15880
15881 n += store_mode_line_string (NULL,
15882 Fsubstring (elt, make_number (charpos),
15883 make_number (endpos)),
15884 0, 0, 0, Qnil);
15885 }
15886 break;
15887 case MODE_LINE_DISPLAY:
15888 {
15889 int bytepos = last - lisp_string;
15890 int charpos = string_byte_to_char (elt, bytepos);
15891 n += display_string (NULL, elt, Qnil, 0, charpos,
15892 it, 0, prec, 0,
15893 STRING_MULTIBYTE (elt));
15894 }
15895 break;
15814 } 15896 }
15815 } 15897 }
15816 else /* c == '%' */ 15898 else /* c == '%' */
@@ -15848,44 +15930,51 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
15848 spec 15930 spec
15849 = decode_mode_spec (it->w, c, field, prec, &multibyte); 15931 = decode_mode_spec (it->w, c, field, prec, &multibyte);
15850 15932
15851 if (frame_title_ptr) 15933 switch (mode_line_target)
15852 n += store_frame_title (spec, field, prec);
15853 else if (!NILP (mode_line_string_list))
15854 {
15855 int len = strlen (spec);
15856 Lisp_Object tem = make_string (spec, len);
15857 props = Ftext_properties_at (make_number (charpos), elt);
15858 /* Should only keep face property in props */
15859 n += store_mode_line_string (NULL, tem, 0, field, prec, props);
15860 }
15861 else
15862 { 15934 {
15863 int nglyphs_before, nwritten; 15935 case MODE_LINE_NOPROP:
15864 15936 case MODE_LINE_TITLE:
15865 nglyphs_before = it->glyph_row->used[TEXT_AREA]; 15937 n += store_mode_line_noprop (spec, field, prec);
15866 nwritten = display_string (spec, Qnil, elt, 15938 break;
15867 charpos, 0, it, 15939 case MODE_LINE_STRING:
15868 field, prec, 0, 15940 {
15869 multibyte); 15941 int len = strlen (spec);
15870 15942 Lisp_Object tem = make_string (spec, len);
15871 /* Assign to the glyphs written above the 15943 props = Ftext_properties_at (make_number (charpos), elt);
15872 string where the `%x' came from, position 15944 /* Should only keep face property in props */
15873 of the `%'. */ 15945 n += store_mode_line_string (NULL, tem, 0, field, prec, props);
15874 if (nwritten > 0) 15946 }
15875 { 15947 break;
15876 struct glyph *glyph 15948 case MODE_LINE_DISPLAY:
15877 = (it->glyph_row->glyphs[TEXT_AREA] 15949 {
15878 + nglyphs_before); 15950 int nglyphs_before, nwritten;
15879 int i; 15951
15880 15952 nglyphs_before = it->glyph_row->used[TEXT_AREA];
15881 for (i = 0; i < nwritten; ++i) 15953 nwritten = display_string (spec, Qnil, elt,
15882 { 15954 charpos, 0, it,
15883 glyph[i].object = elt; 15955 field, prec, 0,
15884 glyph[i].charpos = charpos; 15956 multibyte);
15885 } 15957
15886 15958 /* Assign to the glyphs written above the
15887 n += nwritten; 15959 string where the `%x' came from, position
15888 } 15960 of the `%'. */
15961 if (nwritten > 0)
15962 {
15963 struct glyph *glyph
15964 = (it->glyph_row->glyphs[TEXT_AREA]
15965 + nglyphs_before);
15966 int i;
15967
15968 for (i = 0; i < nwritten; ++i)
15969 {
15970 glyph[i].object = elt;
15971 glyph[i].charpos = charpos;
15972 }
15973
15974 n += nwritten;
15975 }
15976 }
15977 break;
15889 } 15978 }
15890 } 15979 }
15891 else /* c == 0 */ 15980 else /* c == 0 */
@@ -16056,13 +16145,20 @@ display_mode_element (it, depth, field_width, precision, elt, props, risky)
16056 /* Pad to FIELD_WIDTH. */ 16145 /* Pad to FIELD_WIDTH. */
16057 if (field_width > 0 && n < field_width) 16146 if (field_width > 0 && n < field_width)
16058 { 16147 {
16059 if (frame_title_ptr) 16148 switch (mode_line_target)
16060 n += store_frame_title ("", field_width - n, 0); 16149 {
16061 else if (!NILP (mode_line_string_list)) 16150 case MODE_LINE_NOPROP:
16062 n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil); 16151 case MODE_LINE_TITLE:
16063 else 16152 n += store_mode_line_noprop ("", field_width - n, 0);
16064 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n, 16153 break;
16065 0, 0, 0); 16154 case MODE_LINE_STRING:
16155 n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil);
16156 break;
16157 case MODE_LINE_DISPLAY:
16158 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
16159 0, 0, 0);
16160 break;
16161 }
16066 } 16162 }
16067 16163
16068 return n; 16164 return n;
@@ -16194,6 +16290,9 @@ are the selected window and the window's buffer). */)
16194 struct buffer *old_buffer = NULL; 16290 struct buffer *old_buffer = NULL;
16195 int face_id = -1; 16291 int face_id = -1;
16196 int no_props = INTEGERP (face); 16292 int no_props = INTEGERP (face);
16293 int count = SPECPDL_INDEX ();
16294 Lisp_Object str;
16295 char *string_start = NULL;
16197 16296
16198 if (NILP (window)) 16297 if (NILP (window))
16199 window = selected_window; 16298 window = selected_window;
@@ -16221,64 +16320,52 @@ are the selected window and the window's buffer). */)
16221 face_id = DEFAULT_FACE_ID; 16320 face_id = DEFAULT_FACE_ID;
16222 16321
16223 if (XBUFFER (buffer) != current_buffer) 16322 if (XBUFFER (buffer) != current_buffer)
16224 { 16323 old_buffer = current_buffer;
16225 old_buffer = current_buffer; 16324
16226 set_buffer_internal_1 (XBUFFER (buffer)); 16325 record_unwind_protect (unwind_format_mode_line,
16227 } 16326 format_mode_line_unwind_data (old_buffer));
16327
16328 if (old_buffer)
16329 set_buffer_internal_1 (XBUFFER (buffer));
16228 16330
16229 init_iterator (&it, w, -1, -1, NULL, face_id); 16331 init_iterator (&it, w, -1, -1, NULL, face_id);
16230 16332
16231 if (!no_props) 16333 if (no_props)
16232 { 16334 {
16233 mode_line_string_face = face; 16335 mode_line_target = MODE_LINE_NOPROP;
16234 mode_line_string_face_prop 16336 mode_line_string_face_prop = Qnil;
16235 = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil))); 16337 mode_line_string_list = Qnil;
16236 16338 string_start = mode_line_noprop_ptr;
16237 /* We need a dummy last element in mode_line_string_list to
16238 indicate we are building the propertized mode-line string.
16239 Using mode_line_string_face_prop here GC protects it. */
16240 mode_line_string_list
16241 = Fcons (mode_line_string_face_prop, Qnil);
16242 frame_title_ptr = NULL;
16243 } 16339 }
16244 else 16340 else
16245 { 16341 {
16246 mode_line_string_face_prop = Qnil; 16342 mode_line_target = MODE_LINE_STRING;
16247 mode_line_string_list = Qnil; 16343 mode_line_string_list = Qnil;
16248 frame_title_ptr = frame_title_buf; 16344 mode_line_string_face = face;
16345 mode_line_string_face_prop
16346 = (NILP (face) ? Qnil : Fcons (Qface, Fcons (face, Qnil)));
16347
16348 string_start = NULL;
16249 } 16349 }
16250 16350
16251 push_frame_kboard (it.f); 16351 push_frame_kboard (it.f);
16252 display_mode_element (&it, 0, 0, 0, format, Qnil, 0); 16352 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
16253 pop_frame_kboard (); 16353 pop_frame_kboard ();
16254 16354
16255 if (old_buffer) 16355 if (no_props)
16256 set_buffer_internal_1 (old_buffer);
16257
16258 if (!no_props)
16259 { 16356 {
16260 Lisp_Object str; 16357 len = mode_line_noprop_ptr - string_start;
16261 mode_line_string_list = Fnreverse (mode_line_string_list); 16358 str = make_string (string_start, len);
16262 str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list),
16263 make_string ("", 0));
16264 mode_line_string_face_prop = Qnil;
16265 mode_line_string_list = Qnil;
16266 return str;
16267 } 16359 }
16268 16360 else
16269 len = frame_title_ptr - frame_title_buf;
16270 if (len > 0 && frame_title_ptr[-1] == '-')
16271 { 16361 {
16272 /* Mode lines typically ends with numerous dashes; reduce to two dashes. */ 16362 mode_line_string_list = Fnreverse (mode_line_string_list);
16273 while (frame_title_ptr > frame_title_buf && *--frame_title_ptr == '-') 16363 str = Fmapconcat (intern ("identity"), mode_line_string_list,
16274 ; 16364 make_string ("", 0));
16275 frame_title_ptr += 3; /* restore last non-dash + two dashes */
16276 if (len > frame_title_ptr - frame_title_buf)
16277 len = frame_title_ptr - frame_title_buf;
16278 } 16365 }
16279 16366
16280 frame_title_ptr = NULL; 16367 unbind_to (count, Qnil);
16281 return make_string (frame_title_buf, len); 16368 return str;
16282} 16369}
16283 16370
16284/* Write a null-terminated, right justified decimal representation of 16371/* Write a null-terminated, right justified decimal representation of
@@ -16596,7 +16683,8 @@ decode_mode_spec (w, c, field_width, precision, multibyte)
16596 register int i; 16683 register int i;
16597 16684
16598 /* Let lots_of_dashes be a string of infinite length. */ 16685 /* Let lots_of_dashes be a string of infinite length. */
16599 if (!NILP (mode_line_string_list)) 16686 if (mode_line_target == MODE_LINE_NOPROP ||
16687 mode_line_target == MODE_LINE_STRING)
16600 return "--"; 16688 return "--";
16601 if (field_width <= 0 16689 if (field_width <= 0
16602 || field_width > sizeof (lots_of_dashes)) 16690 || field_width > sizeof (lots_of_dashes))
@@ -22689,9 +22777,14 @@ syms_of_xdisp ()
22689 22777
22690 mode_line_proptrans_alist = Qnil; 22778 mode_line_proptrans_alist = Qnil;
22691 staticpro (&mode_line_proptrans_alist); 22779 staticpro (&mode_line_proptrans_alist);
22692
22693 mode_line_string_list = Qnil; 22780 mode_line_string_list = Qnil;
22694 staticpro (&mode_line_string_list); 22781 staticpro (&mode_line_string_list);
22782 mode_line_string_face = Qnil;
22783 staticpro (&mode_line_string_face);
22784 mode_line_string_face_prop = Qnil;
22785 staticpro (&mode_line_string_face_prop);
22786 Vmode_line_unwind_vector = Qnil;
22787 staticpro (&Vmode_line_unwind_vector);
22695 22788
22696 help_echo_string = Qnil; 22789 help_echo_string = Qnil;
22697 staticpro (&help_echo_string); 22790 staticpro (&help_echo_string);
@@ -23041,9 +23134,10 @@ init_xdisp ()
23041 /* Allocate the buffer for frame titles. 23134 /* Allocate the buffer for frame titles.
23042 Also used for `format-mode-line'. */ 23135 Also used for `format-mode-line'. */
23043 int size = 100; 23136 int size = 100;
23044 frame_title_buf = (char *) xmalloc (size); 23137 mode_line_noprop_buf = (char *) xmalloc (size);
23045 frame_title_buf_end = frame_title_buf + size; 23138 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
23046 frame_title_ptr = NULL; 23139 mode_line_noprop_ptr = mode_line_noprop_buf;
23140 mode_line_target = MODE_LINE_DISPLAY;
23047 } 23141 }
23048 23142
23049 help_echo_showing_p = 0; 23143 help_echo_showing_p = 0;