Mercurial > hg > xemacs-beta
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 } |