aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1993-12-23 01:04:26 +0000
committerRichard M. Stallman1993-12-23 01:04:26 +0000
commit90adcf2077e004798b3ace8195ba610cfc822a34 (patch)
tree231f8f2c084115309ad31f7957c98454d6f34cdd /src
parentf58534a3faddd86cf1dea26195db461b16b1bbd8 (diff)
downloademacs-90adcf2077e004798b3ace8195ba610cfc822a34.tar.gz
emacs-90adcf2077e004798b3ace8195ba610cfc822a34.zip
(message): Use message2, not message1.
(display_string): Fix truncation-criterion after main loop for termination due to LENGTH. (echo_area_glyphs_length): New variable. (message1): Set it. (message2): New function. (display_string): New arg LENGTH. (echo_area_display): Pass new arg to display_string. (redisplay_window): Likewise. (display_text_line): Likewise. (display_menu_bar): Likewise. (display_mode_element): Likewise. (update_menu_bar, update_menu_bars): New functions. (prepare_menu_bars): New function. (redisplay_window): Don't update menu bar here. (display_menu_bar): Assume item list already updated. (redisplay_window): Don't alter lpoint when w is selected window in a non-selected frame.
Diffstat (limited to 'src')
-rw-r--r--src/xdisp.c312
1 files changed, 255 insertions, 57 deletions
diff --git a/src/xdisp.c b/src/xdisp.c
index 62542515496..bb007713f6e 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -124,6 +124,8 @@ static void echo_area_display ();
124void mark_window_display_accurate (); 124void mark_window_display_accurate ();
125static void redisplay_windows (); 125static void redisplay_windows ();
126static void redisplay_window (); 126static void redisplay_window ();
127static void update_menu_bars ();
128static void update_menu_bar ();
127static void try_window (); 129static void try_window ();
128static int try_window_id (); 130static int try_window_id ();
129static struct position *display_text_line (); 131static struct position *display_text_line ();
@@ -147,6 +149,9 @@ int minibuf_prompt_width;
147 It overrides the minibuf_prompt as well as the buffer. */ 149 It overrides the minibuf_prompt as well as the buffer. */
148char *echo_area_glyphs; 150char *echo_area_glyphs;
149 151
152/* This is the length of the message in echo_area_glyphs. */
153int echo_area_glyphs_length;
154
150/* true iff we should redraw the mode lines on the next redisplay */ 155/* true iff we should redraw the mode lines on the next redisplay */
151int update_mode_lines; 156int update_mode_lines;
152 157
@@ -182,6 +187,7 @@ int line_number_display_limit;
182 187
183/* Specify m, a string, as a message in the minibuf. If m is 0, clear out 188/* Specify m, a string, as a message in the minibuf. If m is 0, clear out
184 any existing message, and let the minibuffer text show through. */ 189 any existing message, and let the minibuffer text show through. */
190
185void 191void
186message1 (m) 192message1 (m)
187 char *m; 193 char *m;
@@ -214,7 +220,59 @@ message1 (m)
214#endif 220#endif
215 221
216 if (m) 222 if (m)
217 echo_area_glyphs = m; 223 {
224 echo_area_glyphs = m;
225 echo_area_glyphs_length = strlen (m);
226 }
227 else
228 echo_area_glyphs = previous_echo_glyphs = 0;
229
230 do_pending_window_change ();
231 echo_area_display ();
232 update_frame (XFRAME (XWINDOW (minibuf_window)->frame), 1, 1);
233 do_pending_window_change ();
234 }
235}
236
237/* Display an echo area message M with a specified length of LEN chars.
238 This way, null characters can be included. */
239
240void
241message2 (m, len)
242 char *m;
243 int len;
244{
245 if (noninteractive)
246 {
247 if (noninteractive_need_newline)
248 putc ('\n', stderr);
249 noninteractive_need_newline = 0;
250 fwrite (m, len, 1, stderr);
251 if (cursor_in_echo_area == 0)
252 fprintf (stderr, "\n");
253 fflush (stderr);
254 }
255 /* A null message buffer means that the frame hasn't really been
256 initialized yet. Error messages get reported properly by
257 cmd_error, so this must be just an informative message; toss it. */
258 else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
259 {
260#ifdef MULTI_FRAME
261 Lisp_Object minibuf_frame;
262
263 choose_minibuf_frame ();
264 minibuf_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
265 FRAME_SAMPLE_VISIBILITY (XFRAME (minibuf_frame));
266 if (FRAME_VISIBLE_P (selected_frame)
267 && ! FRAME_VISIBLE_P (XFRAME (minibuf_frame)))
268 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (minibuf_window)));
269#endif
270
271 if (m)
272 {
273 echo_area_glyphs = m;
274 echo_area_glyphs_length = len;
275 }
218 else 276 else
219 echo_area_glyphs = previous_echo_glyphs = 0; 277 echo_area_glyphs = previous_echo_glyphs = 0;
220 278
@@ -269,22 +327,21 @@ message (m, a1, a2, a3)
269 { 327 {
270 if (m) 328 if (m)
271 { 329 {
272 { 330 int len;
273#ifdef NO_ARG_ARRAY 331#ifdef NO_ARG_ARRAY
274 int a[3]; 332 int a[3];
275 a[0] = a1; 333 a[0] = a1;
276 a[1] = a2; 334 a[1] = a2;
277 a[2] = a3; 335 a[2] = a3;
278 336
279 doprnt (FRAME_MESSAGE_BUF (echo_frame), 337 len = doprnt (FRAME_MESSAGE_BUF (echo_frame),
280 FRAME_WIDTH (echo_frame), m, 0, 3, a); 338 FRAME_WIDTH (echo_frame), m, 0, 3, a);
281#else 339#else
282 doprnt (FRAME_MESSAGE_BUF (echo_frame), 340 len = doprnt (FRAME_MESSAGE_BUF (echo_frame),
283 FRAME_WIDTH (echo_frame), m, 0, 3, &a1); 341 FRAME_WIDTH (echo_frame), m, 0, 3, &a1);
284#endif /* NO_ARG_ARRAY */ 342#endif /* NO_ARG_ARRAY */
285 }
286 343
287 message1 (FRAME_MESSAGE_BUF (echo_frame)); 344 message2 (FRAME_MESSAGE_BUF (echo_frame), len);
288 } 345 }
289 else 346 else
290 message1 (0); 347 message1 (0);
@@ -323,6 +380,7 @@ echo_area_display ()
323 get_display_line (f, vpos, 0); 380 get_display_line (f, vpos, 0);
324 display_string (XWINDOW (minibuf_window), vpos, 381 display_string (XWINDOW (minibuf_window), vpos,
325 echo_area_glyphs ? echo_area_glyphs : "", 382 echo_area_glyphs ? echo_area_glyphs : "",
383 echo_area_glyphs ? echo_area_glyphs_length : -1,
326 0, 0, 0, FRAME_WIDTH (f)); 384 0, 0, 0, FRAME_WIDTH (f));
327 385
328 /* If desired cursor location is on this line, put it at end of text */ 386 /* If desired cursor location is on this line, put it at end of text */
@@ -338,7 +396,7 @@ echo_area_display ()
338 { 396 {
339 get_display_line (f, i, 0); 397 get_display_line (f, i, 0);
340 display_string (XWINDOW (minibuf_window), vpos, 398 display_string (XWINDOW (minibuf_window), vpos,
341 "", 0, 0, 0, FRAME_WIDTH (f)); 399 "", 0, 0, 0, 0, FRAME_WIDTH (f));
342 } 400 }
343 } 401 }
344 } 402 }
@@ -351,6 +409,77 @@ echo_area_display ()
351 previous_echo_glyphs = echo_area_glyphs; 409 previous_echo_glyphs = echo_area_glyphs;
352} 410}
353 411
412/* Prepare for redisplay by updating menu-bar item lists when appropriate.
413 This can't be done in `redisplay' itself because it can call eval. */
414
415void
416prepare_menu_bars ()
417{
418 register struct window *w = XWINDOW (selected_window);
419 int all_windows;
420
421 if (noninteractive)
422 return;
423
424 /* Set the visible flags for all frames.
425 Do this before checking for resized or garbaged frames; they want
426 to know if their frames are visible.
427 See the comment in frame.h for FRAME_SAMPLE_VISIBILITY. */
428 {
429 Lisp_Object tail, frame;
430
431 FOR_EACH_FRAME (tail, frame)
432 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
433 }
434
435 /* Notice any pending interrupt request to change frame size. */
436 do_pending_window_change ();
437
438 if (frame_garbaged)
439 {
440 redraw_garbaged_frames ();
441 frame_garbaged = 0;
442 }
443
444 if (clip_changed || windows_or_buffers_changed)
445 update_mode_lines++;
446
447 /* Detect case that we need to write a star in the mode line. */
448 if (XFASTINT (w->last_modified) < MODIFF
449 && XFASTINT (w->last_modified) <= current_buffer->save_modified)
450 {
451 w->update_mode_line = Qt;
452 if (buffer_shared > 1)
453 update_mode_lines++;
454 }
455
456 all_windows = update_mode_lines || buffer_shared > 1;
457
458 /* If specs for an arrow have changed, do thorough redisplay
459 to ensure we remove any arrow that should no longer exist. */
460 if (! EQ (Voverlay_arrow_position, last_arrow_position)
461 || ! EQ (Voverlay_arrow_string, last_arrow_string))
462 all_windows = 1, clip_changed = 1;
463
464 /* Update the menu bar item lists, if appropriate.
465 This has to be done before any actual redisplay
466 or generation of display lines. */
467 if (all_windows)
468 {
469 Lisp_Object tail, frame;
470
471 FOR_EACH_FRAME (tail, frame)
472 {
473 FRAME_PTR f = XFRAME (frame);
474
475 if (FRAME_VISIBLE_P (f))
476 update_menu_bars (FRAME_ROOT_WINDOW (f));
477 }
478 }
479 else if (FRAME_VISIBLE_P (selected_frame))
480 update_menu_bar (selected_window);
481}
482
354/* Do a frame update, taking possible shortcuts into account. 483/* Do a frame update, taking possible shortcuts into account.
355 This is the main external entry point for redisplay. 484 This is the main external entry point for redisplay.
356 485
@@ -358,11 +487,14 @@ echo_area_display ()
358 message is no longer requested, we clear the echo area 487 message is no longer requested, we clear the echo area
359 or bring back the minibuffer if that is in use. 488 or bring back the minibuffer if that is in use.
360 489
361 Everyone would like to have a hook here to call eval, 490 Do not call eval from within this function.
362 but that cannot be done safely without a lot of changes elsewhere. 491 Calls to eval after the call to echo_area_display would confuse
363 This can be called from signal handlers; with alarms set up; 492 the display_line mechanism and would cause a crash.
493 Calls to eval before that point will work most of the time,
494 but can still lose, because this function
495 can be called from signal handlers; with alarms set up;
364 or with synchronous processes running. 496 or with synchronous processes running.
365 See the function `echo' in keyboard.c. 497
366 See Fcall_process; if you called it from here, it could be 498 See Fcall_process; if you called it from here, it could be
367 entered recursively. */ 499 entered recursively. */
368 500
@@ -400,16 +532,6 @@ redisplay ()
400 frame_garbaged = 0; 532 frame_garbaged = 0;
401 } 533 }
402 534
403 /* Normally the message* functions will have already displayed and
404 updated the echo area, but the frame may have been trashed, or
405 the update may have been preempted, so display the echo area
406 again here. */
407 if (echo_area_glyphs || previous_echo_glyphs)
408 {
409 echo_area_display ();
410 must_finish = 1;
411 }
412
413 if (clip_changed || windows_or_buffers_changed) 535 if (clip_changed || windows_or_buffers_changed)
414 update_mode_lines++; 536 update_mode_lines++;
415 537
@@ -432,6 +554,16 @@ redisplay ()
432 || ! EQ (Voverlay_arrow_string, last_arrow_string)) 554 || ! EQ (Voverlay_arrow_string, last_arrow_string))
433 all_windows = 1, clip_changed = 1; 555 all_windows = 1, clip_changed = 1;
434 556
557 /* Normally the message* functions will have already displayed and
558 updated the echo area, but the frame may have been trashed, or
559 the update may have been preempted, so display the echo area
560 again here. */
561 if (echo_area_glyphs || previous_echo_glyphs)
562 {
563 echo_area_display ();
564 must_finish = 1;
565 }
566
435 /* If showing region, and mark has changed, must redisplay whole window. */ 567 /* If showing region, and mark has changed, must redisplay whole window. */
436 if (((!NILP (Vtransient_mark_mode) 568 if (((!NILP (Vtransient_mark_mode)
437 && !NILP (XBUFFER (w->buffer)->mark_active)) 569 && !NILP (XBUFFER (w->buffer)->mark_active))
@@ -752,8 +884,78 @@ mark_window_display_accurate (window, flag)
752 } 884 }
753} 885}
754 886
887/* Update the menu bar item lists for WINDOW
888 and its subwindows and siblings.
889 This has to be done before we start to fill in any display lines,
890 because it can call eval. */
891
892static void
893update_menu_bars (window)
894 Lisp_Object window;
895{
896 for (; !NILP (window); window = XWINDOW (window)->next)
897 update_menu_bar (window, 0);
898}
899
900/* Update the menu bar item list for window WINDOW and its subwindows. */
901
902static void
903update_menu_bar (window, just_this_one)
904 Lisp_Object window;
905 int just_this_one;
906{
907 register struct window *w = XWINDOW (window);
908 struct buffer *old = current_buffer;
909 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
910
911 /* If this is a combination window, do its children; that's all. */
912
913 if (!NILP (w->vchild))
914 {
915 update_menu_bars (w->vchild);
916 return;
917 }
918 if (!NILP (w->hchild))
919 {
920 update_menu_bars (w->hchild);
921 return;
922 }
923 if (NILP (w->buffer))
924 abort ();
925
926 if (update_mode_lines)
927 w->update_mode_line = Qt;
928
929 /* When we reach a frame's selected window, redo the frame's menu bar. */
930 if (!NILP (w->update_mode_line)
931 && FRAME_MENU_BAR_LINES (f) > 0
932 && EQ (FRAME_SELECTED_WINDOW (f), window))
933 {
934 /* If the user has switched buffers or windows, we need to
935 recompute to reflect the new bindings. But we'll
936 recompute when update_mode_lines is set too; that means
937 that people can use force-mode-line-update to request
938 that the menu bar be recomputed. The adverse effect on
939 the rest of the redisplay algorithm is about the same as
940 windows_or_buffers_changed anyway. */
941 if (windows_or_buffers_changed
942 || update_mode_lines
943 || (XFASTINT (w->last_modified) < MODIFF
944 && (XFASTINT (w->last_modified)
945 <= XBUFFER (w->buffer)->save_modified)))
946 {
947 struct buffer *prev = current_buffer;
948 current_buffer = XBUFFER (w->buffer);
949 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items ();
950 current_buffer = prev;
951 }
952 }
953}
954
755int do_id = 1; 955int do_id = 1;
756 956
957/* Redisplay WINDOW and its subwindows and siblings. */
958
757static void 959static void
758redisplay_windows (window) 960redisplay_windows (window)
759 Lisp_Object window; 961 Lisp_Object window;
@@ -762,6 +964,8 @@ redisplay_windows (window)
762 redisplay_window (window, 0); 964 redisplay_window (window, 0);
763} 965}
764 966
967/* Redisplay window WINDOW and its subwindows. */
968
765static void 969static void
766redisplay_window (window, just_this_one) 970redisplay_window (window, just_this_one)
767 Lisp_Object window; 971 Lisp_Object window;
@@ -817,7 +1021,7 @@ redisplay_window (window, just_this_one)
817 for (i = 0; i < height; i++) 1021 for (i = 0; i < height; i++)
818 { 1022 {
819 get_display_line (f, vpos + i, 0); 1023 get_display_line (f, vpos + i, 0);
820 display_string (w, vpos + i, "", 0, 0, 0, width); 1024 display_string (w, vpos + i, "", 0, 0, 0, 0, width);
821 } 1025 }
822 1026
823 goto finish_scroll_bars; 1027 goto finish_scroll_bars;
@@ -887,7 +1091,7 @@ redisplay_window (window, just_this_one)
887 - (1 << (SHORTBITS - 1)), 1091 - (1 << (SHORTBITS - 1)),
888 width, hscroll, pos_tab_offset (w, startp)); 1092 width, hscroll, pos_tab_offset (w, startp));
889 SET_PT (pos.bufpos); 1093 SET_PT (pos.bufpos);
890 if (w != XWINDOW (FRAME_SELECTED_WINDOW (f))) 1094 if (w != XWINDOW (selected_window))
891 Fset_marker (w->pointm, make_number (point), Qnil); 1095 Fset_marker (w->pointm, make_number (point), Qnil);
892 else 1096 else
893 { 1097 {
@@ -1765,7 +1969,7 @@ display_text_line (w, start, vpos, hpos, taboffset)
1765 && vpos == XFASTINT (w->top)) 1969 && vpos == XFASTINT (w->top))
1766 { 1970 {
1767 if (minibuf_prompt) 1971 if (minibuf_prompt)
1768 hpos = display_string (w, vpos, minibuf_prompt, hpos, 1972 hpos = display_string (w, vpos, minibuf_prompt, -1, hpos,
1769 (!truncate ? continuer : truncator), 1973 (!truncate ? continuer : truncator),
1770 -1, -1); 1974 -1, -1);
1771 minibuf_prompt_width = hpos; 1975 minibuf_prompt_width = hpos;
@@ -2149,25 +2353,6 @@ display_menu_bar (w)
2149 2353
2150 get_display_line (f, vpos, 0); 2354 get_display_line (f, vpos, 0);
2151 2355
2152 /* If the user has switched buffers or windows, we need to
2153 recompute to reflect the new bindings. But we'll
2154 recompute when update_mode_lines is set too; that means
2155 that people can use force-mode-line-update to request
2156 that the menu bar be recomputed. The adverse effect on
2157 the rest of the redisplay algorithm is about the same as
2158 windows_or_buffers_changed anyway. */
2159 if (windows_or_buffers_changed
2160 || update_mode_lines
2161 || (XFASTINT (w->last_modified) < MODIFF
2162 && (XFASTINT (w->last_modified)
2163 <= XBUFFER (w->buffer)->save_modified)))
2164 {
2165 struct buffer *prev = current_buffer;
2166 current_buffer = XBUFFER (w->buffer);
2167 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items ();
2168 current_buffer = prev;
2169 }
2170
2171 for (tail = FRAME_MENU_BAR_ITEMS (f); CONSP (tail); tail = XCONS (tail)->cdr) 2356 for (tail = FRAME_MENU_BAR_ITEMS (f); CONSP (tail); tail = XCONS (tail)->cdr)
2172 { 2357 {
2173 Lisp_Object string; 2358 Lisp_Object string;
@@ -2180,12 +2365,13 @@ display_menu_bar (w)
2180 if (hpos < maxendcol) 2365 if (hpos < maxendcol)
2181 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos, 2366 hpos = display_string (XWINDOW (FRAME_ROOT_WINDOW (f)), vpos,
2182 XSTRING (string)->data, 2367 XSTRING (string)->data,
2368 XSTRING (string)->size,
2183 hpos, 0, hpos, maxendcol); 2369 hpos, 0, hpos, maxendcol);
2184 /* Put a gap of 3 spaces between items. */ 2370 /* Put a gap of 3 spaces between items. */
2185 if (hpos < maxendcol) 2371 if (hpos < maxendcol)
2186 { 2372 {
2187 int hpos1 = hpos + 3; 2373 int hpos1 = hpos + 3;
2188 hpos = display_string (w, vpos, "", hpos, 0, 2374 hpos = display_string (w, vpos, "", 0, hpos, 0,
2189 min (hpos1, maxendcol), maxendcol); 2375 min (hpos1, maxendcol), maxendcol);
2190 } 2376 }
2191 } 2377 }
@@ -2195,7 +2381,7 @@ display_menu_bar (w)
2195 2381
2196 /* Fill out the line with spaces. */ 2382 /* Fill out the line with spaces. */
2197 if (maxendcol > hpos) 2383 if (maxendcol > hpos)
2198 hpos = display_string (w, vpos, "", hpos, 0, maxendcol, -1); 2384 hpos = display_string (w, vpos, "", 0, hpos, 0, maxendcol, -1);
2199 2385
2200 /* Clear the rest of the lines allocated to the menu bar. */ 2386 /* Clear the rest of the lines allocated to the menu bar. */
2201 vpos++; 2387 vpos++;
@@ -2311,7 +2497,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
2311 if (this - 1 != last) 2497 if (this - 1 != last)
2312 { 2498 {
2313 register int lim = --this - last + hpos; 2499 register int lim = --this - last + hpos;
2314 hpos = display_string (w, vpos, last, hpos, 0, hpos, 2500 hpos = display_string (w, vpos, last, -1, hpos, 0, hpos,
2315 min (lim, maxendcol)); 2501 min (lim, maxendcol));
2316 } 2502 }
2317 else /* c == '%' */ 2503 else /* c == '%' */
@@ -2340,6 +2526,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
2340 hpos = display_string (w, vpos, 2526 hpos = display_string (w, vpos,
2341 decode_mode_spec (w, c, 2527 decode_mode_spec (w, c,
2342 maxendcol - hpos), 2528 maxendcol - hpos),
2529 -1,
2343 hpos, 0, spec_width, maxendcol); 2530 hpos, 0, spec_width, maxendcol);
2344 } 2531 }
2345 } 2532 }
@@ -2361,6 +2548,7 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
2361 don't check for % within it. */ 2548 don't check for % within it. */
2362 if (XTYPE (tem) == Lisp_String) 2549 if (XTYPE (tem) == Lisp_String)
2363 hpos = display_string (w, vpos, XSTRING (tem)->data, 2550 hpos = display_string (w, vpos, XSTRING (tem)->data,
2551 XSTRING (tem)->size,
2364 hpos, 0, minendcol, maxendcol); 2552 hpos, 0, minendcol, maxendcol);
2365 /* Give up right away for nil or t. */ 2553 /* Give up right away for nil or t. */
2366 else if (!EQ (tem, elt)) 2554 else if (!EQ (tem, elt))
@@ -2450,13 +2638,13 @@ display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
2450 2638
2451 default: 2639 default:
2452 invalid: 2640 invalid:
2453 return (display_string (w, vpos, "*invalid*", hpos, 0, 2641 return (display_string (w, vpos, "*invalid*", -1, hpos, 0,
2454 minendcol, maxendcol)); 2642 minendcol, maxendcol));
2455 } 2643 }
2456 2644
2457 end: 2645 end:
2458 if (minendcol > hpos) 2646 if (minendcol > hpos)
2459 hpos = display_string (w, vpos, "", hpos, 0, minendcol, -1); 2647 hpos = display_string (w, vpos, "", 0, hpos, 0, minendcol, -1);
2460 return hpos; 2648 return hpos;
2461} 2649}
2462 2650
@@ -2733,6 +2921,7 @@ display_count_lines (from, limit, n, pos_ptr)
2733/* Display STRING on one line of window W, starting at HPOS. 2921/* Display STRING on one line of window W, starting at HPOS.
2734 Display at position VPOS. Caller should have done get_display_line. 2922 Display at position VPOS. Caller should have done get_display_line.
2735 If VPOS == -1, display it as the current frame's title. 2923 If VPOS == -1, display it as the current frame's title.
2924 LENGTH is the length of STRING, or -1 meaning STRING is null-terminated.
2736 2925
2737 TRUNCATE is GLYPH to display at end if truncated. Zero for none. 2926 TRUNCATE is GLYPH to display at end if truncated. Zero for none.
2738 2927
@@ -2746,9 +2935,10 @@ display_count_lines (from, limit, n, pos_ptr)
2746 Returns ending hpos */ 2935 Returns ending hpos */
2747 2936
2748static int 2937static int
2749display_string (w, vpos, string, hpos, truncate, mincol, maxcol) 2938display_string (w, vpos, string, length, hpos, truncate, mincol, maxcol)
2750 struct window *w; 2939 struct window *w;
2751 unsigned char *string; 2940 unsigned char *string;
2941 int length;
2752 int vpos, hpos; 2942 int vpos, hpos;
2753 GLYPH truncate; 2943 GLYPH truncate;
2754 int mincol, maxcol; 2944 int mincol, maxcol;
@@ -2798,8 +2988,16 @@ display_string (w, vpos, string, hpos, truncate, mincol, maxcol)
2798 2988
2799 while (p1 < end) 2989 while (p1 < end)
2800 { 2990 {
2991 if (length == 0)
2992 break;
2801 c = *string++; 2993 c = *string++;
2802 if (!c) break; 2994 /* Specified length. */
2995 if (length >= 0)
2996 length--;
2997 /* Unspecified length (null-terminated string). */
2998 else if (c == 0)
2999 break;
3000
2803 if (c >= 040 && c < 0177 3001 if (c >= 040 && c < 0177
2804 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector)) 3002 && (dp == 0 || XTYPE (DISP_CHAR_VECTOR (dp, c)) != Lisp_Vector))
2805 { 3003 {
@@ -2847,7 +3045,7 @@ display_string (w, vpos, string, hpos, truncate, mincol, maxcol)
2847 } 3045 }
2848 } 3046 }
2849 3047
2850 if (c) 3048 if (c && length > 0)
2851 { 3049 {
2852 p1 = end; 3050 p1 = end;
2853 if (truncate) *p1++ = truncate; 3051 if (truncate) *p1++ = truncate;