comparison src/redisplay.c @ 424:11054d720c21 r21-2-20

Import from CVS: tag r21-2-20
author cvs
date Mon, 13 Aug 2007 11:26:11 +0200
parents 95016f13131a
children
comparison
equal deleted inserted replaced
423:28d9c139be4c 424:11054d720c21
152 need to be skipped. This is used for horizontal 152 need to be skipped. This is used for horizontal
153 scrolling, where a certain number of columns 153 scrolling, where a certain number of columns
154 (those off the left side of the screen) need 154 (those off the left side of the screen) need
155 to be skipped before anything is displayed. */ 155 to be skipped before anything is displayed. */
156 Bytind bi_start_col_enabled; 156 Bytind bi_start_col_enabled;
157 int start_col_xoffset; /* Number of pixels that still need to
158 be skipped. This is used for
159 horizontal scrolling of glyphs, where we want
160 to be able to scroll over part of the glyph. */
157 161
158 int hscroll_glyph_width_adjust; /* how much the width of the hscroll 162 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
159 glyph differs from space_width (w). 163 glyph differs from space_width (w).
160 0 if no hscroll glyph was used, 164 0 if no hscroll glyph was used,
161 i.e. the window is not scrolled 165 i.e. the window is not scrolled
257 static prop_block_dynarr *add_glyph_rune (pos_data *data, 261 static prop_block_dynarr *add_glyph_rune (pos_data *data,
258 struct glyph_block *gb, 262 struct glyph_block *gb,
259 int pos_type, int allow_cursor, 263 int pos_type, int allow_cursor,
260 struct glyph_cachel *cachel); 264 struct glyph_cachel *cachel);
261 static Bytind create_text_block (struct window *w, struct display_line *dl, 265 static Bytind create_text_block (struct window *w, struct display_line *dl,
262 Bytind bi_start_pos, int start_col, 266 Bytind bi_start_pos, prop_block_dynarr **prop,
263 prop_block_dynarr **prop,
264 int type); 267 int type);
265 static int create_overlay_glyph_block (struct window *w, 268 static int create_overlay_glyph_block (struct window *w,
266 struct display_line *dl); 269 struct display_line *dl);
267 static void create_left_glyph_block (struct window *w, 270 static void create_left_glyph_block (struct window *w,
268 struct display_line *dl, 271 struct display_line *dl,
273 static void decode_mode_spec (struct window *w, Emchar spec, int type); 276 static void decode_mode_spec (struct window *w, Emchar spec, int type);
274 static void free_display_line (struct display_line *dl); 277 static void free_display_line (struct display_line *dl);
275 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to, 278 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
276 Bufpos point, int no_regen); 279 Bufpos point, int no_regen);
277 static int point_visible (struct window *w, Bufpos point, int type); 280 static int point_visible (struct window *w, Bufpos point, int type);
278 extern Bytind bi_find_next_emchar_in_string (struct Lisp_String* str, Emchar target,
279 Bytind st, EMACS_INT count);
280 extern int string_column_at_point (struct Lisp_String* s, Bufpos init_pos, int tab_width);
281 281
282 /* This used to be 10 but 30 seems to give much better performance. */ 282 /* This used to be 10 but 30 seems to give much better performance. */
283 #define INIT_MAX_PREEMPTS 30 283 #define INIT_MAX_PREEMPTS 30
284 static int max_preempts; 284 static int max_preempts;
285 285
300 isn't any reason we need more than a single set. */ 300 isn't any reason we need more than a single set. */
301 display_line_dynarr *cmotion_display_lines; 301 display_line_dynarr *cmotion_display_lines;
302 302
303 /* Used by generate_formatted_string. Global because they get used so 303 /* Used by generate_formatted_string. Global because they get used so
304 much that the dynamic allocation time adds up. */ 304 much that the dynamic allocation time adds up. */
305 Emchar_dynarr *formatted_string_emchar_dynarr; 305 static Emchar_dynarr *formatted_string_emchar_dynarr;
306 struct display_line formatted_string_display_line; 306 static struct display_line formatted_string_display_line;
307 /* We store the extents that we need to generate in a Dynarr and then 307 /* We store the extents that we need to generate in a Dynarr and then
308 frob them all on at the end of generating the string. We do it 308 frob them all on at the end of generating the string. We do it
309 this way rather than adding them as we generate the string because 309 this way rather than adding them as we generate the string because
310 we don't store the text into the resulting string until we're done 310 we don't store the text into the resulting string until we're done
311 (to avoid having to resize the string multiple times), and we don't 311 (to avoid having to resize the string multiple times), and we don't
312 want to go around adding extents to a string when the extents might 312 want to go around adding extents to a string when the extents might
313 stretch off the end of the string. */ 313 stretch off the end of the string. */
314 EXTENT_dynarr *formatted_string_extent_dynarr; 314 static EXTENT_dynarr *formatted_string_extent_dynarr;
315 Bytecount_dynarr *formatted_string_extent_start_dynarr; 315 static Bytecount_dynarr *formatted_string_extent_start_dynarr;
316 Bytecount_dynarr *formatted_string_extent_end_dynarr; 316 static Bytecount_dynarr *formatted_string_extent_end_dynarr;
317 317
318 318
319 /* #### probably temporary */ 319 /* #### probably temporary */
320 int cache_adjustment; 320 int cache_adjustment;
321 321
336 336
337 /* Minimum visible pixel width of clipped glyphs at right margin. */ 337 /* Minimum visible pixel width of clipped glyphs at right margin. */
338 int horizontal_clip; 338 int horizontal_clip;
339 339
340 /* Set if currently inside update_line_start_cache. */ 340 /* Set if currently inside update_line_start_cache. */
341 int updating_line_start_cache; 341 static int updating_line_start_cache;
342 342
343 /* Nonzero means reading single-character input with prompt 343 /* Nonzero means reading single-character input with prompt
344 so put cursor on minibuffer after the prompt. */ 344 so put cursor on minibuffer after the prompt. */
345 int cursor_in_echo_area; 345 int cursor_in_echo_area;
346 Lisp_Object Qcursor_in_echo_area; 346 Lisp_Object Qcursor_in_echo_area;
376 /* non-zero if any displayed subwindow is in need of updating 376 /* non-zero if any displayed subwindow is in need of updating
377 somewhere. */ 377 somewhere. */
378 int subwindows_changed; 378 int subwindows_changed;
379 int subwindows_changed_set; 379 int subwindows_changed_set;
380 380
381 /* non-zero if any displayed subwindow is in need of updating
382 somewhere. */
383 int subwindows_state_changed;
384 int subwindows_state_changed_set;
385
381 /* This variable is 1 if the icon has to be updated. 386 /* This variable is 1 if the icon has to be updated.
382 It is set to 1 when `frame-icon-glyph' changes. */ 387 It is set to 1 when `frame-icon-glyph' changes. */
383 int icon_changed; 388 int icon_changed;
384 int icon_changed_set; 389 int icon_changed_set;
385 390
451 Lisp_Object Voverlay_arrow_position; 456 Lisp_Object Voverlay_arrow_position;
452 /* String to display for the arrow. */ 457 /* String to display for the arrow. */
453 Lisp_Object Voverlay_arrow_string; 458 Lisp_Object Voverlay_arrow_string;
454 459
455 Lisp_Object Vwindow_size_change_functions; 460 Lisp_Object Vwindow_size_change_functions;
456 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; 461 Lisp_Object Vwindow_scroll_functions;
457 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions; 462 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
458 463
459 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about 464 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
460 this more. */ 465 this more. */
461 #ifndef INHIBIT_REDISPLAY_HOOKS 466 #ifndef INHIBIT_REDISPLAY_HOOKS
463 Think about this for 19.14. */ 468 Think about this for 19.14. */
464 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook; 469 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
465 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook; 470 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
466 #endif /* INHIBIT_REDISPLAY_HOOKS */ 471 #endif /* INHIBIT_REDISPLAY_HOOKS */
467 472
468 int last_display_warning_tick, display_warning_tick; 473 static int last_display_warning_tick, display_warning_tick;
469 Lisp_Object Qdisplay_warning_buffer; 474 Lisp_Object Qdisplay_warning_buffer;
470 int inhibit_warning_display; 475 int inhibit_warning_display;
471 476
472 Lisp_Object Vleft_margin_width, Vright_margin_width; 477 Lisp_Object Vleft_margin_width, Vright_margin_width;
473 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; 478 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
474 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; 479 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
475 Lisp_Object Vtext_cursor_visible_p; 480 Lisp_Object Vtext_cursor_visible_p;
476 481
477 int column_number_start_at_one; 482 int column_number_start_at_one;
483
484 #define WINDOW_SCROLLED(w) \
485 (w->hscroll > 0 || w->left_xoffset)
486
478 487
479 /***************************************************************************/ 488 /***************************************************************************/
480 /* */ 489 /* */
481 /* low-level interfaces onto device routines */ 490 /* low-level interfaces onto device routines */
482 /* */ 491 /* */
642 { 651 {
643 int n_pos = left_pixpos; 652 int n_pos = left_pixpos;
644 int pix_tab_width = tab_pix_width (w); 653 int pix_tab_width = tab_pix_width (w);
645 654
646 /* Adjust n_pos for any hscrolling which has happened. */ 655 /* Adjust n_pos for any hscrolling which has happened. */
647 if (w->hscroll > 1) 656 if (WINDOW_SCROLLED (w))
648 n_pos -= space_width (w) * (w->hscroll - 1); 657 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset;
649 658
650 while (n_pos <= start_pixpos) 659 while (n_pos <= start_pixpos)
651 n_pos += pix_tab_width; 660 n_pos += pix_tab_width;
652 661
653 return n_pos; 662 return n_pos;
695 when the contents of the line reach the right boundary of the given 704 when the contents of the line reach the right boundary of the given
696 window. */ 705 window. */
697 706
698 static Bufpos 707 static Bufpos
699 generate_display_line (struct window *w, struct display_line *dl, int bounds, 708 generate_display_line (struct window *w, struct display_line *dl, int bounds,
700 Bufpos start_pos, int start_col, 709 Bufpos start_pos, prop_block_dynarr **prop,
701 prop_block_dynarr **prop,
702 int type) 710 int type)
703 { 711 {
704 Bufpos ret_bufpos; 712 Bufpos ret_bufpos;
705 int overlay_width; 713 int overlay_width;
706 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); 714 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
729 /* Create a display block for the text region of the line. */ 737 /* Create a display block for the text region of the line. */
730 { 738 {
731 /* #### urk urk urk!!! Chuck fix this shit! */ 739 /* #### urk urk urk!!! Chuck fix this shit! */
732 Bytind hacked_up_bytind = 740 Bytind hacked_up_bytind =
733 create_text_block (w, dl, bufpos_to_bytind (b, start_pos), 741 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
734 start_col, prop, type); 742 prop, type);
735 if (hacked_up_bytind > BI_BUF_ZV (b)) 743 if (hacked_up_bytind > BI_BUF_ZV (b))
736 ret_bufpos = BUF_ZV (b) + 1; 744 ret_bufpos = BUF_ZV (b) + 1;
737 else 745 else
738 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind); 746 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
739 } 747 }
1546 width = glyph_width (gb->glyph, Qnil, data->findex, data->window); 1554 width = glyph_width (gb->glyph, Qnil, data->findex, data->window);
1547 1555
1548 if (!width) 1556 if (!width)
1549 return NULL; 1557 return NULL;
1550 1558
1551 if (data->start_col) 1559 if (data->start_col || data->start_col_xoffset)
1552 { 1560 {
1553 prop_block_dynarr *retval; 1561 prop_block_dynarr *retval;
1554 int glyph_char_width = width / space_width (w); 1562 int glyph_char_width = width / space_width (w);
1555 1563
1556 /* If we still have not fully scrolled horizontally after 1564 /* If we still have not fully scrolled horizontally after
1780 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds. 1788 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1781 You must do appropriate conversion. */ 1789 You must do appropriate conversion. */
1782 1790
1783 static Bytind 1791 static Bytind
1784 create_text_block (struct window *w, struct display_line *dl, 1792 create_text_block (struct window *w, struct display_line *dl,
1785 Bytind bi_start_pos, int start_col, 1793 Bytind bi_start_pos, prop_block_dynarr **prop,
1786 prop_block_dynarr **prop,
1787 int type) 1794 int type)
1788 { 1795 {
1789 struct frame *f = XFRAME (w->frame); 1796 struct frame *f = XFRAME (w->frame);
1790 struct buffer *b = XBUFFER (w->buffer); 1797 struct buffer *b = XBUFFER (w->buffer);
1791 struct device *d = XDEVICE (f->device); 1798 struct device *d = XDEVICE (f->device);
1925 else 1932 else
1926 data.cursor_type = NO_CURSOR; 1933 data.cursor_type = NO_CURSOR;
1927 data.cursor_x = -1; 1934 data.cursor_x = -1;
1928 1935
1929 data.start_col = w->hscroll; 1936 data.start_col = w->hscroll;
1937 data.start_col_xoffset = w->left_xoffset;
1930 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0); 1938 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1931 data.hscroll_glyph_width_adjust = 0; 1939 data.hscroll_glyph_width_adjust = 0;
1932 1940
1933 /* We regenerate the line from the very beginning. */ 1941 /* We regenerate the line from the very beginning. */
1934 Dynarr_reset (db->runes); 1942 Dynarr_reset (db->runes);
2244 that the cursor shows up properly. */ 2252 that the cursor shows up properly. */
2245 data.ch = '\n'; 2253 data.ch = '\n';
2246 data.blank_width = DEVMETH (d, eol_cursor_width, ()); 2254 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2247 data.findex = DEFAULT_INDEX; 2255 data.findex = DEFAULT_INDEX;
2248 data.start_col = 0; 2256 data.start_col = 0;
2257 data.start_col_xoffset = 0;
2249 data.bi_start_col_enabled = 0; 2258 data.bi_start_col_enabled = 0;
2250 2259
2251 add_emchar_rune (&data); 2260 add_emchar_rune (&data);
2252 } 2261 }
2253 2262
2277 int next_tab_start; 2286 int next_tab_start;
2278 int char_tab_width; 2287 int char_tab_width;
2279 int prop_width = 0; 2288 int prop_width = 0;
2280 2289
2281 if (data.start_col > 1) 2290 if (data.start_col > 1)
2282 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); 2291 tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
2292 + data.start_col_xoffset;
2283 2293
2284 next_tab_start = 2294 next_tab_start =
2285 next_tab_position (w, tab_start_pixpos, 2295 next_tab_position (w, tab_start_pixpos,
2286 dl->bounds.left_in + 2296 dl->bounds.left_in +
2287 data.hscroll_glyph_width_adjust); 2297 data.hscroll_glyph_width_adjust);
2484 2494
2485 data.ch = '\n'; 2495 data.ch = '\n';
2486 data.blank_width = DEVMETH (d, eol_cursor_width, ()); 2496 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2487 data.findex = DEFAULT_INDEX; 2497 data.findex = DEFAULT_INDEX;
2488 data.start_col = 0; 2498 data.start_col = 0;
2499 data.start_col_xoffset = 0;
2489 data.bi_start_col_enabled = 0; 2500 data.bi_start_col_enabled = 0;
2490 2501
2491 data.max_pixpos += data.blank_width; 2502 data.max_pixpos += data.blank_width;
2492 add_emchar_rune (&data); 2503 add_emchar_rune (&data);
2493 data.max_pixpos -= data.blank_width; 2504 data.max_pixpos -= data.blank_width;
4232 face_index default_face) 4243 face_index default_face)
4233 { 4244 {
4234 struct frame *f = XFRAME (w->frame); 4245 struct frame *f = XFRAME (w->frame);
4235 /* Note that a lot of the buffer controlled stuff has been left in 4246 /* Note that a lot of the buffer controlled stuff has been left in
4236 because you might well want to make use of it (selective display 4247 because you might well want to make use of it (selective display
4237 etc), its just the buffer text that we do not use. */ 4248 etc), its just the buffer text that we do not use. However, it
4238 struct buffer *b = XBUFFER (w->buffer); 4249 seems to be possible for buffer to be nil sometimes so protect
4250 against this case. */
4251 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
4239 struct device *d = XDEVICE (f->device); 4252 struct device *d = XDEVICE (f->device);
4240 struct Lisp_String* s = XSTRING (disp_string); 4253 struct Lisp_String* s = XSTRING (disp_string);
4241 4254
4242 /* we're working with these a lot so precalculate them */ 4255 /* we're working with these a lot so precalculate them */
4243 Bytecount slen = XSTRING_LENGTH (disp_string); 4256 Bytecount slen = XSTRING_LENGTH (disp_string);
4244 Bytecount bi_string_zv = slen; 4257 Bytecount bi_string_zv = slen;
4245 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos); 4258 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4246 4259
4247 pos_data data; 4260 pos_data data;
4248 4261
4249 int truncate_win = window_truncation_on (w); 4262 int truncate_win = b ? window_truncation_on (w) : 0;
4250 int end_glyph_width = 0; 4263 int end_glyph_width = 0;
4251 4264
4252 /* we're going to ditch selective display for static text, its an 4265 /* we're going to ditch selective display for static text, its an
4253 FSF thing and invisble extents are the way to go 4266 FSF thing and invisble extents are the way to go
4254 here. Implementing it also relies on a number of buffer-specific 4267 here. Implementing it also relies on a number of buffer-specific
4294 4307
4295 #s(range-table data ((256 524288) (format "%x"))) 4308 #s(range-table data ((256 524288) (format "%x")))
4296 4309
4297 Since more than one display table is possible, you have 4310 Since more than one display table is possible, you have
4298 great flexibility in mapping ranges of characters. */ 4311 great flexibility in mapping ranges of characters. */
4299 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) 4312 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4300 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) 4313 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4301 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) 4314 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4302 ? 255 : 160)); 4315 ? 255 : 160)) : 255;
4303 4316
4304 Lisp_Object face_dt, window_dt; 4317 Lisp_Object face_dt, window_dt;
4305 4318
4306 /* The text display block for this display line. */ 4319 /* The text display block for this display line. */
4307 struct display_block *db = get_display_block_from_line (dl, TEXT); 4320 struct display_block *db = get_display_block_from_line (dl, TEXT);
4728 } 4741 }
4729 } 4742 }
4730 } 4743 }
4731 else if (data.bi_bufpos == bi_string_zv) 4744 else if (data.bi_bufpos == bi_string_zv)
4732 { 4745 {
4733 /* We need to add a marker to the end of the line since there is no 4746 /* create_text_block () adds a bogus \n marker here which screws
4734 newline character in order for the cursor to get drawn. We label 4747 up subwindow display. Since we never have a cursor in the
4735 it as a newline so that it gets handled correctly by the 4748 gutter we can safely ignore it. */
4736 whitespace routines below. */ 4749 }
4737
4738 data.ch = '\n';
4739 data.blank_width = DEVMETH (d, eol_cursor_width, ());
4740 data.findex = default_face;
4741 data.start_col = 0;
4742 data.bi_start_col_enabled = 0;
4743
4744 data.max_pixpos += data.blank_width;
4745 add_emchar_rune (&data);
4746 data.max_pixpos -= data.blank_width;
4747
4748 /* #### urk! Chuck, this shit is bad news. Going around
4749 manipulating invalid positions is guaranteed to result in
4750 trouble sooner or later. */
4751 data.bi_bufpos = bi_string_zv + 1;
4752 }
4753
4754 /* Calculate left whitespace boundary. */ 4750 /* Calculate left whitespace boundary. */
4755 { 4751 {
4756 int elt = 0; 4752 int elt = 0;
4757 4753
4758 /* Whitespace past a newline is considered right whitespace. */ 4754 /* Whitespace past a newline is considered right whitespace. */
4852 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv); 4848 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4853 else 4849 else
4854 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1; 4850 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4855 if (truncate_win) 4851 if (truncate_win)
4856 data.dl->num_chars = 4852 data.dl->num_chars =
4857 string_column_at_point (s, dl->end_bufpos, XINT (b->tab_width)); 4853 string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
4858 else 4854 else
4859 /* This doesn't correctly take into account tabs and control 4855 /* This doesn't correctly take into account tabs and control
4860 characters but if the window isn't being truncated then this 4856 characters but if the window isn't being truncated then this
4861 value isn't going to end up being used anyhow. */ 4857 value isn't going to end up being used anyhow. */
4862 data.dl->num_chars = dl->end_bufpos - dl->bufpos; 4858 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4907 face_index default_face) 4903 face_index default_face)
4908 { 4904 {
4909 Bufpos ret_bufpos; 4905 Bufpos ret_bufpos;
4910 4906
4911 /* you must set bounds before calling this. */ 4907 /* you must set bounds before calling this. */
4912 4908
4913 /* Reset what this line is using. */ 4909 /* Reset what this line is using. */
4914 if (dl->display_blocks) 4910 if (dl->display_blocks)
4915 Dynarr_reset (dl->display_blocks); 4911 Dynarr_reset (dl->display_blocks);
4916 if (dl->left_glyphs) 4912 if (dl->left_glyphs)
4917 { 4913 {
4968 /* if there's nothing to do then do nothing. code after this assumes 4964 /* if there's nothing to do then do nothing. code after this assumes
4969 there is something to do. */ 4965 there is something to do. */
4970 if (NILP (disp_string)) 4966 if (NILP (disp_string))
4971 return; 4967 return;
4972 4968
4973 s_zv = XSTRING_CHAR_LENGTH (disp_string) - 1; 4969 s_zv = XSTRING_CHAR_LENGTH (disp_string);
4974 4970
4975 bounds.left_out = xpos; 4971 bounds.left_out = xpos;
4976 bounds.right_out = xpos + width; 4972 bounds.right_out = xpos + width;
4977 /* The inner boundaries mark where the glyph margins are located. */ 4973 /* The inner boundaries mark where the glyph margins are located. */
4978 bounds.left_in = bounds.left_out + window_left_margin_width (w); 4974 bounds.left_in = bounds.left_out + window_left_margin_width (w);
5064 { 5060 {
5065 struct frame *f = XFRAME (w->frame); 5061 struct frame *f = XFRAME (w->frame);
5066 struct buffer *b = XBUFFER (w->buffer); 5062 struct buffer *b = XBUFFER (w->buffer);
5067 int ypos = WINDOW_TEXT_TOP (w); 5063 int ypos = WINDOW_TEXT_TOP (w);
5068 int yend; /* set farther down */ 5064 int yend; /* set farther down */
5065 int yclip = WINDOW_TEXT_TOP_CLIP (w);
5069 5066
5070 prop_block_dynarr *prop; 5067 prop_block_dynarr *prop;
5071 layout_bounds bounds; 5068 layout_bounds bounds;
5072 display_line_dynarr *dla; 5069 display_line_dynarr *dla;
5073 int need_modeline; 5070 int need_modeline;
5138 local = 1; 5135 local = 1;
5139 } 5136 }
5140 5137
5141 dlp->bounds = bounds; 5138 dlp->bounds = bounds;
5142 dlp->offset = 0; 5139 dlp->offset = 0;
5143 start_pos = generate_display_line (w, dlp, 1, start_pos, 5140 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
5144 w->hscroll, &prop, type); 5141
5145 dlp->ypos = ypos + dlp->ascent; 5142 if (yclip > dlp->ascent)
5143 {
5144 /* this should never happen, but if it does just display the
5145 whole line */
5146 yclip = 0;
5147 }
5148
5149 dlp->ypos = (ypos + dlp->ascent) - yclip;
5146 ypos = dlp->ypos + dlp->descent; 5150 ypos = dlp->ypos + dlp->descent;
5147 5151
5152 /* See if we've been asked to start midway through a line, for
5153 partial display line scrolling. */
5154 if (yclip)
5155 {
5156 dlp->top_clip = yclip;
5157 yclip = 0;
5158 }
5159 else
5160 dlp->top_clip = 0;
5161
5148 if (ypos > yend) 5162 if (ypos > yend)
5149 { 5163 {
5150 int visible_height = dlp->ascent + dlp->descent; 5164 int visible_height = dlp->ascent + dlp->descent;
5151 5165
5152 dlp->clip = (ypos - yend); 5166 dlp->clip = (ypos - yend);
5153 visible_height -= dlp->clip; 5167 /* Although this seems strange we could have a single very
5168 tall line visible for which we need to account for both
5169 the top clip and the bottom clip. */
5170 visible_height -= (dlp->clip + dlp->top_clip);
5154 5171
5155 if (visible_height < VERTICAL_CLIP (w, 1)) 5172 if (visible_height < VERTICAL_CLIP (w, 1))
5156 { 5173 {
5157 if (local) 5174 if (local)
5158 free_display_line (dlp); 5175 free_display_line (dlp);
5391 we'll have the necessary propagation data. */ 5408 we'll have the necessary propagation data. */
5392 if (line == first_line && ddl->used_prop_data) 5409 if (line == first_line && ddl->used_prop_data)
5393 return 0; 5410 return 0;
5394 5411
5395 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, 5412 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5396 w->hscroll, &prop, DESIRED_DISP); 5413 &prop, DESIRED_DISP);
5397 ddl->offset = 0; 5414 ddl->offset = 0;
5398 5415
5399 /* #### If there is propagated stuff the fail. We could 5416 /* #### If there is propagated stuff the fail. We could
5400 probably actually deal with this if the line had propagated 5417 probably actually deal with this if the line had propagated
5401 information when originally created by a full 5418 information when originally created by a full
5410 cursor has disappeared or disappeared, fail. */ 5427 cursor has disappeared or disappeared, fail. */
5411 db = get_display_block_from_line (ddl, TEXT); 5428 db = get_display_block_from_line (ddl, TEXT);
5412 if (cdl->ypos != ddl->ypos 5429 if (cdl->ypos != ddl->ypos
5413 || cdl->ascent != ddl->ascent 5430 || cdl->ascent != ddl->ascent
5414 || cdl->descent != ddl->descent 5431 || cdl->descent != ddl->descent
5432 || cdl->top_clip != ddl->top_clip
5415 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) 5433 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5416 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) 5434 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5417 || old_start != ddl->bufpos 5435 || old_start != ddl->bufpos
5418 || old_end != ddl->end_bufpos 5436 || old_end != ddl->end_bufpos
5419 || initial_size != Dynarr_length (db->runes)) 5437 || initial_size != Dynarr_length (db->runes))
5553 /* If the line was generated using propagation data, fail. */ 5571 /* If the line was generated using propagation data, fail. */
5554 if (ddl->used_prop_data) 5572 if (ddl->used_prop_data)
5555 return 0; 5573 return 0;
5556 5574
5557 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, 5575 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5558 w->hscroll, &prop, DESIRED_DISP); 5576 &prop, DESIRED_DISP);
5559 ddl->offset = 0; 5577 ddl->offset = 0;
5560 5578
5561 /* If there is propagated stuff then it is pretty much a 5579 /* If there is propagated stuff then it is pretty much a
5562 guarantee that more than just the one line is affected. */ 5580 guarantee that more than just the one line is affected. */
5563 if (prop) 5581 if (prop)
5583 /* If any line position parameters have changed or a 5601 /* If any line position parameters have changed or a
5584 cursor has disappeared or disappeared, fail. */ 5602 cursor has disappeared or disappeared, fail. */
5585 if (cdl->ypos != ddl->ypos 5603 if (cdl->ypos != ddl->ypos
5586 || cdl->ascent != ddl->ascent 5604 || cdl->ascent != ddl->ascent
5587 || cdl->descent != ddl->descent 5605 || cdl->descent != ddl->descent
5606 || cdl->top_clip != ddl->top_clip
5588 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) 5607 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5589 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) 5608 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
5590 { 5609 {
5591 return 0; 5610 return 0;
5592 } 5611 }
5875 || f->faces_changed) 5894 || f->faces_changed)
5876 reset_face_cachels (w); 5895 reset_face_cachels (w);
5877 else 5896 else
5878 mark_face_cachels_as_not_updated (w); 5897 mark_face_cachels_as_not_updated (w);
5879 5898
5880 /* Ditto the glyph cache elements. */ 5899 /* Ditto the glyph cache elements, although we do *not* invalidate
5900 the cache purely because glyphs have changed - this is now
5901 handled by the dirty flag.*/
5881 if ((!echo_active && b != window_display_buffer (w)) 5902 if ((!echo_active && b != window_display_buffer (w))
5882 || !Dynarr_length (w->glyph_cachels) 5903 || !Dynarr_length (w->glyph_cachels))
5883 || f->glyphs_changed)
5884 reset_glyph_cachels (w); 5904 reset_glyph_cachels (w);
5885 else 5905 else
5886 mark_glyph_cachels_as_not_updated (w); 5906 mark_glyph_cachels_as_not_updated (w);
5887 5907
5888 /* If the marker's buffer is not the window's buffer, then we need 5908 /* If the marker's buffer is not the window's buffer, then we need
5964 && !f->clip_changed 5984 && !f->clip_changed
5965 && !f->extents_changed 5985 && !f->extents_changed
5966 && !f->faces_changed 5986 && !f->faces_changed
5967 && !f->glyphs_changed 5987 && !f->glyphs_changed
5968 && !f->subwindows_changed 5988 && !f->subwindows_changed
5989 && !f->subwindows_state_changed
5969 && !f->point_changed 5990 && !f->point_changed
5970 && !f->windows_structure_changed) 5991 && !f->windows_structure_changed)
5971 { 5992 {
5972 /* If not, we're done. */ 5993 /* If not, we're done. */
5973 if (f->modeline_changed) 5994 if (f->modeline_changed)
5985 && !f->clip_changed 6006 && !f->clip_changed
5986 && !f->extents_changed 6007 && !f->extents_changed
5987 && !f->faces_changed 6008 && !f->faces_changed
5988 && !f->glyphs_changed 6009 && !f->glyphs_changed
5989 && !f->subwindows_changed 6010 && !f->subwindows_changed
6011 && !f->subwindows_state_changed
5990 && !f->windows_structure_changed) 6012 && !f->windows_structure_changed)
5991 { 6013 {
5992 if (point_visible (w, pointm, CURRENT_DISP) 6014 if (point_visible (w, pointm, CURRENT_DISP)
5993 && w->last_point_x[CURRENT_DISP] != -1 6015 && w->last_point_x[CURRENT_DISP] != -1
5994 && w->last_point_y[CURRENT_DISP] != -1) 6016 && w->last_point_y[CURRENT_DISP] != -1)
6043 else if (!w->windows_changed 6065 else if (!w->windows_changed
6044 && !f->clip_changed 6066 && !f->clip_changed
6045 && !f->faces_changed 6067 && !f->faces_changed
6046 && !f->glyphs_changed 6068 && !f->glyphs_changed
6047 && !f->subwindows_changed 6069 && !f->subwindows_changed
6070 && !f->subwindows_state_changed
6048 && !f->windows_structure_changed 6071 && !f->windows_structure_changed
6049 && !f->frame_changed 6072 && !f->frame_changed
6050 && !truncation_changed 6073 && !truncation_changed
6051 && pointm >= startp 6074 && pointm >= startp
6052 && regenerate_window_incrementally (w, startp, pointm)) 6075 && regenerate_window_incrementally (w, startp, pointm))
6139 6162
6140 /* #### This should be dependent on face changes and will need to be 6163 /* #### This should be dependent on face changes and will need to be
6141 somewhere else once tty updates occur on a per-frame basis. */ 6164 somewhere else once tty updates occur on a per-frame basis. */
6142 mark_face_cachels_as_clean (w); 6165 mark_face_cachels_as_clean (w);
6143 6166
6167 /* The glyph cachels only get dirty if someone changed something. */
6168 if (glyphs_changed)
6169 mark_glyph_cachels_as_clean (w);
6170
6144 w->windows_changed = 0; 6171 w->windows_changed = 0;
6145 } 6172 }
6146 6173
6147 /* Call buffer_reset_changes for all buffers present in any window 6174 /* Call buffer_reset_changes for all buffers present in any window
6148 currently visible in all frames on all devices. #### There has to 6175 currently visible in all frames on all devices. #### There has to
6260 the menubar's visibility. This way we avoid having flashing 6287 the menubar's visibility. This way we avoid having flashing
6261 caused by an Expose event generated by the visibility change 6288 caused by an Expose event generated by the visibility change
6262 being handled. */ 6289 being handled. */
6263 update_frame_menubars (f); 6290 update_frame_menubars (f);
6264 #endif /* HAVE_MENUBARS */ 6291 #endif /* HAVE_MENUBARS */
6265 update_frame_gutters (f);
6266 /* widgets are similar to menus in that they can call lisp to 6292 /* widgets are similar to menus in that they can call lisp to
6267 determine activation etc. Therefore update them before we get 6293 determine activation etc. Therefore update them before we get
6268 into redisplay. This is primarily for connected widgets such as 6294 into redisplay. This is primarily for connected widgets such as
6269 radio buttons. */ 6295 radio buttons. */
6270 update_frame_subwindows (f); 6296 update_frame_subwindows (f);
6271 #ifdef HAVE_TOOLBARS 6297 #ifdef HAVE_TOOLBARS
6272 /* Update the toolbars. */ 6298 /* Update the toolbars. */
6273 update_frame_toolbars (f); 6299 update_frame_toolbars (f);
6274 #endif /* HAVE_TOOLBARS */ 6300 #endif /* HAVE_TOOLBARS */
6275 6301
6302 /* If we clear the frame we have to force its contents to be redrawn. */
6303 if (f->clear)
6304 f->frame_changed = 1;
6305
6306 /* invalidate the subwindow cache. We use subwindows_changed here to
6307 cause subwindows to get instantiated. This is because
6308 subwindows_state_changed is less strict - dealing with things
6309 like the clicked state of button. We have to do this before
6310 redisplaying the gutters as subwindows get unmapped in the
6311 process.*/
6312 if (!Dynarr_length (f->subwindow_cachels)
6313 || f->subwindows_changed
6314 || f->frame_changed)
6315 {
6316 reset_subwindow_cachels (f);
6317 /* we have to do this so the gutter gets regenerated. */
6318 reset_gutter_display_lines (f);
6319 }
6320 else
6321 mark_subwindow_cachels_as_not_updated (f);
6322 /* We can now update the gutters, safe in the knowledge that our
6323 efforts won't get undone. */
6324 update_frame_gutters (f);
6325
6276 hold_frame_size_changes (); 6326 hold_frame_size_changes ();
6277 6327
6278 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ 6328 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6279 /* Within this section, we are defenseless and assume that the 6329 /* Within this section, we are defenseless and assume that the
6280 following cannot happen: 6330 following cannot happen:
6297 we simply return. #### We should abort instead. 6347 we simply return. #### We should abort instead.
6298 6348
6299 #### If a frame-size change does occur we should probably 6349 #### If a frame-size change does occur we should probably
6300 actually be preempting redisplay. */ 6350 actually be preempting redisplay. */
6301 6351
6302 /* If we clear the frame we have to force its contents to be redrawn. */
6303 if (f->clear)
6304 f->frame_changed = 1;
6305
6306 /* Erase the frame before outputting its contents. */ 6352 /* Erase the frame before outputting its contents. */
6307 if (f->clear) 6353 if (f->clear)
6308 { 6354 {
6309 DEVMETH (d, clear_frame, (f)); 6355 DEVMETH (d, clear_frame, (f));
6310 } 6356 }
6311
6312 /* invalidate the subwindow cache. we are going to reuse the glyphs
6313 flag here to cause subwindows to get instantiated. This is
6314 because subwindows changed is less strict - dealing with things
6315 like the clicked state of button. */
6316 if (!Dynarr_length (f->subwindow_cachels)
6317 || f->glyphs_changed
6318 || f->frame_changed)
6319 reset_subwindow_cachels (f);
6320 else
6321 mark_subwindow_cachels_as_not_updated (f);
6322 6357
6323 /* Do the selected window first. */ 6358 /* Do the selected window first. */
6324 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); 6359 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
6325 6360
6326 /* Then do the rest. */ 6361 /* Then do the rest. */
6332 if (FRAME_TTY_P (f)) 6367 if (FRAME_TTY_P (f))
6333 DEVMETH (d, output_end, (d)); 6368 DEVMETH (d, output_end, (d));
6334 6369
6335 update_frame_title (f); 6370 update_frame_title (f);
6336 6371
6337 f->buffers_changed = 0; 6372 CLASS_RESET_CHANGED_FLAGS (f);
6338 f->clip_changed = 0;
6339 f->extents_changed = 0;
6340 f->faces_changed = 0;
6341 f->frame_changed = 0;
6342 f->glyphs_changed = 0;
6343 f->subwindows_changed = 0;
6344 f->icon_changed = 0;
6345 f->menubar_changed = 0;
6346 f->modeline_changed = 0;
6347 f->point_changed = 0;
6348 f->toolbar_changed = 0;
6349 f->gutter_changed = 0;
6350 f->windows_changed = 0;
6351 f->windows_structure_changed = 0;
6352 f->window_face_cache_reset = 0; 6373 f->window_face_cache_reset = 0;
6353 f->echo_area_garbaged = 0; 6374 f->echo_area_garbaged = 0;
6354
6355 f->clear = 0; 6375 f->clear = 0;
6356 6376
6357 if (!f->size_change_pending) 6377 if (!f->size_change_pending)
6358 f->size_changed = 0; 6378 f->size_changed = 0;
6359 6379
6399 if (f->icon_changed || f->windows_changed) 6419 if (f->icon_changed || f->windows_changed)
6400 update_frame_icon (f); 6420 update_frame_icon (f);
6401 6421
6402 if (FRAME_REPAINT_P (f)) 6422 if (FRAME_REPAINT_P (f))
6403 { 6423 {
6404 if (f->buffers_changed || f->clip_changed || f->extents_changed || 6424 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
6405 f->faces_changed || f->frame_changed || f->menubar_changed ||
6406 f->modeline_changed || f->point_changed || f->size_changed ||
6407 f->toolbar_changed || f->windows_changed || f->size_slipped ||
6408 f->windows_structure_changed || f->glyphs_changed ||
6409 f->subwindows_changed || f->gutter_changed)
6410 { 6425 {
6411 preempted = redisplay_frame (f, 0); 6426 preempted = redisplay_frame (f, 0);
6412 } 6427 }
6413 6428
6414 if (preempted) 6429 if (preempted)
6434 if (f->icon_changed || f->windows_changed) 6449 if (f->icon_changed || f->windows_changed)
6435 update_frame_icon (f); 6450 update_frame_icon (f);
6436 6451
6437 if (FRAME_REPAINT_P (f)) 6452 if (FRAME_REPAINT_P (f))
6438 { 6453 {
6439 if (f->buffers_changed || f->clip_changed || f->extents_changed || 6454 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)
6440 f->faces_changed || f->frame_changed || f->menubar_changed || 6455 || f->size_changed)
6441 f->modeline_changed || f->point_changed || f->size_changed ||
6442 f->toolbar_changed || f->windows_changed ||
6443 f->windows_structure_changed || f->gutter_changed ||
6444 f->glyphs_changed || f->subwindows_changed)
6445 { 6456 {
6446 preempted = redisplay_frame (f, 0); 6457 preempted = redisplay_frame (f, 0);
6447 } 6458 }
6448 6459
6449 if (preempted) 6460 if (preempted)
6454 } 6465 }
6455 } 6466 }
6456 6467
6457 /* If we get here then we redisplayed all of our frames without 6468 /* If we get here then we redisplayed all of our frames without
6458 getting preempted so mark ourselves as clean. */ 6469 getting preempted so mark ourselves as clean. */
6459 d->buffers_changed = 0; 6470 CLASS_RESET_CHANGED_FLAGS (d);
6460 d->clip_changed = 0;
6461 d->extents_changed = 0;
6462 d->faces_changed = 0;
6463 d->frame_changed = 0;
6464 d->glyphs_changed = 0;
6465 d->subwindows_changed = 0;
6466 d->icon_changed = 0;
6467 d->menubar_changed = 0;
6468 d->modeline_changed = 0;
6469 d->point_changed = 0;
6470 d->toolbar_changed = 0;
6471 d->gutter_changed = 0;
6472 d->windows_changed = 0;
6473 d->windows_structure_changed = 0;
6474 6471
6475 if (!size_change_failed) 6472 if (!size_change_failed)
6476 d->size_changed = 0; 6473 d->size_changed = 0;
6477 6474
6478 return 0; 6475 return 0;
6503 } 6500 }
6504 6501
6505 if (asynch_device_change_pending) 6502 if (asynch_device_change_pending)
6506 handle_asynch_device_change (); 6503 handle_asynch_device_change ();
6507 6504
6508 if (!buffers_changed && !clip_changed && !extents_changed && 6505 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6509 !faces_changed && !frame_changed && !icon_changed && 6506 !size_changed && !disable_preemption && preemption_count < max_preempts)
6510 !menubar_changed && !modeline_changed && !point_changed &&
6511 !size_changed && !toolbar_changed && !windows_changed &&
6512 !glyphs_changed && !subwindows_changed &&
6513 !gutter_changed && !windows_structure_changed &&
6514 !disable_preemption && preemption_count < max_preempts)
6515 goto done; 6507 goto done;
6516 6508
6517 DEVICE_LOOP_NO_BREAK (devcons, concons) 6509 DEVICE_LOOP_NO_BREAK (devcons, concons)
6518 { 6510 {
6519 struct device *d = XDEVICE (XCAR (devcons)); 6511 struct device *d = XDEVICE (XCAR (devcons));
6520 int preempted; 6512 int preempted;
6521 6513
6522 if (d->buffers_changed || d->clip_changed || d->extents_changed || 6514 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)
6523 d->faces_changed || d->frame_changed || d->icon_changed || 6515 || d->size_changed)
6524 d->menubar_changed || d->modeline_changed || d->point_changed ||
6525 d->size_changed || d->toolbar_changed || d->windows_changed ||
6526 d->windows_structure_changed || d->gutter_changed ||
6527 d->glyphs_changed || d->subwindows_changed)
6528 { 6516 {
6529 preempted = redisplay_device (d); 6517 preempted = redisplay_device (d);
6530 6518
6531 if (preempted) 6519 if (preempted)
6532 { 6520 {
6541 } 6529 }
6542 } 6530 }
6543 preemption_count = 0; 6531 preemption_count = 0;
6544 6532
6545 /* Mark redisplay as accurate */ 6533 /* Mark redisplay as accurate */
6546 buffers_changed = 0; 6534 GLOBAL_RESET_CHANGED_FLAGS;
6547 clip_changed = 0;
6548 extents_changed = 0;
6549 frame_changed = 0;
6550 glyphs_changed = 0;
6551 subwindows_changed = 0;
6552 icon_changed = 0;
6553 menubar_changed = 0;
6554 modeline_changed = 0;
6555 point_changed = 0;
6556 toolbar_changed = 0;
6557 gutter_changed = 0;
6558 windows_changed = 0;
6559 windows_structure_changed = 0;
6560 RESET_CHANGED_SET_FLAGS; 6535 RESET_CHANGED_SET_FLAGS;
6561 6536
6562 if (faces_changed) 6537 if (faces_changed)
6563 { 6538 {
6564 mark_all_faces_as_clean (); 6539 mark_all_faces_as_clean ();
6785 6760
6786 /* print percent of buffer above top of window, or Top, Bot or All */ 6761 /* print percent of buffer above top of window, or Top, Bot or All */
6787 case 'p': 6762 case 'p':
6788 { 6763 {
6789 Bufpos pos = marker_position (w->start[type]); 6764 Bufpos pos = marker_position (w->start[type]);
6790 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6791 6765
6792 /* This had better be while the desired lines are being done. */ 6766 /* This had better be while the desired lines are being done. */
6793 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) 6767 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
6794 { 6768 {
6795 if (pos <= BUF_BEGV (b)) 6769 if (pos <= BUF_BEGV (b))
6802 else 6776 else
6803 { 6777 {
6804 /* This hard limit is ok since the string it will hold has a 6778 /* This hard limit is ok since the string it will hold has a
6805 fixed maximum length of 3. But just to be safe... */ 6779 fixed maximum length of 3. But just to be safe... */
6806 char buf[10]; 6780 char buf[10];
6807 6781 Charcount chars = pos - BUF_BEGV (b);
6808 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total; 6782 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6783
6784 /* Avoid overflow on big buffers */
6785 int percent = total > LONG_MAX/200 ?
6786 (chars + total/200) / (total / 100) :
6787 (chars * 100 + total/2) / total;
6809 6788
6810 /* We can't normally display a 3-digit number, so get us a 6789 /* We can't normally display a 3-digit number, so get us a
6811 2-digit number that is close. */ 6790 2-digit number that is close. */
6812 if (total == 100) 6791 if (percent == 100)
6813 total = 99; 6792 percent = 99;
6814 6793
6815 sprintf (buf, "%2d%%", total); 6794 sprintf (buf, "%d%%", percent);
6816 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, 6795 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6817 strlen (buf)); 6796 strlen (buf));
6818 6797
6819 goto decode_mode_spec_done; 6798 goto decode_mode_spec_done;
6820 } 6799 }
6825 Top, or print Bottom or All */ 6804 Top, or print Bottom or All */
6826 case 'P': 6805 case 'P':
6827 { 6806 {
6828 Bufpos toppos = marker_position (w->start[type]); 6807 Bufpos toppos = marker_position (w->start[type]);
6829 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type]; 6808 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
6830 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6831 6809
6832 /* botpos is only accurate as of the last redisplay, so we can 6810 /* botpos is only accurate as of the last redisplay, so we can
6833 only treat it as a hint. In particular, after erase-buffer, 6811 only treat it as a hint. In particular, after erase-buffer,
6834 botpos may be negative. */ 6812 botpos may be negative. */
6835 if (botpos < toppos) 6813 if (botpos < toppos)
6845 else 6823 else
6846 { 6824 {
6847 /* This hard limit is ok since the string it will hold has a 6825 /* This hard limit is ok since the string it will hold has a
6848 fixed maximum length of around 6. But just to be safe... */ 6826 fixed maximum length of around 6. But just to be safe... */
6849 char buf[10]; 6827 char buf[10];
6850 6828 Charcount chars = botpos - BUF_BEGV (b);
6851 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total; 6829 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6830
6831 /* Avoid overflow on big buffers */
6832 int percent = total > LONG_MAX/200 ?
6833 (chars + total/200) / (total / 100) :
6834 (chars * 100 + total/2) / max (total, 1);
6852 6835
6853 /* We can't normally display a 3-digit number, so get us a 6836 /* We can't normally display a 3-digit number, so get us a
6854 2-digit number that is close. */ 6837 2-digit number that is close. */
6855 if (total == 100) 6838 if (percent == 100)
6856 total = 99; 6839 percent = 99;
6857 6840
6858 if (toppos <= BUF_BEGV (b)) 6841 if (toppos <= BUF_BEGV (b))
6859 sprintf (buf, "Top%2d%%", total); 6842 sprintf (buf, "Top%d%%", percent);
6860 else 6843 else
6861 sprintf (buf, "%2d%%", total); 6844 sprintf (buf, "%d%%", percent);
6862 6845
6863 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, 6846 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6864 strlen (buf)); 6847 strlen (buf));
6865 6848
6866 goto decode_mode_spec_done; 6849 goto decode_mode_spec_done;
6959 6942
6960 6943
6961 /* Given an array of display lines, free them and all data structures 6944 /* Given an array of display lines, free them and all data structures
6962 contained within them. */ 6945 contained within them. */
6963 6946
6964 static void 6947 void
6965 free_display_lines (display_line_dynarr *dla) 6948 free_display_lines (display_line_dynarr *dla)
6966 { 6949 {
6967 int line; 6950 int line;
6968 6951
6969 for (line = 0; line < Dynarr_largest (dla); line++) 6952 for (line = 0; line < Dynarr_largest (dla); line++)
6992 } 6975 }
6993 } 6976 }
6994 6977
6995 6978
6996 static void 6979 static void
6997 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object)) 6980 mark_glyph_block_dynarr (glyph_block_dynarr *gba)
6998 { 6981 {
6999 if (gba) 6982 if (gba)
7000 { 6983 {
7001 glyph_block *gb = Dynarr_atp (gba, 0); 6984 glyph_block *gb = Dynarr_atp (gba, 0);
7002 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba)); 6985 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
7003 6986
7004 for (; gb < gb_last; gb++) 6987 for (; gb < gb_last; gb++)
7005 { 6988 {
7006 if (!NILP (gb->glyph)) 6989 if (!NILP (gb->glyph))
7007 markobj (gb->glyph); 6990 mark_object (gb->glyph);
7008 if (!NILP (gb->extent)) 6991 if (!NILP (gb->extent))
7009 markobj (gb->extent); 6992 mark_object (gb->extent);
7010 } 6993 }
7011 } 6994 }
7012 } 6995 }
7013 6996
7014 static void 6997 static void
7015 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object)) 6998 mark_redisplay_structs (display_line_dynarr *dla)
7016 { 6999 {
7017 display_line *dl = Dynarr_atp (dla, 0); 7000 display_line *dl = Dynarr_atp (dla, 0);
7018 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla)); 7001 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
7019 7002
7020 for (; dl < dl_last; dl++) 7003 for (; dl < dl_last; dl++)
7032 for (; r < r_last; r++) 7015 for (; r < r_last; r++)
7033 { 7016 {
7034 if (r->type == RUNE_DGLYPH) 7017 if (r->type == RUNE_DGLYPH)
7035 { 7018 {
7036 if (!NILP (r->object.dglyph.glyph)) 7019 if (!NILP (r->object.dglyph.glyph))
7037 markobj (r->object.dglyph.glyph); 7020 mark_object (r->object.dglyph.glyph);
7038 if (!NILP (r->object.dglyph.extent)) 7021 if (!NILP (r->object.dglyph.extent))
7039 markobj (r->object.dglyph.extent); 7022 mark_object (r->object.dglyph.extent);
7040 } 7023 }
7041 } 7024 }
7042 } 7025 }
7043 7026
7044 mark_glyph_block_dynarr (dl->left_glyphs, markobj); 7027 mark_glyph_block_dynarr (dl->left_glyphs);
7045 mark_glyph_block_dynarr (dl->right_glyphs, markobj); 7028 mark_glyph_block_dynarr (dl->right_glyphs);
7046 } 7029 }
7047 } 7030 }
7048 7031
7049 static void 7032 static void
7050 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object)) 7033 mark_window_mirror (struct window_mirror *mir)
7051 { 7034 {
7052 mark_redisplay_structs (mir->current_display_lines, markobj); 7035 mark_redisplay_structs (mir->current_display_lines);
7053 mark_redisplay_structs (mir->desired_display_lines, markobj); 7036 mark_redisplay_structs (mir->desired_display_lines);
7054 7037
7055 if (mir->next) 7038 if (mir->next)
7056 mark_window_mirror (mir->next, markobj); 7039 mark_window_mirror (mir->next);
7057 7040
7058 if (mir->hchild) 7041 if (mir->hchild)
7059 mark_window_mirror (mir->hchild, markobj); 7042 mark_window_mirror (mir->hchild);
7060 else if (mir->vchild) 7043 else if (mir->vchild)
7061 mark_window_mirror (mir->vchild, markobj); 7044 mark_window_mirror (mir->vchild);
7062 } 7045 }
7063 7046
7064 void 7047 void
7065 mark_redisplay (void (*markobj)(Lisp_Object)) 7048 mark_redisplay (void)
7066 { 7049 {
7067 Lisp_Object frmcons, devcons, concons; 7050 Lisp_Object frmcons, devcons, concons;
7068 7051
7069 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) 7052 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
7070 { 7053 {
7071 struct frame *f = XFRAME (XCAR (frmcons)); 7054 struct frame *f = XFRAME (XCAR (frmcons));
7072 update_frame_window_mirror (f); 7055 update_frame_window_mirror (f);
7073 mark_window_mirror (f->root_mirror, markobj); 7056 mark_window_mirror (f->root_mirror);
7074 } 7057 }
7075 } 7058 }
7076 7059
7077 /***************************************************************************** 7060 /*****************************************************************************
7078 Line Start Cache Description and Rationale 7061 Line Start Cache Description and Rationale
7132 applicable. 7115 applicable.
7133 ****************************************************************************/ 7116 ****************************************************************************/
7134 7117
7135 /* This will get used quite a bit so we don't want to be constantly 7118 /* This will get used quite a bit so we don't want to be constantly
7136 allocating and freeing it. */ 7119 allocating and freeing it. */
7137 line_start_cache_dynarr *internal_cache; 7120 static line_start_cache_dynarr *internal_cache;
7138 7121
7139 /* Makes internal_cache represent the TYPE display structs and only 7122 /* Makes internal_cache represent the TYPE display structs and only
7140 the TYPE display structs. */ 7123 the TYPE display structs. */
7141 7124
7142 static void 7125 static void
7651 else 7634 else
7652 return cur_pos; 7635 return cur_pos;
7653 } 7636 }
7654 7637
7655 cur_elt--; 7638 cur_elt--;
7656 if (cur_elt < 0) 7639 while (cur_elt < 0)
7657 { 7640 {
7658 Bufpos from, to; 7641 Bufpos from, to;
7659 int win_char_height; 7642 int win_char_height;
7660 7643
7661 if (cur_pos <= BUF_BEGV (b)) 7644 if (cur_pos <= BUF_BEGV (b))
7671 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); 7654 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
7672 to = line_start_cache_end (w); 7655 to = line_start_cache_end (w);
7673 update_line_start_cache (w, from, to, point, 0); 7656 update_line_start_cache (w, from, to, point, 0);
7674 7657
7675 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; 7658 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
7676 assert (cur_elt >= 0); 7659 assert (cur_elt >= -1);
7660 /* This used to be cur_elt>=0 under the assumption that if
7661 point is in the top line and not at BUF_BEGV, then
7662 setting the window_start to a newline before the start of
7663 the first line will always cause scrolling.
7664
7665 However in my (jv) opinion this is wrong. That new line
7666 can be hidden in various ways: invisible extents, an
7667 explicit window-start not at a newline character etc.
7668 The existence of those are indeed known to create crashes
7669 on that assert. So we have no option but to continue the
7670 search if we found point at the top of the line_start_cache
7671 again. */
7672 cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
7677 } 7673 }
7678 prev_pos = cur_pos; 7674 prev_pos = cur_pos;
7679 } 7675 }
7680 } 7676 }
7681 7677
8967 global_redisplay_change. */ 8963 global_redisplay_change. */
8968 MARK_CLIP_CHANGED; 8964 MARK_CLIP_CHANGED;
8969 return 0; 8965 return 0;
8970 } 8966 }
8971 8967
8968 /* This is called if the built-in glyphs have their properties
8969 changed. */
8972 void 8970 void
8973 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property, 8971 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8974 Lisp_Object locale) 8972 Lisp_Object locale)
8975 { 8973 {
8976 if (WINDOWP (locale)) 8974 if (WINDOWP (locale))
9089 { 9087 {
9090 disable_preemption = 0; 9088 disable_preemption = 0;
9091 preemption_count = 0; 9089 preemption_count = 0;
9092 max_preempts = INIT_MAX_PREEMPTS; 9090 max_preempts = INIT_MAX_PREEMPTS;
9093 9091
9092 #ifndef PDUMP
9094 if (!initialized) 9093 if (!initialized)
9094 #endif
9095 { 9095 {
9096 cmotion_display_lines = Dynarr_new (display_line); 9096 cmotion_display_lines = Dynarr_new (display_line);
9097 mode_spec_bufbyte_string = Dynarr_new (Bufbyte); 9097 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
9098 formatted_string_emchar_dynarr = Dynarr_new (Emchar); 9098 formatted_string_emchar_dynarr = Dynarr_new (Emchar);
9099 formatted_string_extent_dynarr = Dynarr_new (EXTENT); 9099 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
9169 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook"); 9169 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
9170 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook"); 9170 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
9171 #endif /* INHIBIT_REDISPLAY_HOOKS */ 9171 #endif /* INHIBIT_REDISPLAY_HOOKS */
9172 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer"); 9172 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
9173 defsymbol (&Qbar_cursor, "bar-cursor"); 9173 defsymbol (&Qbar_cursor, "bar-cursor");
9174 defsymbol (&Qwindow_scroll_functions, "window-scroll-functions");
9175 defsymbol (&Qredisplay_end_trigger_functions, 9174 defsymbol (&Qredisplay_end_trigger_functions,
9176 "redisplay-end-trigger-functions"); 9175 "redisplay-end-trigger-functions");
9177 9176
9178 DEFSUBR (Fredisplay_echo_area); 9177 DEFSUBR (Fredisplay_echo_area);
9179 DEFSUBR (Fredraw_frame); 9178 DEFSUBR (Fredraw_frame);
9183 DEFSUBR (Fredraw_modeline); 9182 DEFSUBR (Fredraw_modeline);
9184 DEFSUBR (Fforce_cursor_redisplay); 9183 DEFSUBR (Fforce_cursor_redisplay);
9185 } 9184 }
9186 9185
9187 void 9186 void
9187 reinit_vars_of_redisplay (void)
9188 {
9189 updating_line_start_cache = 0;
9190 }
9191
9192 void
9188 vars_of_redisplay (void) 9193 vars_of_redisplay (void)
9189 { 9194 {
9195 reinit_vars_of_redisplay ();
9196
9190 #if 0 9197 #if 0
9191 staticpro (&last_arrow_position); 9198 staticpro (&last_arrow_position);
9192 staticpro (&last_arrow_string); 9199 staticpro (&last_arrow_string);
9193 last_arrow_position = Qnil; 9200 last_arrow_position = Qnil;
9194 last_arrow_string = Qnil; 9201 last_arrow_string = Qnil;
9195 #endif /* 0 */ 9202 #endif /* 0 */
9196
9197 updating_line_start_cache = 0;
9198 9203
9199 /* #### Probably temporary */ 9204 /* #### Probably temporary */
9200 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* 9205 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
9201 \(Temporary) Setting this will impact the performance of the internal 9206 \(Temporary) Setting this will impact the performance of the internal
9202 line start cache. 9207 line start cache.
9278 instead. 9283 instead.
9279 */ ); 9284 */ );
9280 Vwindow_system = Qnil; 9285 Vwindow_system = Qnil;
9281 9286
9282 /* #### Temporary shit until window-system is eliminated. */ 9287 /* #### Temporary shit until window-system is eliminated. */
9283 DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /* 9288 DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /*
9284 DON'T TOUCH 9289 DON'T TOUCH
9285 */ ); 9290 */ );
9286 Vinitial_window_system = Qnil; 9291 Vinitial_window_system = Qnil;
9287 9292
9288 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* 9293 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*