comparison src/redisplay.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents bbff43aa5eb7
children a86b2b5e0111
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
49 #include "elhash.h" 49 #include "elhash.h"
50 #include "extents.h" 50 #include "extents.h"
51 #include "faces.h" 51 #include "faces.h"
52 #include "frame.h" 52 #include "frame.h"
53 #include "glyphs.h" 53 #include "glyphs.h"
54 #include "gutter.h"
54 #include "insdel.h" 55 #include "insdel.h"
55 #include "menubar.h" 56 #include "menubar.h"
56 #include "objects.h" 57 #include "objects.h"
57 #include "process.h" 58 #include "process.h"
58 #include "redisplay.h" 59 #include "redisplay.h"
105 typedef struct position_redisplay_data_type 106 typedef struct position_redisplay_data_type
106 { 107 {
107 /* This information is normally filled in by the create_*_block 108 /* This information is normally filled in by the create_*_block
108 routines and is used by the add_*_rune routines. */ 109 routines and is used by the add_*_rune routines. */
109 Lisp_Object window; 110 Lisp_Object window;
111 /* if we are working with strings rather than buffers we need a
112 handle to the string */
113 Lisp_Object string;
110 struct device *d; 114 struct device *d;
111 struct display_block *db; 115 struct display_block *db;
112 struct display_line *dl; 116 struct display_line *dl;
113 Emchar ch; /* Character that is to be added. This is 117 Emchar ch; /* Character that is to be added. This is
114 used to communicate this information to 118 used to communicate this information to
148 need to be skipped. This is used for horizontal 152 need to be skipped. This is used for horizontal
149 scrolling, where a certain number of columns 153 scrolling, where a certain number of columns
150 (those off the left side of the screen) need 154 (those off the left side of the screen) need
151 to be skipped before anything is displayed. */ 155 to be skipped before anything is displayed. */
152 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. */
153 161
154 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
155 glyph differs from space_width (w). 163 glyph differs from space_width (w).
156 0 if no hscroll glyph was used, 164 0 if no hscroll glyph was used,
157 i.e. the window is not scrolled 165 i.e. the window is not scrolled
236 { 244 {
237 Dynarr_declare (prop_block); 245 Dynarr_declare (prop_block);
238 } prop_block_dynarr; 246 } prop_block_dynarr;
239 247
240 248
241 static void generate_formatted_string_db (Lisp_Object format_str,
242 Lisp_Object result_str,
243 struct window *w,
244 struct display_line *dl,
245 struct display_block *db,
246 face_index findex, int min_pixpos,
247 int max_pixpos, int type);
248 static Charcount generate_fstring_runes (struct window *w, pos_data *data, 249 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
249 Charcount pos, Charcount min_pos, 250 Charcount pos, Charcount min_pos,
250 Charcount max_pos, Lisp_Object elt, 251 Charcount max_pos, Lisp_Object elt,
251 int depth, int max_pixsize, 252 int depth, int max_pixsize,
252 face_index findex, int type); 253 face_index findex, int type,
254 Charcount *offset,
255 Lisp_Object cur_ext);
253 static prop_block_dynarr *add_glyph_rune (pos_data *data, 256 static prop_block_dynarr *add_glyph_rune (pos_data *data,
254 struct glyph_block *gb, 257 struct glyph_block *gb,
255 int pos_type, int allow_cursor, 258 int pos_type, int allow_cursor,
256 struct glyph_cachel *cachel); 259 struct glyph_cachel *cachel);
257 static Bytind create_text_block (struct window *w, struct display_line *dl, 260 static Bytind create_text_block (struct window *w, struct display_line *dl,
258 Bytind bi_start_pos, int start_col, 261 Bytind bi_start_pos, prop_block_dynarr **prop,
259 prop_block_dynarr **prop,
260 int type); 262 int type);
261 static int create_overlay_glyph_block (struct window *w, 263 static int create_overlay_glyph_block (struct window *w,
262 struct display_line *dl); 264 struct display_line *dl);
263 static void create_left_glyph_block (struct window *w, 265 static void create_left_glyph_block (struct window *w,
264 struct display_line *dl, 266 struct display_line *dl,
291 routines. We used to just give each window a third set. However, 293 routines. We used to just give each window a third set. However,
292 we always fully regenerate the structures when needed so there 294 we always fully regenerate the structures when needed so there
293 isn't any reason we need more than a single set. */ 295 isn't any reason we need more than a single set. */
294 display_line_dynarr *cmotion_display_lines; 296 display_line_dynarr *cmotion_display_lines;
295 297
296 /* Used by generate_formatted_string. Global because they get used so
297 much that the dynamic allocation time adds up. */
298 Emchar_dynarr *formatted_string_emchar_dynarr;
299 struct display_line formatted_string_display_line;
300 /* We store the extents that we need to generate in a Dynarr and then 298 /* We store the extents that we need to generate in a Dynarr and then
301 frob them all on at the end of generating the string. We do it 299 frob them all on at the end of generating the string. We do it
302 this way rather than adding them as we generate the string because 300 this way rather than adding them as we generate the string because
303 we don't store the text into the resulting string until we're done 301 we don't store the text into the resulting string until we're done
304 (to avoid having to resize the string multiple times), and we don't 302 (to avoid having to resize the string multiple times), and we don't
305 want to go around adding extents to a string when the extents might 303 want to go around adding extents to a string when the extents might
306 stretch off the end of the string. */ 304 stretch off the end of the string. */
307 EXTENT_dynarr *formatted_string_extent_dynarr; 305 static EXTENT_dynarr *formatted_string_extent_dynarr;
308 Bytecount_dynarr *formatted_string_extent_start_dynarr; 306 static Bytecount_dynarr *formatted_string_extent_start_dynarr;
309 Bytecount_dynarr *formatted_string_extent_end_dynarr; 307 static Bytecount_dynarr *formatted_string_extent_end_dynarr;
310 308
311 309
312 /* #### probably temporary */ 310 /* #### probably temporary */
313 int cache_adjustment; 311 int cache_adjustment;
314 312
329 327
330 /* Minimum visible pixel width of clipped glyphs at right margin. */ 328 /* Minimum visible pixel width of clipped glyphs at right margin. */
331 int horizontal_clip; 329 int horizontal_clip;
332 330
333 /* Set if currently inside update_line_start_cache. */ 331 /* Set if currently inside update_line_start_cache. */
334 int updating_line_start_cache; 332 static int updating_line_start_cache;
335 333
336 /* Nonzero means reading single-character input with prompt 334 /* Nonzero means reading single-character input with prompt
337 so put cursor on minibuffer after the prompt. */ 335 so put cursor on minibuffer after the prompt. */
338 int cursor_in_echo_area; 336 int cursor_in_echo_area;
339 Lisp_Object Qcursor_in_echo_area; 337 Lisp_Object Qcursor_in_echo_area;
369 /* non-zero if any displayed subwindow is in need of updating 367 /* non-zero if any displayed subwindow is in need of updating
370 somewhere. */ 368 somewhere. */
371 int subwindows_changed; 369 int subwindows_changed;
372 int subwindows_changed_set; 370 int subwindows_changed_set;
373 371
372 /* non-zero if any displayed subwindow is in need of updating
373 somewhere. */
374 int subwindows_state_changed;
375 int subwindows_state_changed_set;
376
374 /* This variable is 1 if the icon has to be updated. 377 /* This variable is 1 if the icon has to be updated.
375 It is set to 1 when `frame-icon-glyph' changes. */ 378 It is set to 1 when `frame-icon-glyph' changes. */
376 int icon_changed; 379 int icon_changed;
377 int icon_changed_set; 380 int icon_changed_set;
378 381
399 402
400 /* non-nil if any toolbar has changed */ 403 /* non-nil if any toolbar has changed */
401 int toolbar_changed; 404 int toolbar_changed;
402 int toolbar_changed_set; 405 int toolbar_changed_set;
403 406
407 /* non-nil if any gutter has changed */
408 int gutter_changed;
409 int gutter_changed_set;
410
404 /* non-nil if any window has changed since the last time redisplay completed */ 411 /* non-nil if any window has changed since the last time redisplay completed */
405 int windows_changed; 412 int windows_changed;
406 413
407 /* non-nil if any frame's window structure has changed since the last 414 /* non-nil if any frame's window structure has changed since the last
408 time redisplay completed */ 415 time redisplay completed */
409 int windows_structure_changed; 416 int windows_structure_changed;
410 417
411 /* If non-nil, use vertical bar cursor. */ 418 /* If non-nil, use vertical bar cursor. */
412 Lisp_Object Vbar_cursor; 419 Lisp_Object Vbar_cursor;
413 Lisp_Object Qbar_cursor; 420 Lisp_Object Qbar_cursor;
414
415 421
416 int visible_bell; /* If true and the terminal will support it 422 int visible_bell; /* If true and the terminal will support it
417 then the frame will flash instead of 423 then the frame will flash instead of
418 beeping when an error occurs */ 424 beeping when an error occurs */
419 425
440 Lisp_Object Voverlay_arrow_position; 446 Lisp_Object Voverlay_arrow_position;
441 /* String to display for the arrow. */ 447 /* String to display for the arrow. */
442 Lisp_Object Voverlay_arrow_string; 448 Lisp_Object Voverlay_arrow_string;
443 449
444 Lisp_Object Vwindow_size_change_functions; 450 Lisp_Object Vwindow_size_change_functions;
445 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; 451 Lisp_Object Vwindow_scroll_functions;
446 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions; 452 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
447 453
448 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about 454 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
449 this more. */ 455 this more. */
450 #ifndef INHIBIT_REDISPLAY_HOOKS 456 #ifndef INHIBIT_REDISPLAY_HOOKS
452 Think about this for 19.14. */ 458 Think about this for 19.14. */
453 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook; 459 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
454 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook; 460 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
455 #endif /* INHIBIT_REDISPLAY_HOOKS */ 461 #endif /* INHIBIT_REDISPLAY_HOOKS */
456 462
457 int last_display_warning_tick, display_warning_tick; 463 static int last_display_warning_tick, display_warning_tick;
458 Lisp_Object Qdisplay_warning_buffer; 464 Lisp_Object Qdisplay_warning_buffer;
459 int inhibit_warning_display; 465 int inhibit_warning_display;
460 466
461 Lisp_Object Vleft_margin_width, Vright_margin_width; 467 Lisp_Object Vleft_margin_width, Vright_margin_width;
462 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; 468 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
463 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; 469 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
464 Lisp_Object Vtext_cursor_visible_p; 470 Lisp_Object Vtext_cursor_visible_p;
465 471
466 int column_number_start_at_one; 472 int column_number_start_at_one;
473
474 #define WINDOW_SCROLLED(w) \
475 (w->hscroll > 0 || w->left_xoffset)
476
467 477
468 /***************************************************************************/ 478 /***************************************************************************/
469 /* */ 479 /* */
470 /* low-level interfaces onto device routines */ 480 /* low-level interfaces onto device routines */
471 /* */ 481 /* */
631 { 641 {
632 int n_pos = left_pixpos; 642 int n_pos = left_pixpos;
633 int pix_tab_width = tab_pix_width (w); 643 int pix_tab_width = tab_pix_width (w);
634 644
635 /* Adjust n_pos for any hscrolling which has happened. */ 645 /* Adjust n_pos for any hscrolling which has happened. */
636 if (w->hscroll > 1) 646 if (WINDOW_SCROLLED (w))
637 n_pos -= space_width (w) * (w->hscroll - 1); 647 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset;
638 648
639 while (n_pos <= start_pixpos) 649 while (n_pos <= start_pixpos)
640 n_pos += pix_tab_width; 650 n_pos += pix_tab_width;
641 651
642 return n_pos; 652 return n_pos;
684 when the contents of the line reach the right boundary of the given 694 when the contents of the line reach the right boundary of the given
685 window. */ 695 window. */
686 696
687 static Bufpos 697 static Bufpos
688 generate_display_line (struct window *w, struct display_line *dl, int bounds, 698 generate_display_line (struct window *w, struct display_line *dl, int bounds,
689 Bufpos start_pos, int start_col, 699 Bufpos start_pos, prop_block_dynarr **prop,
690 prop_block_dynarr **prop,
691 int type) 700 int type)
692 { 701 {
693 Bufpos ret_bufpos; 702 Bufpos ret_bufpos;
694 int overlay_width; 703 int overlay_width;
695 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); 704 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
718 /* Create a display block for the text region of the line. */ 727 /* Create a display block for the text region of the line. */
719 { 728 {
720 /* #### urk urk urk!!! Chuck fix this shit! */ 729 /* #### urk urk urk!!! Chuck fix this shit! */
721 Bytind hacked_up_bytind = 730 Bytind hacked_up_bytind =
722 create_text_block (w, dl, bufpos_to_bytind (b, start_pos), 731 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
723 start_col, prop, type); 732 prop, type);
724 if (hacked_up_bytind > BI_BUF_ZV (b)) 733 if (hacked_up_bytind > BI_BUF_ZV (b))
725 ret_bufpos = BUF_ZV (b) + 1; 734 ret_bufpos = BUF_ZV (b) + 1;
726 else 735 else
727 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind); 736 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
728 } 737 }
848 struct window *w = XWINDOW (data->window); 857 struct window *w = XWINDOW (data->window);
849 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex); 858 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
850 Lisp_Object font_instance = 859 Lisp_Object font_instance =
851 ensure_face_cachel_contains_charset (cachel, data->window, 860 ensure_face_cachel_contains_charset (cachel, data->window,
852 charset); 861 charset);
853 struct Lisp_Font_Instance *fi; 862 Lisp_Font_Instance *fi;
854 863
855 if (EQ (font_instance, Vthe_null_font_instance)) 864 if (EQ (font_instance, Vthe_null_font_instance))
856 { 865 {
857 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); 866 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
858 data->font_is_bogus = 1; 867 data->font_is_bogus = 1;
900 909
901 crb->findex = data->findex; 910 crb->findex = data->findex;
902 crb->xpos = data->pixpos; 911 crb->xpos = data->pixpos;
903 crb->width = width; 912 crb->width = width;
904 if (data->bi_bufpos) 913 if (data->bi_bufpos)
905 crb->bufpos = 914 {
906 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))), 915 if (NILP (data->string))
907 data->bi_bufpos); 916 crb->bufpos =
917 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
918 data->bi_bufpos);
919 else
920 crb->bufpos =
921 bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
922 }
908 else if (data->is_modeline) 923 else if (data->is_modeline)
909 crb->bufpos = data->modeline_charpos; 924 crb->bufpos = data->modeline_charpos;
910 else 925 else
911 /* fuckme if this shouldn't be an abort. */ 926 /* fuckme if this shouldn't be an abort. */
912 /* abort (); fuckme harder, this abort gets tripped quite often, 927 /* abort (); fuckme harder, this abort gets tripped quite often,
1324 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) 1339 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1325 { 1340 {
1326 prop_block_dynarr *prop = NULL; 1341 prop_block_dynarr *prop = NULL;
1327 if (VECTORP (entry)) 1342 if (VECTORP (entry))
1328 { 1343 {
1329 struct Lisp_Vector *de = XVECTOR (entry); 1344 Lisp_Vector *de = XVECTOR (entry);
1330 EMACS_INT len = vector_length (de); 1345 EMACS_INT len = vector_length (de);
1331 int elt; 1346 int elt;
1332 1347
1333 for (elt = 0; elt < len; elt++) 1348 for (elt = 0; elt < len; elt++)
1334 { 1349 {
1507 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, 1522 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1508 int allow_cursor, struct glyph_cachel *cachel) 1523 int allow_cursor, struct glyph_cachel *cachel)
1509 { 1524 {
1510 struct window *w = XWINDOW (data->window); 1525 struct window *w = XWINDOW (data->window);
1511 1526
1527 /* If window faces changed, and glyph instance is text, then
1528 glyph sizes might have changed too */
1529 invalidate_glyph_geometry_maybe (gb->glyph, w);
1530
1531 /* This makes sure the glyph is in the cachels.
1532
1533 #### We need to change this so that we hold onto the glyph_index
1534 here, not the glyph itself. */
1535 get_glyph_cachel_index (w, gb->glyph);
1536
1512 /* A nil extent indicates a special glyph (ex. truncator). */ 1537 /* A nil extent indicates a special glyph (ex. truncator). */
1513 if (NILP (gb->extent) 1538 if (NILP (gb->extent)
1514 || (pos_type == BEGIN_GLYPHS && 1539 || (pos_type == BEGIN_GLYPHS &&
1515 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) 1540 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1516 || (pos_type == END_GLYPHS && 1541 || (pos_type == END_GLYPHS &&
1524 Lisp_Object face; 1549 Lisp_Object face;
1525 1550
1526 if (cachel) 1551 if (cachel)
1527 width = cachel->width; 1552 width = cachel->width;
1528 else 1553 else
1529 width = glyph_width (gb->glyph, Qnil, data->findex, data->window); 1554 width = glyph_width (gb->glyph, data->window);
1530 1555
1531 if (!width) 1556 if (!width)
1532 return NULL; 1557 return NULL;
1533 1558
1534 if (data->start_col) 1559 if (data->start_col || data->start_col_xoffset)
1535 { 1560 {
1536 prop_block_dynarr *retval; 1561 prop_block_dynarr *retval;
1537 int glyph_char_width = width / space_width (w); 1562 int glyph_char_width = width / space_width (w);
1538 1563
1539 /* If we still have not fully scrolled horizontally after 1564 /* If we still have not fully scrolled horizontally after
1587 ascent = cachel->ascent; 1612 ascent = cachel->ascent;
1588 descent = cachel->descent; 1613 descent = cachel->descent;
1589 } 1614 }
1590 else 1615 else
1591 { 1616 {
1592 ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window); 1617 ascent = glyph_ascent (gb->glyph, data->window);
1593 descent = glyph_descent (gb->glyph, Qnil, data->findex, 1618 descent = glyph_descent (gb->glyph, data->window);
1594 data->window);
1595 } 1619 }
1596 1620
1597 baseline = glyph_baseline (gb->glyph, data->window); 1621 baseline = glyph_baseline (gb->glyph, data->window);
1598 1622
1599 if (glyph_contrib_p (gb->glyph, data->window)) 1623 if (glyph_contrib_p (gb->glyph, data->window))
1763 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds. 1787 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1764 You must do appropriate conversion. */ 1788 You must do appropriate conversion. */
1765 1789
1766 static Bytind 1790 static Bytind
1767 create_text_block (struct window *w, struct display_line *dl, 1791 create_text_block (struct window *w, struct display_line *dl,
1768 Bytind bi_start_pos, int start_col, 1792 Bytind bi_start_pos, prop_block_dynarr **prop,
1769 prop_block_dynarr **prop,
1770 int type) 1793 int type)
1771 { 1794 {
1772 struct frame *f = XFRAME (w->frame); 1795 struct frame *f = XFRAME (w->frame);
1773 struct buffer *b = XBUFFER (w->buffer); 1796 struct buffer *b = XBUFFER (w->buffer);
1774 struct device *d = XDEVICE (f->device); 1797 struct device *d = XDEVICE (f->device);
1789 only lines that start with less than selective_display columns of 1812 only lines that start with less than selective_display columns of
1790 space will be displayed. If selective_display is t then all text 1813 space will be displayed. If selective_display is t then all text
1791 after a ^M is invisible. */ 1814 after a ^M is invisible. */
1792 int selective = (INTP (b->selective_display) 1815 int selective = (INTP (b->selective_display)
1793 ? XINT (b->selective_display) 1816 ? XINT (b->selective_display)
1794 : ((!NILP (b->selective_display) ? -1 : 0))); 1817 : (!NILP (b->selective_display) ? -1 : 0));
1795 1818
1796 /* The variable ctl-arrow allows the user to specify what characters 1819 /* The variable ctl-arrow allows the user to specify what characters
1797 can actually be displayed and which octal should be used for. 1820 can actually be displayed and which octal should be used for.
1798 #### This variable should probably have some rethought done to 1821 #### This variable should probably have some rethought done to
1799 it. 1822 it.
1864 1887
1865 /* These values are used by all of the rune addition routines. We add 1888 /* These values are used by all of the rune addition routines. We add
1866 them to this structure for ease of passing. */ 1889 them to this structure for ease of passing. */
1867 data.d = d; 1890 data.d = d;
1868 XSETWINDOW (data.window, w); 1891 XSETWINDOW (data.window, w);
1892 data.string = Qnil;
1869 data.db = db; 1893 data.db = db;
1870 data.dl = dl; 1894 data.dl = dl;
1871 1895
1872 data.bi_bufpos = bi_start_pos; 1896 data.bi_bufpos = bi_start_pos;
1873 data.pixpos = dl->bounds.left_in; 1897 data.pixpos = dl->bounds.left_in;
1907 else 1931 else
1908 data.cursor_type = NO_CURSOR; 1932 data.cursor_type = NO_CURSOR;
1909 data.cursor_x = -1; 1933 data.cursor_x = -1;
1910 1934
1911 data.start_col = w->hscroll; 1935 data.start_col = w->hscroll;
1936 data.start_col_xoffset = w->left_xoffset;
1912 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0); 1937 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1913 data.hscroll_glyph_width_adjust = 0; 1938 data.hscroll_glyph_width_adjust = 0;
1914 1939
1915 /* We regenerate the line from the very beginning. */ 1940 /* We regenerate the line from the very beginning. */
1916 Dynarr_reset (db->runes); 1941 Dynarr_reset (db->runes);
2226 that the cursor shows up properly. */ 2251 that the cursor shows up properly. */
2227 data.ch = '\n'; 2252 data.ch = '\n';
2228 data.blank_width = DEVMETH (d, eol_cursor_width, ()); 2253 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2229 data.findex = DEFAULT_INDEX; 2254 data.findex = DEFAULT_INDEX;
2230 data.start_col = 0; 2255 data.start_col = 0;
2256 data.start_col_xoffset = 0;
2231 data.bi_start_col_enabled = 0; 2257 data.bi_start_col_enabled = 0;
2232 2258
2233 add_emchar_rune (&data); 2259 add_emchar_rune (&data);
2234 } 2260 }
2235 2261
2259 int next_tab_start; 2285 int next_tab_start;
2260 int char_tab_width; 2286 int char_tab_width;
2261 int prop_width = 0; 2287 int prop_width = 0;
2262 2288
2263 if (data.start_col > 1) 2289 if (data.start_col > 1)
2264 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); 2290 tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
2291 + data.start_col_xoffset;
2265 2292
2266 next_tab_start = 2293 next_tab_start =
2267 next_tab_position (w, tab_start_pixpos, 2294 next_tab_position (w, tab_start_pixpos,
2268 dl->bounds.left_in + 2295 dl->bounds.left_in +
2269 data.hscroll_glyph_width_adjust); 2296 data.hscroll_glyph_width_adjust);
2466 2493
2467 data.ch = '\n'; 2494 data.ch = '\n';
2468 data.blank_width = DEVMETH (d, eol_cursor_width, ()); 2495 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2469 data.findex = DEFAULT_INDEX; 2496 data.findex = DEFAULT_INDEX;
2470 data.start_col = 0; 2497 data.start_col = 0;
2498 data.start_col_xoffset = 0;
2471 data.bi_start_col_enabled = 0; 2499 data.bi_start_col_enabled = 0;
2472 2500
2473 data.max_pixpos += data.blank_width; 2501 data.max_pixpos += data.blank_width;
2474 add_emchar_rune (&data); 2502 add_emchar_rune (&data);
2475 data.max_pixpos -= data.blank_width; 2503 data.max_pixpos -= data.blank_width;
2641 data.cursor_x = -1; 2669 data.cursor_x = -1;
2642 data.findex = DEFAULT_INDEX; 2670 data.findex = DEFAULT_INDEX;
2643 data.last_charset = Qunbound; 2671 data.last_charset = Qunbound;
2644 data.last_findex = DEFAULT_INDEX; 2672 data.last_findex = DEFAULT_INDEX;
2645 data.result_str = Qnil; 2673 data.result_str = Qnil;
2674 data.string = Qnil;
2646 2675
2647 Dynarr_reset (data.db->runes); 2676 Dynarr_reset (data.db->runes);
2648 2677
2649 if (STRINGP (Voverlay_arrow_string)) 2678 if (STRINGP (Voverlay_arrow_string))
2650 { 2679 {
2745 if (glyph_contrib_p (gb->glyph, window)) 2774 if (glyph_contrib_p (gb->glyph, window))
2746 { 2775 {
2747 unsigned short ascent, descent; 2776 unsigned short ascent, descent;
2748 Lisp_Object baseline = glyph_baseline (gb->glyph, window); 2777 Lisp_Object baseline = glyph_baseline (gb->glyph, window);
2749 2778
2750 ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window); 2779 ascent = glyph_ascent (gb->glyph, window);
2751 descent = glyph_descent (gb->glyph, Qnil, gb->findex, window); 2780 descent = glyph_descent (gb->glyph, window);
2752 2781
2753 /* A pixmap that has not had a baseline explicitly set. 2782 /* A pixmap that has not had a baseline explicitly set.
2754 We use the existing ascent / descent ratio of the 2783 We use the existing ascent / descent ratio of the
2755 line. */ 2784 line. */
2756 if (NILP (baseline)) 2785 if (NILP (baseline))
2860 2889
2861 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) 2890 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2862 { 2891 {
2863 int width; 2892 int width;
2864 2893
2865 width = glyph_width (gb->glyph, Qnil, gb->findex, window); 2894 width = glyph_width (gb->glyph, window);
2866 2895
2867 if (white_in_start - width >= left_in_end) 2896 if (white_in_start - width >= left_in_end)
2868 { 2897 {
2869 white_in_cnt++; 2898 white_in_cnt++;
2870 white_in_start -= width; 2899 white_in_start -= width;
2911 abort (); /* these should have been handled in add_glyph_rune */ 2940 abort (); /* these should have been handled in add_glyph_rune */
2912 2941
2913 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == 2942 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2914 GL_INSIDE_MARGIN) 2943 GL_INSIDE_MARGIN)
2915 { 2944 {
2916 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window); 2945 gb->width = glyph_width (gb->glyph, window);
2917 used_in += gb->width; 2946 used_in += gb->width;
2918 Dynarr_add (ib, *gb); 2947 Dynarr_add (ib, *gb);
2919 } 2948 }
2920 2949
2921 elt++; 2950 elt++;
2980 abort (); /* these should have been handled in add_glyph_rune */ 3009 abort (); /* these should have been handled in add_glyph_rune */
2981 3010
2982 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == 3011 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2983 GL_INSIDE_MARGIN) 3012 GL_INSIDE_MARGIN)
2984 { 3013 {
2985 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); 3014 int width = glyph_width (gb->glyph, window);
2986 3015
2987 if (used_out) 3016 if (used_out)
2988 { 3017 {
2989 in_out_cnt++; 3018 in_out_cnt++;
2990 in_out_start -= width; 3019 in_out_start -= width;
3022 abort (); /* these should have been handled in add_glyph_rune */ 3051 abort (); /* these should have been handled in add_glyph_rune */
3023 3052
3024 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == 3053 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3025 GL_OUTSIDE_MARGIN) 3054 GL_OUTSIDE_MARGIN)
3026 { 3055 {
3027 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); 3056 int width = glyph_width (gb->glyph, window);
3028 3057
3029 if (out_end + width <= in_out_start) 3058 if (out_end + width <= in_out_start)
3030 { 3059 {
3031 out_cnt++; 3060 out_cnt++;
3032 out_end += width; 3061 out_end += width;
3179 if (NILP (gb->extent)) 3208 if (NILP (gb->extent))
3180 abort (); /* these should have been handled in add_glyph_rune */ 3209 abort (); /* these should have been handled in add_glyph_rune */
3181 3210
3182 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) 3211 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3183 { 3212 {
3184 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); 3213 int width = glyph_width (gb->glyph, window);
3185 3214
3186 if (white_in_end + width <= dl->bounds.right_in) 3215 if (white_in_end + width <= dl->bounds.right_in)
3187 { 3216 {
3188 white_in_cnt++; 3217 white_in_cnt++;
3189 white_in_end += width; 3218 white_in_end += width;
3229 if (NILP (gb->extent)) 3258 if (NILP (gb->extent))
3230 abort (); /* these should have been handled in add_glyph_rune */ 3259 abort (); /* these should have been handled in add_glyph_rune */
3231 3260
3232 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) 3261 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3233 { 3262 {
3234 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window); 3263 gb->width = glyph_width (gb->glyph, window);
3235 used_in += gb->width; 3264 used_in += gb->width;
3236 Dynarr_add (ib, *gb); 3265 Dynarr_add (ib, *gb);
3237 } 3266 }
3238 3267
3239 elt++; 3268 elt++;
3293 if (NILP (gb->extent)) 3322 if (NILP (gb->extent))
3294 abort (); /* these should have been handled in add_glyph_rune */ 3323 abort (); /* these should have been handled in add_glyph_rune */
3295 3324
3296 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) 3325 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3297 { 3326 {
3298 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); 3327 int width = glyph_width (gb->glyph, window);
3299 3328
3300 if (used_out) 3329 if (used_out)
3301 { 3330 {
3302 in_out_cnt++; 3331 in_out_cnt++;
3303 in_out_end += width; 3332 in_out_end += width;
3334 if (NILP (gb->extent)) 3363 if (NILP (gb->extent))
3335 abort (); /* these should have been handled in add_glyph_rune */ 3364 abort (); /* these should have been handled in add_glyph_rune */
3336 3365
3337 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) 3366 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3338 { 3367 {
3339 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); 3368 int width = glyph_width (gb->glyph, window);
3340 3369
3341 if (out_start - width >= in_out_end) 3370 if (out_start - width >= in_out_end)
3342 { 3371 {
3343 out_cnt++; 3372 out_cnt++;
3344 out_start -= width; 3373 out_start -= width;
3450 /* */ 3479 /* */
3451 /* modeline routines */ 3480 /* modeline routines */
3452 /* */ 3481 /* */
3453 /***************************************************************************/ 3482 /***************************************************************************/
3454 3483
3455 /* Ensure that the given display line DL accurately represents the 3484 /* This function is also used in frame.c by `generate_title_string' */
3456 modeline for the given window. */ 3485 void
3457
3458 static void
3459 generate_modeline (struct window *w, struct display_line *dl, int type)
3460 {
3461 struct buffer *b = XBUFFER (w->buffer);
3462 struct frame *f = XFRAME (w->frame);
3463 struct device *d = XDEVICE (f->device);
3464
3465 /* Unlike display line and rune pointers, this one can't change underneath
3466 our feet. */
3467 struct display_block *db = get_display_block_from_line (dl, TEXT);
3468 int max_pixpos, min_pixpos, ypos_adj;
3469 Lisp_Object font_inst;
3470
3471 /* This will actually determine incorrect inside boundaries for the
3472 modeline since it ignores the margins. However being aware of this fact
3473 we never use those values anywhere so it doesn't matter. */
3474 dl->bounds = calculate_display_line_boundaries (w, 1);
3475
3476 /* We are generating a modeline. */
3477 dl->modeline = 1;
3478 dl->cursor_elt = -1;
3479
3480 /* Reset the runes on the modeline. */
3481 Dynarr_reset (db->runes);
3482
3483 if (!WINDOW_HAS_MODELINE_P (w))
3484 {
3485 struct rune rb;
3486
3487 /* If there is a horizontal scrollbar, don't add anything. */
3488 if (window_scrollbar_height (w))
3489 return;
3490
3491 dl->ascent = DEVMETH (d, divider_height, ());
3492 dl->descent = 0;
3493 /* The modeline is at the bottom of the gutters. */
3494 dl->ypos = WINDOW_BOTTOM (w);
3495
3496 rb.findex = MODELINE_INDEX;
3497 rb.xpos = dl->bounds.left_out;
3498 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3499 rb.bufpos = 0;
3500 rb.endpos = 0;
3501 rb.type = RUNE_HLINE;
3502 rb.object.hline.thickness = 1;
3503 rb.object.hline.yoffset = 0;
3504 rb.cursor_type = NO_CURSOR;
3505
3506 if (!EQ (Qzero, w->modeline_shadow_thickness)
3507 && FRAME_WIN_P (f))
3508 {
3509 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3510
3511 dl->ypos -= shadow_thickness;
3512 rb.xpos += shadow_thickness;
3513 rb.width -= 2 * shadow_thickness;
3514 }
3515
3516 Dynarr_add (db->runes, rb);
3517 return;
3518 }
3519
3520 /* !!#### not right; needs to compute the max height of
3521 all the charsets */
3522 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3523
3524 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3525 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3526
3527 min_pixpos = dl->bounds.left_out;
3528 max_pixpos = dl->bounds.right_out;
3529
3530 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3531 {
3532 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3533
3534 ypos_adj = shadow_thickness;
3535 min_pixpos += shadow_thickness;
3536 max_pixpos -= shadow_thickness;
3537 }
3538 else
3539 ypos_adj = 0;
3540
3541 generate_formatted_string_db (b->modeline_format,
3542 b->generated_modeline_string, w, dl, db,
3543 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3544
3545 /* The modeline is at the bottom of the gutters. We have to wait to
3546 set this until we've generated the modeline in order to account
3547 for any embedded faces. */
3548 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3549 }
3550
3551 static void
3552 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, 3486 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3553 struct window *w, struct display_line *dl, 3487 struct window *w, struct display_line *dl,
3554 struct display_block *db, face_index findex, 3488 struct display_block *db, face_index findex,
3555 int min_pixpos, int max_pixpos, int type) 3489 int min_pixpos, int max_pixpos, int type)
3556 { 3490 {
3557 struct frame *f = XFRAME (w->frame); 3491 struct frame *f = XFRAME (w->frame);
3558 struct device *d = XDEVICE (f->device); 3492 struct device *d = XDEVICE (f->device);
3559 3493
3560 pos_data data; 3494 pos_data data;
3561 int c_pixpos; 3495 int c_pixpos;
3496 Charcount offset = 0;
3562 3497
3563 xzero (data); 3498 xzero (data);
3564 data.d = d; 3499 data.d = d;
3565 data.db = db; 3500 data.db = db;
3566 data.dl = dl; 3501 data.dl = dl;
3570 data.cursor_type = NO_CURSOR; 3505 data.cursor_type = NO_CURSOR;
3571 data.last_charset = Qunbound; 3506 data.last_charset = Qunbound;
3572 data.last_findex = DEFAULT_INDEX; 3507 data.last_findex = DEFAULT_INDEX;
3573 data.result_str = result_str; 3508 data.result_str = result_str;
3574 data.is_modeline = 1; 3509 data.is_modeline = 1;
3510 data.string = Qnil;
3575 XSETWINDOW (data.window, w); 3511 XSETWINDOW (data.window, w);
3576 3512
3577 Dynarr_reset (formatted_string_extent_dynarr); 3513 Dynarr_reset (formatted_string_extent_dynarr);
3578 Dynarr_reset (formatted_string_extent_start_dynarr); 3514 Dynarr_reset (formatted_string_extent_start_dynarr);
3579 Dynarr_reset (formatted_string_extent_end_dynarr); 3515 Dynarr_reset (formatted_string_extent_end_dynarr);
3580 3516
3581 /* This recursively builds up the modeline. */ 3517 /* result_str is nil when we're building a frame or icon title. Otherwise,
3518 we're building a modeline, so the offset starts at the modeline
3519 horizontal scrolling ammount */
3520 if (! NILP (result_str))
3521 offset = w->modeline_hscroll;
3582 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, 3522 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3583 max_pixpos - min_pixpos, findex, type); 3523 max_pixpos - min_pixpos, findex, type, &offset,
3524 Qnil);
3584 3525
3585 if (Dynarr_length (db->runes)) 3526 if (Dynarr_length (db->runes))
3586 { 3527 {
3587 struct rune *rb = 3528 struct rune *rb =
3588 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); 3529 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3649 result_str); 3590 result_str);
3650 } 3591 }
3651 } 3592 }
3652 } 3593 }
3653 3594
3595 /* Ensure that the given display line DL accurately represents the
3596 modeline for the given window. */
3597 static void
3598 generate_modeline (struct window *w, struct display_line *dl, int type)
3599 {
3600 struct buffer *b = XBUFFER (w->buffer);
3601 struct frame *f = XFRAME (w->frame);
3602 struct device *d = XDEVICE (f->device);
3603
3604 /* Unlike display line and rune pointers, this one can't change underneath
3605 our feet. */
3606 struct display_block *db = get_display_block_from_line (dl, TEXT);
3607 int max_pixpos, min_pixpos, ypos_adj;
3608 Lisp_Object font_inst;
3609
3610 /* This will actually determine incorrect inside boundaries for the
3611 modeline since it ignores the margins. However being aware of this fact
3612 we never use those values anywhere so it doesn't matter. */
3613 dl->bounds = calculate_display_line_boundaries (w, 1);
3614
3615 /* We are generating a modeline. */
3616 dl->modeline = 1;
3617 dl->cursor_elt = -1;
3618
3619 /* Reset the runes on the modeline. */
3620 Dynarr_reset (db->runes);
3621
3622 if (!WINDOW_HAS_MODELINE_P (w))
3623 {
3624 struct rune rb;
3625
3626 /* If there is a horizontal scrollbar, don't add anything. */
3627 if (window_scrollbar_height (w))
3628 return;
3629
3630 dl->ascent = DEVMETH (d, divider_height, ());
3631 dl->descent = 0;
3632 /* The modeline is at the bottom of the gutters. */
3633 dl->ypos = WINDOW_BOTTOM (w);
3634
3635 /* adjust for the bottom gutter */
3636 if (window_is_lowest (w))
3637 dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
3638
3639 rb.findex = MODELINE_INDEX;
3640 rb.xpos = dl->bounds.left_out;
3641 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3642 rb.bufpos = 0;
3643 rb.endpos = 0;
3644 rb.type = RUNE_HLINE;
3645 rb.object.hline.thickness = 1;
3646 rb.object.hline.yoffset = 0;
3647 rb.cursor_type = NO_CURSOR;
3648
3649 if (!EQ (Qzero, w->modeline_shadow_thickness)
3650 && FRAME_WIN_P (f))
3651 {
3652 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3653
3654 dl->ypos -= shadow_thickness;
3655 rb.xpos += shadow_thickness;
3656 rb.width -= 2 * shadow_thickness;
3657 }
3658
3659 Dynarr_add (db->runes, rb);
3660 return;
3661 }
3662
3663 /* !!#### not right; needs to compute the max height of
3664 all the charsets */
3665 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3666
3667 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3668 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3669
3670 min_pixpos = dl->bounds.left_out;
3671 max_pixpos = dl->bounds.right_out;
3672
3673 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3674 {
3675 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3676
3677 ypos_adj = shadow_thickness;
3678 min_pixpos += shadow_thickness;
3679 max_pixpos -= shadow_thickness;
3680 }
3681 else
3682 ypos_adj = 0;
3683
3684 generate_formatted_string_db (b->modeline_format,
3685 b->generated_modeline_string, w, dl, db,
3686 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3687
3688 /* The modeline is at the bottom of the gutters. We have to wait to
3689 set this until we've generated the modeline in order to account
3690 for any embedded faces. */
3691 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3692 /* adjust for the bottom gutter */
3693 if (window_is_lowest (w))
3694 dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
3695 }
3696
3654 static Charcount 3697 static Charcount
3655 add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str, 3698 add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str,
3656 Charcount pos, Charcount min_pos, Charcount max_pos) 3699 Charcount pos, Charcount min_pos, Charcount max_pos)
3657 { 3700 {
3658 /* This function has been Mule-ized. */ 3701 /* This function has been Mule-ized. */
3659 Charcount end; 3702 Charcount end;
3660 CONST Bufbyte *cur_pos = str; 3703 const Bufbyte *cur_pos = str;
3661 struct display_block *db = data->db; 3704 struct display_block *db = data->db;
3662 3705
3663 data->blank_width = space_width (XWINDOW (data->window)); 3706 data->blank_width = space_width (XWINDOW (data->window));
3664 while (Dynarr_length (db->runes) < pos) 3707 while (Dynarr_length (db->runes) < pos)
3665 add_blank_rune (data, NULL, 0); 3708 add_blank_rune (data, NULL, 0);
3666 3709
3667 end = (Dynarr_length (db->runes) + 3710 end = (Dynarr_length (db->runes) +
3668 bytecount_to_charcount (str, strlen ((CONST char *) str))); 3711 bytecount_to_charcount (str, strlen ((const char *) str)));
3669 if (max_pos != -1) 3712 if (max_pos != -1)
3670 end = min (max_pos, end); 3713 end = min (max_pos, end);
3671 3714
3672 while (pos < end && *cur_pos) 3715 while (pos < end && *cur_pos)
3673 { 3716 {
3674 CONST Bufbyte *old_cur_pos = cur_pos; 3717 const Bufbyte *old_cur_pos = cur_pos;
3675 int succeeded; 3718 int succeeded;
3676 3719
3677 data->ch = charptr_emchar (cur_pos); 3720 data->ch = charptr_emchar (cur_pos);
3678 succeeded = (add_emchar_rune (data) != ADD_FAILED); 3721 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3679 INC_CHARPTR (cur_pos); 3722 INC_CHARPTR (cur_pos);
3694 3737
3695 /* #### Urk! Should also handle begin-glyphs and end-glyphs in 3738 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3696 modeline extents. */ 3739 modeline extents. */
3697 static Charcount 3740 static Charcount
3698 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, 3741 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3699 Charcount pos, Charcount min_pos, Charcount max_pos) 3742 Charcount pos, Charcount min_pos,
3743 Charcount max_pos, Lisp_Object extent)
3700 { 3744 {
3701 /* This function has been Mule-ized. */ 3745 /* This function has been Mule-ized. */
3702 Charcount end; 3746 Charcount end;
3703 struct display_block *db = data->db; 3747 struct display_block *db = data->db;
3704 struct glyph_block gb; 3748 struct glyph_block gb;
3710 end = Dynarr_length (db->runes) + 1; 3754 end = Dynarr_length (db->runes) + 1;
3711 if (max_pos != -1) 3755 if (max_pos != -1)
3712 end = min (max_pos, end); 3756 end = min (max_pos, end);
3713 3757
3714 gb.glyph = glyph; 3758 gb.glyph = glyph;
3715 gb.extent = Qnil; 3759 gb.extent = extent;
3716 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); 3760 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3717 pos++; 3761 pos++;
3718 3762
3719 while (Dynarr_length (db->runes) < pos && 3763 while (Dynarr_length (db->runes) < pos &&
3720 (data->pixpos + data->blank_width <= data->max_pixpos)) 3764 (data->pixpos + data->blank_width <= data->max_pixpos))
3737 modeline. */ 3781 modeline. */
3738 static Charcount 3782 static Charcount
3739 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, 3783 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3740 Charcount min_pos, Charcount max_pos, 3784 Charcount min_pos, Charcount max_pos,
3741 Lisp_Object elt, int depth, int max_pixsize, 3785 Lisp_Object elt, int depth, int max_pixsize,
3742 face_index findex, int type) 3786 face_index findex, int type, Charcount *offset,
3787 Lisp_Object cur_ext)
3743 { 3788 {
3744 /* This function has been Mule-ized. */ 3789 /* This function has been Mule-ized. */
3745 /* #### The other losing things in this function are: 3790 /* #### The other losing things in this function are:
3746 3791
3747 -- C zero-terminated-string lossage. 3792 -- C zero-terminated-string lossage.
3769 while (*this && *this != '%') 3814 while (*this && *this != '%')
3770 this++; 3815 this++;
3771 3816
3772 if (this != last) 3817 if (this != last)
3773 { 3818 {
3774 /* The string is just a string. */ 3819 /* No %-construct */
3775 Charcount size = 3820 Charcount size =
3776 bytecount_to_charcount (last, this - last) + pos; 3821 bytecount_to_charcount (last, this - last);
3777 Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos)); 3822
3778 3823 if (size <= *offset)
3779 pos = add_string_to_fstring_db_runes (data, last, pos, pos, 3824 *offset -= size;
3780 tmp_max); 3825 else
3826 {
3827 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
3828 min (pos + size - *offset, max_pos));
3829 const Bufbyte *tmp_last = charptr_n_addr (last, *offset);
3830
3831 pos = add_string_to_fstring_db_runes (data, tmp_last,
3832 pos, pos, tmp_max);
3833 *offset = 0;
3834 }
3781 } 3835 }
3782 else /* *this == '%' */ 3836 else /* *this == '%' */
3783 { 3837 {
3784 Charcount spec_width = 0; 3838 Charcount spec_width = 0;
3785 3839
3800 if (*this == 'M') 3854 if (*this == 'M')
3801 { 3855 {
3802 pos = generate_fstring_runes (w, data, pos, spec_width, 3856 pos = generate_fstring_runes (w, data, pos, spec_width,
3803 max_pos, Vglobal_mode_string, 3857 max_pos, Vglobal_mode_string,
3804 depth, max_pixsize, findex, 3858 depth, max_pixsize, findex,
3805 type); 3859 type, offset, cur_ext);
3806 } 3860 }
3807 else if (*this == '-') 3861 else if (*this == '-')
3808 { 3862 {
3809 Charcount num_to_add; 3863 Charcount num_to_add;
3810 3864
3827 num_to_add++; 3881 num_to_add++;
3828 } 3882 }
3829 3883
3830 while (num_to_add--) 3884 while (num_to_add--)
3831 pos = add_string_to_fstring_db_runes 3885 pos = add_string_to_fstring_db_runes
3832 (data, (CONST Bufbyte *) "-", pos, pos, max_pos); 3886 (data, (const Bufbyte *) "-", pos, pos, max_pos);
3833 } 3887 }
3834 else if (*this != 0) 3888 else if (*this != 0)
3835 { 3889 {
3890 Emchar ch = charptr_emchar (this);
3836 Bufbyte *str; 3891 Bufbyte *str;
3837 Emchar ch = charptr_emchar (this); 3892 Charcount size;
3893
3838 decode_mode_spec (w, ch, type); 3894 decode_mode_spec (w, ch, type);
3839 3895
3840 str = Dynarr_atp (mode_spec_bufbyte_string, 0); 3896 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3841 pos = add_string_to_fstring_db_runes (data,str, pos, pos, 3897 size = bytecount_to_charcount
3842 max_pos); 3898 /* Skip the null character added by `decode_mode_spec' */
3899 (str, Dynarr_length (mode_spec_bufbyte_string)) - 1;
3900
3901 if (size <= *offset)
3902 *offset -= size;
3903 else
3904 {
3905 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3906
3907 /* #### NOTE: I don't understand why a tmp_max is not
3908 computed and used here as in the plain string case
3909 above. -- dv */
3910 pos = add_string_to_fstring_db_runes (data, tmp_str,
3911 pos, pos,
3912 max_pos);
3913 *offset = 0;
3914 }
3843 } 3915 }
3844 3916
3845 /* NOT this++. There could be any sort of character at 3917 /* NOT this++. There could be any sort of character at
3846 the current position. */ 3918 the current position. */
3847 INC_CHARPTR (this); 3919 INC_CHARPTR (this);
3863 as if it appeared here directly. */ 3935 as if it appeared here directly. */
3864 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); 3936 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3865 3937
3866 if (!UNBOUNDP (tem)) 3938 if (!UNBOUNDP (tem))
3867 { 3939 {
3868 /* If value is a string, output that string literally: 3940 /* If value is a string, output that string literally:
3869 don't check for % within it. */ 3941 don't check for % within it. */
3870 if (STRINGP (tem)) 3942 if (STRINGP (tem))
3871 { 3943 {
3872 pos = 3944 Bufbyte *str = XSTRING_DATA (tem);
3873 add_string_to_fstring_db_runes 3945 Charcount size = XSTRING_CHAR_LENGTH (tem);
3874 (data, XSTRING_DATA (tem), pos, min_pos, max_pos); 3946
3947 if (size <= *offset)
3948 *offset -= size;
3949 else
3950 {
3951 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3952
3953 /* #### NOTE: I don't understand why a tmp_max is not
3954 computed and used here as in the plain string case
3955 above. -- dv */
3956 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
3957 min_pos, max_pos);
3958 *offset = 0;
3959 }
3875 } 3960 }
3876 /* Give up right away for nil or t. */ 3961 /* Give up right away for nil or t. */
3877 else if (!EQ (tem, elt)) 3962 else if (!EQ (tem, elt))
3878 { 3963 {
3879 elt = tem; 3964 elt = tem;
3894 } 3979 }
3895 } 3980 }
3896 else if (CONSP (elt)) 3981 else if (CONSP (elt))
3897 { 3982 {
3898 /* A cons cell: four distinct cases. 3983 /* A cons cell: four distinct cases.
3899 * If first element is a string or a cons, process all the elements 3984 * - If first element is a string or a cons, process all the elements
3900 * and effectively concatenate them. 3985 * and effectively concatenate them.
3901 * If first element is a negative number, truncate displaying cdr to 3986 * - If first element is a negative number, truncate displaying cdr to
3902 * at most that many characters. If positive, pad (with spaces) 3987 * at most that many characters. If positive, pad (with spaces)
3903 * to at least that many characters. 3988 * to at least that many characters.
3904 * If first element is a symbol, process the cadr or caddr recursively 3989 * - If first element is another symbol, process the cadr or caddr
3905 * according to whether the symbol's value is non-nil or nil. 3990 * recursively according to whether the symbol's value is non-nil or
3906 * If first element is a face, process the cdr recursively 3991 * nil.
3907 * without altering the depth. 3992 * - If first element is a face, process the cdr recursively
3993 * without altering the depth.
3908 */ 3994 */
3995
3909 Lisp_Object car, tem; 3996 Lisp_Object car, tem;
3910 3997
3911 car = XCAR (elt); 3998 car = XCAR (elt);
3912 if (SYMBOLP (car)) 3999 if (SYMBOLP (car))
3913 { 4000 {
3914 elt = XCDR (elt); 4001 elt = XCDR (elt);
3915 if (!CONSP (elt)) 4002 if (!CONSP (elt))
3916 goto invalid; 4003 goto invalid;
3917 tem = symbol_value_in_buffer (car, w->buffer); 4004
3918 /* elt is now the cdr, and we know it is a cons cell. 4005 tem = symbol_value_in_buffer (car, w->buffer);
3919 Use its car if CAR has a non-nil value. */ 4006 /* elt is now the cdr, and we know it is a cons cell.
3920 if (!UNBOUNDP (tem)) 4007 Use its car if CAR has a non-nil value. */
3921 { 4008 if (!UNBOUNDP (tem))
3922 if (!NILP (tem)) 4009 {
3923 { 4010 if (!NILP (tem))
3924 elt = XCAR (elt); 4011 {
3925 goto tail_recurse; 4012 elt = XCAR (elt);
3926 } 4013 goto tail_recurse;
3927 } 4014 }
3928 /* Symbol's value is nil (or symbol is unbound) 4015 }
3929 * Get the cddr of the original list 4016 /* Symbol's value is nil (or symbol is unbound)
3930 * and if possible find the caddr and use that. 4017 * Get the cddr of the original list
3931 */ 4018 * and if possible find the caddr and use that.
3932 elt = XCDR (elt); 4019 */
3933 if (NILP (elt)) 4020 elt = XCDR (elt);
3934 ; 4021 if (NILP (elt))
3935 else if (!CONSP (elt)) 4022 ;
3936 goto invalid; 4023 else if (!CONSP (elt))
3937 else 4024 goto invalid;
3938 { 4025 else
3939 elt = XCAR (elt); 4026 {
3940 goto tail_recurse; 4027 elt = XCAR (elt);
3941 } 4028 goto tail_recurse;
3942 } 4029 }
4030 }
3943 else if (INTP (car)) 4031 else if (INTP (car))
3944 { 4032 {
3945 Charcount lim = XINT (car); 4033 Charcount lim = XINT (car);
3946 4034
3947 elt = XCDR (elt); 4035 elt = XCDR (elt);
3976 goto tail_recurse; 4064 goto tail_recurse;
3977 } 4065 }
3978 else if (STRINGP (car) || CONSP (car)) 4066 else if (STRINGP (car) || CONSP (car))
3979 { 4067 {
3980 int limit = 50; 4068 int limit = 50;
4069
3981 /* LIMIT is to protect against circular lists. */ 4070 /* LIMIT is to protect against circular lists. */
3982 while (CONSP (elt) && --limit > 0 4071 while (CONSP (elt) && --limit > 0
3983 && (pos < max_pos || max_pos == -1)) 4072 && (pos < max_pos || max_pos == -1))
3984 { 4073 {
3985 pos = generate_fstring_runes (w, data, pos, pos, max_pos, 4074 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
3986 XCAR (elt), depth, 4075 XCAR (elt), depth, max_pixsize,
3987 max_pixsize, findex, type); 4076 findex, type, offset, cur_ext);
3988 elt = XCDR (elt); 4077 elt = XCDR (elt);
3989 } 4078 }
3990 } 4079 }
3991 else if (EXTENTP (car)) 4080 else if (EXTENTP (car))
3992 { 4081 {
4021 new_findex = old_findex; 4110 new_findex = old_findex;
4022 4111
4023 data->findex = new_findex; 4112 data->findex = new_findex;
4024 pos = generate_fstring_runes (w, data, pos, pos, max_pos, 4113 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4025 XCDR (elt), depth - 1, 4114 XCDR (elt), depth - 1,
4026 max_pixsize, new_findex, type); 4115 max_pixsize, new_findex, type,
4116 offset, car);
4027 data->findex = old_findex; 4117 data->findex = old_findex;
4028 Dynarr_add (formatted_string_extent_dynarr, ext); 4118 Dynarr_add (formatted_string_extent_dynarr, ext);
4029 Dynarr_add (formatted_string_extent_start_dynarr, start); 4119 Dynarr_add (formatted_string_extent_start_dynarr, start);
4030 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); 4120 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4031 } 4121 }
4032 } 4122 }
4033 } 4123 }
4034 else if (GLYPHP (elt)) 4124 else if (GLYPHP (elt))
4035 { 4125 {
4036 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos); 4126 /* Glyphs are considered as one character with respect to the modeline
4127 horizontal scrolling facility. -- dv */
4128 if (*offset > 0)
4129 *offset -= 1;
4130 else
4131 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos,
4132 cur_ext);
4037 } 4133 }
4038 else 4134 else
4039 { 4135 {
4040 invalid: 4136 invalid:
4041 pos = 4137 {
4042 add_string_to_fstring_db_runes 4138 char *str = GETTEXT ("*invalid*");
4043 (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos, 4139 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */
4044 max_pos); 4140
4141 if (size <= *offset)
4142 *offset -= size;
4143 else
4144 {
4145 const Bufbyte *tmp_str =
4146 charptr_n_addr ((const Bufbyte *) str, *offset);
4147
4148 /* #### NOTE: I don't understand why a tmp_max is not computed and
4149 used here as in the plain string case above. -- dv */
4150 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
4151 min_pos, max_pos);
4152 *offset = 0;
4153 }
4154 }
4045 } 4155 }
4046 4156
4047 if (min_pos > pos) 4157 if (min_pos > pos)
4048 { 4158 {
4049 add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos, 4159 add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos,
4050 -1); 4160 min_pos, -1);
4051 } 4161 }
4052 4162
4053 return pos; 4163 return pos;
4054 }
4055
4056 /* The caller is responsible for freeing the returned string. */
4057 Bufbyte *
4058 generate_formatted_string (struct window *w, Lisp_Object format_str,
4059 Lisp_Object result_str, face_index findex, int type)
4060 {
4061 struct display_line *dl;
4062 struct display_block *db;
4063 int elt = 0;
4064
4065 dl = &formatted_string_display_line;
4066 db = get_display_block_from_line (dl, TEXT);
4067 Dynarr_reset (db->runes);
4068
4069 generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
4070 -1, type);
4071
4072 Dynarr_reset (formatted_string_emchar_dynarr);
4073 while (elt < Dynarr_length (db->runes))
4074 {
4075 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
4076 Dynarr_add (formatted_string_emchar_dynarr,
4077 Dynarr_atp (db->runes, elt)->object.chr.ch);
4078 elt++;
4079 }
4080
4081 return
4082 convert_emchar_string_into_malloced_string
4083 ( Dynarr_atp (formatted_string_emchar_dynarr, 0),
4084 Dynarr_length (formatted_string_emchar_dynarr), 0);
4085 } 4164 }
4086 4165
4087 /* Update just the modeline. Assumes the desired display structs. If 4166 /* Update just the modeline. Assumes the desired display structs. If
4088 they do not have a modeline block, it does nothing. */ 4167 they do not have a modeline block, it does nothing. */
4089 static void 4168 static void
4176 return 0; 4255 return 0;
4177 } 4256 }
4178 4257
4179 4258
4180 /***************************************************************************/ 4259 /***************************************************************************/
4260 /* */
4261 /* displayable string routines */
4262 /* */
4263 /***************************************************************************/
4264
4265 /* Given a position for a string in a window, ensure that the given
4266 display line DL accurately represents the text on a line starting
4267 at the given position.
4268
4269 Yes, this is duplicating the code of create_text_block, but it
4270 looked just too hard to change create_text_block to handle strings
4271 *and* buffers. We already make a distinction between the two
4272 elsewhere in the code so I think unifying them would require a
4273 complete MULE rewrite. Besides, the other distinction is that these
4274 functions cover text that the user *cannot edit* so we can remove
4275 everything to do with cursors, minibuffers etc. Eventually the
4276 modeline routines should be modified to use this code as it copes
4277 with many more types of display situation. */
4278
4279 static Bufpos
4280 create_string_text_block (struct window *w, Lisp_Object disp_string,
4281 struct display_line *dl,
4282 Bufpos start_pos,
4283 prop_block_dynarr **prop,
4284 face_index default_face)
4285 {
4286 struct frame *f = XFRAME (w->frame);
4287 /* Note that a lot of the buffer controlled stuff has been left in
4288 because you might well want to make use of it (selective display
4289 etc), its just the buffer text that we do not use. However, it
4290 seems to be possible for buffer to be nil sometimes so protect
4291 against this case. */
4292 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
4293 struct device *d = XDEVICE (f->device);
4294 Lisp_String* s = XSTRING (disp_string);
4295
4296 /* we're working with these a lot so precalculate them */
4297 Bytecount slen = XSTRING_LENGTH (disp_string);
4298 Bytecount bi_string_zv = slen;
4299 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4300
4301 pos_data data;
4302
4303 int truncate_win = b ? window_truncation_on (w) : 0;
4304 int end_glyph_width = 0;
4305
4306 /* we're going to ditch selective display for static text, its an
4307 FSF thing and invisble extents are the way to go
4308 here. Implementing it also relies on a number of buffer-specific
4309 functions that we don't have the luxury of being able to use
4310 here. */
4311
4312 /* The variable ctl-arrow allows the user to specify what characters
4313 can actually be displayed and which octal should be used for.
4314 #### This variable should probably have some rethought done to
4315 it.
4316
4317 #### It would also be really nice if you could specify that
4318 the characters come out in hex instead of in octal. Mule
4319 does that by adding a ctl-hexa variable similar to ctl-arrow,
4320 but that's bogus -- we need a more general solution. I
4321 think you need to extend the concept of display tables
4322 into a more general conversion mechanism. Ideally you
4323 could specify a Lisp function that converts characters,
4324 but this violates the Second Golden Rule and besides would
4325 make things way way way way slow.
4326
4327 So instead, we extend the display-table concept, which was
4328 historically limited to 256-byte vectors, to one of the
4329 following:
4330
4331 a) A 256-entry vector, for backward compatibility;
4332 b) char-table, mapping characters to values;
4333 c) range-table, mapping ranges of characters to values;
4334 d) a list of the above.
4335
4336 The (d) option allows you to specify multiple display tables
4337 instead of just one. Each display table can specify conversions
4338 for some characters and leave others unchanged. The way the
4339 character gets displayed is determined by the first display table
4340 with a binding for that character. This way, you could call a
4341 function `enable-hex-display' that adds a hex display-table to
4342 the list of display tables for the current buffer.
4343
4344 #### ...not yet implemented... Also, we extend the concept of
4345 "mapping" to include a printf-like spec. Thus you can make all
4346 extended characters show up as hex with a display table like
4347 this:
4348
4349 #s(range-table data ((256 524288) (format "%x")))
4350
4351 Since more than one display table is possible, you have
4352 great flexibility in mapping ranges of characters. */
4353 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4354 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4355 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4356 ? 255 : 160)) : 255;
4357
4358 Lisp_Object face_dt, window_dt;
4359
4360 /* The text display block for this display line. */
4361 struct display_block *db = get_display_block_from_line (dl, TEXT);
4362
4363 /* The first time through the main loop we need to force the glyph
4364 data to be updated. */
4365 int initial = 1;
4366
4367 /* Apparently the new extent_fragment_update returns an end position
4368 equal to the position passed in if there are no more runs to be
4369 displayed. */
4370 int no_more_frags = 0;
4371
4372 dl->used_prop_data = 0;
4373 dl->num_chars = 0;
4374
4375 /* set up faces to use for clearing areas, used by
4376 output_display_line */
4377 dl->default_findex = default_face;
4378 if (default_face)
4379 {
4380 dl->left_margin_findex = default_face;
4381 dl->right_margin_findex = default_face;
4382 }
4383 else
4384 {
4385 dl->left_margin_findex =
4386 get_builtin_face_cache_index (w, Vleft_margin_face);
4387 dl->right_margin_findex =
4388 get_builtin_face_cache_index (w, Vright_margin_face);
4389 }
4390
4391 xzero (data);
4392 data.ef = extent_fragment_new (disp_string, f);
4393
4394 /* These values are used by all of the rune addition routines. We add
4395 them to this structure for ease of passing. */
4396 data.d = d;
4397 XSETWINDOW (data.window, w);
4398 data.db = db;
4399 data.dl = dl;
4400
4401 data.bi_bufpos = bi_start_pos;
4402 data.pixpos = dl->bounds.left_in;
4403 data.last_charset = Qunbound;
4404 data.last_findex = default_face;
4405 data.result_str = Qnil;
4406 data.string = disp_string;
4407
4408 /* Set the right boundary adjusting it to take into account any end
4409 glyph. Save the width of the end glyph for later use. */
4410 data.max_pixpos = dl->bounds.right_in;
4411 #if 0
4412 if (truncate_win)
4413 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
4414 else
4415 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
4416 #endif
4417 data.max_pixpos -= end_glyph_width;
4418
4419 data.cursor_type = NO_CURSOR;
4420 data.cursor_x = -1;
4421
4422 data.start_col = 0;
4423 /* I don't think we want this, string areas should not scroll with
4424 the window
4425 data.start_col = w->hscroll;
4426 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4427 */
4428 data.bi_start_col_enabled = 0;
4429 data.hscroll_glyph_width_adjust = 0;
4430
4431 /* We regenerate the line from the very beginning. */
4432 Dynarr_reset (db->runes);
4433
4434 /* Why is this less than or equal and not just less than? If the
4435 starting position is already equal to the maximum we can't add
4436 anything else, right? Wrong. We might still have a newline to
4437 add. A newline can use the room allocated for an end glyph since
4438 if we add it we know we aren't going to be adding any end
4439 glyph. */
4440
4441 /* #### Chuck -- I think this condition should be while (1).
4442 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4443 and the begin-glyph ends exactly at the end of the window, the
4444 end-glyph and text might not be displayed. while (1) ensures
4445 that the loop terminates only when either (a) there is
4446 propagation data or (b) the end-of-line or end-of-buffer is hit.
4447
4448 #### Also I think you need to ensure that the operation
4449 "add begin glyphs; add end glyphs; add text" is atomic and
4450 can't get interrupted in the middle. If you run off the end
4451 of the line during that operation, then you keep accumulating
4452 propagation data until you're done. Otherwise, if the (e.g.)
4453 there's a begin glyph at a particular position and attempting
4454 to display that glyph results in window-end being hit and
4455 propagation data being generated, then the character at that
4456 position won't be displayed.
4457
4458 #### See also the comment after the end of this loop, below.
4459 */
4460 while (data.pixpos <= data.max_pixpos)
4461 {
4462 /* #### This check probably should not be necessary. */
4463 if (data.bi_bufpos > bi_string_zv)
4464 {
4465 /* #### urk! More of this lossage! */
4466 data.bi_bufpos--;
4467 goto done;
4468 }
4469
4470 /* Check for face changes. */
4471 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
4472 {
4473 /* Now compute the face and begin/end-glyph information. */
4474 data.findex =
4475 /* Remember that the extent-fragment routines deal in Bytind's. */
4476 extent_fragment_update (w, data.ef, data.bi_bufpos);
4477 /* This is somewhat cheesy but the alternative is to
4478 propagate default_face into extent_fragment_update. */
4479 if (data.findex == DEFAULT_INDEX)
4480 data.findex = default_face;
4481
4482 get_display_tables (w, data.findex, &face_dt, &window_dt);
4483
4484 if (data.bi_bufpos == data.ef->end)
4485 no_more_frags = 1;
4486 }
4487 initial = 0;
4488
4489 /* Determine what is next to be displayed. We first handle any
4490 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4491 display then we determine what to do based on the character at the
4492 current buffer position. */
4493
4494 /* If the current position is covered by an invisible extent, do
4495 nothing (except maybe add some ellipses).
4496
4497 #### The behavior of begin and end-glyphs at the edge of an
4498 invisible extent should be investigated further. This is
4499 fairly low priority though. */
4500 if (data.ef->invisible)
4501 {
4502 /* #### Chuck, perhaps you could look at this code? I don't
4503 really know what I'm doing. */
4504 if (*prop)
4505 {
4506 Dynarr_free (*prop);
4507 *prop = 0;
4508 }
4509
4510 /* The extent fragment code only sets this when we should
4511 really display the ellipses. It makes sure the ellipses
4512 don't get displayed more than once in a row. */
4513 if (data.ef->invisible_ellipses)
4514 {
4515 struct glyph_block gb;
4516
4517 data.ef->invisible_ellipses_already_displayed = 1;
4518 data.ef->invisible_ellipses = 0;
4519 gb.extent = Qnil;
4520 gb.glyph = Vinvisible_text_glyph;
4521 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
4522 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
4523 /* Perhaps they shouldn't propagate if the very next thing
4524 is to display a newline (for compatibility with
4525 selective-display-ellipses)? Maybe that's too
4526 abstruse. */
4527 if (*prop)
4528 goto done;
4529 }
4530
4531 /* #### What if we we're dealing with a display table? */
4532 if (data.start_col)
4533 data.start_col--;
4534
4535 if (data.bi_bufpos == bi_string_zv)
4536 goto done;
4537 else
4538 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4539 }
4540
4541 /* If there is propagation data, then it represents the current
4542 buffer position being displayed. Add them and advance the
4543 position counter. This might also add the minibuffer
4544 prompt. */
4545 else if (*prop)
4546 {
4547 dl->used_prop_data = 1;
4548 *prop = add_propagation_runes (prop, &data);
4549
4550 if (*prop)
4551 goto done; /* gee, a really narrow window */
4552 else if (data.bi_bufpos == bi_string_zv)
4553 goto done;
4554 else if (data.bi_bufpos < 0)
4555 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4556 data.bi_bufpos = 0;
4557 else
4558 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4559 }
4560
4561 /* If there are end glyphs, add them to the line. These are
4562 the end glyphs for the previous run of text. We add them
4563 here rather than doing them at the end of handling the
4564 previous run so that glyphs at the beginning and end of
4565 a line are handled correctly. */
4566 else if (Dynarr_length (data.ef->end_glyphs) > 0)
4567 {
4568 *prop = add_glyph_runes (&data, END_GLYPHS);
4569 if (*prop)
4570 goto done;
4571 }
4572
4573 /* If there are begin glyphs, add them to the line. */
4574 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
4575 {
4576 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
4577 if (*prop)
4578 goto done;
4579 }
4580
4581 /* If at end-of-buffer, we've already processed begin and
4582 end-glyphs at this point and there's no text to process,
4583 so we're done. */
4584 else if (data.bi_bufpos == bi_string_zv)
4585 goto done;
4586
4587 else
4588 {
4589 Lisp_Object entry = Qnil;
4590 /* Get the character at the current buffer position. */
4591 data.ch = string_char (s, data.bi_bufpos);
4592 if (!NILP (face_dt) || !NILP (window_dt))
4593 entry = display_table_entry (data.ch, face_dt, window_dt);
4594
4595 /* If there is a display table entry for it, hand it off to
4596 add_disp_table_entry_runes and let it worry about it. */
4597 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
4598 {
4599 *prop = add_disp_table_entry_runes (&data, entry);
4600
4601 if (*prop)
4602 goto done;
4603 }
4604
4605 /* Check if we have hit a newline character. If so, add a marker
4606 to the line and end this loop. */
4607 else if (data.ch == '\n')
4608 {
4609 /* We aren't going to be adding an end glyph so give its
4610 space back in order to make sure that the cursor can
4611 fit. */
4612 data.max_pixpos += end_glyph_width;
4613 goto done;
4614 }
4615
4616 /* If the current character is considered to be printable, then
4617 just add it. */
4618 else if (data.ch >= printable_min)
4619 {
4620 *prop = add_emchar_rune (&data);
4621 if (*prop)
4622 goto done;
4623 }
4624
4625 /* If the current character is a tab, determine the next tab
4626 starting position and add a blank rune which extends from the
4627 current pixel position to that starting position. */
4628 else if (data.ch == '\t')
4629 {
4630 int tab_start_pixpos = data.pixpos;
4631 int next_tab_start;
4632 int char_tab_width;
4633 int prop_width = 0;
4634
4635 if (data.start_col > 1)
4636 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
4637
4638 next_tab_start =
4639 next_tab_position (w, tab_start_pixpos,
4640 dl->bounds.left_in +
4641 data.hscroll_glyph_width_adjust);
4642 if (next_tab_start > data.max_pixpos)
4643 {
4644 prop_width = next_tab_start - data.max_pixpos;
4645 next_tab_start = data.max_pixpos;
4646 }
4647 data.blank_width = next_tab_start - data.pixpos;
4648 char_tab_width =
4649 (next_tab_start - tab_start_pixpos) / space_width (w);
4650
4651 *prop = add_blank_rune (&data, w, char_tab_width);
4652
4653 /* add_blank_rune is only supposed to be called with
4654 sizes guaranteed to fit in the available space. */
4655 assert (!(*prop));
4656
4657 if (prop_width)
4658 {
4659 struct prop_block pb;
4660 *prop = Dynarr_new (prop_block);
4661
4662 pb.type = PROP_BLANK;
4663 pb.data.p_blank.width = prop_width;
4664 pb.data.p_blank.findex = data.findex;
4665 Dynarr_add (*prop, pb);
4666
4667 goto done;
4668 }
4669 }
4670
4671 /* If character is a control character, pass it off to
4672 add_control_char_runes.
4673
4674 The is_*() routines have undefined results on
4675 arguments outside of the range [-1, 255]. (This
4676 often bites people who carelessly use `char' instead
4677 of `unsigned char'.)
4678 */
4679 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
4680 {
4681 *prop = add_control_char_runes (&data, b);
4682
4683 if (*prop)
4684 goto done;
4685 }
4686
4687 /* If the character is above the ASCII range and we have not
4688 already handled it, then print it as an octal number. */
4689 else if (data.ch >= 0200)
4690 {
4691 *prop = add_octal_runes (&data);
4692
4693 if (*prop)
4694 goto done;
4695 }
4696
4697 /* Assume the current character is considered to be printable,
4698 then just add it. */
4699 else
4700 {
4701 *prop = add_emchar_rune (&data);
4702 if (*prop)
4703 goto done;
4704 }
4705
4706 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4707 }
4708 }
4709
4710 done:
4711
4712 /* Determine the starting point of the next line if we did not hit the
4713 end of the buffer. */
4714 if (data.bi_bufpos < bi_string_zv)
4715 {
4716 /* #### This check is not correct. If the line terminated
4717 due to a begin-glyph or end-glyph hitting window-end, then
4718 data.ch will not point to the character at data.bi_bufpos. If
4719 you make the two changes mentioned at the top of this loop,
4720 you should be able to say '(if (*prop))'. That should also
4721 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4722 check. */
4723
4724 /* The common case is that the line ended because we hit a newline.
4725 In that case, the next character is just the next buffer
4726 position. */
4727 if (data.ch == '\n')
4728 {
4729 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4730 }
4731
4732 /* Otherwise we have a buffer line which cannot fit on one display
4733 line. */
4734 else
4735 {
4736 struct glyph_block gb;
4737 struct glyph_cachel *cachel;
4738
4739 /* If the line is to be truncated then we actually have to look
4740 for the next newline. We also add the end-of-line glyph which
4741 we know will fit because we adjusted the right border before
4742 we starting laying out the line. */
4743 data.max_pixpos += end_glyph_width;
4744 data.findex = default_face;
4745 gb.extent = Qnil;
4746
4747 if (truncate_win)
4748 {
4749 Bytind bi_pos;
4750
4751 /* Now find the start of the next line. */
4752 bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
4753
4754 data.cursor_type = NO_CURSOR;
4755 data.bi_bufpos = bi_pos;
4756 gb.glyph = Vtruncation_glyph;
4757 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
4758 }
4759 else
4760 {
4761 /* The cursor can never be on the continuation glyph. */
4762 data.cursor_type = NO_CURSOR;
4763
4764 /* data.bi_bufpos is already at the start of the next line. */
4765
4766 gb.glyph = Vcontinuation_glyph;
4767 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
4768 }
4769
4770 if (end_glyph_width)
4771 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
4772
4773 if (truncate_win && data.bi_bufpos == bi_string_zv)
4774 {
4775 const Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
4776 DEC_CHARPTR (endb);
4777 if (charptr_emchar (endb) != '\n')
4778 {
4779 /* #### Damn this losing shit. */
4780 data.bi_bufpos++;
4781 }
4782 }
4783 }
4784 }
4785 else if (data.bi_bufpos == bi_string_zv)
4786 {
4787 /* create_text_block () adds a bogus \n marker here which screws
4788 up subwindow display. Since we never have a cursor in the
4789 gutter we can safely ignore it. */
4790 }
4791 /* Calculate left whitespace boundary. */
4792 {
4793 int elt = 0;
4794
4795 /* Whitespace past a newline is considered right whitespace. */
4796 while (elt < Dynarr_length (db->runes))
4797 {
4798 struct rune *rb = Dynarr_atp (db->runes, elt);
4799
4800 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4801 || rb->type == RUNE_BLANK)
4802 {
4803 dl->bounds.left_white += rb->width;
4804 elt++;
4805 }
4806 else
4807 elt = Dynarr_length (db->runes);
4808 }
4809 }
4810
4811 /* Calculate right whitespace boundary. */
4812 {
4813 int elt = Dynarr_length (db->runes) - 1;
4814 int done = 0;
4815
4816 while (!done && elt >= 0)
4817 {
4818 struct rune *rb = Dynarr_atp (db->runes, elt);
4819
4820 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4821 && isspace (rb->object.chr.ch))
4822 && !rb->type == RUNE_BLANK)
4823 {
4824 dl->bounds.right_white = rb->xpos + rb->width;
4825 done = 1;
4826 }
4827
4828 elt--;
4829
4830 }
4831
4832 /* The line is blank so everything is considered to be right
4833 whitespace. */
4834 if (!done)
4835 dl->bounds.right_white = dl->bounds.left_in;
4836 }
4837
4838 /* Set the display blocks bounds. */
4839 db->start_pos = dl->bounds.left_in;
4840 if (Dynarr_length (db->runes))
4841 {
4842 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4843
4844 db->end_pos = rb->xpos + rb->width;
4845 }
4846 else
4847 db->end_pos = dl->bounds.right_white;
4848
4849 /* update line height parameters */
4850 if (!data.new_ascent && !data.new_descent)
4851 {
4852 /* We've got a blank line so initialize these values from the default
4853 face. */
4854 default_face_font_info (data.window, &data.new_ascent,
4855 &data.new_descent, 0, 0, 0);
4856 }
4857
4858 if (data.max_pixmap_height)
4859 {
4860 int height = data.new_ascent + data.new_descent;
4861 int pix_ascent, pix_descent;
4862
4863 pix_descent = data.max_pixmap_height * data.new_descent / height;
4864 pix_ascent = data.max_pixmap_height - pix_descent;
4865
4866 data.new_ascent = max (data.new_ascent, pix_ascent);
4867 data.new_descent = max (data.new_descent, pix_descent);
4868 }
4869
4870 dl->ascent = data.new_ascent;
4871 dl->descent = data.new_descent;
4872
4873 {
4874 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
4875
4876 if (dl->ascent < ascent)
4877 dl->ascent = ascent;
4878 }
4879 {
4880 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
4881
4882 if (dl->descent < descent)
4883 dl->descent = descent;
4884 }
4885
4886 dl->cursor_elt = data.cursor_x;
4887 /* #### lossage lossage lossage! Fix this shit! */
4888 if (data.bi_bufpos > bi_string_zv)
4889 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4890 else
4891 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4892 if (truncate_win)
4893 data.dl->num_chars =
4894 string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
4895 else
4896 /* This doesn't correctly take into account tabs and control
4897 characters but if the window isn't being truncated then this
4898 value isn't going to end up being used anyhow. */
4899 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4900
4901 /* #### handle horizontally scrolled line with text none of which
4902 was actually laid out. */
4903
4904 /* #### handle any remainder of overlay arrow */
4905
4906 if (*prop == ADD_FAILED)
4907 *prop = NULL;
4908
4909 if (truncate_win && *prop)
4910 {
4911 Dynarr_free (*prop);
4912 *prop = NULL;
4913 }
4914
4915 extent_fragment_delete (data.ef);
4916
4917 /* #### If we started at EOB, then make sure we return a value past
4918 it so that regenerate_window will exit properly. This is bogus.
4919 The main loop should get fixed so that it isn't necessary to call
4920 this function if we are already at EOB. */
4921
4922 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4923 return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
4924 else
4925 return bytecount_to_charcount (string_data (s), data.bi_bufpos);
4926 }
4927
4928 /* Given a display line and a starting position, ensure that the
4929 contents of the display line accurately represent the visual
4930 representation of the buffer contents starting from the given
4931 position when displayed in the given window. The display line ends
4932 when the contents of the line reach the right boundary of the given
4933 window.
4934
4935 This is very similar to generate_display_line but with the same
4936 limitations as create_string_text_block. I have taken the liberty
4937 of fixing the bytind stuff though.*/
4938
4939 static Bufpos
4940 generate_string_display_line (struct window *w, Lisp_Object disp_string,
4941 struct display_line *dl,
4942 Bufpos start_pos,
4943 prop_block_dynarr **prop,
4944 face_index default_face)
4945 {
4946 Bufpos ret_bufpos;
4947
4948 /* you must set bounds before calling this. */
4949
4950 /* Reset what this line is using. */
4951 if (dl->display_blocks)
4952 Dynarr_reset (dl->display_blocks);
4953 if (dl->left_glyphs)
4954 {
4955 Dynarr_free (dl->left_glyphs);
4956 dl->left_glyphs = 0;
4957 }
4958 if (dl->right_glyphs)
4959 {
4960 Dynarr_free (dl->right_glyphs);
4961 dl->right_glyphs = 0;
4962 }
4963
4964 /* We aren't generating a modeline at the moment. */
4965 dl->modeline = 0;
4966
4967 /* Create a display block for the text region of the line. */
4968 ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
4969 prop, default_face);
4970 dl->bufpos = start_pos;
4971 if (dl->end_bufpos < dl->bufpos)
4972 dl->end_bufpos = dl->bufpos;
4973
4974 /* If there are left glyphs associated with any character in the
4975 text block, then create a display block to handle them. */
4976 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
4977 create_left_glyph_block (w, dl, 0);
4978
4979 /* If there are right glyphs associated with any character in the
4980 text block, then create a display block to handle them. */
4981 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
4982 create_right_glyph_block (w, dl);
4983
4984 return ret_bufpos;
4985 }
4986
4987 /* This is ripped off from regenerate_window. All we want to do is
4988 loop through elements in the string creating display lines until we
4989 have covered the provided area. Simple really. */
4990 void
4991 generate_displayable_area (struct window *w, Lisp_Object disp_string,
4992 int xpos, int ypos, int width, int height,
4993 display_line_dynarr* dla,
4994 Bufpos start_pos,
4995 face_index default_face)
4996 {
4997 int yend = ypos + height;
4998 Charcount s_zv;
4999
5000 prop_block_dynarr *prop = 0;
5001 layout_bounds bounds;
5002 assert (dla);
5003
5004 Dynarr_reset (dla);
5005 /* if there's nothing to do then do nothing. code after this assumes
5006 there is something to do. */
5007 if (NILP (disp_string))
5008 return;
5009
5010 s_zv = XSTRING_CHAR_LENGTH (disp_string);
5011
5012 bounds.left_out = xpos;
5013 bounds.right_out = xpos + width;
5014 /* The inner boundaries mark where the glyph margins are located. */
5015 bounds.left_in = bounds.left_out + window_left_margin_width (w);
5016 bounds.right_in = bounds.right_out - window_right_margin_width (w);
5017 /* We cannot fully calculate the whitespace boundaries as they
5018 depend on the contents of the line being displayed. */
5019 bounds.left_white = bounds.left_in;
5020 bounds.right_white = bounds.right_in;
5021
5022 while (ypos < yend)
5023 {
5024 struct display_line dl;
5025 struct display_line *dlp;
5026 Bufpos next_pos;
5027 int local;
5028
5029 if (Dynarr_length (dla) < Dynarr_largest (dla))
5030 {
5031 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5032 local = 0;
5033 }
5034 else
5035 {
5036
5037 xzero (dl);
5038 dlp = &dl;
5039 local = 1;
5040 }
5041
5042 dlp->bounds = bounds;
5043 dlp->offset = 0;
5044 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5045 &prop, default_face);
5046 /* we need to make sure that we continue along the line if there
5047 is more left to display otherwise we just end up redisplaying
5048 the same chunk over and over again. */
5049 if (next_pos == start_pos && next_pos < s_zv)
5050 start_pos++;
5051 else
5052 start_pos = next_pos;
5053
5054 dlp->ypos = ypos + dlp->ascent;
5055 ypos = dlp->ypos + dlp->descent;
5056
5057 if (ypos > yend)
5058 {
5059 int visible_height = dlp->ascent + dlp->descent;
5060
5061 dlp->clip = (ypos - yend);
5062 visible_height -= dlp->clip;
5063
5064 if (visible_height < VERTICAL_CLIP (w, 1))
5065 {
5066 if (local)
5067 free_display_line (dlp);
5068 break;
5069 }
5070 }
5071 else
5072 dlp->clip = 0;
5073
5074 Dynarr_add (dla, *dlp);
5075
5076 /* #### This type of check needs to be done down in the
5077 generate_display_line call. */
5078 if (start_pos >= s_zv)
5079 break;
5080 }
5081
5082 if (prop)
5083 Dynarr_free (prop);
5084 }
5085
5086
5087 /***************************************************************************/
4181 /* */ 5088 /* */
4182 /* window-regeneration routines */ 5089 /* window-regeneration routines */
4183 /* */ 5090 /* */
4184 /***************************************************************************/ 5091 /***************************************************************************/
4185 5092
4194 { 5101 {
4195 struct frame *f = XFRAME (w->frame); 5102 struct frame *f = XFRAME (w->frame);
4196 struct buffer *b = XBUFFER (w->buffer); 5103 struct buffer *b = XBUFFER (w->buffer);
4197 int ypos = WINDOW_TEXT_TOP (w); 5104 int ypos = WINDOW_TEXT_TOP (w);
4198 int yend; /* set farther down */ 5105 int yend; /* set farther down */
5106 int yclip = WINDOW_TEXT_TOP_CLIP (w);
4199 5107
4200 prop_block_dynarr *prop; 5108 prop_block_dynarr *prop;
4201 layout_bounds bounds; 5109 layout_bounds bounds;
4202 display_line_dynarr *dla; 5110 display_line_dynarr *dla;
4203 int need_modeline; 5111 int need_modeline;
4260 dlp = Dynarr_atp (dla, Dynarr_length (dla)); 5168 dlp = Dynarr_atp (dla, Dynarr_length (dla));
4261 local = 0; 5169 local = 0;
4262 } 5170 }
4263 else 5171 else
4264 { 5172 {
5173
4265 xzero (dl); 5174 xzero (dl);
4266 dlp = &dl; 5175 dlp = &dl;
4267 local = 1; 5176 local = 1;
4268 } 5177 }
4269 5178
4270 dlp->bounds = bounds; 5179 dlp->bounds = bounds;
4271 dlp->offset = 0; 5180 dlp->offset = 0;
4272 start_pos = generate_display_line (w, dlp, 1, start_pos, 5181 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
4273 w->hscroll, &prop, type); 5182
4274 dlp->ypos = ypos + dlp->ascent; 5183 if (yclip > dlp->ascent)
5184 {
5185 /* this should never happen, but if it does just display the
5186 whole line */
5187 yclip = 0;
5188 }
5189
5190 dlp->ypos = (ypos + dlp->ascent) - yclip;
4275 ypos = dlp->ypos + dlp->descent; 5191 ypos = dlp->ypos + dlp->descent;
4276 5192
5193 /* See if we've been asked to start midway through a line, for
5194 partial display line scrolling. */
5195 if (yclip)
5196 {
5197 dlp->top_clip = yclip;
5198 yclip = 0;
5199 }
5200 else
5201 dlp->top_clip = 0;
5202
4277 if (ypos > yend) 5203 if (ypos > yend)
4278 { 5204 {
4279 int visible_height = dlp->ascent + dlp->descent; 5205 int visible_height = dlp->ascent + dlp->descent;
4280 5206
4281 dlp->clip = (ypos - yend); 5207 dlp->clip = (ypos - yend);
4282 visible_height -= dlp->clip; 5208 /* Although this seems strange we could have a single very
5209 tall line visible for which we need to account for both
5210 the top clip and the bottom clip. */
5211 visible_height -= (dlp->clip + dlp->top_clip);
4283 5212
4284 if (visible_height < VERTICAL_CLIP (w, 1)) 5213 if (visible_height < VERTICAL_CLIP (w, 1))
4285 { 5214 {
4286 if (local) 5215 if (local)
4287 free_display_line (dlp); 5216 free_display_line (dlp);
4520 we'll have the necessary propagation data. */ 5449 we'll have the necessary propagation data. */
4521 if (line == first_line && ddl->used_prop_data) 5450 if (line == first_line && ddl->used_prop_data)
4522 return 0; 5451 return 0;
4523 5452
4524 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, 5453 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
4525 w->hscroll, &prop, DESIRED_DISP); 5454 &prop, DESIRED_DISP);
4526 ddl->offset = 0; 5455 ddl->offset = 0;
4527 5456
4528 /* #### If there is propagated stuff the fail. We could 5457 /* #### If there is propagated stuff the fail. We could
4529 probably actually deal with this if the line had propagated 5458 probably actually deal with this if the line had propagated
4530 information when originally created by a full 5459 information when originally created by a full
4539 cursor has disappeared or disappeared, fail. */ 5468 cursor has disappeared or disappeared, fail. */
4540 db = get_display_block_from_line (ddl, TEXT); 5469 db = get_display_block_from_line (ddl, TEXT);
4541 if (cdl->ypos != ddl->ypos 5470 if (cdl->ypos != ddl->ypos
4542 || cdl->ascent != ddl->ascent 5471 || cdl->ascent != ddl->ascent
4543 || cdl->descent != ddl->descent 5472 || cdl->descent != ddl->descent
5473 || cdl->top_clip != ddl->top_clip
4544 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) 5474 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
4545 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) 5475 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
4546 || old_start != ddl->bufpos 5476 || old_start != ddl->bufpos
4547 || old_end != ddl->end_bufpos 5477 || old_end != ddl->end_bufpos
4548 || initial_size != Dynarr_length (db->runes)) 5478 || initial_size != Dynarr_length (db->runes))
4682 /* If the line was generated using propagation data, fail. */ 5612 /* If the line was generated using propagation data, fail. */
4683 if (ddl->used_prop_data) 5613 if (ddl->used_prop_data)
4684 return 0; 5614 return 0;
4685 5615
4686 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, 5616 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
4687 w->hscroll, &prop, DESIRED_DISP); 5617 &prop, DESIRED_DISP);
4688 ddl->offset = 0; 5618 ddl->offset = 0;
4689 5619
4690 /* If there is propagated stuff then it is pretty much a 5620 /* If there is propagated stuff then it is pretty much a
4691 guarantee that more than just the one line is affected. */ 5621 guarantee that more than just the one line is affected. */
4692 if (prop) 5622 if (prop)
4712 /* If any line position parameters have changed or a 5642 /* If any line position parameters have changed or a
4713 cursor has disappeared or disappeared, fail. */ 5643 cursor has disappeared or disappeared, fail. */
4714 if (cdl->ypos != ddl->ypos 5644 if (cdl->ypos != ddl->ypos
4715 || cdl->ascent != ddl->ascent 5645 || cdl->ascent != ddl->ascent
4716 || cdl->descent != ddl->descent 5646 || cdl->descent != ddl->descent
5647 || cdl->top_clip != ddl->top_clip
4717 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) 5648 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
4718 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) 5649 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
4719 { 5650 {
4720 return 0; 5651 return 0;
4721 } 5652 }
4995 pointm = BUF_ZV (b); 5926 pointm = BUF_ZV (b);
4996 } 5927 }
4997 } 5928 }
4998 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); 5929 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
4999 5930
5000 /* If the buffer has changed we have to invalid all of our face 5931 /* If the buffer has changed we have to invalidate all of our face
5001 cache elements. */ 5932 cache elements. */
5002 if ((!echo_active && b != window_display_buffer (w)) 5933 if ((!echo_active && b != window_display_buffer (w))
5003 || !Dynarr_length (w->face_cachels) 5934 || !Dynarr_length (w->face_cachels)
5004 || f->faces_changed) 5935 || f->faces_changed)
5005 reset_face_cachels (w); 5936 reset_face_cachels (w);
5006 else 5937 else
5007 mark_face_cachels_as_not_updated (w); 5938 mark_face_cachels_as_not_updated (w);
5008 5939
5009 /* Ditto the glyph cache elements. */ 5940 /* Ditto the glyph cache elements, although we do *not* invalidate
5941 the cache purely because glyphs have changed - this is now
5942 handled by the dirty flag.*/
5010 if ((!echo_active && b != window_display_buffer (w)) 5943 if ((!echo_active && b != window_display_buffer (w))
5011 || !Dynarr_length (w->glyph_cachels) 5944 || !Dynarr_length (w->glyph_cachels) || f->faces_changed)
5012 || f->glyphs_changed)
5013 reset_glyph_cachels (w); 5945 reset_glyph_cachels (w);
5014 else 5946 else
5015 mark_glyph_cachels_as_not_updated (w); 5947 mark_glyph_cachels_as_not_updated (w);
5016 5948
5017 /* If the marker's buffer is not the window's buffer, then we need 5949 /* If the marker's buffer is not the window's buffer, then we need
5093 && !f->clip_changed 6025 && !f->clip_changed
5094 && !f->extents_changed 6026 && !f->extents_changed
5095 && !f->faces_changed 6027 && !f->faces_changed
5096 && !f->glyphs_changed 6028 && !f->glyphs_changed
5097 && !f->subwindows_changed 6029 && !f->subwindows_changed
6030 && !f->subwindows_state_changed
5098 && !f->point_changed 6031 && !f->point_changed
5099 && !f->windows_structure_changed) 6032 && !f->windows_structure_changed)
5100 { 6033 {
5101 /* If not, we're done. */ 6034 /* If not, we're done. */
5102 if (f->modeline_changed) 6035 if (f->modeline_changed)
5114 && !f->clip_changed 6047 && !f->clip_changed
5115 && !f->extents_changed 6048 && !f->extents_changed
5116 && !f->faces_changed 6049 && !f->faces_changed
5117 && !f->glyphs_changed 6050 && !f->glyphs_changed
5118 && !f->subwindows_changed 6051 && !f->subwindows_changed
6052 && !f->subwindows_state_changed
5119 && !f->windows_structure_changed) 6053 && !f->windows_structure_changed)
5120 { 6054 {
5121 if (point_visible (w, pointm, CURRENT_DISP) 6055 if (point_visible (w, pointm, CURRENT_DISP)
5122 && w->last_point_x[CURRENT_DISP] != -1 6056 && w->last_point_x[CURRENT_DISP] != -1
5123 && w->last_point_y[CURRENT_DISP] != -1) 6057 && w->last_point_y[CURRENT_DISP] != -1)
5172 else if (!w->windows_changed 6106 else if (!w->windows_changed
5173 && !f->clip_changed 6107 && !f->clip_changed
5174 && !f->faces_changed 6108 && !f->faces_changed
5175 && !f->glyphs_changed 6109 && !f->glyphs_changed
5176 && !f->subwindows_changed 6110 && !f->subwindows_changed
6111 && !f->subwindows_state_changed
5177 && !f->windows_structure_changed 6112 && !f->windows_structure_changed
5178 && !f->frame_changed 6113 && !f->frame_changed
5179 && !truncation_changed 6114 && !truncation_changed
5180 && pointm >= startp 6115 && pointm >= startp
5181 && regenerate_window_incrementally (w, startp, pointm)) 6116 && regenerate_window_incrementally (w, startp, pointm))
5251 { 6186 {
5252 Bufpos start = marker_position (w->start[DESIRED_DISP]); 6187 Bufpos start = marker_position (w->start[DESIRED_DISP]);
5253 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1 6188 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
5254 ? BUF_ZV (b) 6189 ? BUF_ZV (b)
5255 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1); 6190 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
5256 6191 /* Don't pollute the cache if not sure if we are correct */
5257 update_line_start_cache (w, start, end, pointm, 1); 6192 if (w->start_at_line_beg)
6193 update_line_start_cache (w, start, end, pointm, 1);
5258 redisplay_output_window (w); 6194 redisplay_output_window (w);
5259 /* 6195 /*
5260 * If we just displayed the echo area, the line start cache is 6196 * If we just displayed the echo area, the line start cache is
5261 * no longer valid, because the minibuffer window is associated 6197 * no longer valid, because the minibuffer window is associated
5262 * with the window now. 6198 * with the window now.
5266 } 6202 }
5267 6203
5268 /* #### This should be dependent on face changes and will need to be 6204 /* #### This should be dependent on face changes and will need to be
5269 somewhere else once tty updates occur on a per-frame basis. */ 6205 somewhere else once tty updates occur on a per-frame basis. */
5270 mark_face_cachels_as_clean (w); 6206 mark_face_cachels_as_clean (w);
6207
6208 /* The glyph cachels only get dirty if someone changed something.
6209 Since redisplay has now effectively ended we can reset the dirty
6210 flag since everything must be up-to-date. */
6211 if (glyphs_changed)
6212 mark_glyph_cachels_as_clean (w);
5271 6213
5272 w->windows_changed = 0; 6214 w->windows_changed = 0;
5273 } 6215 }
5274 6216
5275 /* Call buffer_reset_changes for all buffers present in any window 6217 /* Call buffer_reset_changes for all buffers present in any window
5398 #ifdef HAVE_TOOLBARS 6340 #ifdef HAVE_TOOLBARS
5399 /* Update the toolbars. */ 6341 /* Update the toolbars. */
5400 update_frame_toolbars (f); 6342 update_frame_toolbars (f);
5401 #endif /* HAVE_TOOLBARS */ 6343 #endif /* HAVE_TOOLBARS */
5402 6344
6345 /* If we clear the frame we have to force its contents to be redrawn. */
6346 if (f->clear)
6347 f->frame_changed = 1;
6348
6349 /* invalidate the subwindow cache. We use subwindows_changed here to
6350 cause subwindows to get instantiated. This is because
6351 subwindows_state_changed is less strict - dealing with things
6352 like the clicked state of button. We have to do this before
6353 redisplaying the gutters as subwindows get unmapped in the
6354 process.*/
6355 if (!Dynarr_length (f->subwindow_cachels)
6356 || f->subwindows_changed
6357 || f->faces_changed
6358 || f->frame_changed)
6359 {
6360 reset_subwindow_cachels (f);
6361 /* we have to do this so the gutter gets regenerated. */
6362 reset_gutter_display_lines (f);
6363 }
6364 else
6365 mark_subwindow_cachels_as_not_updated (f);
6366 /* We can now update the gutters, safe in the knowledge that our
6367 efforts won't get undone. */
6368 update_frame_gutters (f);
6369
5403 hold_frame_size_changes (); 6370 hold_frame_size_changes ();
5404 6371
5405 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ 6372 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
5406 /* Within this section, we are defenseless and assume that the 6373 /* Within this section, we are defenseless and assume that the
5407 following cannot happen: 6374 following cannot happen:
5424 we simply return. #### We should abort instead. 6391 we simply return. #### We should abort instead.
5425 6392
5426 #### If a frame-size change does occur we should probably 6393 #### If a frame-size change does occur we should probably
5427 actually be preempting redisplay. */ 6394 actually be preempting redisplay. */
5428 6395
5429 /* If we clear the frame we have to force its contents to be redrawn. */
5430 if (f->clear)
5431 f->frame_changed = 1;
5432
5433 /* Erase the frame before outputting its contents. */ 6396 /* Erase the frame before outputting its contents. */
5434 if (f->clear) 6397 if (f->clear)
5435 { 6398 {
5436 DEVMETH (d, clear_frame, (f)); 6399 DEVMETH (d, clear_frame, (f));
5437 } 6400 }
5438
5439 /* invalidate the subwindow cache. we are going to reuse the glyphs
5440 flag here to cause subwindows to get instantiated. This is
5441 because subwindows changed is less strict - dealing with things
5442 like the clicked state of button. */
5443 if (!Dynarr_length (f->subwindow_cachels)
5444 || f->glyphs_changed
5445 || f->frame_changed)
5446 reset_subwindow_cachels (f);
5447 else
5448 mark_subwindow_cachels_as_not_updated (f);
5449 6401
5450 /* Do the selected window first. */ 6402 /* Do the selected window first. */
5451 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); 6403 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
5452 6404
5453 /* Then do the rest. */ 6405 /* Then do the rest. */
5459 if (FRAME_TTY_P (f)) 6411 if (FRAME_TTY_P (f))
5460 DEVMETH (d, output_end, (d)); 6412 DEVMETH (d, output_end, (d));
5461 6413
5462 update_frame_title (f); 6414 update_frame_title (f);
5463 6415
5464 f->buffers_changed = 0; 6416 CLASS_RESET_CHANGED_FLAGS (f);
5465 f->clip_changed = 0;
5466 f->extents_changed = 0;
5467 f->faces_changed = 0;
5468 f->frame_changed = 0;
5469 f->glyphs_changed = 0;
5470 f->subwindows_changed = 0;
5471 f->icon_changed = 0;
5472 f->menubar_changed = 0;
5473 f->modeline_changed = 0;
5474 f->point_changed = 0;
5475 f->toolbar_changed = 0;
5476 f->windows_changed = 0;
5477 f->windows_structure_changed = 0;
5478 f->window_face_cache_reset = 0; 6417 f->window_face_cache_reset = 0;
5479 f->echo_area_garbaged = 0; 6418 f->echo_area_garbaged = 0;
5480
5481 f->clear = 0; 6419 f->clear = 0;
5482 6420
5483 if (!f->size_change_pending) 6421 if (!f->size_change_pending)
5484 f->size_changed = 0; 6422 f->size_changed = 0;
5485 6423
5492 6430
5493 map_windows (f, call_redisplay_end_triggers, 0); 6431 map_windows (f, call_redisplay_end_triggers, 0);
5494 return 0; 6432 return 0;
5495 } 6433 }
5496 6434
5497 /* Ensure that all frames on the given device are correctly displayed. */ 6435 /* Ensure that all frames on the given device are correctly displayed.
6436 If AUTOMATIC is non-zero, and the device implementation indicates
6437 no automatic redisplay, as printers do, then the device is not
6438 redisplayed. AUTOMATIC is set to zero when called from lisp
6439 functions (redraw-device) and (redisplay-device), and to non-zero
6440 when called from "lazy" redisplay();
6441 */
5498 6442
5499 static int 6443 static int
5500 redisplay_device (struct device *d) 6444 redisplay_device (struct device *d, int automatic)
5501 { 6445 {
5502 Lisp_Object frame, frmcons; 6446 Lisp_Object frame, frmcons;
5503 int preempted = 0; 6447 int preempted = 0;
5504 int size_change_failed = 0; 6448 int size_change_failed = 0;
5505 struct frame *f; 6449 struct frame *f;
6450
6451 if (automatic
6452 && (MAYBE_INT_DEVMETH (d, device_implementation_flags, ())
6453 & XDEVIMPF_NO_AUTO_REDISPLAY))
6454 return 0;
5506 6455
5507 if (DEVICE_STREAM_P (d)) /* nothing to do */ 6456 if (DEVICE_STREAM_P (d)) /* nothing to do */
5508 return 0; 6457 return 0;
5509 6458
5510 /* It is possible that redisplay has been called before the 6459 /* It is possible that redisplay has been called before the
5525 if (f->icon_changed || f->windows_changed) 6474 if (f->icon_changed || f->windows_changed)
5526 update_frame_icon (f); 6475 update_frame_icon (f);
5527 6476
5528 if (FRAME_REPAINT_P (f)) 6477 if (FRAME_REPAINT_P (f))
5529 { 6478 {
5530 if (f->buffers_changed || f->clip_changed || f->extents_changed || 6479 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
5531 f->faces_changed || f->frame_changed || f->menubar_changed ||
5532 f->modeline_changed || f->point_changed || f->size_changed ||
5533 f->toolbar_changed || f->windows_changed || f->size_slipped ||
5534 f->windows_structure_changed || f->glyphs_changed || f->subwindows_changed)
5535 { 6480 {
5536 preempted = redisplay_frame (f, 0); 6481 preempted = redisplay_frame (f, 0);
5537 } 6482 }
5538 6483
5539 if (preempted) 6484 if (preempted)
5559 if (f->icon_changed || f->windows_changed) 6504 if (f->icon_changed || f->windows_changed)
5560 update_frame_icon (f); 6505 update_frame_icon (f);
5561 6506
5562 if (FRAME_REPAINT_P (f)) 6507 if (FRAME_REPAINT_P (f))
5563 { 6508 {
5564 if (f->buffers_changed || f->clip_changed || f->extents_changed || 6509 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
5565 f->faces_changed || f->frame_changed || f->menubar_changed ||
5566 f->modeline_changed || f->point_changed || f->size_changed ||
5567 f->toolbar_changed || f->windows_changed ||
5568 f->windows_structure_changed ||
5569 f->glyphs_changed || f->subwindows_changed)
5570 { 6510 {
5571 preempted = redisplay_frame (f, 0); 6511 preempted = redisplay_frame (f, 0);
5572 } 6512 }
5573 6513
5574 if (preempted) 6514 if (preempted)
5579 } 6519 }
5580 } 6520 }
5581 6521
5582 /* If we get here then we redisplayed all of our frames without 6522 /* If we get here then we redisplayed all of our frames without
5583 getting preempted so mark ourselves as clean. */ 6523 getting preempted so mark ourselves as clean. */
5584 d->buffers_changed = 0; 6524 CLASS_RESET_CHANGED_FLAGS (d);
5585 d->clip_changed = 0;
5586 d->extents_changed = 0;
5587 d->faces_changed = 0;
5588 d->frame_changed = 0;
5589 d->glyphs_changed = 0;
5590 d->subwindows_changed = 0;
5591 d->icon_changed = 0;
5592 d->menubar_changed = 0;
5593 d->modeline_changed = 0;
5594 d->point_changed = 0;
5595 d->toolbar_changed = 0;
5596 d->windows_changed = 0;
5597 d->windows_structure_changed = 0;
5598 6525
5599 if (!size_change_failed) 6526 if (!size_change_failed)
5600 d->size_changed = 0; 6527 d->size_changed = 0;
5601 6528
5602 return 0; 6529 return 0;
5627 } 6554 }
5628 6555
5629 if (asynch_device_change_pending) 6556 if (asynch_device_change_pending)
5630 handle_asynch_device_change (); 6557 handle_asynch_device_change ();
5631 6558
5632 if (!buffers_changed && !clip_changed && !extents_changed && 6559 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
5633 !faces_changed && !frame_changed && !icon_changed && 6560 !disable_preemption && preemption_count < max_preempts)
5634 !menubar_changed && !modeline_changed && !point_changed &&
5635 !size_changed && !toolbar_changed && !windows_changed &&
5636 !glyphs_changed && !subwindows_changed &&
5637 !windows_structure_changed && !disable_preemption &&
5638 preemption_count < max_preempts)
5639 goto done; 6561 goto done;
5640 6562
5641 DEVICE_LOOP_NO_BREAK (devcons, concons) 6563 DEVICE_LOOP_NO_BREAK (devcons, concons)
5642 { 6564 {
5643 struct device *d = XDEVICE (XCAR (devcons)); 6565 struct device *d = XDEVICE (XCAR (devcons));
5644 int preempted; 6566 int preempted;
5645 6567
5646 if (d->buffers_changed || d->clip_changed || d->extents_changed || 6568 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d))
5647 d->faces_changed || d->frame_changed || d->icon_changed || 6569 {
5648 d->menubar_changed || d->modeline_changed || d->point_changed || 6570 preempted = redisplay_device (d, 1);
5649 d->size_changed || d->toolbar_changed || d->windows_changed ||
5650 d->windows_structure_changed ||
5651 d->glyphs_changed || d->subwindows_changed)
5652 {
5653 preempted = redisplay_device (d);
5654 6571
5655 if (preempted) 6572 if (preempted)
5656 { 6573 {
5657 preemption_count++; 6574 preemption_count++;
5658 RESET_CHANGED_SET_FLAGS; 6575 RESET_CHANGED_SET_FLAGS;
5665 } 6582 }
5666 } 6583 }
5667 preemption_count = 0; 6584 preemption_count = 0;
5668 6585
5669 /* Mark redisplay as accurate */ 6586 /* Mark redisplay as accurate */
5670 buffers_changed = 0; 6587 GLOBAL_RESET_CHANGED_FLAGS;
5671 clip_changed = 0;
5672 extents_changed = 0;
5673 frame_changed = 0;
5674 glyphs_changed = 0;
5675 subwindows_changed = 0;
5676 icon_changed = 0;
5677 menubar_changed = 0;
5678 modeline_changed = 0;
5679 point_changed = 0;
5680 toolbar_changed = 0;
5681 windows_changed = 0;
5682 windows_structure_changed = 0;
5683 RESET_CHANGED_SET_FLAGS; 6588 RESET_CHANGED_SET_FLAGS;
5684 6589
5685 if (faces_changed) 6590 if (faces_changed)
5686 { 6591 {
5687 mark_all_faces_as_clean (); 6592 mark_all_faces_as_clean ();
5774 6679
5775 static void 6680 static void
5776 decode_mode_spec (struct window *w, Emchar spec, int type) 6681 decode_mode_spec (struct window *w, Emchar spec, int type)
5777 { 6682 {
5778 Lisp_Object obj = Qnil; 6683 Lisp_Object obj = Qnil;
5779 CONST char *str = NULL; 6684 const char *str = NULL;
5780 struct buffer *b = XBUFFER (w->buffer); 6685 struct buffer *b = XBUFFER (w->buffer);
5781 6686
5782 Dynarr_reset (mode_spec_bufbyte_string); 6687 Dynarr_reset (mode_spec_bufbyte_string);
5783 6688
5784 switch (spec) 6689 switch (spec)
5803 char buf[32]; 6708 char buf[32];
5804 6709
5805 long_to_string (buf, col); 6710 long_to_string (buf, col);
5806 6711
5807 Dynarr_add_many (mode_spec_bufbyte_string, 6712 Dynarr_add_many (mode_spec_bufbyte_string,
5808 (CONST Bufbyte *) buf, strlen (buf)); 6713 (const Bufbyte *) buf, strlen (buf));
5809 6714
5810 goto decode_mode_spec_done; 6715 goto decode_mode_spec_done;
5811 } 6716 }
5812 /* print the file coding system */ 6717 /* print the file coding system */
5813 case 'C': 6718 case 'C':
5908 6813
5909 /* print percent of buffer above top of window, or Top, Bot or All */ 6814 /* print percent of buffer above top of window, or Top, Bot or All */
5910 case 'p': 6815 case 'p':
5911 { 6816 {
5912 Bufpos pos = marker_position (w->start[type]); 6817 Bufpos pos = marker_position (w->start[type]);
5913 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5914 6818
5915 /* This had better be while the desired lines are being done. */ 6819 /* This had better be while the desired lines are being done. */
5916 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) 6820 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
5917 { 6821 {
5918 if (pos <= BUF_BEGV (b)) 6822 if (pos <= BUF_BEGV (b))
5925 else 6829 else
5926 { 6830 {
5927 /* This hard limit is ok since the string it will hold has a 6831 /* This hard limit is ok since the string it will hold has a
5928 fixed maximum length of 3. But just to be safe... */ 6832 fixed maximum length of 3. But just to be safe... */
5929 char buf[10]; 6833 char buf[10];
5930 6834 Charcount chars = pos - BUF_BEGV (b);
5931 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total; 6835 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6836
6837 /* Avoid overflow on big buffers */
6838 int percent = total > LONG_MAX/200 ?
6839 (chars + total/200) / (total / 100) :
6840 (chars * 100 + total/2) / total;
5932 6841
5933 /* We can't normally display a 3-digit number, so get us a 6842 /* We can't normally display a 3-digit number, so get us a
5934 2-digit number that is close. */ 6843 2-digit number that is close. */
5935 if (total == 100) 6844 if (percent == 100)
5936 total = 99; 6845 percent = 99;
5937 6846
5938 sprintf (buf, "%2d%%", total); 6847 sprintf (buf, "%d%%", percent);
5939 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, 6848 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5940 strlen (buf)); 6849 strlen (buf));
5941 6850
5942 goto decode_mode_spec_done; 6851 goto decode_mode_spec_done;
5943 } 6852 }
5948 Top, or print Bottom or All */ 6857 Top, or print Bottom or All */
5949 case 'P': 6858 case 'P':
5950 { 6859 {
5951 Bufpos toppos = marker_position (w->start[type]); 6860 Bufpos toppos = marker_position (w->start[type]);
5952 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type]; 6861 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
5953 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5954 6862
5955 /* botpos is only accurate as of the last redisplay, so we can 6863 /* botpos is only accurate as of the last redisplay, so we can
5956 only treat it as a hint. In particular, after erase-buffer, 6864 only treat it as a hint. In particular, after erase-buffer,
5957 botpos may be negative. */ 6865 botpos may be negative. */
5958 if (botpos < toppos) 6866 if (botpos < toppos)
5968 else 6876 else
5969 { 6877 {
5970 /* This hard limit is ok since the string it will hold has a 6878 /* This hard limit is ok since the string it will hold has a
5971 fixed maximum length of around 6. But just to be safe... */ 6879 fixed maximum length of around 6. But just to be safe... */
5972 char buf[10]; 6880 char buf[10];
5973 6881 Charcount chars = botpos - BUF_BEGV (b);
5974 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total; 6882 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6883
6884 /* Avoid overflow on big buffers */
6885 int percent = total > LONG_MAX/200 ?
6886 (chars + total/200) / (total / 100) :
6887 (chars * 100 + total/2) / max (total, 1);
5975 6888
5976 /* We can't normally display a 3-digit number, so get us a 6889 /* We can't normally display a 3-digit number, so get us a
5977 2-digit number that is close. */ 6890 2-digit number that is close. */
5978 if (total == 100) 6891 if (percent == 100)
5979 total = 99; 6892 percent = 99;
5980 6893
5981 if (toppos <= BUF_BEGV (b)) 6894 if (toppos <= BUF_BEGV (b))
5982 sprintf (buf, "Top%2d%%", total); 6895 sprintf (buf, "Top%d%%", percent);
5983 else 6896 else
5984 sprintf (buf, "%2d%%", total); 6897 sprintf (buf, "%d%%", percent);
5985 6898
5986 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, 6899 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5987 strlen (buf)); 6900 strlen (buf));
5988 6901
5989 goto decode_mode_spec_done; 6902 goto decode_mode_spec_done;
6082 6995
6083 6996
6084 /* Given an array of display lines, free them and all data structures 6997 /* Given an array of display lines, free them and all data structures
6085 contained within them. */ 6998 contained within them. */
6086 6999
6087 static void 7000 void
6088 free_display_lines (display_line_dynarr *dla) 7001 free_display_lines (display_line_dynarr *dla)
6089 { 7002 {
6090 int line; 7003 int line;
6091 7004
6092 for (line = 0; line < Dynarr_largest (dla); line++) 7005 for (line = 0; line < Dynarr_largest (dla); line++)
6115 } 7028 }
6116 } 7029 }
6117 7030
6118 7031
6119 static void 7032 static void
6120 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object)) 7033 mark_glyph_block_dynarr (glyph_block_dynarr *gba)
6121 { 7034 {
6122 if (gba) 7035 if (gba)
6123 { 7036 {
6124 glyph_block *gb = Dynarr_atp (gba, 0); 7037 glyph_block *gb = Dynarr_atp (gba, 0);
6125 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba)); 7038 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
6126 7039
6127 for (; gb < gb_last; gb++) 7040 for (; gb < gb_last; gb++)
6128 { 7041 {
6129 if (!NILP (gb->glyph)) 7042 if (!NILP (gb->glyph))
6130 markobj (gb->glyph); 7043 mark_object (gb->glyph);
6131 if (!NILP (gb->extent)) 7044 if (!NILP (gb->extent))
6132 markobj (gb->extent); 7045 mark_object (gb->extent);
6133 } 7046 }
6134 } 7047 }
6135 } 7048 }
6136 7049
6137 static void 7050 static void
6138 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object)) 7051 mark_redisplay_structs (display_line_dynarr *dla)
6139 { 7052 {
6140 display_line *dl = Dynarr_atp (dla, 0); 7053 display_line *dl = Dynarr_atp (dla, 0);
6141 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla)); 7054 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
6142 7055
6143 for (; dl < dl_last; dl++) 7056 for (; dl < dl_last; dl++)
6155 for (; r < r_last; r++) 7068 for (; r < r_last; r++)
6156 { 7069 {
6157 if (r->type == RUNE_DGLYPH) 7070 if (r->type == RUNE_DGLYPH)
6158 { 7071 {
6159 if (!NILP (r->object.dglyph.glyph)) 7072 if (!NILP (r->object.dglyph.glyph))
6160 markobj (r->object.dglyph.glyph); 7073 mark_object (r->object.dglyph.glyph);
6161 if (!NILP (r->object.dglyph.extent)) 7074 if (!NILP (r->object.dglyph.extent))
6162 markobj (r->object.dglyph.extent); 7075 mark_object (r->object.dglyph.extent);
6163 } 7076 }
6164 } 7077 }
6165 } 7078 }
6166 7079
6167 mark_glyph_block_dynarr (dl->left_glyphs, markobj); 7080 mark_glyph_block_dynarr (dl->left_glyphs);
6168 mark_glyph_block_dynarr (dl->right_glyphs, markobj); 7081 mark_glyph_block_dynarr (dl->right_glyphs);
6169 } 7082 }
6170 } 7083 }
6171 7084
6172 static void 7085 static void
6173 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object)) 7086 mark_window_mirror (struct window_mirror *mir)
6174 { 7087 {
6175 mark_redisplay_structs (mir->current_display_lines, markobj); 7088 mark_redisplay_structs (mir->current_display_lines);
6176 mark_redisplay_structs (mir->desired_display_lines, markobj); 7089 mark_redisplay_structs (mir->desired_display_lines);
6177 7090
6178 if (mir->next) 7091 if (mir->next)
6179 mark_window_mirror (mir->next, markobj); 7092 mark_window_mirror (mir->next);
6180 7093
6181 if (mir->hchild) 7094 if (mir->hchild)
6182 mark_window_mirror (mir->hchild, markobj); 7095 mark_window_mirror (mir->hchild);
6183 else if (mir->vchild) 7096 else if (mir->vchild)
6184 mark_window_mirror (mir->vchild, markobj); 7097 mark_window_mirror (mir->vchild);
6185 } 7098 }
6186 7099
6187 void 7100 void
6188 mark_redisplay (void (*markobj)(Lisp_Object)) 7101 mark_redisplay (void)
6189 { 7102 {
6190 Lisp_Object frmcons, devcons, concons; 7103 Lisp_Object frmcons, devcons, concons;
6191 7104
6192 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) 7105 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6193 { 7106 {
6194 struct frame *f = XFRAME (XCAR (frmcons)); 7107 struct frame *f = XFRAME (XCAR (frmcons));
6195 update_frame_window_mirror (f); 7108 update_frame_window_mirror (f);
6196 mark_window_mirror (f->root_mirror, markobj); 7109 mark_window_mirror (f->root_mirror);
6197 } 7110 }
6198 } 7111 }
6199 7112
6200 /***************************************************************************** 7113 /*****************************************************************************
6201 Line Start Cache Description and Rationale 7114 Line Start Cache Description and Rationale
6255 applicable. 7168 applicable.
6256 ****************************************************************************/ 7169 ****************************************************************************/
6257 7170
6258 /* This will get used quite a bit so we don't want to be constantly 7171 /* This will get used quite a bit so we don't want to be constantly
6259 allocating and freeing it. */ 7172 allocating and freeing it. */
6260 line_start_cache_dynarr *internal_cache; 7173 static line_start_cache_dynarr *internal_cache;
6261 7174
6262 /* Makes internal_cache represent the TYPE display structs and only 7175 /* Makes internal_cache represent the TYPE display structs and only
6263 the TYPE display structs. */ 7176 the TYPE display structs. */
6264 7177
6265 static void 7178 static void
6549 7462
6550 int 7463 int
6551 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point) 7464 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
6552 { 7465 {
6553 struct buffer *b = XBUFFER (w->buffer); 7466 struct buffer *b = XBUFFER (w->buffer);
6554 int pixpos = 0; 7467 int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
6555 int bottom = WINDOW_TEXT_HEIGHT (w); 7468 int bottom = WINDOW_TEXT_HEIGHT (w);
6556 int start_elt; 7469 int start_elt;
6557 7470
6558 /* If point is before the intended start it obviously can't be visible. */ 7471 /* If point is before the intended start it obviously can't be visible. */
6559 if (point < startp) 7472 if (point < startp)
6774 else 7687 else
6775 return cur_pos; 7688 return cur_pos;
6776 } 7689 }
6777 7690
6778 cur_elt--; 7691 cur_elt--;
6779 if (cur_elt < 0) 7692 while (cur_elt < 0)
6780 { 7693 {
6781 Bufpos from, to; 7694 Bufpos from, to;
6782 int win_char_height; 7695 int win_char_height;
6783 7696
6784 if (cur_pos <= BUF_BEGV (b)) 7697 if (cur_pos <= BUF_BEGV (b))
6794 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); 7707 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
6795 to = line_start_cache_end (w); 7708 to = line_start_cache_end (w);
6796 update_line_start_cache (w, from, to, point, 0); 7709 update_line_start_cache (w, from, to, point, 0);
6797 7710
6798 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; 7711 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
6799 assert (cur_elt >= 0); 7712 assert (cur_elt >= -1);
7713 /* This used to be cur_elt>=0 under the assumption that if
7714 point is in the top line and not at BUF_BEGV, then
7715 setting the window_start to a newline before the start of
7716 the first line will always cause scrolling.
7717
7718 However in my (jv) opinion this is wrong. That new line
7719 can be hidden in various ways: invisible extents, an
7720 explicit window-start not at a newline character etc.
7721 The existence of those are indeed known to create crashes
7722 on that assert. So we have no option but to continue the
7723 search if we found point at the top of the line_start_cache
7724 again. */
7725 cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
6800 } 7726 }
6801 prev_pos = cur_pos; 7727 prev_pos = cur_pos;
6802 } 7728 }
6803 } 7729 }
6804 7730
8011 8937
8012 DEVICE_FRAME_LOOP (frmcons, d) 8938 DEVICE_FRAME_LOOP (frmcons, d)
8013 { 8939 {
8014 XFRAME (XCAR (frmcons))->clear = 1; 8940 XFRAME (XCAR (frmcons))->clear = 1;
8015 } 8941 }
8016 redisplay_device (d); 8942 redisplay_device (d, 0);
8017 8943
8018 return unbind_to (count, Qnil); 8944 return unbind_to (count, Qnil);
8019 } 8945 }
8020 8946
8021 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* 8947 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8038 record_unwind_protect (restore_disable_preemption_value, 8964 record_unwind_protect (restore_disable_preemption_value,
8039 make_int (disable_preemption)); 8965 make_int (disable_preemption));
8040 disable_preemption++; 8966 disable_preemption++;
8041 } 8967 }
8042 8968
8043 redisplay_device (d); 8969 redisplay_device (d, 0);
8044 8970
8045 return unbind_to (count, Qnil); 8971 return unbind_to (count, Qnil);
8046 } 8972 }
8047 8973
8048 /* Big lie. Big lie. This will force all modelines to be updated 8974 /* Big lie. Big lie. This will force all modelines to be updated
8090 global_redisplay_change. */ 9016 global_redisplay_change. */
8091 MARK_CLIP_CHANGED; 9017 MARK_CLIP_CHANGED;
8092 return 0; 9018 return 0;
8093 } 9019 }
8094 9020
9021 /* This is called if the built-in glyphs have their properties
9022 changed. */
8095 void 9023 void
8096 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property, 9024 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8097 Lisp_Object locale) 9025 Lisp_Object locale)
8098 { 9026 {
8099 if (WINDOWP (locale)) 9027 if (WINDOWP (locale))
8212 { 9140 {
8213 disable_preemption = 0; 9141 disable_preemption = 0;
8214 preemption_count = 0; 9142 preemption_count = 0;
8215 max_preempts = INIT_MAX_PREEMPTS; 9143 max_preempts = INIT_MAX_PREEMPTS;
8216 9144
9145 #ifndef PDUMP
8217 if (!initialized) 9146 if (!initialized)
8218 { 9147 #endif
8219 cmotion_display_lines = Dynarr_new (display_line); 9148 {
8220 mode_spec_bufbyte_string = Dynarr_new (Bufbyte); 9149 if (!cmotion_display_lines)
8221 formatted_string_emchar_dynarr = Dynarr_new (Emchar); 9150 cmotion_display_lines = Dynarr_new (display_line);
8222 formatted_string_extent_dynarr = Dynarr_new (EXTENT); 9151 if (!mode_spec_bufbyte_string)
8223 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); 9152 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
8224 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); 9153 if (!formatted_string_extent_dynarr)
8225 internal_cache = Dynarr_new (line_start_cache); 9154 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
8226 xzero (formatted_string_display_line); 9155 if (!formatted_string_extent_start_dynarr)
9156 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
9157 if (!formatted_string_extent_end_dynarr)
9158 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
9159 if (!internal_cache)
9160 internal_cache = Dynarr_new (line_start_cache);
8227 } 9161 }
8228 9162
8229 /* window system is nil when in -batch mode */ 9163 /* window system is nil when in -batch mode */
8230 if (!initialized || noninteractive) 9164 if (!initialized || noninteractive)
8231 return; 9165 return;
8292 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook"); 9226 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
8293 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook"); 9227 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
8294 #endif /* INHIBIT_REDISPLAY_HOOKS */ 9228 #endif /* INHIBIT_REDISPLAY_HOOKS */
8295 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer"); 9229 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
8296 defsymbol (&Qbar_cursor, "bar-cursor"); 9230 defsymbol (&Qbar_cursor, "bar-cursor");
8297 defsymbol (&Qwindow_scroll_functions, "window-scroll-functions");
8298 defsymbol (&Qredisplay_end_trigger_functions, 9231 defsymbol (&Qredisplay_end_trigger_functions,
8299 "redisplay-end-trigger-functions"); 9232 "redisplay-end-trigger-functions");
8300 9233
8301 DEFSUBR (Fredisplay_echo_area); 9234 DEFSUBR (Fredisplay_echo_area);
8302 DEFSUBR (Fredraw_frame); 9235 DEFSUBR (Fredraw_frame);
8306 DEFSUBR (Fredraw_modeline); 9239 DEFSUBR (Fredraw_modeline);
8307 DEFSUBR (Fforce_cursor_redisplay); 9240 DEFSUBR (Fforce_cursor_redisplay);
8308 } 9241 }
8309 9242
8310 void 9243 void
9244 reinit_vars_of_redisplay (void)
9245 {
9246 updating_line_start_cache = 0;
9247 }
9248
9249 void
8311 vars_of_redisplay (void) 9250 vars_of_redisplay (void)
8312 { 9251 {
9252 reinit_vars_of_redisplay ();
9253
8313 #if 0 9254 #if 0
8314 staticpro (&last_arrow_position); 9255 staticpro (&last_arrow_position);
8315 staticpro (&last_arrow_string); 9256 staticpro (&last_arrow_string);
8316 last_arrow_position = Qnil; 9257 last_arrow_position = Qnil;
8317 last_arrow_string = Qnil; 9258 last_arrow_string = Qnil;
8318 #endif /* 0 */ 9259 #endif /* 0 */
8319
8320 updating_line_start_cache = 0;
8321 9260
8322 /* #### Probably temporary */ 9261 /* #### Probably temporary */
8323 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* 9262 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
8324 \(Temporary) Setting this will impact the performance of the internal 9263 \(Temporary) Setting this will impact the performance of the internal
8325 line start cache. 9264 line start cache.
8401 instead. 9340 instead.
8402 */ ); 9341 */ );
8403 Vwindow_system = Qnil; 9342 Vwindow_system = Qnil;
8404 9343
8405 /* #### Temporary shit until window-system is eliminated. */ 9344 /* #### Temporary shit until window-system is eliminated. */
8406 DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /* 9345 DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /*
8407 DON'T TOUCH 9346 DON'T TOUCH
8408 */ ); 9347 */ );
8409 Vinitial_window_system = Qnil; 9348 Vinitial_window_system = Qnil;
8410 9349
8411 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* 9350 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
8500 This is a specifier; use `set-specifier' to change it. 9439 This is a specifier; use `set-specifier' to change it.
8501 */ ); 9440 */ );
8502 Vleft_margin_width = Fmake_specifier (Qnatnum); 9441 Vleft_margin_width = Fmake_specifier (Qnatnum);
8503 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); 9442 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
8504 set_specifier_caching (Vleft_margin_width, 9443 set_specifier_caching (Vleft_margin_width,
8505 slot_offset (struct window, left_margin_width), 9444 offsetof (struct window, left_margin_width),
8506 some_window_value_changed, 9445 some_window_value_changed,
8507 slot_offset (struct frame, left_margin_width), 9446 offsetof (struct frame, left_margin_width),
8508 margin_width_changed_in_frame); 9447 margin_width_changed_in_frame);
8509 9448
8510 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* 9449 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
8511 *Width of right margin. 9450 *Width of right margin.
8512 This is a specifier; use `set-specifier' to change it. 9451 This is a specifier; use `set-specifier' to change it.
8513 */ ); 9452 */ );
8514 Vright_margin_width = Fmake_specifier (Qnatnum); 9453 Vright_margin_width = Fmake_specifier (Qnatnum);
8515 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); 9454 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
8516 set_specifier_caching (Vright_margin_width, 9455 set_specifier_caching (Vright_margin_width,
8517 slot_offset (struct window, right_margin_width), 9456 offsetof (struct window, right_margin_width),
8518 some_window_value_changed, 9457 some_window_value_changed,
8519 slot_offset (struct frame, right_margin_width), 9458 offsetof (struct frame, right_margin_width),
8520 margin_width_changed_in_frame); 9459 margin_width_changed_in_frame);
8521 9460
8522 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* 9461 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
8523 *Minimum ascent height of lines. 9462 *Minimum ascent height of lines.
8524 This is a specifier; use `set-specifier' to change it. 9463 This is a specifier; use `set-specifier' to change it.
8525 */ ); 9464 */ );
8526 Vminimum_line_ascent = Fmake_specifier (Qnatnum); 9465 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
8527 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); 9466 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
8528 set_specifier_caching (Vminimum_line_ascent, 9467 set_specifier_caching (Vminimum_line_ascent,
8529 slot_offset (struct window, minimum_line_ascent), 9468 offsetof (struct window, minimum_line_ascent),
8530 some_window_value_changed, 9469 some_window_value_changed,
8531 0, 0); 9470 0, 0);
8532 9471
8533 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* 9472 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
8534 *Minimum descent height of lines. 9473 *Minimum descent height of lines.
8535 This is a specifier; use `set-specifier' to change it. 9474 This is a specifier; use `set-specifier' to change it.
8536 */ ); 9475 */ );
8537 Vminimum_line_descent = Fmake_specifier (Qnatnum); 9476 Vminimum_line_descent = Fmake_specifier (Qnatnum);
8538 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); 9477 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
8539 set_specifier_caching (Vminimum_line_descent, 9478 set_specifier_caching (Vminimum_line_descent,
8540 slot_offset (struct window, minimum_line_descent), 9479 offsetof (struct window, minimum_line_descent),
8541 some_window_value_changed, 9480 some_window_value_changed,
8542 0, 0); 9481 0, 0);
8543 9482
8544 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* 9483 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
8545 *Non-nil means use the left outside margin as extra whitespace when 9484 *Non-nil means use the left outside margin as extra whitespace when
8547 This is a specifier; use `set-specifier' to change it. 9486 This is a specifier; use `set-specifier' to change it.
8548 */ ); 9487 */ );
8549 Vuse_left_overflow = Fmake_specifier (Qboolean); 9488 Vuse_left_overflow = Fmake_specifier (Qboolean);
8550 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); 9489 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
8551 set_specifier_caching (Vuse_left_overflow, 9490 set_specifier_caching (Vuse_left_overflow,
8552 slot_offset (struct window, use_left_overflow), 9491 offsetof (struct window, use_left_overflow),
8553 some_window_value_changed, 9492 some_window_value_changed,
8554 0, 0); 9493 0, 0);
8555 9494
8556 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* 9495 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
8557 *Non-nil means use the right outside margin as extra whitespace when 9496 *Non-nil means use the right outside margin as extra whitespace when
8559 This is a specifier; use `set-specifier' to change it. 9498 This is a specifier; use `set-specifier' to change it.
8560 */ ); 9499 */ );
8561 Vuse_right_overflow = Fmake_specifier (Qboolean); 9500 Vuse_right_overflow = Fmake_specifier (Qboolean);
8562 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); 9501 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
8563 set_specifier_caching (Vuse_right_overflow, 9502 set_specifier_caching (Vuse_right_overflow,
8564 slot_offset (struct window, use_right_overflow), 9503 offsetof (struct window, use_right_overflow),
8565 some_window_value_changed, 9504 some_window_value_changed,
8566 0, 0); 9505 0, 0);
8567 9506
8568 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* 9507 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
8569 *Non-nil means the text cursor is visible (this is usually the case). 9508 *Non-nil means the text cursor is visible (this is usually the case).
8570 This is a specifier; use `set-specifier' to change it. 9509 This is a specifier; use `set-specifier' to change it.
8571 */ ); 9510 */ );
8572 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); 9511 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
8573 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); 9512 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
8574 set_specifier_caching (Vtext_cursor_visible_p, 9513 set_specifier_caching (Vtext_cursor_visible_p,
8575 slot_offset (struct window, text_cursor_visible_p), 9514 offsetof (struct window, text_cursor_visible_p),
8576 text_cursor_visible_p_changed, 9515 text_cursor_visible_p_changed,
8577 0, 0); 9516 0, 0);
8578 9517
8579 } 9518 }