Mercurial > hg > xemacs-beta
comparison src/redisplay.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | 95016f13131a |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
38 Third: It Is Better To Be Fast Than Not To Be | 38 Third: It Is Better To Be Fast Than Not To Be |
39 ****************************************************************************/ | 39 ****************************************************************************/ |
40 | 40 |
41 #include <config.h> | 41 #include <config.h> |
42 #include "lisp.h" | 42 #include "lisp.h" |
43 #include <limits.h> | |
43 | 44 |
44 #include "buffer.h" | 45 #include "buffer.h" |
45 #include "commands.h" | 46 #include "commands.h" |
46 #include "debug.h" | 47 #include "debug.h" |
47 #include "device.h" | 48 #include "device.h" |
48 #include "elhash.h" | 49 #include "elhash.h" |
49 #include "extents.h" | 50 #include "extents.h" |
50 #include "faces.h" | 51 #include "faces.h" |
51 #include "frame.h" | 52 #include "frame.h" |
52 #include "glyphs.h" | 53 #include "glyphs.h" |
53 #include "gutter.h" | |
54 #include "insdel.h" | 54 #include "insdel.h" |
55 #include "menubar.h" | 55 #include "menubar.h" |
56 #include "objects.h" | 56 #include "objects.h" |
57 #include "process.h" | 57 #include "process.h" |
58 #include "redisplay.h" | 58 #include "redisplay.h" |
61 #include "line-number.h" | 61 #include "line-number.h" |
62 #ifdef FILE_CODING | 62 #ifdef FILE_CODING |
63 #include "file-coding.h" | 63 #include "file-coding.h" |
64 #endif | 64 #endif |
65 | 65 |
66 #include "sysfile.h" | |
67 | |
68 #ifdef HAVE_TTY | 66 #ifdef HAVE_TTY |
69 #include "console-tty.h" | 67 #include "console-tty.h" |
68 #ifdef HAVE_UNISTD_H | |
69 #include <unistd.h> /* for isatty() */ | |
70 #endif | |
70 #endif /* HAVE_TTY */ | 71 #endif /* HAVE_TTY */ |
71 | 72 |
72 /* Note: We have to be careful throughout this code to properly handle | 73 /* Note: We have to be careful throughout this code to properly handle |
73 and differentiate between Bufbytes and Emchars. | 74 and differentiate between Bufbytes and Emchars. |
74 | 75 |
83 #define BEGIN_GLYPHS 0 | 84 #define BEGIN_GLYPHS 0 |
84 #define END_GLYPHS 1 | 85 #define END_GLYPHS 1 |
85 #define LEFT_GLYPHS 2 | 86 #define LEFT_GLYPHS 2 |
86 #define RIGHT_GLYPHS 3 | 87 #define RIGHT_GLYPHS 3 |
87 | 88 |
89 /* Set the vertical clip to 0 if we are currently updating the line | |
90 start cache. Otherwise for buffers of line height 1 it may fail to | |
91 be able to work properly because regenerate_window will not layout | |
92 a single line. */ | |
88 #define VERTICAL_CLIP(w, display) \ | 93 #define VERTICAL_CLIP(w, display) \ |
89 ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \ | 94 (updating_line_start_cache \ |
95 ? 0 \ | |
96 : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \ | |
90 ? INT_MAX \ | 97 ? INT_MAX \ |
91 : vertical_clip) | 98 : vertical_clip)) |
92 | 99 |
93 /* The following structures are completely private to redisplay.c so | 100 /* The following structures are completely private to redisplay.c so |
94 we put them here instead of in a header file, for modularity. */ | 101 we put them here instead of in a header file, for modularity. */ |
95 | 102 |
96 /* NOTE: Bytinds not Bufpos's in this structure. */ | 103 /* NOTE: Bytinds not Bufpos's in this structure. */ |
98 typedef struct position_redisplay_data_type | 105 typedef struct position_redisplay_data_type |
99 { | 106 { |
100 /* This information is normally filled in by the create_*_block | 107 /* This information is normally filled in by the create_*_block |
101 routines and is used by the add_*_rune routines. */ | 108 routines and is used by the add_*_rune routines. */ |
102 Lisp_Object window; | 109 Lisp_Object window; |
103 /* if we are working with strings rather than buffers we need a | |
104 handle to the string */ | |
105 Lisp_Object string; | |
106 struct device *d; | 110 struct device *d; |
107 struct display_block *db; | 111 struct display_block *db; |
108 struct display_line *dl; | 112 struct display_line *dl; |
109 Emchar ch; /* Character that is to be added. This is | 113 Emchar ch; /* Character that is to be added. This is |
110 used to communicate this information to | 114 used to communicate this information to |
144 need to be skipped. This is used for horizontal | 148 need to be skipped. This is used for horizontal |
145 scrolling, where a certain number of columns | 149 scrolling, where a certain number of columns |
146 (those off the left side of the screen) need | 150 (those off the left side of the screen) need |
147 to be skipped before anything is displayed. */ | 151 to be skipped before anything is displayed. */ |
148 Bytind bi_start_col_enabled; | 152 Bytind bi_start_col_enabled; |
149 int start_col_xoffset; /* Number of pixels that still need to | |
150 be skipped. This is used for | |
151 horizontal scrolling of glyphs, where we want | |
152 to be able to scroll over part of the glyph. */ | |
153 | 153 |
154 int hscroll_glyph_width_adjust; /* how much the width of the hscroll | 154 int hscroll_glyph_width_adjust; /* how much the width of the hscroll |
155 glyph differs from space_width (w). | 155 glyph differs from space_width (w). |
156 0 if no hscroll glyph was used, | 156 0 if no hscroll glyph was used, |
157 i.e. the window is not scrolled | 157 i.e. the window is not scrolled |
236 { | 236 { |
237 Dynarr_declare (prop_block); | 237 Dynarr_declare (prop_block); |
238 } prop_block_dynarr; | 238 } prop_block_dynarr; |
239 | 239 |
240 | 240 |
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); | |
241 static Charcount generate_fstring_runes (struct window *w, pos_data *data, | 248 static Charcount generate_fstring_runes (struct window *w, pos_data *data, |
242 Charcount pos, Charcount min_pos, | 249 Charcount pos, Charcount min_pos, |
243 Charcount max_pos, Lisp_Object elt, | 250 Charcount max_pos, Lisp_Object elt, |
244 int depth, int max_pixsize, | 251 int depth, int max_pixsize, |
245 face_index findex, int type, | 252 face_index findex, int type); |
246 Charcount *offset, | |
247 Lisp_Object cur_ext); | |
248 static prop_block_dynarr *add_glyph_rune (pos_data *data, | 253 static prop_block_dynarr *add_glyph_rune (pos_data *data, |
249 struct glyph_block *gb, | 254 struct glyph_block *gb, |
250 int pos_type, int allow_cursor, | 255 int pos_type, int allow_cursor, |
251 struct glyph_cachel *cachel); | 256 struct glyph_cachel *cachel); |
252 static Bytind create_text_block (struct window *w, struct display_line *dl, | 257 static Bytind create_text_block (struct window *w, struct display_line *dl, |
253 Bytind bi_start_pos, prop_block_dynarr **prop, | 258 Bytind bi_start_pos, int start_col, |
259 prop_block_dynarr **prop, | |
254 int type); | 260 int type); |
255 static int create_overlay_glyph_block (struct window *w, | 261 static int create_overlay_glyph_block (struct window *w, |
256 struct display_line *dl); | 262 struct display_line *dl); |
257 static void create_left_glyph_block (struct window *w, | 263 static void create_left_glyph_block (struct window *w, |
258 struct display_line *dl, | 264 struct display_line *dl, |
285 routines. We used to just give each window a third set. However, | 291 routines. We used to just give each window a third set. However, |
286 we always fully regenerate the structures when needed so there | 292 we always fully regenerate the structures when needed so there |
287 isn't any reason we need more than a single set. */ | 293 isn't any reason we need more than a single set. */ |
288 display_line_dynarr *cmotion_display_lines; | 294 display_line_dynarr *cmotion_display_lines; |
289 | 295 |
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; | |
290 /* We store the extents that we need to generate in a Dynarr and then | 300 /* We store the extents that we need to generate in a Dynarr and then |
291 frob them all on at the end of generating the string. We do it | 301 frob them all on at the end of generating the string. We do it |
292 this way rather than adding them as we generate the string because | 302 this way rather than adding them as we generate the string because |
293 we don't store the text into the resulting string until we're done | 303 we don't store the text into the resulting string until we're done |
294 (to avoid having to resize the string multiple times), and we don't | 304 (to avoid having to resize the string multiple times), and we don't |
295 want to go around adding extents to a string when the extents might | 305 want to go around adding extents to a string when the extents might |
296 stretch off the end of the string. */ | 306 stretch off the end of the string. */ |
297 static EXTENT_dynarr *formatted_string_extent_dynarr; | 307 EXTENT_dynarr *formatted_string_extent_dynarr; |
298 static Bytecount_dynarr *formatted_string_extent_start_dynarr; | 308 Bytecount_dynarr *formatted_string_extent_start_dynarr; |
299 static Bytecount_dynarr *formatted_string_extent_end_dynarr; | 309 Bytecount_dynarr *formatted_string_extent_end_dynarr; |
300 | 310 |
301 | 311 |
302 /* #### probably temporary */ | 312 /* #### probably temporary */ |
303 int cache_adjustment; | 313 int cache_adjustment; |
304 | 314 |
317 /* Minimum pixel height of clipped bottom display line. */ | 327 /* Minimum pixel height of clipped bottom display line. */ |
318 int vertical_clip; | 328 int vertical_clip; |
319 | 329 |
320 /* Minimum visible pixel width of clipped glyphs at right margin. */ | 330 /* Minimum visible pixel width of clipped glyphs at right margin. */ |
321 int horizontal_clip; | 331 int horizontal_clip; |
332 | |
333 /* Set if currently inside update_line_start_cache. */ | |
334 int updating_line_start_cache; | |
322 | 335 |
323 /* Nonzero means reading single-character input with prompt | 336 /* Nonzero means reading single-character input with prompt |
324 so put cursor on minibuffer after the prompt. */ | 337 so put cursor on minibuffer after the prompt. */ |
325 int cursor_in_echo_area; | 338 int cursor_in_echo_area; |
326 Lisp_Object Qcursor_in_echo_area; | 339 Lisp_Object Qcursor_in_echo_area; |
351 hscroll, control-arrow, etc) is in need of updating | 364 hscroll, control-arrow, etc) is in need of updating |
352 somewhere. */ | 365 somewhere. */ |
353 int glyphs_changed; | 366 int glyphs_changed; |
354 int glyphs_changed_set; | 367 int glyphs_changed_set; |
355 | 368 |
356 /* non-zero if any subwindow has been deleted. */ | 369 /* non-zero if any displayed subwindow is in need of updating |
370 somewhere. */ | |
357 int subwindows_changed; | 371 int subwindows_changed; |
358 int subwindows_changed_set; | 372 int subwindows_changed_set; |
359 | |
360 /* non-zero if any displayed subwindow is in need of updating | |
361 somewhere. */ | |
362 int subwindows_state_changed; | |
363 int subwindows_state_changed_set; | |
364 | 373 |
365 /* This variable is 1 if the icon has to be updated. | 374 /* This variable is 1 if the icon has to be updated. |
366 It is set to 1 when `frame-icon-glyph' changes. */ | 375 It is set to 1 when `frame-icon-glyph' changes. */ |
367 int icon_changed; | 376 int icon_changed; |
368 int icon_changed_set; | 377 int icon_changed_set; |
390 | 399 |
391 /* non-nil if any toolbar has changed */ | 400 /* non-nil if any toolbar has changed */ |
392 int toolbar_changed; | 401 int toolbar_changed; |
393 int toolbar_changed_set; | 402 int toolbar_changed_set; |
394 | 403 |
395 /* non-nil if any gutter has changed */ | |
396 int gutter_changed; | |
397 int gutter_changed_set; | |
398 | |
399 /* non-nil if any window has changed since the last time redisplay completed */ | 404 /* non-nil if any window has changed since the last time redisplay completed */ |
400 int windows_changed; | 405 int windows_changed; |
401 | 406 |
402 /* non-nil if any frame's window structure has changed since the last | 407 /* non-nil if any frame's window structure has changed since the last |
403 time redisplay completed */ | 408 time redisplay completed */ |
405 | 410 |
406 /* If non-nil, use vertical bar cursor. */ | 411 /* If non-nil, use vertical bar cursor. */ |
407 Lisp_Object Vbar_cursor; | 412 Lisp_Object Vbar_cursor; |
408 Lisp_Object Qbar_cursor; | 413 Lisp_Object Qbar_cursor; |
409 | 414 |
410 Lisp_Object Vvisible_bell; /* If true and the terminal will support it | 415 |
411 then the frame will flash instead of | 416 int visible_bell; /* If true and the terminal will support it |
412 beeping when an error occurs */ | 417 then the frame will flash instead of |
418 beeping when an error occurs */ | |
413 | 419 |
414 /* Nonzero means no need to redraw the entire frame on resuming | 420 /* Nonzero means no need to redraw the entire frame on resuming |
415 a suspended Emacs. This is useful on terminals with multiple pages, | 421 a suspended Emacs. This is useful on terminals with multiple pages, |
416 where one page is used for Emacs and another for all else. */ | 422 where one page is used for Emacs and another for all else. */ |
417 int no_redraw_on_reenter; | 423 int no_redraw_on_reenter; |
434 Lisp_Object Voverlay_arrow_position; | 440 Lisp_Object Voverlay_arrow_position; |
435 /* String to display for the arrow. */ | 441 /* String to display for the arrow. */ |
436 Lisp_Object Voverlay_arrow_string; | 442 Lisp_Object Voverlay_arrow_string; |
437 | 443 |
438 Lisp_Object Vwindow_size_change_functions; | 444 Lisp_Object Vwindow_size_change_functions; |
439 Lisp_Object Vwindow_scroll_functions; | 445 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; |
440 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions; | 446 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions; |
441 | |
442 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook; | |
443 | |
444 | 447 |
445 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about | 448 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about |
446 this more. */ | 449 this more. */ |
447 #ifndef INHIBIT_REDISPLAY_HOOKS | 450 #ifndef INHIBIT_REDISPLAY_HOOKS |
448 /* #### Chuck says: I think this needs more thought. | 451 /* #### Chuck says: I think this needs more thought. |
449 Think about this for 19.14. */ | 452 Think about this for 19.14. */ |
450 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook; | 453 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook; |
451 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook; | 454 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook; |
452 #endif /* INHIBIT_REDISPLAY_HOOKS */ | 455 #endif /* INHIBIT_REDISPLAY_HOOKS */ |
453 | 456 |
454 static int last_display_warning_tick, display_warning_tick; | 457 int last_display_warning_tick, display_warning_tick; |
455 Lisp_Object Qdisplay_warning_buffer; | 458 Lisp_Object Qdisplay_warning_buffer; |
456 int inhibit_warning_display; | 459 int inhibit_warning_display; |
457 | 460 |
458 Lisp_Object Vleft_margin_width, Vright_margin_width; | 461 Lisp_Object Vleft_margin_width, Vright_margin_width; |
459 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; | 462 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent; |
460 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; | 463 Lisp_Object Vuse_left_overflow, Vuse_right_overflow; |
461 Lisp_Object Vtext_cursor_visible_p; | 464 Lisp_Object Vtext_cursor_visible_p; |
462 | 465 |
463 int column_number_start_at_one; | 466 int column_number_start_at_one; |
464 | |
465 Lisp_Object Qtop_bottom; | |
466 | |
467 #define WINDOW_SCROLLED(w) \ | |
468 (w->hscroll > 0 || w->left_xoffset) | |
469 | |
470 | 467 |
471 /***************************************************************************/ | 468 /***************************************************************************/ |
472 /* */ | 469 /* */ |
473 /* low-level interfaces onto device routines */ | 470 /* low-level interfaces onto device routines */ |
474 /* */ | 471 /* */ |
634 { | 631 { |
635 int n_pos = left_pixpos; | 632 int n_pos = left_pixpos; |
636 int pix_tab_width = tab_pix_width (w); | 633 int pix_tab_width = tab_pix_width (w); |
637 | 634 |
638 /* Adjust n_pos for any hscrolling which has happened. */ | 635 /* Adjust n_pos for any hscrolling which has happened. */ |
639 if (WINDOW_SCROLLED (w)) | 636 if (w->hscroll > 1) |
640 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset; | 637 n_pos -= space_width (w) * (w->hscroll - 1); |
641 | 638 |
642 while (n_pos <= start_pixpos) | 639 while (n_pos <= start_pixpos) |
643 n_pos += pix_tab_width; | 640 n_pos += pix_tab_width; |
644 | 641 |
645 return n_pos; | 642 return n_pos; |
687 when the contents of the line reach the right boundary of the given | 684 when the contents of the line reach the right boundary of the given |
688 window. */ | 685 window. */ |
689 | 686 |
690 static Bufpos | 687 static Bufpos |
691 generate_display_line (struct window *w, struct display_line *dl, int bounds, | 688 generate_display_line (struct window *w, struct display_line *dl, int bounds, |
692 Bufpos start_pos, prop_block_dynarr **prop, | 689 Bufpos start_pos, int start_col, |
690 prop_block_dynarr **prop, | |
693 int type) | 691 int type) |
694 { | 692 { |
695 Bufpos ret_bufpos; | 693 Bufpos ret_bufpos; |
696 int overlay_width; | 694 int overlay_width; |
697 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); | 695 struct buffer *b = XBUFFER (WINDOW_BUFFER (w)); |
720 /* Create a display block for the text region of the line. */ | 718 /* Create a display block for the text region of the line. */ |
721 { | 719 { |
722 /* #### urk urk urk!!! Chuck fix this shit! */ | 720 /* #### urk urk urk!!! Chuck fix this shit! */ |
723 Bytind hacked_up_bytind = | 721 Bytind hacked_up_bytind = |
724 create_text_block (w, dl, bufpos_to_bytind (b, start_pos), | 722 create_text_block (w, dl, bufpos_to_bytind (b, start_pos), |
725 prop, type); | 723 start_col, prop, type); |
726 if (hacked_up_bytind > BI_BUF_ZV (b)) | 724 if (hacked_up_bytind > BI_BUF_ZV (b)) |
727 ret_bufpos = BUF_ZV (b) + 1; | 725 ret_bufpos = BUF_ZV (b) + 1; |
728 else | 726 else |
729 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind); | 727 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind); |
730 } | 728 } |
794 | 792 |
795 gb.extent = Qnil; | 793 gb.extent = Qnil; |
796 gb.glyph = Vhscroll_glyph; | 794 gb.glyph = Vhscroll_glyph; |
797 { | 795 { |
798 int oldpixpos = data->pixpos; | 796 int oldpixpos = data->pixpos; |
799 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, | 797 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1, |
800 GLYPH_CACHEL (XWINDOW (data->window), | 798 GLYPH_CACHEL (XWINDOW (data->window), |
801 HSCROLL_GLYPH_INDEX)); | 799 HSCROLL_GLYPH_INDEX)); |
802 data->hscroll_glyph_width_adjust = | 800 data->hscroll_glyph_width_adjust = |
803 data->pixpos - oldpixpos - space_width (XWINDOW (data->window)); | 801 data->pixpos - oldpixpos - space_width (XWINDOW (data->window)); |
804 } | 802 } |
850 struct window *w = XWINDOW (data->window); | 848 struct window *w = XWINDOW (data->window); |
851 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex); | 849 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex); |
852 Lisp_Object font_instance = | 850 Lisp_Object font_instance = |
853 ensure_face_cachel_contains_charset (cachel, data->window, | 851 ensure_face_cachel_contains_charset (cachel, data->window, |
854 charset); | 852 charset); |
855 Lisp_Font_Instance *fi; | 853 struct Lisp_Font_Instance *fi; |
856 | 854 |
857 if (EQ (font_instance, Vthe_null_font_instance)) | 855 if (EQ (font_instance, Vthe_null_font_instance)) |
858 { | 856 { |
859 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); | 857 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii); |
860 data->font_is_bogus = 1; | 858 data->font_is_bogus = 1; |
902 | 900 |
903 crb->findex = data->findex; | 901 crb->findex = data->findex; |
904 crb->xpos = data->pixpos; | 902 crb->xpos = data->pixpos; |
905 crb->width = width; | 903 crb->width = width; |
906 if (data->bi_bufpos) | 904 if (data->bi_bufpos) |
907 { | 905 crb->bufpos = |
908 if (NILP (data->string)) | 906 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))), |
909 crb->bufpos = | 907 data->bi_bufpos); |
910 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))), | |
911 data->bi_bufpos); | |
912 else | |
913 crb->bufpos = | |
914 bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos); | |
915 } | |
916 else if (data->is_modeline) | 908 else if (data->is_modeline) |
917 crb->bufpos = data->modeline_charpos; | 909 crb->bufpos = data->modeline_charpos; |
918 else | 910 else |
919 /* Text but not in buffer */ | 911 /* fuckme if this shouldn't be an abort. */ |
912 /* abort (); fuckme harder, this abort gets tripped quite often, | |
913 in propagation and whatnot. #### fixme */ | |
920 crb->bufpos = 0; | 914 crb->bufpos = 0; |
921 crb->type = RUNE_CHAR; | 915 crb->type = RUNE_CHAR; |
922 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch; | 916 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch; |
923 crb->endpos = 0; | 917 crb->endpos = 0; |
924 | 918 |
1309 dst += long_to_string_base ((char *)dst, data->ch, 16); | 1303 dst += long_to_string_base ((char *)dst, data->ch, 16); |
1310 break;*/ | 1304 break;*/ |
1311 case '%': | 1305 case '%': |
1312 dst += set_charptr_emchar (dst, '%'); | 1306 dst += set_charptr_emchar (dst, '%'); |
1313 break; | 1307 break; |
1314 /* #### unimplemented */ | |
1315 } | 1308 } |
1316 } | 1309 } |
1317 } | 1310 } |
1318 prop = add_bufbyte_string_runes (data, result, dst - result, 0); | 1311 prop = add_bufbyte_string_runes (data, result, dst - result, 0); |
1319 } | 1312 } |
1331 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) | 1324 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry) |
1332 { | 1325 { |
1333 prop_block_dynarr *prop = NULL; | 1326 prop_block_dynarr *prop = NULL; |
1334 if (VECTORP (entry)) | 1327 if (VECTORP (entry)) |
1335 { | 1328 { |
1336 Lisp_Vector *de = XVECTOR (entry); | 1329 struct Lisp_Vector *de = XVECTOR (entry); |
1337 EMACS_INT len = vector_length (de); | 1330 EMACS_INT len = vector_length (de); |
1338 int elt; | 1331 int elt; |
1339 | 1332 |
1340 for (elt = 0; elt < len; elt++) | 1333 for (elt = 0; elt < len; elt++) |
1341 { | 1334 { |
1514 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, | 1507 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, |
1515 int allow_cursor, struct glyph_cachel *cachel) | 1508 int allow_cursor, struct glyph_cachel *cachel) |
1516 { | 1509 { |
1517 struct window *w = XWINDOW (data->window); | 1510 struct window *w = XWINDOW (data->window); |
1518 | 1511 |
1519 /* If window faces changed, and glyph instance is text, then | |
1520 glyph sizes might have changed too */ | |
1521 invalidate_glyph_geometry_maybe (gb->glyph, w); | |
1522 | |
1523 /* This makes sure the glyph is in the cachels. | |
1524 | |
1525 #### We do this to make sure the glyph is in the glyph cachels, | |
1526 so that the dirty flag can be reset after redisplay has | |
1527 finished. We should do this some other way, maybe by iterating | |
1528 over the window cache of subwindows. */ | |
1529 get_glyph_cachel_index (w, gb->glyph); | |
1530 | |
1531 /* A nil extent indicates a special glyph (ex. truncator). */ | 1512 /* A nil extent indicates a special glyph (ex. truncator). */ |
1532 if (NILP (gb->extent) | 1513 if (NILP (gb->extent) |
1533 || (pos_type == BEGIN_GLYPHS && | 1514 || (pos_type == BEGIN_GLYPHS && |
1534 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) | 1515 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) |
1535 || (pos_type == END_GLYPHS && | 1516 || (pos_type == END_GLYPHS && |
1536 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT) | 1517 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)) |
1537 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) | |
1538 { | 1518 { |
1539 struct rune rb; | 1519 struct rune rb; |
1540 int width; | 1520 int width; |
1541 int xoffset = 0; | 1521 int xoffset = 0; |
1542 int ascent, descent; | 1522 int ascent, descent; |
1543 Lisp_Object baseline; | 1523 Lisp_Object baseline; |
1544 Lisp_Object face; | 1524 Lisp_Object face; |
1545 Lisp_Object instance; | |
1546 face_index findex; | |
1547 | 1525 |
1548 if (cachel) | 1526 if (cachel) |
1549 width = cachel->width; | 1527 width = cachel->width; |
1550 else | 1528 else |
1551 width = glyph_width (gb->glyph, data->window); | 1529 width = glyph_width (gb->glyph, Qnil, data->findex, data->window); |
1552 | 1530 |
1553 if (!width) | 1531 if (!width) |
1554 return NULL; | 1532 return NULL; |
1555 | 1533 |
1556 if (data->start_col || data->start_col_xoffset) | 1534 if (data->start_col) |
1557 { | 1535 { |
1558 prop_block_dynarr *retval; | 1536 prop_block_dynarr *retval; |
1559 int glyph_char_width = width / space_width (w); | 1537 int glyph_char_width = width / space_width (w); |
1560 | 1538 |
1561 /* If we still have not fully scrolled horizontally after | 1539 /* If we still have not fully scrolled horizontally after |
1609 ascent = cachel->ascent; | 1587 ascent = cachel->ascent; |
1610 descent = cachel->descent; | 1588 descent = cachel->descent; |
1611 } | 1589 } |
1612 else | 1590 else |
1613 { | 1591 { |
1614 ascent = glyph_ascent (gb->glyph, data->window); | 1592 ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window); |
1615 descent = glyph_descent (gb->glyph, data->window); | 1593 descent = glyph_descent (gb->glyph, Qnil, data->findex, |
1594 data->window); | |
1616 } | 1595 } |
1617 | 1596 |
1618 baseline = glyph_baseline (gb->glyph, data->window); | 1597 baseline = glyph_baseline (gb->glyph, data->window); |
1619 | 1598 |
1620 if (glyph_contrib_p (gb->glyph, data->window)) | 1599 if (glyph_contrib_p (gb->glyph, data->window)) |
1653 abort (); | 1632 abort (); |
1654 } | 1633 } |
1655 | 1634 |
1656 face = glyph_face (gb->glyph, data->window); | 1635 face = glyph_face (gb->glyph, data->window); |
1657 if (NILP (face)) | 1636 if (NILP (face)) |
1658 findex = data->findex; | 1637 rb.findex = data->findex; |
1659 else | 1638 else |
1660 findex = get_builtin_face_cache_index (w, face); | 1639 rb.findex = get_builtin_face_cache_index (w, face); |
1661 | 1640 |
1662 instance = glyph_image_instance (gb->glyph, data->window, | |
1663 ERROR_ME_NOT, 1); | |
1664 if (TEXT_IMAGE_INSTANCEP (instance)) | |
1665 { | |
1666 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance); | |
1667 face_index orig_findex = data->findex; | |
1668 Bytind orig_bufpos = data->bi_bufpos; | |
1669 Bytind orig_start_col_enabled = data->bi_start_col_enabled; | |
1670 | |
1671 data->findex = findex; | |
1672 data->bi_start_col_enabled = 0; | |
1673 if (!allow_cursor) | |
1674 data->bi_bufpos = 0; | |
1675 add_bufbyte_string_runes (data, XSTRING_DATA (string), | |
1676 XSTRING_LENGTH (string), 0); | |
1677 data->findex = orig_findex; | |
1678 data->bi_bufpos = orig_bufpos; | |
1679 data->bi_start_col_enabled = orig_start_col_enabled; | |
1680 return NULL; | |
1681 } | |
1682 | |
1683 rb.findex = findex; | |
1684 rb.xpos = data->pixpos; | 1641 rb.xpos = data->pixpos; |
1685 rb.width = width; | 1642 rb.width = width; |
1686 rb.bufpos = 0; /* glyphs are never "at" anywhere */ | 1643 rb.bufpos = 0; /* glyphs are never "at" anywhere */ |
1687 if (data->bi_endpos) | 1644 if (data->bi_endpos) |
1688 /* #### is this necessary at all? */ | 1645 /* #### is this necessary at all? */ |
1689 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)), | 1646 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)), |
1690 data->bi_endpos); | 1647 data->bi_endpos); |
1691 else | 1648 else |
1692 rb.endpos = 0; | 1649 rb.endpos = 0; |
1693 rb.type = RUNE_DGLYPH; | 1650 rb.type = RUNE_DGLYPH; |
1651 /* #### Ben sez: this is way bogus if the glyph is a string. | |
1652 You should not make the output routines have to cope with | |
1653 this. The string could contain Mule characters, or non- | |
1654 printable characters, or characters to be passed through | |
1655 the display table, or non-character objects (when this gets | |
1656 implemented), etc. Instead, this routine here should parse | |
1657 the string into a series of runes. */ | |
1694 rb.object.dglyph.glyph = gb->glyph; | 1658 rb.object.dglyph.glyph = gb->glyph; |
1695 rb.object.dglyph.extent = gb->extent; | 1659 rb.object.dglyph.extent = gb->extent; |
1696 rb.object.dglyph.xoffset = xoffset; | 1660 rb.object.dglyph.xoffset = xoffset; |
1697 | 1661 |
1698 if (allow_cursor) | 1662 if (allow_cursor) |
1799 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds. | 1763 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds. |
1800 You must do appropriate conversion. */ | 1764 You must do appropriate conversion. */ |
1801 | 1765 |
1802 static Bytind | 1766 static Bytind |
1803 create_text_block (struct window *w, struct display_line *dl, | 1767 create_text_block (struct window *w, struct display_line *dl, |
1804 Bytind bi_start_pos, prop_block_dynarr **prop, | 1768 Bytind bi_start_pos, int start_col, |
1769 prop_block_dynarr **prop, | |
1805 int type) | 1770 int type) |
1806 { | 1771 { |
1807 struct frame *f = XFRAME (w->frame); | 1772 struct frame *f = XFRAME (w->frame); |
1808 struct buffer *b = XBUFFER (w->buffer); | 1773 struct buffer *b = XBUFFER (w->buffer); |
1809 struct device *d = XDEVICE (f->device); | 1774 struct device *d = XDEVICE (f->device); |
1824 only lines that start with less than selective_display columns of | 1789 only lines that start with less than selective_display columns of |
1825 space will be displayed. If selective_display is t then all text | 1790 space will be displayed. If selective_display is t then all text |
1826 after a ^M is invisible. */ | 1791 after a ^M is invisible. */ |
1827 int selective = (INTP (b->selective_display) | 1792 int selective = (INTP (b->selective_display) |
1828 ? XINT (b->selective_display) | 1793 ? XINT (b->selective_display) |
1829 : (!NILP (b->selective_display) ? -1 : 0)); | 1794 : ((!NILP (b->selective_display) ? -1 : 0))); |
1830 | 1795 |
1831 /* The variable ctl-arrow allows the user to specify what characters | 1796 /* The variable ctl-arrow allows the user to specify what characters |
1832 can actually be displayed and which octal should be used for. | 1797 can actually be displayed and which octal should be used for. |
1833 #### This variable should probably have some rethought done to | 1798 #### This variable should probably have some rethought done to |
1834 it. | 1799 it. |
1891 Lisp_Object synch_minibuffers_value = | 1856 Lisp_Object synch_minibuffers_value = |
1892 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer); | 1857 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer); |
1893 | 1858 |
1894 dl->used_prop_data = 0; | 1859 dl->used_prop_data = 0; |
1895 dl->num_chars = 0; | 1860 dl->num_chars = 0; |
1896 dl->line_continuation = 0; | |
1897 | 1861 |
1898 xzero (data); | 1862 xzero (data); |
1899 data.ef = extent_fragment_new (w->buffer, f); | 1863 data.ef = extent_fragment_new (w->buffer, f); |
1900 | 1864 |
1901 /* These values are used by all of the rune addition routines. We add | 1865 /* These values are used by all of the rune addition routines. We add |
1902 them to this structure for ease of passing. */ | 1866 them to this structure for ease of passing. */ |
1903 data.d = d; | 1867 data.d = d; |
1904 XSETWINDOW (data.window, w); | 1868 XSETWINDOW (data.window, w); |
1905 data.string = Qnil; | |
1906 data.db = db; | 1869 data.db = db; |
1907 data.dl = dl; | 1870 data.dl = dl; |
1908 | 1871 |
1909 data.bi_bufpos = bi_start_pos; | 1872 data.bi_bufpos = bi_start_pos; |
1910 data.pixpos = dl->bounds.left_in; | 1873 data.pixpos = dl->bounds.left_in; |
1944 else | 1907 else |
1945 data.cursor_type = NO_CURSOR; | 1908 data.cursor_type = NO_CURSOR; |
1946 data.cursor_x = -1; | 1909 data.cursor_x = -1; |
1947 | 1910 |
1948 data.start_col = w->hscroll; | 1911 data.start_col = w->hscroll; |
1949 data.start_col_xoffset = w->left_xoffset; | |
1950 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0); | 1912 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0); |
1951 data.hscroll_glyph_width_adjust = 0; | 1913 data.hscroll_glyph_width_adjust = 0; |
1952 | 1914 |
1953 /* We regenerate the line from the very beginning. */ | 1915 /* We regenerate the line from the very beginning. */ |
1954 Dynarr_reset (db->runes); | 1916 Dynarr_reset (db->runes); |
2264 that the cursor shows up properly. */ | 2226 that the cursor shows up properly. */ |
2265 data.ch = '\n'; | 2227 data.ch = '\n'; |
2266 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | 2228 data.blank_width = DEVMETH (d, eol_cursor_width, ()); |
2267 data.findex = DEFAULT_INDEX; | 2229 data.findex = DEFAULT_INDEX; |
2268 data.start_col = 0; | 2230 data.start_col = 0; |
2269 data.start_col_xoffset = 0; | |
2270 data.bi_start_col_enabled = 0; | 2231 data.bi_start_col_enabled = 0; |
2271 | 2232 |
2272 add_emchar_rune (&data); | 2233 add_emchar_rune (&data); |
2273 } | 2234 } |
2274 | 2235 |
2298 int next_tab_start; | 2259 int next_tab_start; |
2299 int char_tab_width; | 2260 int char_tab_width; |
2300 int prop_width = 0; | 2261 int prop_width = 0; |
2301 | 2262 |
2302 if (data.start_col > 1) | 2263 if (data.start_col > 1) |
2303 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)) | 2264 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); |
2304 + data.start_col_xoffset; | |
2305 | 2265 |
2306 next_tab_start = | 2266 next_tab_start = |
2307 next_tab_position (w, tab_start_pixpos, | 2267 next_tab_position (w, tab_start_pixpos, |
2308 dl->bounds.left_in + | 2268 dl->bounds.left_in + |
2309 data.hscroll_glyph_width_adjust); | 2269 data.hscroll_glyph_width_adjust); |
2482 /* The cursor can never be on the continuation glyph. */ | 2442 /* The cursor can never be on the continuation glyph. */ |
2483 data.cursor_type = NO_CURSOR; | 2443 data.cursor_type = NO_CURSOR; |
2484 | 2444 |
2485 /* data.bi_bufpos is already at the start of the next line. */ | 2445 /* data.bi_bufpos is already at the start of the next line. */ |
2486 | 2446 |
2487 dl->line_continuation = 1; | |
2488 gb.glyph = Vcontinuation_glyph; | 2447 gb.glyph = Vcontinuation_glyph; |
2489 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | 2448 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); |
2490 } | 2449 } |
2491 | 2450 |
2492 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); | 2451 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel); |
2493 | 2452 |
2494 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b) | 2453 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b) |
2495 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n') | 2454 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n') |
2496 /* #### Damn this losing shit. */ | 2455 /* #### Damn this losing shit. */ |
2497 data.bi_bufpos++; | 2456 data.bi_bufpos++; |
2507 | 2466 |
2508 data.ch = '\n'; | 2467 data.ch = '\n'; |
2509 data.blank_width = DEVMETH (d, eol_cursor_width, ()); | 2468 data.blank_width = DEVMETH (d, eol_cursor_width, ()); |
2510 data.findex = DEFAULT_INDEX; | 2469 data.findex = DEFAULT_INDEX; |
2511 data.start_col = 0; | 2470 data.start_col = 0; |
2512 data.start_col_xoffset = 0; | |
2513 data.bi_start_col_enabled = 0; | 2471 data.bi_start_col_enabled = 0; |
2514 | 2472 |
2515 data.max_pixpos += data.blank_width; | 2473 data.max_pixpos += data.blank_width; |
2516 add_emchar_rune (&data); | 2474 add_emchar_rune (&data); |
2517 data.max_pixpos -= data.blank_width; | 2475 data.max_pixpos -= data.blank_width; |
2683 data.cursor_x = -1; | 2641 data.cursor_x = -1; |
2684 data.findex = DEFAULT_INDEX; | 2642 data.findex = DEFAULT_INDEX; |
2685 data.last_charset = Qunbound; | 2643 data.last_charset = Qunbound; |
2686 data.last_findex = DEFAULT_INDEX; | 2644 data.last_findex = DEFAULT_INDEX; |
2687 data.result_str = Qnil; | 2645 data.result_str = Qnil; |
2688 data.string = Qnil; | |
2689 | 2646 |
2690 Dynarr_reset (data.db->runes); | 2647 Dynarr_reset (data.db->runes); |
2691 | 2648 |
2692 if (STRINGP (Voverlay_arrow_string)) | 2649 if (STRINGP (Voverlay_arrow_string)) |
2693 { | 2650 { |
2735 { | 2692 { |
2736 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS | 2693 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS |
2737 ? dl->left_glyphs | 2694 ? dl->left_glyphs |
2738 : dl->right_glyphs); | 2695 : dl->right_glyphs); |
2739 int elt, end; | 2696 int elt, end; |
2697 int xpos = start; | |
2740 int reverse; | 2698 int reverse; |
2741 struct window *w = XWINDOW (window); | |
2742 struct frame *f = XFRAME (w->frame); | |
2743 struct device *d = XDEVICE (f->device); | |
2744 pos_data data; | |
2745 | |
2746 xzero (data); | |
2747 data.d = d; | |
2748 data.window = window; | |
2749 data.db = db; | |
2750 data.dl = dl; | |
2751 data.pixpos = start; | |
2752 data.cursor_type = NO_CURSOR; | |
2753 data.cursor_x = -1; | |
2754 data.last_charset = Qunbound; | |
2755 data.last_findex = DEFAULT_INDEX; | |
2756 data.result_str = Qnil; | |
2757 data.string = Qnil; | |
2758 data.new_ascent = dl->ascent; | |
2759 data.new_descent = dl->descent; | |
2760 | 2699 |
2761 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) | 2700 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS) |
2762 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) | 2701 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) |
2763 { | 2702 { |
2764 reverse = 1; | 2703 reverse = 1; |
2783 ((side == LEFT_GLYPHS && | 2722 ((side == LEFT_GLYPHS && |
2784 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout) | 2723 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout) |
2785 || (side == RIGHT_GLYPHS && | 2724 || (side == RIGHT_GLYPHS && |
2786 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) | 2725 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout))) |
2787 { | 2726 { |
2788 data.findex = gb->findex; | 2727 struct rune rb; |
2789 data.max_pixpos = data.pixpos + gb->width; | 2728 |
2790 add_glyph_rune (&data, gb, side, 0, NULL); | 2729 rb.width = gb->width; |
2730 rb.findex = gb->findex; | |
2731 rb.xpos = xpos; | |
2732 rb.bufpos = -1; | |
2733 rb.endpos = 0; | |
2734 rb.type = RUNE_DGLYPH; | |
2735 rb.object.dglyph.glyph = gb->glyph; | |
2736 rb.object.dglyph.extent = gb->extent; | |
2737 rb.object.dglyph.xoffset = 0; | |
2738 rb.cursor_type = CURSOR_OFF; | |
2739 | |
2740 Dynarr_add (db->runes, rb); | |
2741 xpos += rb.width; | |
2791 count--; | 2742 count--; |
2792 gb->active = 0; | 2743 gb->active = 0; |
2744 | |
2745 if (glyph_contrib_p (gb->glyph, window)) | |
2746 { | |
2747 unsigned short ascent, descent; | |
2748 Lisp_Object baseline = glyph_baseline (gb->glyph, window); | |
2749 | |
2750 ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window); | |
2751 descent = glyph_descent (gb->glyph, Qnil, gb->findex, window); | |
2752 | |
2753 /* A pixmap that has not had a baseline explicitly set. | |
2754 We use the existing ascent / descent ratio of the | |
2755 line. */ | |
2756 if (NILP (baseline)) | |
2757 { | |
2758 int gheight = ascent + descent; | |
2759 int line_height = dl->ascent + dl->descent; | |
2760 int pix_ascent, pix_descent; | |
2761 | |
2762 pix_descent = (int) (gheight * dl->descent) / line_height; | |
2763 pix_ascent = gheight - pix_descent; | |
2764 | |
2765 dl->ascent = max ((int) dl->ascent, pix_ascent); | |
2766 dl->descent = max ((int) dl->descent, pix_descent); | |
2767 } | |
2768 | |
2769 /* A string so determine contribution normally. */ | |
2770 else if (EQ (baseline, Qt)) | |
2771 { | |
2772 dl->ascent = max (dl->ascent, ascent); | |
2773 dl->descent = max (dl->descent, descent); | |
2774 } | |
2775 | |
2776 /* A pixmap with an explicitly set baseline. We determine the | |
2777 contribution here. */ | |
2778 else if (INTP (baseline)) | |
2779 { | |
2780 int height = ascent + descent; | |
2781 int pix_ascent, pix_descent; | |
2782 | |
2783 pix_ascent = height * XINT (baseline) / 100; | |
2784 pix_descent = height - pix_ascent; | |
2785 | |
2786 dl->ascent = max ((int) dl->ascent, pix_ascent); | |
2787 dl->descent = max ((int) dl->descent, pix_descent); | |
2788 } | |
2789 | |
2790 /* Otherwise something is screwed up. */ | |
2791 else | |
2792 abort (); | |
2793 } | |
2793 } | 2794 } |
2794 | 2795 |
2795 (reverse ? elt-- : elt++); | 2796 (reverse ? elt-- : elt++); |
2796 } | 2797 } |
2797 | 2798 |
2798 if (data.max_pixmap_height) | 2799 return xpos; |
2799 { | |
2800 int height = data.new_ascent + data.new_descent; | |
2801 int pix_ascent, pix_descent; | |
2802 | |
2803 pix_descent = data.max_pixmap_height * data.new_descent / height; | |
2804 pix_ascent = data.max_pixmap_height - pix_descent; | |
2805 data.new_ascent = max (data.new_ascent, pix_ascent); | |
2806 data.new_descent = max (data.new_descent, pix_descent); | |
2807 } | |
2808 | |
2809 dl->ascent = data.new_ascent; | |
2810 dl->descent = data.new_descent; | |
2811 | |
2812 return data.pixpos; | |
2813 } | 2800 } |
2814 | 2801 |
2815 /* Add a blank to a margin display block. */ | 2802 /* Add a blank to a margin display block. */ |
2816 | 2803 |
2817 static void | 2804 static void |
2873 | 2860 |
2874 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | 2861 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) |
2875 { | 2862 { |
2876 int width; | 2863 int width; |
2877 | 2864 |
2878 width = glyph_width (gb->glyph, window); | 2865 width = glyph_width (gb->glyph, Qnil, gb->findex, window); |
2879 | 2866 |
2880 if (white_in_start - width >= left_in_end) | 2867 if (white_in_start - width >= left_in_end) |
2881 { | 2868 { |
2882 white_in_cnt++; | 2869 white_in_cnt++; |
2883 white_in_start -= width; | 2870 white_in_start -= width; |
2924 abort (); /* these should have been handled in add_glyph_rune */ | 2911 abort (); /* these should have been handled in add_glyph_rune */ |
2925 | 2912 |
2926 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | 2913 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == |
2927 GL_INSIDE_MARGIN) | 2914 GL_INSIDE_MARGIN) |
2928 { | 2915 { |
2929 gb->width = glyph_width (gb->glyph, window); | 2916 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window); |
2930 used_in += gb->width; | 2917 used_in += gb->width; |
2931 Dynarr_add (ib, *gb); | 2918 Dynarr_add (ib, *gb); |
2932 } | 2919 } |
2933 | 2920 |
2934 elt++; | 2921 elt++; |
2993 abort (); /* these should have been handled in add_glyph_rune */ | 2980 abort (); /* these should have been handled in add_glyph_rune */ |
2994 | 2981 |
2995 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | 2982 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == |
2996 GL_INSIDE_MARGIN) | 2983 GL_INSIDE_MARGIN) |
2997 { | 2984 { |
2998 int width = glyph_width (gb->glyph, window); | 2985 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); |
2999 | 2986 |
3000 if (used_out) | 2987 if (used_out) |
3001 { | 2988 { |
3002 in_out_cnt++; | 2989 in_out_cnt++; |
3003 in_out_start -= width; | 2990 in_out_start -= width; |
3035 abort (); /* these should have been handled in add_glyph_rune */ | 3022 abort (); /* these should have been handled in add_glyph_rune */ |
3036 | 3023 |
3037 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == | 3024 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == |
3038 GL_OUTSIDE_MARGIN) | 3025 GL_OUTSIDE_MARGIN) |
3039 { | 3026 { |
3040 int width = glyph_width (gb->glyph, window); | 3027 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); |
3041 | 3028 |
3042 if (out_end + width <= in_out_start) | 3029 if (out_end + width <= in_out_start) |
3043 { | 3030 { |
3044 out_cnt++; | 3031 out_cnt++; |
3045 out_end += width; | 3032 out_end += width; |
3192 if (NILP (gb->extent)) | 3179 if (NILP (gb->extent)) |
3193 abort (); /* these should have been handled in add_glyph_rune */ | 3180 abort (); /* these should have been handled in add_glyph_rune */ |
3194 | 3181 |
3195 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) | 3182 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE) |
3196 { | 3183 { |
3197 int width = glyph_width (gb->glyph, window); | 3184 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); |
3198 | 3185 |
3199 if (white_in_end + width <= dl->bounds.right_in) | 3186 if (white_in_end + width <= dl->bounds.right_in) |
3200 { | 3187 { |
3201 white_in_cnt++; | 3188 white_in_cnt++; |
3202 white_in_end += width; | 3189 white_in_end += width; |
3242 if (NILP (gb->extent)) | 3229 if (NILP (gb->extent)) |
3243 abort (); /* these should have been handled in add_glyph_rune */ | 3230 abort (); /* these should have been handled in add_glyph_rune */ |
3244 | 3231 |
3245 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | 3232 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) |
3246 { | 3233 { |
3247 gb->width = glyph_width (gb->glyph, window); | 3234 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window); |
3248 used_in += gb->width; | 3235 used_in += gb->width; |
3249 Dynarr_add (ib, *gb); | 3236 Dynarr_add (ib, *gb); |
3250 } | 3237 } |
3251 | 3238 |
3252 elt++; | 3239 elt++; |
3306 if (NILP (gb->extent)) | 3293 if (NILP (gb->extent)) |
3307 abort (); /* these should have been handled in add_glyph_rune */ | 3294 abort (); /* these should have been handled in add_glyph_rune */ |
3308 | 3295 |
3309 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) | 3296 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN) |
3310 { | 3297 { |
3311 int width = glyph_width (gb->glyph, window); | 3298 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); |
3312 | 3299 |
3313 if (used_out) | 3300 if (used_out) |
3314 { | 3301 { |
3315 in_out_cnt++; | 3302 in_out_cnt++; |
3316 in_out_end += width; | 3303 in_out_end += width; |
3347 if (NILP (gb->extent)) | 3334 if (NILP (gb->extent)) |
3348 abort (); /* these should have been handled in add_glyph_rune */ | 3335 abort (); /* these should have been handled in add_glyph_rune */ |
3349 | 3336 |
3350 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) | 3337 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN) |
3351 { | 3338 { |
3352 int width = glyph_width (gb->glyph, window); | 3339 int width = glyph_width (gb->glyph, Qnil, gb->findex, window); |
3353 | 3340 |
3354 if (out_start - width >= in_out_end) | 3341 if (out_start - width >= in_out_end) |
3355 { | 3342 { |
3356 out_cnt++; | 3343 out_cnt++; |
3357 out_start -= width; | 3344 out_start -= width; |
3463 /* */ | 3450 /* */ |
3464 /* modeline routines */ | 3451 /* modeline routines */ |
3465 /* */ | 3452 /* */ |
3466 /***************************************************************************/ | 3453 /***************************************************************************/ |
3467 | 3454 |
3468 /* This function is also used in frame.c by `generate_title_string' */ | 3455 /* Ensure that the given display line DL accurately represents the |
3469 void | 3456 modeline for the given window. */ |
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 | |
3470 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, | 3552 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str, |
3471 struct window *w, struct display_line *dl, | 3553 struct window *w, struct display_line *dl, |
3472 struct display_block *db, face_index findex, | 3554 struct display_block *db, face_index findex, |
3473 int min_pixpos, int max_pixpos, int type) | 3555 int min_pixpos, int max_pixpos, int type) |
3474 { | 3556 { |
3475 struct frame *f = XFRAME (w->frame); | 3557 struct frame *f = XFRAME (w->frame); |
3476 struct device *d = XDEVICE (f->device); | 3558 struct device *d = XDEVICE (f->device); |
3477 | 3559 |
3478 pos_data data; | 3560 pos_data data; |
3479 int c_pixpos; | 3561 int c_pixpos; |
3480 Charcount offset = 0; | |
3481 | 3562 |
3482 xzero (data); | 3563 xzero (data); |
3483 data.d = d; | 3564 data.d = d; |
3484 data.db = db; | 3565 data.db = db; |
3485 data.dl = dl; | 3566 data.dl = dl; |
3489 data.cursor_type = NO_CURSOR; | 3570 data.cursor_type = NO_CURSOR; |
3490 data.last_charset = Qunbound; | 3571 data.last_charset = Qunbound; |
3491 data.last_findex = DEFAULT_INDEX; | 3572 data.last_findex = DEFAULT_INDEX; |
3492 data.result_str = result_str; | 3573 data.result_str = result_str; |
3493 data.is_modeline = 1; | 3574 data.is_modeline = 1; |
3494 data.string = Qnil; | |
3495 XSETWINDOW (data.window, w); | 3575 XSETWINDOW (data.window, w); |
3496 | 3576 |
3497 Dynarr_reset (formatted_string_extent_dynarr); | 3577 Dynarr_reset (formatted_string_extent_dynarr); |
3498 Dynarr_reset (formatted_string_extent_start_dynarr); | 3578 Dynarr_reset (formatted_string_extent_start_dynarr); |
3499 Dynarr_reset (formatted_string_extent_end_dynarr); | 3579 Dynarr_reset (formatted_string_extent_end_dynarr); |
3500 | 3580 |
3501 /* result_str is nil when we're building a frame or icon title. Otherwise, | 3581 /* This recursively builds up the modeline. */ |
3502 we're building a modeline, so the offset starts at the modeline | |
3503 horizontal scrolling ammount */ | |
3504 if (! NILP (result_str)) | |
3505 offset = w->modeline_hscroll; | |
3506 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, | 3582 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0, |
3507 max_pixpos - min_pixpos, findex, type, &offset, | 3583 max_pixpos - min_pixpos, findex, type); |
3508 Qnil); | |
3509 | 3584 |
3510 if (Dynarr_length (db->runes)) | 3585 if (Dynarr_length (db->runes)) |
3511 { | 3586 { |
3512 struct rune *rb = | 3587 struct rune *rb = |
3513 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); | 3588 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); |
3534 { | 3609 { |
3535 int elt; | 3610 int elt; |
3536 Bytecount len; | 3611 Bytecount len; |
3537 Bufbyte *strdata; | 3612 Bufbyte *strdata; |
3538 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); | 3613 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w)); |
3539 | |
3540 in_modeline_generation = 1; | |
3541 | 3614 |
3542 detach_all_extents (result_str); | 3615 detach_all_extents (result_str); |
3543 resize_string (XSTRING (result_str), -1, | 3616 resize_string (XSTRING (result_str), -1, |
3544 data.bytepos - XSTRING_LENGTH (result_str)); | 3617 data.bytepos - XSTRING_LENGTH (result_str)); |
3545 | 3618 |
3573 (XEXTENT (child), | 3646 (XEXTENT (child), |
3574 Dynarr_at (formatted_string_extent_start_dynarr, elt), | 3647 Dynarr_at (formatted_string_extent_start_dynarr, elt), |
3575 Dynarr_at (formatted_string_extent_end_dynarr, elt), | 3648 Dynarr_at (formatted_string_extent_end_dynarr, elt), |
3576 result_str); | 3649 result_str); |
3577 } | 3650 } |
3578 | 3651 } |
3579 in_modeline_generation = 0; | |
3580 } | |
3581 } | |
3582 | |
3583 /* Ensure that the given display line DL accurately represents the | |
3584 modeline for the given window. */ | |
3585 static void | |
3586 generate_modeline (struct window *w, struct display_line *dl, int type) | |
3587 { | |
3588 struct buffer *b = XBUFFER (w->buffer); | |
3589 struct frame *f = XFRAME (w->frame); | |
3590 struct device *d = XDEVICE (f->device); | |
3591 | |
3592 /* Unlike display line and rune pointers, this one can't change underneath | |
3593 our feet. */ | |
3594 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
3595 int max_pixpos, min_pixpos, ypos_adj; | |
3596 Lisp_Object font_inst; | |
3597 | |
3598 /* This will actually determine incorrect inside boundaries for the | |
3599 modeline since it ignores the margins. However being aware of this fact | |
3600 we never use those values anywhere so it doesn't matter. */ | |
3601 dl->bounds = calculate_display_line_boundaries (w, 1); | |
3602 | |
3603 /* We are generating a modeline. */ | |
3604 dl->modeline = 1; | |
3605 dl->cursor_elt = -1; | |
3606 | |
3607 /* Reset the runes on the modeline. */ | |
3608 Dynarr_reset (db->runes); | |
3609 | |
3610 if (!WINDOW_HAS_MODELINE_P (w)) | |
3611 { | |
3612 struct rune rb; | |
3613 | |
3614 /* If there is a horizontal scrollbar, don't add anything. */ | |
3615 if (window_scrollbar_height (w)) | |
3616 return; | |
3617 | |
3618 dl->ascent = DEVMETH (d, divider_height, ()); | |
3619 dl->descent = 0; | |
3620 /* The modeline is at the bottom of the gutters. */ | |
3621 dl->ypos = WINDOW_BOTTOM (w); | |
3622 | |
3623 rb.findex = MODELINE_INDEX; | |
3624 rb.xpos = dl->bounds.left_out; | |
3625 rb.width = dl->bounds.right_out - dl->bounds.left_out; | |
3626 rb.bufpos = 0; | |
3627 rb.endpos = 0; | |
3628 rb.type = RUNE_HLINE; | |
3629 rb.object.hline.thickness = 1; | |
3630 rb.object.hline.yoffset = 0; | |
3631 rb.cursor_type = NO_CURSOR; | |
3632 | |
3633 if (!EQ (Qzero, w->modeline_shadow_thickness) | |
3634 && FRAME_WIN_P (f)) | |
3635 { | |
3636 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
3637 | |
3638 dl->ypos -= shadow_thickness; | |
3639 rb.xpos += shadow_thickness; | |
3640 rb.width -= 2 * shadow_thickness; | |
3641 } | |
3642 | |
3643 Dynarr_add (db->runes, rb); | |
3644 return; | |
3645 } | |
3646 | |
3647 /* !!#### not right; needs to compute the max height of | |
3648 all the charsets */ | |
3649 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii); | |
3650 | |
3651 dl->ascent = XFONT_INSTANCE (font_inst)->ascent; | |
3652 dl->descent = XFONT_INSTANCE (font_inst)->descent; | |
3653 | |
3654 min_pixpos = dl->bounds.left_out; | |
3655 max_pixpos = dl->bounds.right_out; | |
3656 | |
3657 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
3658 { | |
3659 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
3660 | |
3661 ypos_adj = shadow_thickness; | |
3662 min_pixpos += shadow_thickness; | |
3663 max_pixpos -= shadow_thickness; | |
3664 } | |
3665 else | |
3666 ypos_adj = 0; | |
3667 | |
3668 generate_formatted_string_db (b->modeline_format, | |
3669 b->generated_modeline_string, w, dl, db, | |
3670 MODELINE_INDEX, min_pixpos, max_pixpos, type); | |
3671 | |
3672 /* The modeline is at the bottom of the gutters. We have to wait to | |
3673 set this until we've generated the modeline in order to account | |
3674 for any embedded faces. */ | |
3675 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj; | |
3676 } | 3652 } |
3677 | 3653 |
3678 static Charcount | 3654 static Charcount |
3679 add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str, | 3655 add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str, |
3680 Charcount pos, Charcount min_pos, Charcount max_pos) | 3656 Charcount pos, Charcount min_pos, Charcount max_pos) |
3681 { | 3657 { |
3682 /* This function has been Mule-ized. */ | 3658 /* This function has been Mule-ized. */ |
3683 Charcount end; | 3659 Charcount end; |
3684 const Bufbyte *cur_pos = str; | 3660 CONST Bufbyte *cur_pos = str; |
3685 struct display_block *db = data->db; | 3661 struct display_block *db = data->db; |
3686 | 3662 |
3687 data->blank_width = space_width (XWINDOW (data->window)); | 3663 data->blank_width = space_width (XWINDOW (data->window)); |
3688 while (Dynarr_length (db->runes) < pos) | 3664 while (Dynarr_length (db->runes) < pos) |
3689 add_blank_rune (data, NULL, 0); | 3665 add_blank_rune (data, NULL, 0); |
3690 | 3666 |
3691 end = (Dynarr_length (db->runes) + | 3667 end = (Dynarr_length (db->runes) + |
3692 bytecount_to_charcount (str, strlen ((const char *) str))); | 3668 bytecount_to_charcount (str, strlen ((CONST char *) str))); |
3693 if (max_pos != -1) | 3669 if (max_pos != -1) |
3694 end = min (max_pos, end); | 3670 end = min (max_pos, end); |
3695 | 3671 |
3696 while (pos < end && *cur_pos) | 3672 while (pos < end && *cur_pos) |
3697 { | 3673 { |
3698 const Bufbyte *old_cur_pos = cur_pos; | 3674 CONST Bufbyte *old_cur_pos = cur_pos; |
3699 int succeeded; | 3675 int succeeded; |
3700 | 3676 |
3701 data->ch = charptr_emchar (cur_pos); | 3677 data->ch = charptr_emchar (cur_pos); |
3702 succeeded = (add_emchar_rune (data) != ADD_FAILED); | 3678 succeeded = (add_emchar_rune (data) != ADD_FAILED); |
3703 INC_CHARPTR (cur_pos); | 3679 INC_CHARPTR (cur_pos); |
3718 | 3694 |
3719 /* #### Urk! Should also handle begin-glyphs and end-glyphs in | 3695 /* #### Urk! Should also handle begin-glyphs and end-glyphs in |
3720 modeline extents. */ | 3696 modeline extents. */ |
3721 static Charcount | 3697 static Charcount |
3722 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, | 3698 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph, |
3723 Charcount pos, Charcount min_pos, | 3699 Charcount pos, Charcount min_pos, Charcount max_pos) |
3724 Charcount max_pos, Lisp_Object extent) | |
3725 { | 3700 { |
3726 /* This function has been Mule-ized. */ | 3701 /* This function has been Mule-ized. */ |
3727 Charcount end; | 3702 Charcount end; |
3728 struct display_block *db = data->db; | 3703 struct display_block *db = data->db; |
3729 struct glyph_block gb; | 3704 struct glyph_block gb; |
3735 end = Dynarr_length (db->runes) + 1; | 3710 end = Dynarr_length (db->runes) + 1; |
3736 if (max_pos != -1) | 3711 if (max_pos != -1) |
3737 end = min (max_pos, end); | 3712 end = min (max_pos, end); |
3738 | 3713 |
3739 gb.glyph = glyph; | 3714 gb.glyph = glyph; |
3740 gb.extent = extent; | 3715 gb.extent = Qnil; |
3741 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); | 3716 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0); |
3742 pos++; | 3717 pos++; |
3743 | 3718 |
3744 while (Dynarr_length (db->runes) < pos && | 3719 while (Dynarr_length (db->runes) < pos && |
3745 (data->pixpos + data->blank_width <= data->max_pixpos)) | 3720 (data->pixpos + data->blank_width <= data->max_pixpos)) |
3762 modeline. */ | 3737 modeline. */ |
3763 static Charcount | 3738 static Charcount |
3764 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, | 3739 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos, |
3765 Charcount min_pos, Charcount max_pos, | 3740 Charcount min_pos, Charcount max_pos, |
3766 Lisp_Object elt, int depth, int max_pixsize, | 3741 Lisp_Object elt, int depth, int max_pixsize, |
3767 face_index findex, int type, Charcount *offset, | 3742 face_index findex, int type) |
3768 Lisp_Object cur_ext) | |
3769 { | 3743 { |
3770 /* This function has been Mule-ized. */ | 3744 /* This function has been Mule-ized. */ |
3771 /* #### The other losing things in this function are: | 3745 /* #### The other losing things in this function are: |
3772 | 3746 |
3773 -- C zero-terminated-string lossage. | 3747 -- C zero-terminated-string lossage. |
3795 while (*this && *this != '%') | 3769 while (*this && *this != '%') |
3796 this++; | 3770 this++; |
3797 | 3771 |
3798 if (this != last) | 3772 if (this != last) |
3799 { | 3773 { |
3800 /* No %-construct */ | 3774 /* The string is just a string. */ |
3801 Charcount size = | 3775 Charcount size = |
3802 bytecount_to_charcount (last, this - last); | 3776 bytecount_to_charcount (last, this - last) + pos; |
3803 | 3777 Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos)); |
3804 if (size <= *offset) | 3778 |
3805 *offset -= size; | 3779 pos = add_string_to_fstring_db_runes (data, last, pos, pos, |
3806 else | 3780 tmp_max); |
3807 { | |
3808 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset : | |
3809 min (pos + size - *offset, max_pos)); | |
3810 const Bufbyte *tmp_last = charptr_n_addr (last, *offset); | |
3811 | |
3812 pos = add_string_to_fstring_db_runes (data, tmp_last, | |
3813 pos, pos, tmp_max); | |
3814 *offset = 0; | |
3815 } | |
3816 } | 3781 } |
3817 else /* *this == '%' */ | 3782 else /* *this == '%' */ |
3818 { | 3783 { |
3819 Charcount spec_width = 0; | 3784 Charcount spec_width = 0; |
3820 | 3785 |
3835 if (*this == 'M') | 3800 if (*this == 'M') |
3836 { | 3801 { |
3837 pos = generate_fstring_runes (w, data, pos, spec_width, | 3802 pos = generate_fstring_runes (w, data, pos, spec_width, |
3838 max_pos, Vglobal_mode_string, | 3803 max_pos, Vglobal_mode_string, |
3839 depth, max_pixsize, findex, | 3804 depth, max_pixsize, findex, |
3840 type, offset, cur_ext); | 3805 type); |
3841 } | 3806 } |
3842 else if (*this == '-') | 3807 else if (*this == '-') |
3843 { | 3808 { |
3844 Charcount num_to_add; | 3809 Charcount num_to_add; |
3845 | 3810 |
3862 num_to_add++; | 3827 num_to_add++; |
3863 } | 3828 } |
3864 | 3829 |
3865 while (num_to_add--) | 3830 while (num_to_add--) |
3866 pos = add_string_to_fstring_db_runes | 3831 pos = add_string_to_fstring_db_runes |
3867 (data, (const Bufbyte *) "-", pos, pos, max_pos); | 3832 (data, (CONST Bufbyte *) "-", pos, pos, max_pos); |
3868 } | 3833 } |
3869 else if (*this != 0) | 3834 else if (*this != 0) |
3870 { | 3835 { |
3836 Bufbyte *str; | |
3871 Emchar ch = charptr_emchar (this); | 3837 Emchar ch = charptr_emchar (this); |
3872 Bufbyte *str; | |
3873 Charcount size; | |
3874 | |
3875 decode_mode_spec (w, ch, type); | 3838 decode_mode_spec (w, ch, type); |
3876 | 3839 |
3877 str = Dynarr_atp (mode_spec_bufbyte_string, 0); | 3840 str = Dynarr_atp (mode_spec_bufbyte_string, 0); |
3878 size = bytecount_to_charcount | 3841 pos = add_string_to_fstring_db_runes (data,str, pos, pos, |
3879 /* Skip the null character added by `decode_mode_spec' */ | 3842 max_pos); |
3880 (str, Dynarr_length (mode_spec_bufbyte_string)) - 1; | |
3881 | |
3882 if (size <= *offset) | |
3883 *offset -= size; | |
3884 else | |
3885 { | |
3886 const Bufbyte *tmp_str = charptr_n_addr (str, *offset); | |
3887 | |
3888 /* #### NOTE: I don't understand why a tmp_max is not | |
3889 computed and used here as in the plain string case | |
3890 above. -- dv */ | |
3891 pos = add_string_to_fstring_db_runes (data, tmp_str, | |
3892 pos, pos, | |
3893 max_pos); | |
3894 *offset = 0; | |
3895 } | |
3896 } | 3843 } |
3897 | 3844 |
3898 /* NOT this++. There could be any sort of character at | 3845 /* NOT this++. There could be any sort of character at |
3899 the current position. */ | 3846 the current position. */ |
3900 INC_CHARPTR (this); | 3847 INC_CHARPTR (this); |
3916 as if it appeared here directly. */ | 3863 as if it appeared here directly. */ |
3917 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); | 3864 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer); |
3918 | 3865 |
3919 if (!UNBOUNDP (tem)) | 3866 if (!UNBOUNDP (tem)) |
3920 { | 3867 { |
3921 /* If value is a string, output that string literally: | 3868 /* If value is a string, output that string literally: |
3922 don't check for % within it. */ | 3869 don't check for % within it. */ |
3923 if (STRINGP (tem)) | 3870 if (STRINGP (tem)) |
3924 { | 3871 { |
3925 Bufbyte *str = XSTRING_DATA (tem); | 3872 pos = |
3926 Charcount size = XSTRING_CHAR_LENGTH (tem); | 3873 add_string_to_fstring_db_runes |
3927 | 3874 (data, XSTRING_DATA (tem), pos, min_pos, max_pos); |
3928 if (size <= *offset) | |
3929 *offset -= size; | |
3930 else | |
3931 { | |
3932 const Bufbyte *tmp_str = charptr_n_addr (str, *offset); | |
3933 | |
3934 /* #### NOTE: I don't understand why a tmp_max is not | |
3935 computed and used here as in the plain string case | |
3936 above. -- dv */ | |
3937 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
3938 min_pos, max_pos); | |
3939 *offset = 0; | |
3940 } | |
3941 } | 3875 } |
3942 /* Give up right away for nil or t. */ | 3876 /* Give up right away for nil or t. */ |
3943 else if (!EQ (tem, elt)) | 3877 else if (!EQ (tem, elt)) |
3944 { | 3878 { |
3945 elt = tem; | 3879 elt = tem; |
3960 } | 3894 } |
3961 } | 3895 } |
3962 else if (CONSP (elt)) | 3896 else if (CONSP (elt)) |
3963 { | 3897 { |
3964 /* A cons cell: four distinct cases. | 3898 /* A cons cell: four distinct cases. |
3965 * - If first element is a string or a cons, process all the elements | 3899 * If first element is a string or a cons, process all the elements |
3966 * and effectively concatenate them. | 3900 * and effectively concatenate them. |
3967 * - If first element is a negative number, truncate displaying cdr to | 3901 * If first element is a negative number, truncate displaying cdr to |
3968 * at most that many characters. If positive, pad (with spaces) | 3902 * at most that many characters. If positive, pad (with spaces) |
3969 * to at least that many characters. | 3903 * to at least that many characters. |
3970 * - If first element is another symbol, process the cadr or caddr | 3904 * If first element is a symbol, process the cadr or caddr recursively |
3971 * recursively according to whether the symbol's value is non-nil or | 3905 * according to whether the symbol's value is non-nil or nil. |
3972 * nil. | 3906 * If first element is a face, process the cdr recursively |
3973 * - If first element is an extent, process the cdr recursively | 3907 * without altering the depth. |
3974 * and handle the extent's face. | |
3975 */ | 3908 */ |
3976 | |
3977 Lisp_Object car, tem; | 3909 Lisp_Object car, tem; |
3978 | 3910 |
3979 car = XCAR (elt); | 3911 car = XCAR (elt); |
3980 if (SYMBOLP (car)) | 3912 if (SYMBOLP (car)) |
3981 { | 3913 { |
3982 elt = XCDR (elt); | 3914 elt = XCDR (elt); |
3983 if (!CONSP (elt)) | 3915 if (!CONSP (elt)) |
3984 goto invalid; | 3916 goto invalid; |
3985 | 3917 tem = symbol_value_in_buffer (car, w->buffer); |
3986 tem = symbol_value_in_buffer (car, w->buffer); | 3918 /* elt is now the cdr, and we know it is a cons cell. |
3987 /* elt is now the cdr, and we know it is a cons cell. | 3919 Use its car if CAR has a non-nil value. */ |
3988 Use its car if CAR has a non-nil value. */ | 3920 if (!UNBOUNDP (tem)) |
3989 if (!UNBOUNDP (tem)) | 3921 { |
3990 { | 3922 if (!NILP (tem)) |
3991 if (!NILP (tem)) | 3923 { |
3992 { | 3924 elt = XCAR (elt); |
3993 elt = XCAR (elt); | 3925 goto tail_recurse; |
3994 goto tail_recurse; | 3926 } |
3995 } | 3927 } |
3996 } | 3928 /* Symbol's value is nil (or symbol is unbound) |
3997 /* Symbol's value is nil (or symbol is unbound) | 3929 * Get the cddr of the original list |
3998 * Get the cddr of the original list | 3930 * and if possible find the caddr and use that. |
3999 * and if possible find the caddr and use that. | 3931 */ |
4000 */ | 3932 elt = XCDR (elt); |
4001 elt = XCDR (elt); | 3933 if (NILP (elt)) |
4002 if (NILP (elt)) | 3934 ; |
4003 ; | 3935 else if (!CONSP (elt)) |
4004 else if (!CONSP (elt)) | 3936 goto invalid; |
4005 goto invalid; | 3937 else |
4006 else | 3938 { |
4007 { | 3939 elt = XCAR (elt); |
4008 elt = XCAR (elt); | 3940 goto tail_recurse; |
4009 goto tail_recurse; | 3941 } |
4010 } | 3942 } |
4011 } | |
4012 else if (INTP (car)) | 3943 else if (INTP (car)) |
4013 { | 3944 { |
4014 Charcount lim = XINT (car); | 3945 Charcount lim = XINT (car); |
4015 | 3946 |
4016 elt = XCDR (elt); | 3947 elt = XCDR (elt); |
4045 goto tail_recurse; | 3976 goto tail_recurse; |
4046 } | 3977 } |
4047 else if (STRINGP (car) || CONSP (car)) | 3978 else if (STRINGP (car) || CONSP (car)) |
4048 { | 3979 { |
4049 int limit = 50; | 3980 int limit = 50; |
4050 | |
4051 /* LIMIT is to protect against circular lists. */ | 3981 /* LIMIT is to protect against circular lists. */ |
4052 while (CONSP (elt) && --limit > 0 | 3982 while (CONSP (elt) && --limit > 0 |
4053 && (pos < max_pos || max_pos == -1)) | 3983 && (pos < max_pos || max_pos == -1)) |
4054 { | 3984 { |
4055 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | 3985 pos = generate_fstring_runes (w, data, pos, pos, max_pos, |
4056 XCAR (elt), depth, max_pixsize, | 3986 XCAR (elt), depth, |
4057 findex, type, offset, cur_ext); | 3987 max_pixsize, findex, type); |
4058 elt = XCDR (elt); | 3988 elt = XCDR (elt); |
4059 } | 3989 } |
4060 } | 3990 } |
4061 else if (EXTENTP (car)) | 3991 else if (EXTENTP (car)) |
4062 { | 3992 { |
4091 new_findex = old_findex; | 4021 new_findex = old_findex; |
4092 | 4022 |
4093 data->findex = new_findex; | 4023 data->findex = new_findex; |
4094 pos = generate_fstring_runes (w, data, pos, pos, max_pos, | 4024 pos = generate_fstring_runes (w, data, pos, pos, max_pos, |
4095 XCDR (elt), depth - 1, | 4025 XCDR (elt), depth - 1, |
4096 max_pixsize, new_findex, type, | 4026 max_pixsize, new_findex, type); |
4097 offset, car); | |
4098 data->findex = old_findex; | 4027 data->findex = old_findex; |
4099 Dynarr_add (formatted_string_extent_dynarr, ext); | 4028 Dynarr_add (formatted_string_extent_dynarr, ext); |
4100 Dynarr_add (formatted_string_extent_start_dynarr, start); | 4029 Dynarr_add (formatted_string_extent_start_dynarr, start); |
4101 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); | 4030 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos); |
4102 } | 4031 } |
4103 } | 4032 } |
4104 } | 4033 } |
4105 else if (GLYPHP (elt)) | 4034 else if (GLYPHP (elt)) |
4106 { | 4035 { |
4107 /* Glyphs are considered as one character with respect to the modeline | 4036 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos); |
4108 horizontal scrolling facility. -- dv */ | |
4109 if (*offset > 0) | |
4110 *offset -= 1; | |
4111 else | |
4112 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos, | |
4113 cur_ext); | |
4114 } | 4037 } |
4115 else | 4038 else |
4116 { | 4039 { |
4117 invalid: | 4040 invalid: |
4118 { | 4041 pos = |
4119 char *str = GETTEXT ("*invalid*"); | 4042 add_string_to_fstring_db_runes |
4120 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */ | 4043 (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos, |
4121 | 4044 max_pos); |
4122 if (size <= *offset) | |
4123 *offset -= size; | |
4124 else | |
4125 { | |
4126 const Bufbyte *tmp_str = | |
4127 charptr_n_addr ((const Bufbyte *) str, *offset); | |
4128 | |
4129 /* #### NOTE: I don't understand why a tmp_max is not computed and | |
4130 used here as in the plain string case above. -- dv */ | |
4131 pos = add_string_to_fstring_db_runes (data, tmp_str, pos, | |
4132 min_pos, max_pos); | |
4133 *offset = 0; | |
4134 } | |
4135 } | |
4136 } | 4045 } |
4137 | 4046 |
4138 if (min_pos > pos) | 4047 if (min_pos > pos) |
4139 { | 4048 { |
4140 add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos, | 4049 add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos, |
4141 min_pos, -1); | 4050 -1); |
4142 } | 4051 } |
4143 | 4052 |
4144 return pos; | 4053 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); | |
4145 } | 4085 } |
4146 | 4086 |
4147 /* Update just the modeline. Assumes the desired display structs. If | 4087 /* Update just the modeline. Assumes the desired display structs. If |
4148 they do not have a modeline block, it does nothing. */ | 4088 they do not have a modeline block, it does nothing. */ |
4149 static void | 4089 static void |
4236 return 0; | 4176 return 0; |
4237 } | 4177 } |
4238 | 4178 |
4239 | 4179 |
4240 /***************************************************************************/ | 4180 /***************************************************************************/ |
4241 /* */ | |
4242 /* displayable string routines */ | |
4243 /* */ | |
4244 /***************************************************************************/ | |
4245 | |
4246 /* Given a position for a string in a window, ensure that the given | |
4247 display line DL accurately represents the text on a line starting | |
4248 at the given position. | |
4249 | |
4250 Yes, this is duplicating the code of create_text_block, but it | |
4251 looked just too hard to change create_text_block to handle strings | |
4252 *and* buffers. We already make a distinction between the two | |
4253 elsewhere in the code so I think unifying them would require a | |
4254 complete MULE rewrite. Besides, the other distinction is that these | |
4255 functions cover text that the user *cannot edit* so we can remove | |
4256 everything to do with cursors, minibuffers etc. Eventually the | |
4257 modeline routines should be modified to use this code as it copes | |
4258 with many more types of display situation. */ | |
4259 | |
4260 static Bufpos | |
4261 create_string_text_block (struct window *w, Lisp_Object disp_string, | |
4262 struct display_line *dl, | |
4263 Bufpos start_pos, | |
4264 prop_block_dynarr **prop, | |
4265 face_index default_face) | |
4266 { | |
4267 struct frame *f = XFRAME (w->frame); | |
4268 /* Note that a lot of the buffer controlled stuff has been left in | |
4269 because you might well want to make use of it (selective display | |
4270 etc), its just the buffer text that we do not use. However, it | |
4271 seems to be possible for buffer to be nil sometimes so protect | |
4272 against this case. */ | |
4273 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; | |
4274 struct device *d = XDEVICE (f->device); | |
4275 Lisp_String* s = XSTRING (disp_string); | |
4276 | |
4277 /* we're working with these a lot so precalculate them */ | |
4278 Bytecount slen = XSTRING_LENGTH (disp_string); | |
4279 Bytecount bi_string_zv = slen; | |
4280 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos); | |
4281 | |
4282 pos_data data; | |
4283 | |
4284 int truncate_win = b ? window_truncation_on (w) : 0; | |
4285 int end_glyph_width = 0; | |
4286 | |
4287 /* we're going to ditch selective display for static text, its an | |
4288 FSF thing and invisble extents are the way to go | |
4289 here. Implementing it also relies on a number of buffer-specific | |
4290 functions that we don't have the luxury of being able to use | |
4291 here. */ | |
4292 | |
4293 /* The variable ctl-arrow allows the user to specify what characters | |
4294 can actually be displayed and which octal should be used for. | |
4295 #### This variable should probably have some rethought done to | |
4296 it. | |
4297 | |
4298 #### It would also be really nice if you could specify that | |
4299 the characters come out in hex instead of in octal. Mule | |
4300 does that by adding a ctl-hexa variable similar to ctl-arrow, | |
4301 but that's bogus -- we need a more general solution. I | |
4302 think you need to extend the concept of display tables | |
4303 into a more general conversion mechanism. Ideally you | |
4304 could specify a Lisp function that converts characters, | |
4305 but this violates the Second Golden Rule and besides would | |
4306 make things way way way way slow. | |
4307 | |
4308 So instead, we extend the display-table concept, which was | |
4309 historically limited to 256-byte vectors, to one of the | |
4310 following: | |
4311 | |
4312 a) A 256-entry vector, for backward compatibility; | |
4313 b) char-table, mapping characters to values; | |
4314 c) range-table, mapping ranges of characters to values; | |
4315 d) a list of the above. | |
4316 | |
4317 The (d) option allows you to specify multiple display tables | |
4318 instead of just one. Each display table can specify conversions | |
4319 for some characters and leave others unchanged. The way the | |
4320 character gets displayed is determined by the first display table | |
4321 with a binding for that character. This way, you could call a | |
4322 function `enable-hex-display' that adds a hex display-table to | |
4323 the list of display tables for the current buffer. | |
4324 | |
4325 #### ...not yet implemented... Also, we extend the concept of | |
4326 "mapping" to include a printf-like spec. Thus you can make all | |
4327 extended characters show up as hex with a display table like | |
4328 this: | |
4329 | |
4330 #s(range-table data ((256 524288) (format "%x"))) | |
4331 | |
4332 Since more than one display table is possible, you have | |
4333 great flexibility in mapping ranges of characters. */ | |
4334 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) | |
4335 ? XCHAR_OR_CHAR_INT (b->ctl_arrow) | |
4336 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) | |
4337 ? 255 : 160)) : 255; | |
4338 | |
4339 Lisp_Object face_dt, window_dt; | |
4340 | |
4341 /* The text display block for this display line. */ | |
4342 struct display_block *db = get_display_block_from_line (dl, TEXT); | |
4343 | |
4344 /* The first time through the main loop we need to force the glyph | |
4345 data to be updated. */ | |
4346 int initial = 1; | |
4347 | |
4348 /* Apparently the new extent_fragment_update returns an end position | |
4349 equal to the position passed in if there are no more runs to be | |
4350 displayed. */ | |
4351 int no_more_frags = 0; | |
4352 | |
4353 dl->used_prop_data = 0; | |
4354 dl->num_chars = 0; | |
4355 dl->line_continuation = 0; | |
4356 | |
4357 /* set up faces to use for clearing areas, used by | |
4358 output_display_line */ | |
4359 dl->default_findex = default_face; | |
4360 if (default_face) | |
4361 { | |
4362 dl->left_margin_findex = default_face; | |
4363 dl->right_margin_findex = default_face; | |
4364 } | |
4365 else | |
4366 { | |
4367 dl->left_margin_findex = | |
4368 get_builtin_face_cache_index (w, Vleft_margin_face); | |
4369 dl->right_margin_findex = | |
4370 get_builtin_face_cache_index (w, Vright_margin_face); | |
4371 } | |
4372 | |
4373 xzero (data); | |
4374 data.ef = extent_fragment_new (disp_string, f); | |
4375 | |
4376 /* These values are used by all of the rune addition routines. We add | |
4377 them to this structure for ease of passing. */ | |
4378 data.d = d; | |
4379 XSETWINDOW (data.window, w); | |
4380 data.db = db; | |
4381 data.dl = dl; | |
4382 | |
4383 data.bi_bufpos = bi_start_pos; | |
4384 data.pixpos = dl->bounds.left_in; | |
4385 data.last_charset = Qunbound; | |
4386 data.last_findex = default_face; | |
4387 data.result_str = Qnil; | |
4388 data.string = disp_string; | |
4389 | |
4390 /* Set the right boundary adjusting it to take into account any end | |
4391 glyph. Save the width of the end glyph for later use. */ | |
4392 data.max_pixpos = dl->bounds.right_in; | |
4393 #if 0 | |
4394 if (truncate_win) | |
4395 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX); | |
4396 else | |
4397 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX); | |
4398 #endif | |
4399 data.max_pixpos -= end_glyph_width; | |
4400 | |
4401 data.cursor_type = NO_CURSOR; | |
4402 data.cursor_x = -1; | |
4403 | |
4404 data.start_col = 0; | |
4405 /* I don't think we want this, string areas should not scroll with | |
4406 the window | |
4407 data.start_col = w->hscroll; | |
4408 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0); | |
4409 */ | |
4410 data.bi_start_col_enabled = 0; | |
4411 data.hscroll_glyph_width_adjust = 0; | |
4412 | |
4413 /* We regenerate the line from the very beginning. */ | |
4414 Dynarr_reset (db->runes); | |
4415 | |
4416 /* Why is this less than or equal and not just less than? If the | |
4417 starting position is already equal to the maximum we can't add | |
4418 anything else, right? Wrong. We might still have a newline to | |
4419 add. A newline can use the room allocated for an end glyph since | |
4420 if we add it we know we aren't going to be adding any end | |
4421 glyph. */ | |
4422 | |
4423 /* #### Chuck -- I think this condition should be while (1). | |
4424 Otherwise if (e.g.) there is one begin-glyph and one end-glyph | |
4425 and the begin-glyph ends exactly at the end of the window, the | |
4426 end-glyph and text might not be displayed. while (1) ensures | |
4427 that the loop terminates only when either (a) there is | |
4428 propagation data or (b) the end-of-line or end-of-buffer is hit. | |
4429 | |
4430 #### Also I think you need to ensure that the operation | |
4431 "add begin glyphs; add end glyphs; add text" is atomic and | |
4432 can't get interrupted in the middle. If you run off the end | |
4433 of the line during that operation, then you keep accumulating | |
4434 propagation data until you're done. Otherwise, if the (e.g.) | |
4435 there's a begin glyph at a particular position and attempting | |
4436 to display that glyph results in window-end being hit and | |
4437 propagation data being generated, then the character at that | |
4438 position won't be displayed. | |
4439 | |
4440 #### See also the comment after the end of this loop, below. | |
4441 */ | |
4442 while (data.pixpos <= data.max_pixpos) | |
4443 { | |
4444 /* #### This check probably should not be necessary. */ | |
4445 if (data.bi_bufpos > bi_string_zv) | |
4446 { | |
4447 /* #### urk! More of this lossage! */ | |
4448 data.bi_bufpos--; | |
4449 goto done; | |
4450 } | |
4451 | |
4452 /* Check for face changes. */ | |
4453 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end)) | |
4454 { | |
4455 /* Now compute the face and begin/end-glyph information. */ | |
4456 data.findex = | |
4457 /* Remember that the extent-fragment routines deal in Bytind's. */ | |
4458 extent_fragment_update (w, data.ef, data.bi_bufpos); | |
4459 /* This is somewhat cheesy but the alternative is to | |
4460 propagate default_face into extent_fragment_update. */ | |
4461 if (data.findex == DEFAULT_INDEX) | |
4462 data.findex = default_face; | |
4463 | |
4464 get_display_tables (w, data.findex, &face_dt, &window_dt); | |
4465 | |
4466 if (data.bi_bufpos == data.ef->end) | |
4467 no_more_frags = 1; | |
4468 } | |
4469 initial = 0; | |
4470 | |
4471 /* Determine what is next to be displayed. We first handle any | |
4472 glyphs returned by glyphs_at_bufpos. If there are no glyphs to | |
4473 display then we determine what to do based on the character at the | |
4474 current buffer position. */ | |
4475 | |
4476 /* If the current position is covered by an invisible extent, do | |
4477 nothing (except maybe add some ellipses). | |
4478 | |
4479 #### The behavior of begin and end-glyphs at the edge of an | |
4480 invisible extent should be investigated further. This is | |
4481 fairly low priority though. */ | |
4482 if (data.ef->invisible) | |
4483 { | |
4484 /* #### Chuck, perhaps you could look at this code? I don't | |
4485 really know what I'm doing. */ | |
4486 if (*prop) | |
4487 { | |
4488 Dynarr_free (*prop); | |
4489 *prop = 0; | |
4490 } | |
4491 | |
4492 /* The extent fragment code only sets this when we should | |
4493 really display the ellipses. It makes sure the ellipses | |
4494 don't get displayed more than once in a row. */ | |
4495 if (data.ef->invisible_ellipses) | |
4496 { | |
4497 struct glyph_block gb; | |
4498 | |
4499 data.ef->invisible_ellipses_already_displayed = 1; | |
4500 data.ef->invisible_ellipses = 0; | |
4501 gb.extent = Qnil; | |
4502 gb.glyph = Vinvisible_text_glyph; | |
4503 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, | |
4504 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX)); | |
4505 /* Perhaps they shouldn't propagate if the very next thing | |
4506 is to display a newline (for compatibility with | |
4507 selective-display-ellipses)? Maybe that's too | |
4508 abstruse. */ | |
4509 if (*prop) | |
4510 goto done; | |
4511 } | |
4512 | |
4513 /* #### What if we we're dealing with a display table? */ | |
4514 if (data.start_col) | |
4515 data.start_col--; | |
4516 | |
4517 if (data.bi_bufpos == bi_string_zv) | |
4518 goto done; | |
4519 else | |
4520 INC_CHARBYTIND (string_data (s), data.bi_bufpos); | |
4521 } | |
4522 | |
4523 /* If there is propagation data, then it represents the current | |
4524 buffer position being displayed. Add them and advance the | |
4525 position counter. This might also add the minibuffer | |
4526 prompt. */ | |
4527 else if (*prop) | |
4528 { | |
4529 dl->used_prop_data = 1; | |
4530 *prop = add_propagation_runes (prop, &data); | |
4531 | |
4532 if (*prop) | |
4533 goto done; /* gee, a really narrow window */ | |
4534 else if (data.bi_bufpos == bi_string_zv) | |
4535 goto done; | |
4536 else if (data.bi_bufpos < 0) | |
4537 /* #### urk urk urk! Aborts are not very fun! Fix this please! */ | |
4538 data.bi_bufpos = 0; | |
4539 else | |
4540 INC_CHARBYTIND (string_data (s), data.bi_bufpos); | |
4541 } | |
4542 | |
4543 /* If there are end glyphs, add them to the line. These are | |
4544 the end glyphs for the previous run of text. We add them | |
4545 here rather than doing them at the end of handling the | |
4546 previous run so that glyphs at the beginning and end of | |
4547 a line are handled correctly. */ | |
4548 else if (Dynarr_length (data.ef->end_glyphs) > 0) | |
4549 { | |
4550 *prop = add_glyph_runes (&data, END_GLYPHS); | |
4551 if (*prop) | |
4552 goto done; | |
4553 } | |
4554 | |
4555 /* If there are begin glyphs, add them to the line. */ | |
4556 else if (Dynarr_length (data.ef->begin_glyphs) > 0) | |
4557 { | |
4558 *prop = add_glyph_runes (&data, BEGIN_GLYPHS); | |
4559 if (*prop) | |
4560 goto done; | |
4561 } | |
4562 | |
4563 /* If at end-of-buffer, we've already processed begin and | |
4564 end-glyphs at this point and there's no text to process, | |
4565 so we're done. */ | |
4566 else if (data.bi_bufpos == bi_string_zv) | |
4567 goto done; | |
4568 | |
4569 else | |
4570 { | |
4571 Lisp_Object entry = Qnil; | |
4572 /* Get the character at the current buffer position. */ | |
4573 data.ch = string_char (s, data.bi_bufpos); | |
4574 if (!NILP (face_dt) || !NILP (window_dt)) | |
4575 entry = display_table_entry (data.ch, face_dt, window_dt); | |
4576 | |
4577 /* If there is a display table entry for it, hand it off to | |
4578 add_disp_table_entry_runes and let it worry about it. */ | |
4579 if (!NILP (entry) && !EQ (entry, make_char (data.ch))) | |
4580 { | |
4581 *prop = add_disp_table_entry_runes (&data, entry); | |
4582 | |
4583 if (*prop) | |
4584 goto done; | |
4585 } | |
4586 | |
4587 /* Check if we have hit a newline character. If so, add a marker | |
4588 to the line and end this loop. */ | |
4589 else if (data.ch == '\n') | |
4590 { | |
4591 /* We aren't going to be adding an end glyph so give its | |
4592 space back in order to make sure that the cursor can | |
4593 fit. */ | |
4594 data.max_pixpos += end_glyph_width; | |
4595 goto done; | |
4596 } | |
4597 | |
4598 /* If the current character is considered to be printable, then | |
4599 just add it. */ | |
4600 else if (data.ch >= printable_min) | |
4601 { | |
4602 *prop = add_emchar_rune (&data); | |
4603 if (*prop) | |
4604 goto done; | |
4605 } | |
4606 | |
4607 /* If the current character is a tab, determine the next tab | |
4608 starting position and add a blank rune which extends from the | |
4609 current pixel position to that starting position. */ | |
4610 else if (data.ch == '\t') | |
4611 { | |
4612 int tab_start_pixpos = data.pixpos; | |
4613 int next_tab_start; | |
4614 int char_tab_width; | |
4615 int prop_width = 0; | |
4616 | |
4617 if (data.start_col > 1) | |
4618 tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); | |
4619 | |
4620 next_tab_start = | |
4621 next_tab_position (w, tab_start_pixpos, | |
4622 dl->bounds.left_in + | |
4623 data.hscroll_glyph_width_adjust); | |
4624 if (next_tab_start > data.max_pixpos) | |
4625 { | |
4626 prop_width = next_tab_start - data.max_pixpos; | |
4627 next_tab_start = data.max_pixpos; | |
4628 } | |
4629 data.blank_width = next_tab_start - data.pixpos; | |
4630 char_tab_width = | |
4631 (next_tab_start - tab_start_pixpos) / space_width (w); | |
4632 | |
4633 *prop = add_blank_rune (&data, w, char_tab_width); | |
4634 | |
4635 /* add_blank_rune is only supposed to be called with | |
4636 sizes guaranteed to fit in the available space. */ | |
4637 assert (!(*prop)); | |
4638 | |
4639 if (prop_width) | |
4640 { | |
4641 struct prop_block pb; | |
4642 *prop = Dynarr_new (prop_block); | |
4643 | |
4644 pb.type = PROP_BLANK; | |
4645 pb.data.p_blank.width = prop_width; | |
4646 pb.data.p_blank.findex = data.findex; | |
4647 Dynarr_add (*prop, pb); | |
4648 | |
4649 goto done; | |
4650 } | |
4651 } | |
4652 | |
4653 /* If character is a control character, pass it off to | |
4654 add_control_char_runes. | |
4655 | |
4656 The is_*() routines have undefined results on | |
4657 arguments outside of the range [-1, 255]. (This | |
4658 often bites people who carelessly use `char' instead | |
4659 of `unsigned char'.) | |
4660 */ | |
4661 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch)) | |
4662 { | |
4663 *prop = add_control_char_runes (&data, b); | |
4664 | |
4665 if (*prop) | |
4666 goto done; | |
4667 } | |
4668 | |
4669 /* If the character is above the ASCII range and we have not | |
4670 already handled it, then print it as an octal number. */ | |
4671 else if (data.ch >= 0200) | |
4672 { | |
4673 *prop = add_octal_runes (&data); | |
4674 | |
4675 if (*prop) | |
4676 goto done; | |
4677 } | |
4678 | |
4679 /* Assume the current character is considered to be printable, | |
4680 then just add it. */ | |
4681 else | |
4682 { | |
4683 *prop = add_emchar_rune (&data); | |
4684 if (*prop) | |
4685 goto done; | |
4686 } | |
4687 | |
4688 INC_CHARBYTIND (string_data (s), data.bi_bufpos); | |
4689 } | |
4690 } | |
4691 | |
4692 done: | |
4693 | |
4694 /* Determine the starting point of the next line if we did not hit the | |
4695 end of the buffer. */ | |
4696 if (data.bi_bufpos < bi_string_zv) | |
4697 { | |
4698 /* #### This check is not correct. If the line terminated | |
4699 due to a begin-glyph or end-glyph hitting window-end, then | |
4700 data.ch will not point to the character at data.bi_bufpos. If | |
4701 you make the two changes mentioned at the top of this loop, | |
4702 you should be able to say '(if (*prop))'. That should also | |
4703 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b) | |
4704 check. */ | |
4705 | |
4706 /* The common case is that the line ended because we hit a newline. | |
4707 In that case, the next character is just the next buffer | |
4708 position. */ | |
4709 if (data.ch == '\n') | |
4710 { | |
4711 INC_CHARBYTIND (string_data (s), data.bi_bufpos); | |
4712 } | |
4713 | |
4714 /* Otherwise we have a buffer line which cannot fit on one display | |
4715 line. */ | |
4716 else | |
4717 { | |
4718 struct glyph_block gb; | |
4719 struct glyph_cachel *cachel; | |
4720 | |
4721 /* If the line is to be truncated then we actually have to look | |
4722 for the next newline. We also add the end-of-line glyph which | |
4723 we know will fit because we adjusted the right border before | |
4724 we starting laying out the line. */ | |
4725 data.max_pixpos += end_glyph_width; | |
4726 data.findex = default_face; | |
4727 gb.extent = Qnil; | |
4728 | |
4729 if (truncate_win) | |
4730 { | |
4731 Bytind bi_pos; | |
4732 | |
4733 /* Now find the start of the next line. */ | |
4734 bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1); | |
4735 | |
4736 data.cursor_type = NO_CURSOR; | |
4737 data.bi_bufpos = bi_pos; | |
4738 gb.glyph = Vtruncation_glyph; | |
4739 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX); | |
4740 } | |
4741 else | |
4742 { | |
4743 /* The cursor can never be on the continuation glyph. */ | |
4744 data.cursor_type = NO_CURSOR; | |
4745 | |
4746 /* data.bi_bufpos is already at the start of the next line. */ | |
4747 | |
4748 dl->line_continuation = 1; | |
4749 gb.glyph = Vcontinuation_glyph; | |
4750 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX); | |
4751 } | |
4752 | |
4753 if (end_glyph_width) | |
4754 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel); | |
4755 | |
4756 if (truncate_win && data.bi_bufpos == bi_string_zv) | |
4757 { | |
4758 const Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv); | |
4759 DEC_CHARPTR (endb); | |
4760 if (charptr_emchar (endb) != '\n') | |
4761 { | |
4762 /* #### Damn this losing shit. */ | |
4763 data.bi_bufpos++; | |
4764 } | |
4765 } | |
4766 } | |
4767 } | |
4768 else if (data.bi_bufpos == bi_string_zv) | |
4769 { | |
4770 /* create_text_block () adds a bogus \n marker here which screws | |
4771 up subwindow display. Since we never have a cursor in the | |
4772 gutter we can safely ignore it. */ | |
4773 } | |
4774 /* Calculate left whitespace boundary. */ | |
4775 { | |
4776 int elt = 0; | |
4777 | |
4778 /* Whitespace past a newline is considered right whitespace. */ | |
4779 while (elt < Dynarr_length (db->runes)) | |
4780 { | |
4781 struct rune *rb = Dynarr_atp (db->runes, elt); | |
4782 | |
4783 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ') | |
4784 || rb->type == RUNE_BLANK) | |
4785 { | |
4786 dl->bounds.left_white += rb->width; | |
4787 elt++; | |
4788 } | |
4789 else | |
4790 elt = Dynarr_length (db->runes); | |
4791 } | |
4792 } | |
4793 | |
4794 /* Calculate right whitespace boundary. */ | |
4795 { | |
4796 int elt = Dynarr_length (db->runes) - 1; | |
4797 int done = 0; | |
4798 | |
4799 while (!done && elt >= 0) | |
4800 { | |
4801 struct rune *rb = Dynarr_atp (db->runes, elt); | |
4802 | |
4803 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100 | |
4804 && isspace (rb->object.chr.ch)) | |
4805 && !rb->type == RUNE_BLANK) | |
4806 { | |
4807 dl->bounds.right_white = rb->xpos + rb->width; | |
4808 done = 1; | |
4809 } | |
4810 | |
4811 elt--; | |
4812 | |
4813 } | |
4814 | |
4815 /* The line is blank so everything is considered to be right | |
4816 whitespace. */ | |
4817 if (!done) | |
4818 dl->bounds.right_white = dl->bounds.left_in; | |
4819 } | |
4820 | |
4821 /* Set the display blocks bounds. */ | |
4822 db->start_pos = dl->bounds.left_in; | |
4823 if (Dynarr_length (db->runes)) | |
4824 { | |
4825 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); | |
4826 | |
4827 db->end_pos = rb->xpos + rb->width; | |
4828 } | |
4829 else | |
4830 db->end_pos = dl->bounds.right_white; | |
4831 | |
4832 /* update line height parameters */ | |
4833 if (!data.new_ascent && !data.new_descent) | |
4834 { | |
4835 /* We've got a blank line so initialize these values from the default | |
4836 face. */ | |
4837 default_face_font_info (data.window, &data.new_ascent, | |
4838 &data.new_descent, 0, 0, 0); | |
4839 } | |
4840 | |
4841 if (data.max_pixmap_height) | |
4842 { | |
4843 int height = data.new_ascent + data.new_descent; | |
4844 int pix_ascent, pix_descent; | |
4845 | |
4846 pix_descent = data.max_pixmap_height * data.new_descent / height; | |
4847 pix_ascent = data.max_pixmap_height - pix_descent; | |
4848 | |
4849 data.new_ascent = max (data.new_ascent, pix_ascent); | |
4850 data.new_descent = max (data.new_descent, pix_descent); | |
4851 } | |
4852 | |
4853 dl->ascent = data.new_ascent; | |
4854 dl->descent = data.new_descent; | |
4855 | |
4856 { | |
4857 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent); | |
4858 | |
4859 if (dl->ascent < ascent) | |
4860 dl->ascent = ascent; | |
4861 } | |
4862 { | |
4863 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent); | |
4864 | |
4865 if (dl->descent < descent) | |
4866 dl->descent = descent; | |
4867 } | |
4868 | |
4869 dl->cursor_elt = data.cursor_x; | |
4870 /* #### lossage lossage lossage! Fix this shit! */ | |
4871 if (data.bi_bufpos > bi_string_zv) | |
4872 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv); | |
4873 else | |
4874 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1; | |
4875 if (truncate_win) | |
4876 data.dl->num_chars = | |
4877 string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8); | |
4878 else | |
4879 /* This doesn't correctly take into account tabs and control | |
4880 characters but if the window isn't being truncated then this | |
4881 value isn't going to end up being used anyhow. */ | |
4882 data.dl->num_chars = dl->end_bufpos - dl->bufpos; | |
4883 | |
4884 /* #### handle horizontally scrolled line with text none of which | |
4885 was actually laid out. */ | |
4886 | |
4887 /* #### handle any remainder of overlay arrow */ | |
4888 | |
4889 if (*prop == ADD_FAILED) | |
4890 *prop = NULL; | |
4891 | |
4892 if (truncate_win && *prop) | |
4893 { | |
4894 Dynarr_free (*prop); | |
4895 *prop = NULL; | |
4896 } | |
4897 | |
4898 extent_fragment_delete (data.ef); | |
4899 | |
4900 /* #### If we started at EOB, then make sure we return a value past | |
4901 it so that regenerate_window will exit properly. This is bogus. | |
4902 The main loop should get fixed so that it isn't necessary to call | |
4903 this function if we are already at EOB. */ | |
4904 | |
4905 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv) | |
4906 return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */ | |
4907 else | |
4908 return bytecount_to_charcount (string_data (s), data.bi_bufpos); | |
4909 } | |
4910 | |
4911 /* Given a display line and a starting position, ensure that the | |
4912 contents of the display line accurately represent the visual | |
4913 representation of the buffer contents starting from the given | |
4914 position when displayed in the given window. The display line ends | |
4915 when the contents of the line reach the right boundary of the given | |
4916 window. | |
4917 | |
4918 This is very similar to generate_display_line but with the same | |
4919 limitations as create_string_text_block. I have taken the liberty | |
4920 of fixing the bytind stuff though.*/ | |
4921 | |
4922 static Bufpos | |
4923 generate_string_display_line (struct window *w, Lisp_Object disp_string, | |
4924 struct display_line *dl, | |
4925 Bufpos start_pos, | |
4926 prop_block_dynarr **prop, | |
4927 face_index default_face) | |
4928 { | |
4929 Bufpos ret_bufpos; | |
4930 | |
4931 /* you must set bounds before calling this. */ | |
4932 | |
4933 /* Reset what this line is using. */ | |
4934 if (dl->display_blocks) | |
4935 Dynarr_reset (dl->display_blocks); | |
4936 if (dl->left_glyphs) | |
4937 { | |
4938 Dynarr_free (dl->left_glyphs); | |
4939 dl->left_glyphs = 0; | |
4940 } | |
4941 if (dl->right_glyphs) | |
4942 { | |
4943 Dynarr_free (dl->right_glyphs); | |
4944 dl->right_glyphs = 0; | |
4945 } | |
4946 | |
4947 /* We aren't generating a modeline at the moment. */ | |
4948 dl->modeline = 0; | |
4949 | |
4950 /* Create a display block for the text region of the line. */ | |
4951 ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos, | |
4952 prop, default_face); | |
4953 dl->bufpos = start_pos; | |
4954 if (dl->end_bufpos < dl->bufpos) | |
4955 dl->end_bufpos = dl->bufpos; | |
4956 | |
4957 /* If there are left glyphs associated with any character in the | |
4958 text block, then create a display block to handle them. */ | |
4959 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs)) | |
4960 create_left_glyph_block (w, dl, 0); | |
4961 | |
4962 /* If there are right glyphs associated with any character in the | |
4963 text block, then create a display block to handle them. */ | |
4964 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs)) | |
4965 create_right_glyph_block (w, dl); | |
4966 | |
4967 return ret_bufpos; | |
4968 } | |
4969 | |
4970 /* This is ripped off from regenerate_window. All we want to do is | |
4971 loop through elements in the string creating display lines until we | |
4972 have covered the provided area. Simple really. */ | |
4973 void | |
4974 generate_displayable_area (struct window *w, Lisp_Object disp_string, | |
4975 int xpos, int ypos, int width, int height, | |
4976 display_line_dynarr* dla, | |
4977 Bufpos start_pos, | |
4978 face_index default_face) | |
4979 { | |
4980 int yend = ypos + height; | |
4981 Charcount s_zv; | |
4982 | |
4983 prop_block_dynarr *prop = 0; | |
4984 layout_bounds bounds; | |
4985 assert (dla); | |
4986 | |
4987 Dynarr_reset (dla); | |
4988 /* if there's nothing to do then do nothing. code after this assumes | |
4989 there is something to do. */ | |
4990 if (NILP (disp_string)) | |
4991 return; | |
4992 | |
4993 s_zv = XSTRING_CHAR_LENGTH (disp_string); | |
4994 | |
4995 bounds.left_out = xpos; | |
4996 bounds.right_out = xpos + width; | |
4997 /* The inner boundaries mark where the glyph margins are located. */ | |
4998 bounds.left_in = bounds.left_out + window_left_margin_width (w); | |
4999 bounds.right_in = bounds.right_out - window_right_margin_width (w); | |
5000 /* We cannot fully calculate the whitespace boundaries as they | |
5001 depend on the contents of the line being displayed. */ | |
5002 bounds.left_white = bounds.left_in; | |
5003 bounds.right_white = bounds.right_in; | |
5004 | |
5005 while (ypos < yend) | |
5006 { | |
5007 struct display_line dl; | |
5008 struct display_line *dlp; | |
5009 Bufpos next_pos; | |
5010 int local; | |
5011 | |
5012 if (Dynarr_length (dla) < Dynarr_largest (dla)) | |
5013 { | |
5014 dlp = Dynarr_atp (dla, Dynarr_length (dla)); | |
5015 local = 0; | |
5016 } | |
5017 else | |
5018 { | |
5019 | |
5020 xzero (dl); | |
5021 dlp = &dl; | |
5022 local = 1; | |
5023 } | |
5024 | |
5025 dlp->bounds = bounds; | |
5026 dlp->offset = 0; | |
5027 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos, | |
5028 &prop, default_face); | |
5029 /* we need to make sure that we continue along the line if there | |
5030 is more left to display otherwise we just end up redisplaying | |
5031 the same chunk over and over again. */ | |
5032 if (next_pos == start_pos && next_pos < s_zv) | |
5033 start_pos++; | |
5034 else | |
5035 start_pos = next_pos; | |
5036 | |
5037 dlp->ypos = ypos + dlp->ascent; | |
5038 ypos = dlp->ypos + dlp->descent; | |
5039 | |
5040 if (ypos > yend) | |
5041 { | |
5042 int visible_height = dlp->ascent + dlp->descent; | |
5043 | |
5044 dlp->clip = (ypos - yend); | |
5045 visible_height -= dlp->clip; | |
5046 | |
5047 if (visible_height < VERTICAL_CLIP (w, 1)) | |
5048 { | |
5049 if (local) | |
5050 free_display_line (dlp); | |
5051 break; | |
5052 } | |
5053 } | |
5054 else | |
5055 dlp->clip = 0; | |
5056 | |
5057 Dynarr_add (dla, *dlp); | |
5058 | |
5059 /* #### This type of check needs to be done down in the | |
5060 generate_display_line call. */ | |
5061 if (start_pos >= s_zv) | |
5062 break; | |
5063 } | |
5064 | |
5065 if (prop) | |
5066 Dynarr_free (prop); | |
5067 } | |
5068 | |
5069 | |
5070 /***************************************************************************/ | |
5071 /* */ | 4181 /* */ |
5072 /* window-regeneration routines */ | 4182 /* window-regeneration routines */ |
5073 /* */ | 4183 /* */ |
5074 /***************************************************************************/ | 4184 /***************************************************************************/ |
5075 | 4185 |
5084 { | 4194 { |
5085 struct frame *f = XFRAME (w->frame); | 4195 struct frame *f = XFRAME (w->frame); |
5086 struct buffer *b = XBUFFER (w->buffer); | 4196 struct buffer *b = XBUFFER (w->buffer); |
5087 int ypos = WINDOW_TEXT_TOP (w); | 4197 int ypos = WINDOW_TEXT_TOP (w); |
5088 int yend; /* set farther down */ | 4198 int yend; /* set farther down */ |
5089 int yclip = WINDOW_TEXT_TOP_CLIP (w); | |
5090 int force; | |
5091 | 4199 |
5092 prop_block_dynarr *prop; | 4200 prop_block_dynarr *prop; |
5093 layout_bounds bounds; | 4201 layout_bounds bounds; |
5094 display_line_dynarr *dla; | 4202 display_line_dynarr *dla; |
5095 int need_modeline; | 4203 int need_modeline; |
5139 Dynarr_add (prop, pb); | 4247 Dynarr_add (prop, pb); |
5140 } | 4248 } |
5141 else | 4249 else |
5142 prop = 0; | 4250 prop = 0; |
5143 | 4251 |
5144 /* When we are computing things for scrolling purposes, make | 4252 while (ypos < yend) |
5145 sure at least one line is always generated */ | |
5146 force = (type == CMOTION_DISP); | |
5147 | |
5148 /* Make sure this is set always */ | |
5149 /* Note the conversion at end */ | |
5150 w->window_end_pos[type] = start_pos; | |
5151 while (ypos < yend || force) | |
5152 { | 4253 { |
5153 struct display_line dl; | 4254 struct display_line dl; |
5154 struct display_line *dlp; | 4255 struct display_line *dlp; |
5155 int local; | 4256 int local; |
5156 | 4257 |
5159 dlp = Dynarr_atp (dla, Dynarr_length (dla)); | 4260 dlp = Dynarr_atp (dla, Dynarr_length (dla)); |
5160 local = 0; | 4261 local = 0; |
5161 } | 4262 } |
5162 else | 4263 else |
5163 { | 4264 { |
5164 | |
5165 xzero (dl); | 4265 xzero (dl); |
5166 dlp = &dl; | 4266 dlp = &dl; |
5167 local = 1; | 4267 local = 1; |
5168 } | 4268 } |
5169 | 4269 |
5170 dlp->bounds = bounds; | 4270 dlp->bounds = bounds; |
5171 dlp->offset = 0; | 4271 dlp->offset = 0; |
5172 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); | 4272 start_pos = generate_display_line (w, dlp, 1, start_pos, |
5173 | 4273 w->hscroll, &prop, type); |
5174 if (yclip > dlp->ascent) | 4274 dlp->ypos = ypos + dlp->ascent; |
5175 { | |
5176 /* this should never happen, but if it does just display the | |
5177 whole line */ | |
5178 yclip = 0; | |
5179 } | |
5180 | |
5181 dlp->ypos = (ypos + dlp->ascent) - yclip; | |
5182 ypos = dlp->ypos + dlp->descent; | 4275 ypos = dlp->ypos + dlp->descent; |
5183 | 4276 |
5184 /* See if we've been asked to start midway through a line, for | |
5185 partial display line scrolling. */ | |
5186 if (yclip) | |
5187 { | |
5188 dlp->top_clip = yclip; | |
5189 yclip = 0; | |
5190 } | |
5191 else | |
5192 dlp->top_clip = 0; | |
5193 | |
5194 if (ypos > yend) | 4277 if (ypos > yend) |
5195 { | 4278 { |
5196 int visible_height = dlp->ascent + dlp->descent; | 4279 int visible_height = dlp->ascent + dlp->descent; |
5197 | 4280 |
5198 dlp->clip = (ypos - yend); | 4281 dlp->clip = (ypos - yend); |
5199 /* Although this seems strange we could have a single very | 4282 visible_height -= dlp->clip; |
5200 tall line visible for which we need to account for both | 4283 |
5201 the top clip and the bottom clip. */ | 4284 if (visible_height < VERTICAL_CLIP (w, 1)) |
5202 visible_height -= (dlp->clip + dlp->top_clip); | |
5203 | |
5204 if (visible_height < VERTICAL_CLIP (w, 1) && !force) | |
5205 { | 4285 { |
5206 if (local) | 4286 if (local) |
5207 free_display_line (dlp); | 4287 free_display_line (dlp); |
5208 break; | 4288 break; |
5209 } | 4289 } |
5243 | 4323 |
5244 /* #### This type of check needs to be done down in the | 4324 /* #### This type of check needs to be done down in the |
5245 generate_display_line call. */ | 4325 generate_display_line call. */ |
5246 if (start_pos > BUF_ZV (b)) | 4326 if (start_pos > BUF_ZV (b)) |
5247 break; | 4327 break; |
5248 | |
5249 force = 0; | |
5250 } | 4328 } |
5251 | 4329 |
5252 if (prop) | 4330 if (prop) |
5253 Dynarr_free (prop); | 4331 Dynarr_free (prop); |
5254 | 4332 |
5255 /* #### More not quite right, but close enough. */ | 4333 /* #### More not quite right, but close enough. */ |
5256 /* Ben sez: apparently window_end_pos[] is measured | 4334 /* #### Ben sez: apparently window_end_pos[] is measured |
5257 as the number of characters between the window end and the | 4335 as the number of characters between the window end and the |
5258 end of the buffer? This seems rather weirdo. What's | 4336 end of the buffer? This seems rather weirdo. What's |
5259 the justification for this? | 4337 the justification for this? */ |
5260 | |
5261 JV sez: Because BUF_Z (b) would be a good initial value, however | |
5262 that can change. This representation allows initalizing with 0. | |
5263 */ | |
5264 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; | 4338 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type]; |
5265 | 4339 |
5266 if (need_modeline) | 4340 if (need_modeline) |
5267 { | 4341 { |
5268 /* We know that this is the right thing to use because we put it | 4342 /* We know that this is the right thing to use because we put it |
5446 we'll have the necessary propagation data. */ | 4520 we'll have the necessary propagation data. */ |
5447 if (line == first_line && ddl->used_prop_data) | 4521 if (line == first_line && ddl->used_prop_data) |
5448 return 0; | 4522 return 0; |
5449 | 4523 |
5450 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, | 4524 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, |
5451 &prop, DESIRED_DISP); | 4525 w->hscroll, &prop, DESIRED_DISP); |
5452 ddl->offset = 0; | 4526 ddl->offset = 0; |
5453 | 4527 |
5454 /* #### If there is propagated stuff the fail. We could | 4528 /* #### If there is propagated stuff the fail. We could |
5455 probably actually deal with this if the line had propagated | 4529 probably actually deal with this if the line had propagated |
5456 information when originally created by a full | 4530 information when originally created by a full |
5465 cursor has disappeared or disappeared, fail. */ | 4539 cursor has disappeared or disappeared, fail. */ |
5466 db = get_display_block_from_line (ddl, TEXT); | 4540 db = get_display_block_from_line (ddl, TEXT); |
5467 if (cdl->ypos != ddl->ypos | 4541 if (cdl->ypos != ddl->ypos |
5468 || cdl->ascent != ddl->ascent | 4542 || cdl->ascent != ddl->ascent |
5469 || cdl->descent != ddl->descent | 4543 || cdl->descent != ddl->descent |
5470 || cdl->top_clip != ddl->top_clip | |
5471 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | 4544 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) |
5472 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | 4545 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) |
5473 || old_start != ddl->bufpos | 4546 || old_start != ddl->bufpos |
5474 || old_end != ddl->end_bufpos | 4547 || old_end != ddl->end_bufpos |
5475 || initial_size != Dynarr_length (db->runes)) | 4548 || initial_size != Dynarr_length (db->runes)) |
5589 | 4662 |
5590 assert (cdl->bufpos == ddl->bufpos); | 4663 assert (cdl->bufpos == ddl->bufpos); |
5591 assert (cdl->end_bufpos == ddl->end_bufpos); | 4664 assert (cdl->end_bufpos == ddl->end_bufpos); |
5592 assert (cdl->offset == ddl->offset); | 4665 assert (cdl->offset == ddl->offset); |
5593 | 4666 |
5594 /* If the line continues to next display line, fail. */ | 4667 /* If the last rune is already a continuation glyph, fail. |
5595 if (ddl->line_continuation) | 4668 #### We should be able to handle this better. */ |
5596 return 0; | 4669 { |
4670 struct display_block *db = get_display_block_from_line (ddl, TEXT); | |
4671 if (Dynarr_length (db->runes)) | |
4672 { | |
4673 struct rune *rb = | |
4674 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); | |
4675 | |
4676 if (rb->type == RUNE_DGLYPH | |
4677 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)) | |
4678 return 0; | |
4679 } | |
4680 } | |
5597 | 4681 |
5598 /* If the line was generated using propagation data, fail. */ | 4682 /* If the line was generated using propagation data, fail. */ |
5599 if (ddl->used_prop_data) | 4683 if (ddl->used_prop_data) |
5600 return 0; | 4684 return 0; |
5601 | 4685 |
5602 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, | 4686 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, |
5603 &prop, DESIRED_DISP); | 4687 w->hscroll, &prop, DESIRED_DISP); |
5604 ddl->offset = 0; | 4688 ddl->offset = 0; |
5605 | 4689 |
5606 /* If there is propagated stuff then it is pretty much a | 4690 /* If there is propagated stuff then it is pretty much a |
5607 guarantee that more than just the one line is affected. */ | 4691 guarantee that more than just the one line is affected. */ |
5608 if (prop) | 4692 if (prop) |
5609 { | 4693 { |
5610 Dynarr_free (prop); | 4694 Dynarr_free (prop); |
5611 return 0; | 4695 return 0; |
5612 } | 4696 } |
5613 | 4697 |
5614 /* If the line continues to next display line, fail. */ | 4698 /* If the last rune is now a continuation glyph, fail. */ |
5615 if (ddl->line_continuation) | 4699 { |
5616 return 0; | 4700 struct display_block *db = get_display_block_from_line (ddl, TEXT); |
4701 if (Dynarr_length (db->runes)) | |
4702 { | |
4703 struct rune *rb = | |
4704 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1); | |
4705 | |
4706 if (rb->type == RUNE_DGLYPH | |
4707 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)) | |
4708 return 0; | |
4709 } | |
4710 } | |
5617 | 4711 |
5618 /* If any line position parameters have changed or a | 4712 /* If any line position parameters have changed or a |
5619 cursor has disappeared or disappeared, fail. */ | 4713 cursor has disappeared or disappeared, fail. */ |
5620 if (cdl->ypos != ddl->ypos | 4714 if (cdl->ypos != ddl->ypos |
5621 || cdl->ascent != ddl->ascent | 4715 || cdl->ascent != ddl->ascent |
5622 || cdl->descent != ddl->descent | 4716 || cdl->descent != ddl->descent |
5623 || cdl->top_clip != ddl->top_clip | |
5624 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) | 4717 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) |
5625 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) | 4718 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) |
5626 { | 4719 { |
5627 return 0; | 4720 return 0; |
5628 } | 4721 } |
5902 pointm = BUF_ZV (b); | 4995 pointm = BUF_ZV (b); |
5903 } | 4996 } |
5904 } | 4997 } |
5905 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); | 4998 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer); |
5906 | 4999 |
5907 /* If the buffer has changed we have to invalidate all of our face | 5000 /* If the buffer has changed we have to invalid all of our face |
5908 cache elements. */ | 5001 cache elements. */ |
5909 if ((!echo_active && b != window_display_buffer (w)) | 5002 if ((!echo_active && b != window_display_buffer (w)) |
5910 || !Dynarr_length (w->face_cachels) | 5003 || !Dynarr_length (w->face_cachels) |
5911 || f->faces_changed) | 5004 || f->faces_changed) |
5912 reset_face_cachels (w); | 5005 reset_face_cachels (w); |
5913 else | 5006 else |
5914 mark_face_cachels_as_not_updated (w); | 5007 mark_face_cachels_as_not_updated (w); |
5915 | 5008 |
5916 /* Ditto the glyph cache elements, although we do *not* invalidate | 5009 /* Ditto the glyph cache elements. */ |
5917 the cache purely because glyphs have changed - this is now | |
5918 handled by the dirty flag.*/ | |
5919 if ((!echo_active && b != window_display_buffer (w)) | 5010 if ((!echo_active && b != window_display_buffer (w)) |
5920 || !Dynarr_length (w->glyph_cachels) || f->faces_changed) | 5011 || !Dynarr_length (w->glyph_cachels) |
5012 || f->glyphs_changed) | |
5921 reset_glyph_cachels (w); | 5013 reset_glyph_cachels (w); |
5922 else | 5014 else |
5923 mark_glyph_cachels_as_not_updated (w); | 5015 mark_glyph_cachels_as_not_updated (w); |
5924 | 5016 |
5925 /* If the marker's buffer is not the window's buffer, then we need | 5017 /* If the marker's buffer is not the window's buffer, then we need |
6001 && !f->clip_changed | 5093 && !f->clip_changed |
6002 && !f->extents_changed | 5094 && !f->extents_changed |
6003 && !f->faces_changed | 5095 && !f->faces_changed |
6004 && !f->glyphs_changed | 5096 && !f->glyphs_changed |
6005 && !f->subwindows_changed | 5097 && !f->subwindows_changed |
6006 /* && !f->subwindows_state_changed*/ | |
6007 && !f->point_changed | 5098 && !f->point_changed |
6008 && !f->windows_structure_changed) | 5099 && !f->windows_structure_changed) |
6009 { | 5100 { |
6010 /* If not, we're done. */ | 5101 /* If not, we're done. */ |
6011 if (f->modeline_changed) | 5102 if (f->modeline_changed) |
6023 && !f->clip_changed | 5114 && !f->clip_changed |
6024 && !f->extents_changed | 5115 && !f->extents_changed |
6025 && !f->faces_changed | 5116 && !f->faces_changed |
6026 && !f->glyphs_changed | 5117 && !f->glyphs_changed |
6027 && !f->subwindows_changed | 5118 && !f->subwindows_changed |
6028 /* && !f->subwindows_state_changed*/ | |
6029 && !f->windows_structure_changed) | 5119 && !f->windows_structure_changed) |
6030 { | 5120 { |
6031 if (point_visible (w, pointm, CURRENT_DISP) | 5121 if (point_visible (w, pointm, CURRENT_DISP) |
6032 && w->last_point_x[CURRENT_DISP] != -1 | 5122 && w->last_point_x[CURRENT_DISP] != -1 |
6033 && w->last_point_y[CURRENT_DISP] != -1) | 5123 && w->last_point_y[CURRENT_DISP] != -1) |
6082 else if (!w->windows_changed | 5172 else if (!w->windows_changed |
6083 && !f->clip_changed | 5173 && !f->clip_changed |
6084 && !f->faces_changed | 5174 && !f->faces_changed |
6085 && !f->glyphs_changed | 5175 && !f->glyphs_changed |
6086 && !f->subwindows_changed | 5176 && !f->subwindows_changed |
6087 /* && !f->subwindows_state_changed*/ | |
6088 && !f->windows_structure_changed | 5177 && !f->windows_structure_changed |
6089 && !f->frame_changed | 5178 && !f->frame_changed |
6090 && !truncation_changed | 5179 && !truncation_changed |
6091 && pointm >= startp | 5180 && pointm >= startp |
6092 && regenerate_window_incrementally (w, startp, pointm)) | 5181 && regenerate_window_incrementally (w, startp, pointm)) |
6179 | 5268 |
6180 /* #### This should be dependent on face changes and will need to be | 5269 /* #### This should be dependent on face changes and will need to be |
6181 somewhere else once tty updates occur on a per-frame basis. */ | 5270 somewhere else once tty updates occur on a per-frame basis. */ |
6182 mark_face_cachels_as_clean (w); | 5271 mark_face_cachels_as_clean (w); |
6183 | 5272 |
6184 /* The glyph cachels only get dirty if someone changed something. | |
6185 Since redisplay has now effectively ended we can reset the dirty | |
6186 flag since everything must be up-to-date. */ | |
6187 if (glyphs_changed) | |
6188 mark_glyph_cachels_as_clean (w); | |
6189 | |
6190 w->windows_changed = 0; | 5273 w->windows_changed = 0; |
6191 } | 5274 } |
6192 | 5275 |
6193 /* Call buffer_reset_changes for all buffers present in any window | 5276 /* Call buffer_reset_changes for all buffers present in any window |
6194 currently visible in all frames on all devices. #### There has to | 5277 currently visible in all frames on all devices. #### There has to |
6264 return 0; | 5347 return 0; |
6265 } | 5348 } |
6266 | 5349 |
6267 /* Ensure that all windows on the given frame are correctly displayed. */ | 5350 /* Ensure that all windows on the given frame are correctly displayed. */ |
6268 | 5351 |
6269 int | 5352 static int |
6270 redisplay_frame (struct frame *f, int preemption_check) | 5353 redisplay_frame (struct frame *f, int preemption_check) |
6271 { | 5354 { |
6272 struct device *d = XDEVICE (f->device); | 5355 struct device *d = XDEVICE (f->device); |
6273 | 5356 |
6274 if (preemption_check) | 5357 if (preemption_check) |
6279 int preempted; | 5362 int preempted; |
6280 | 5363 |
6281 REDISPLAY_PREEMPTION_CHECK; | 5364 REDISPLAY_PREEMPTION_CHECK; |
6282 if (preempted) | 5365 if (preempted) |
6283 return 1; | 5366 return 1; |
6284 } | |
6285 | |
6286 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0)) | |
6287 { | |
6288 Lisp_Object frame; | |
6289 | |
6290 f->old_buffer_alist = Freplace_list (f->old_buffer_alist, | |
6291 f->buffer_alist); | |
6292 XSETFRAME (frame, f); | |
6293 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame); | |
6294 } | 5367 } |
6295 | 5368 |
6296 /* Before we put a hold on frame size changes, attempt to process | 5369 /* Before we put a hold on frame size changes, attempt to process |
6297 any which are already pending. */ | 5370 any which are already pending. */ |
6298 if (f->size_change_pending) | 5371 if (f->size_change_pending) |
6316 the menubar's visibility. This way we avoid having flashing | 5389 the menubar's visibility. This way we avoid having flashing |
6317 caused by an Expose event generated by the visibility change | 5390 caused by an Expose event generated by the visibility change |
6318 being handled. */ | 5391 being handled. */ |
6319 update_frame_menubars (f); | 5392 update_frame_menubars (f); |
6320 #endif /* HAVE_MENUBARS */ | 5393 #endif /* HAVE_MENUBARS */ |
5394 /* widgets are similar to menus in that they can call lisp to | |
5395 determine activation etc. Therefore update them before we get | |
5396 into redisplay. This is primarily for connected widgets such as | |
5397 radio buttons. */ | |
5398 update_frame_subwindows (f); | |
6321 #ifdef HAVE_TOOLBARS | 5399 #ifdef HAVE_TOOLBARS |
6322 /* Update the toolbars. */ | 5400 /* Update the toolbars. */ |
6323 update_frame_toolbars (f); | 5401 update_frame_toolbars (f); |
6324 #endif /* HAVE_TOOLBARS */ | 5402 #endif /* HAVE_TOOLBARS */ |
6325 /* Gutter update proper has to be done inside display when no frame | |
6326 size changes can occur, thus we separately update the gutter | |
6327 geometry here if it needs it. */ | |
6328 update_frame_gutter_geometry (f); | |
6329 | |
6330 /* If we clear the frame we have to force its contents to be redrawn. */ | |
6331 if (f->clear) | |
6332 f->frame_changed = 1; | |
6333 | |
6334 /* Invalidate the subwindow cache. We use subwindows_changed here to | |
6335 cause subwindows to get instantiated. This is because | |
6336 subwindows_state_changed is less strict - dealing with things | |
6337 like the clicked state of button. We have to do this before | |
6338 redisplaying the gutters as subwindows get unmapped in the | |
6339 process.*/ | |
6340 if (f->frame_changed || f->subwindows_changed) | |
6341 { | |
6342 /* we have to do this so the gutter gets regenerated. */ | |
6343 reset_gutter_display_lines (f); | |
6344 } | |
6345 | 5403 |
6346 hold_frame_size_changes (); | 5404 hold_frame_size_changes (); |
6347 | 5405 |
6348 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ | 5406 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ |
6349 /* Within this section, we are defenseless and assume that the | 5407 /* Within this section, we are defenseless and assume that the |
6367 we simply return. #### We should abort instead. | 5425 we simply return. #### We should abort instead. |
6368 | 5426 |
6369 #### If a frame-size change does occur we should probably | 5427 #### If a frame-size change does occur we should probably |
6370 actually be preempting redisplay. */ | 5428 actually be preempting redisplay. */ |
6371 | 5429 |
6372 MAYBE_DEVMETH (d, frame_output_begin, (f)); | 5430 /* If we clear the frame we have to force its contents to be redrawn. */ |
6373 | 5431 if (f->clear) |
6374 /* We can now update the gutters, safe in the knowledge that our | 5432 f->frame_changed = 1; |
6375 efforts won't get undone. */ | |
6376 | |
6377 /* This can call lisp, but redisplay is protected by binding | |
6378 inhibit_quit. More importantly the code involving display lines | |
6379 *assumes* that GC will not happen and so does not GCPRO | |
6380 anything. Since we use this code the whole time with the gutters | |
6381 we cannot allow GC to happen when manipulating the gutters. */ | |
6382 update_frame_gutters (f); | |
6383 | 5433 |
6384 /* Erase the frame before outputting its contents. */ | 5434 /* Erase the frame before outputting its contents. */ |
6385 if (f->clear) | 5435 if (f->clear) |
6386 { | 5436 { |
6387 MAYBE_DEVMETH (d, clear_frame, (f)); | 5437 DEVMETH (d, clear_frame, (f)); |
6388 } | 5438 } |
5439 | |
5440 /* invalidate the subwindow cache. we are going to reuse the glyphs | |
5441 flag here to cause subwindows to get instantiated. This is | |
5442 because subwindows changed is less strict - dealing with things | |
5443 like the clicked state of button. */ | |
5444 if (!Dynarr_length (f->subwindow_cachels) | |
5445 || f->glyphs_changed | |
5446 || f->frame_changed) | |
5447 reset_subwindow_cachels (f); | |
5448 else | |
5449 mark_subwindow_cachels_as_not_updated (f); | |
6389 | 5450 |
6390 /* Do the selected window first. */ | 5451 /* Do the selected window first. */ |
6391 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); | 5452 redisplay_window (FRAME_SELECTED_WINDOW (f), 0); |
6392 | 5453 |
6393 /* Then do the rest. */ | 5454 /* Then do the rest. */ |
6394 redisplay_windows (f->root_window, 1); | 5455 redisplay_windows (f->root_window, 1); |
6395 | 5456 |
6396 MAYBE_DEVMETH (d, frame_output_end, (f)); | 5457 /* We now call the output_end routine for tty frames. We delay |
5458 doing so in order to avoid cursor flicker. So much for 100% | |
5459 encapsulation. */ | |
5460 if (FRAME_TTY_P (f)) | |
5461 DEVMETH (d, output_end, (d)); | |
6397 | 5462 |
6398 update_frame_title (f); | 5463 update_frame_title (f); |
6399 | 5464 |
6400 CLASS_RESET_CHANGED_FLAGS (f); | 5465 f->buffers_changed = 0; |
5466 f->clip_changed = 0; | |
5467 f->extents_changed = 0; | |
5468 f->faces_changed = 0; | |
5469 f->frame_changed = 0; | |
5470 f->glyphs_changed = 0; | |
5471 f->subwindows_changed = 0; | |
5472 f->icon_changed = 0; | |
5473 f->menubar_changed = 0; | |
5474 f->modeline_changed = 0; | |
5475 f->point_changed = 0; | |
5476 f->toolbar_changed = 0; | |
5477 f->windows_changed = 0; | |
5478 f->windows_structure_changed = 0; | |
6401 f->window_face_cache_reset = 0; | 5479 f->window_face_cache_reset = 0; |
6402 f->echo_area_garbaged = 0; | 5480 f->echo_area_garbaged = 0; |
5481 | |
6403 f->clear = 0; | 5482 f->clear = 0; |
6404 | 5483 |
6405 if (!f->size_change_pending) | 5484 if (!f->size_change_pending) |
6406 f->size_changed = 0; | 5485 f->size_changed = 0; |
6407 | 5486 |
6414 | 5493 |
6415 map_windows (f, call_redisplay_end_triggers, 0); | 5494 map_windows (f, call_redisplay_end_triggers, 0); |
6416 return 0; | 5495 return 0; |
6417 } | 5496 } |
6418 | 5497 |
6419 /* Ensure that all frames on the given device are correctly displayed. | 5498 /* Ensure that all frames on the given device are correctly displayed. */ |
6420 If AUTOMATIC is non-zero, and the device implementation indicates | |
6421 no automatic redisplay, as printers do, then the device is not | |
6422 redisplayed. AUTOMATIC is set to zero when called from lisp | |
6423 functions (redraw-device) and (redisplay-device), and to non-zero | |
6424 when called from "lazy" redisplay(); | |
6425 */ | |
6426 | 5499 |
6427 static int | 5500 static int |
6428 redisplay_device (struct device *d, int automatic) | 5501 redisplay_device (struct device *d) |
6429 { | 5502 { |
6430 Lisp_Object frame, frmcons; | 5503 Lisp_Object frame, frmcons; |
6431 int preempted = 0; | 5504 int preempted = 0; |
6432 int size_change_failed = 0; | 5505 int size_change_failed = 0; |
6433 struct frame *f; | 5506 struct frame *f; |
6434 | |
6435 if (automatic | |
6436 && (MAYBE_INT_DEVMETH (d, device_implementation_flags, ()) | |
6437 & XDEVIMPF_NO_AUTO_REDISPLAY)) | |
6438 return 0; | |
6439 | 5507 |
6440 if (DEVICE_STREAM_P (d)) /* nothing to do */ | 5508 if (DEVICE_STREAM_P (d)) /* nothing to do */ |
6441 return 0; | 5509 return 0; |
6442 | 5510 |
6443 /* It is possible that redisplay has been called before the | 5511 /* It is possible that redisplay has been called before the |
6458 if (f->icon_changed || f->windows_changed) | 5526 if (f->icon_changed || f->windows_changed) |
6459 update_frame_icon (f); | 5527 update_frame_icon (f); |
6460 | 5528 |
6461 if (FRAME_REPAINT_P (f)) | 5529 if (FRAME_REPAINT_P (f)) |
6462 { | 5530 { |
6463 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) | 5531 if (f->buffers_changed || f->clip_changed || f->extents_changed || |
5532 f->faces_changed || f->frame_changed || f->menubar_changed || | |
5533 f->modeline_changed || f->point_changed || f->size_changed || | |
5534 f->toolbar_changed || f->windows_changed || f->size_slipped || | |
5535 f->windows_structure_changed || f->glyphs_changed || f->subwindows_changed) | |
6464 { | 5536 { |
6465 preempted = redisplay_frame (f, 0); | 5537 preempted = redisplay_frame (f, 0); |
6466 } | 5538 } |
6467 | 5539 |
6468 if (preempted) | 5540 if (preempted) |
6488 if (f->icon_changed || f->windows_changed) | 5560 if (f->icon_changed || f->windows_changed) |
6489 update_frame_icon (f); | 5561 update_frame_icon (f); |
6490 | 5562 |
6491 if (FRAME_REPAINT_P (f)) | 5563 if (FRAME_REPAINT_P (f)) |
6492 { | 5564 { |
6493 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f)) | 5565 if (f->buffers_changed || f->clip_changed || f->extents_changed || |
5566 f->faces_changed || f->frame_changed || f->menubar_changed || | |
5567 f->modeline_changed || f->point_changed || f->size_changed || | |
5568 f->toolbar_changed || f->windows_changed || | |
5569 f->windows_structure_changed || | |
5570 f->glyphs_changed || f->subwindows_changed) | |
6494 { | 5571 { |
6495 preempted = redisplay_frame (f, 0); | 5572 preempted = redisplay_frame (f, 0); |
6496 } | 5573 } |
6497 | 5574 |
6498 if (preempted) | 5575 if (preempted) |
6503 } | 5580 } |
6504 } | 5581 } |
6505 | 5582 |
6506 /* If we get here then we redisplayed all of our frames without | 5583 /* If we get here then we redisplayed all of our frames without |
6507 getting preempted so mark ourselves as clean. */ | 5584 getting preempted so mark ourselves as clean. */ |
6508 CLASS_RESET_CHANGED_FLAGS (d); | 5585 d->buffers_changed = 0; |
5586 d->clip_changed = 0; | |
5587 d->extents_changed = 0; | |
5588 d->faces_changed = 0; | |
5589 d->frame_changed = 0; | |
5590 d->glyphs_changed = 0; | |
5591 d->subwindows_changed = 0; | |
5592 d->icon_changed = 0; | |
5593 d->menubar_changed = 0; | |
5594 d->modeline_changed = 0; | |
5595 d->point_changed = 0; | |
5596 d->toolbar_changed = 0; | |
5597 d->windows_changed = 0; | |
5598 d->windows_structure_changed = 0; | |
6509 | 5599 |
6510 if (!size_change_failed) | 5600 if (!size_change_failed) |
6511 d->size_changed = 0; | 5601 d->size_changed = 0; |
6512 | 5602 |
6513 return 0; | 5603 return 0; |
6538 } | 5628 } |
6539 | 5629 |
6540 if (asynch_device_change_pending) | 5630 if (asynch_device_change_pending) |
6541 handle_asynch_device_change (); | 5631 handle_asynch_device_change (); |
6542 | 5632 |
6543 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && | 5633 if (!buffers_changed && !clip_changed && !extents_changed && |
6544 !disable_preemption && preemption_count < max_preempts) | 5634 !faces_changed && !frame_changed && !icon_changed && |
5635 !menubar_changed && !modeline_changed && !point_changed && | |
5636 !size_changed && !toolbar_changed && !windows_changed && | |
5637 !glyphs_changed && !subwindows_changed && | |
5638 !windows_structure_changed && !disable_preemption && | |
5639 preemption_count < max_preempts) | |
6545 goto done; | 5640 goto done; |
6546 | 5641 |
6547 DEVICE_LOOP_NO_BREAK (devcons, concons) | 5642 DEVICE_LOOP_NO_BREAK (devcons, concons) |
6548 { | 5643 { |
6549 struct device *d = XDEVICE (XCAR (devcons)); | 5644 struct device *d = XDEVICE (XCAR (devcons)); |
6550 int preempted; | 5645 int preempted; |
6551 | 5646 |
6552 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)) | 5647 if (d->buffers_changed || d->clip_changed || d->extents_changed || |
6553 { | 5648 d->faces_changed || d->frame_changed || d->icon_changed || |
6554 preempted = redisplay_device (d, 1); | 5649 d->menubar_changed || d->modeline_changed || d->point_changed || |
5650 d->size_changed || d->toolbar_changed || d->windows_changed || | |
5651 d->windows_structure_changed || | |
5652 d->glyphs_changed || d->subwindows_changed) | |
5653 { | |
5654 preempted = redisplay_device (d); | |
6555 | 5655 |
6556 if (preempted) | 5656 if (preempted) |
6557 { | 5657 { |
6558 preemption_count++; | 5658 preemption_count++; |
6559 RESET_CHANGED_SET_FLAGS; | 5659 RESET_CHANGED_SET_FLAGS; |
6566 } | 5666 } |
6567 } | 5667 } |
6568 preemption_count = 0; | 5668 preemption_count = 0; |
6569 | 5669 |
6570 /* Mark redisplay as accurate */ | 5670 /* Mark redisplay as accurate */ |
6571 GLOBAL_RESET_CHANGED_FLAGS; | 5671 buffers_changed = 0; |
5672 clip_changed = 0; | |
5673 extents_changed = 0; | |
5674 frame_changed = 0; | |
5675 glyphs_changed = 0; | |
5676 subwindows_changed = 0; | |
5677 icon_changed = 0; | |
5678 menubar_changed = 0; | |
5679 modeline_changed = 0; | |
5680 point_changed = 0; | |
5681 toolbar_changed = 0; | |
5682 windows_changed = 0; | |
5683 windows_structure_changed = 0; | |
6572 RESET_CHANGED_SET_FLAGS; | 5684 RESET_CHANGED_SET_FLAGS; |
6573 | 5685 |
6574 if (faces_changed) | 5686 if (faces_changed) |
6575 { | 5687 { |
6576 mark_all_faces_as_clean (); | 5688 mark_all_faces_as_clean (); |
6663 | 5775 |
6664 static void | 5776 static void |
6665 decode_mode_spec (struct window *w, Emchar spec, int type) | 5777 decode_mode_spec (struct window *w, Emchar spec, int type) |
6666 { | 5778 { |
6667 Lisp_Object obj = Qnil; | 5779 Lisp_Object obj = Qnil; |
6668 const char *str = NULL; | 5780 CONST char *str = NULL; |
6669 struct buffer *b = XBUFFER (w->buffer); | 5781 struct buffer *b = XBUFFER (w->buffer); |
6670 | 5782 |
6671 Dynarr_reset (mode_spec_bufbyte_string); | 5783 Dynarr_reset (mode_spec_bufbyte_string); |
6672 | 5784 |
6673 switch (spec) | 5785 switch (spec) |
6692 char buf[32]; | 5804 char buf[32]; |
6693 | 5805 |
6694 long_to_string (buf, col); | 5806 long_to_string (buf, col); |
6695 | 5807 |
6696 Dynarr_add_many (mode_spec_bufbyte_string, | 5808 Dynarr_add_many (mode_spec_bufbyte_string, |
6697 (const Bufbyte *) buf, strlen (buf)); | 5809 (CONST Bufbyte *) buf, strlen (buf)); |
6698 | 5810 |
6699 goto decode_mode_spec_done; | 5811 goto decode_mode_spec_done; |
6700 } | 5812 } |
6701 /* print the file coding system */ | 5813 /* print the file coding system */ |
6702 case 'C': | 5814 case 'C': |
6797 | 5909 |
6798 /* print percent of buffer above top of window, or Top, Bot or All */ | 5910 /* print percent of buffer above top of window, or Top, Bot or All */ |
6799 case 'p': | 5911 case 'p': |
6800 { | 5912 { |
6801 Bufpos pos = marker_position (w->start[type]); | 5913 Bufpos pos = marker_position (w->start[type]); |
5914 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
6802 | 5915 |
6803 /* This had better be while the desired lines are being done. */ | 5916 /* This had better be while the desired lines are being done. */ |
6804 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) | 5917 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) |
6805 { | 5918 { |
6806 if (pos <= BUF_BEGV (b)) | 5919 if (pos <= BUF_BEGV (b)) |
6813 else | 5926 else |
6814 { | 5927 { |
6815 /* This hard limit is ok since the string it will hold has a | 5928 /* This hard limit is ok since the string it will hold has a |
6816 fixed maximum length of 3. But just to be safe... */ | 5929 fixed maximum length of 3. But just to be safe... */ |
6817 char buf[10]; | 5930 char buf[10]; |
6818 Charcount chars = pos - BUF_BEGV (b); | 5931 |
6819 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | 5932 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total; |
6820 | |
6821 /* Avoid overflow on big buffers */ | |
6822 int percent = total > LONG_MAX/200 ? | |
6823 (chars + total/200) / (total / 100) : | |
6824 (chars * 100 + total/2) / total; | |
6825 | 5933 |
6826 /* We can't normally display a 3-digit number, so get us a | 5934 /* We can't normally display a 3-digit number, so get us a |
6827 2-digit number that is close. */ | 5935 2-digit number that is close. */ |
6828 if (percent == 100) | 5936 if (total == 100) |
6829 percent = 99; | 5937 total = 99; |
6830 | 5938 |
6831 sprintf (buf, "%d%%", percent); | 5939 sprintf (buf, "%2d%%", total); |
6832 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, | 5940 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, |
6833 strlen (buf)); | 5941 strlen (buf)); |
6834 | 5942 |
6835 goto decode_mode_spec_done; | 5943 goto decode_mode_spec_done; |
6836 } | 5944 } |
6841 Top, or print Bottom or All */ | 5949 Top, or print Bottom or All */ |
6842 case 'P': | 5950 case 'P': |
6843 { | 5951 { |
6844 Bufpos toppos = marker_position (w->start[type]); | 5952 Bufpos toppos = marker_position (w->start[type]); |
6845 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type]; | 5953 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type]; |
5954 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | |
6846 | 5955 |
6847 /* botpos is only accurate as of the last redisplay, so we can | 5956 /* botpos is only accurate as of the last redisplay, so we can |
6848 only treat it as a hint. In particular, after erase-buffer, | 5957 only treat it as a hint. In particular, after erase-buffer, |
6849 botpos may be negative. */ | 5958 botpos may be negative. */ |
6850 if (botpos < toppos) | 5959 if (botpos < toppos) |
6860 else | 5969 else |
6861 { | 5970 { |
6862 /* This hard limit is ok since the string it will hold has a | 5971 /* This hard limit is ok since the string it will hold has a |
6863 fixed maximum length of around 6. But just to be safe... */ | 5972 fixed maximum length of around 6. But just to be safe... */ |
6864 char buf[10]; | 5973 char buf[10]; |
6865 Charcount chars = botpos - BUF_BEGV (b); | 5974 |
6866 Charcount total = BUF_ZV (b) - BUF_BEGV (b); | 5975 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total; |
6867 | |
6868 /* Avoid overflow on big buffers */ | |
6869 int percent = total > LONG_MAX/200 ? | |
6870 (chars + total/200) / (total / 100) : | |
6871 (chars * 100 + total/2) / max (total, 1); | |
6872 | 5976 |
6873 /* We can't normally display a 3-digit number, so get us a | 5977 /* We can't normally display a 3-digit number, so get us a |
6874 2-digit number that is close. */ | 5978 2-digit number that is close. */ |
6875 if (percent == 100) | 5979 if (total == 100) |
6876 percent = 99; | 5980 total = 99; |
6877 | 5981 |
6878 if (toppos <= BUF_BEGV (b)) | 5982 if (toppos <= BUF_BEGV (b)) |
6879 sprintf (buf, "Top%d%%", percent); | 5983 sprintf (buf, "Top%2d%%", total); |
6880 else | 5984 else |
6881 sprintf (buf, "%d%%", percent); | 5985 sprintf (buf, "%2d%%", total); |
6882 | 5986 |
6883 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, | 5987 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, |
6884 strlen (buf)); | 5988 strlen (buf)); |
6885 | 5989 |
6886 goto decode_mode_spec_done; | 5990 goto decode_mode_spec_done; |
6979 | 6083 |
6980 | 6084 |
6981 /* Given an array of display lines, free them and all data structures | 6085 /* Given an array of display lines, free them and all data structures |
6982 contained within them. */ | 6086 contained within them. */ |
6983 | 6087 |
6984 void | 6088 static void |
6985 free_display_lines (display_line_dynarr *dla) | 6089 free_display_lines (display_line_dynarr *dla) |
6986 { | 6090 { |
6987 int line; | 6091 int line; |
6988 | 6092 |
6989 for (line = 0; line < Dynarr_largest (dla); line++) | 6093 for (line = 0; line < Dynarr_largest (dla); line++) |
7012 } | 6116 } |
7013 } | 6117 } |
7014 | 6118 |
7015 | 6119 |
7016 static void | 6120 static void |
7017 mark_glyph_block_dynarr (glyph_block_dynarr *gba) | 6121 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object)) |
7018 { | 6122 { |
7019 if (gba) | 6123 if (gba) |
7020 { | 6124 { |
7021 glyph_block *gb = Dynarr_atp (gba, 0); | 6125 glyph_block *gb = Dynarr_atp (gba, 0); |
7022 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba)); | 6126 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba)); |
7023 | 6127 |
7024 for (; gb < gb_last; gb++) | 6128 for (; gb < gb_last; gb++) |
7025 { | 6129 { |
7026 if (!NILP (gb->glyph)) | 6130 if (!NILP (gb->glyph)) |
7027 mark_object (gb->glyph); | 6131 markobj (gb->glyph); |
7028 if (!NILP (gb->extent)) | 6132 if (!NILP (gb->extent)) |
7029 mark_object (gb->extent); | 6133 markobj (gb->extent); |
7030 } | 6134 } |
7031 } | 6135 } |
7032 } | 6136 } |
7033 | 6137 |
7034 /* See the comment in image_instantiate_cache_result as to why marking | 6138 static void |
7035 the glyph will also mark the image_instance. */ | 6139 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object)) |
7036 void | |
7037 mark_redisplay_structs (display_line_dynarr *dla) | |
7038 { | 6140 { |
7039 display_line *dl = Dynarr_atp (dla, 0); | 6141 display_line *dl = Dynarr_atp (dla, 0); |
7040 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla)); | 6142 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla)); |
7041 | 6143 |
7042 for (; dl < dl_last; dl++) | 6144 for (; dl < dl_last; dl++) |
7054 for (; r < r_last; r++) | 6156 for (; r < r_last; r++) |
7055 { | 6157 { |
7056 if (r->type == RUNE_DGLYPH) | 6158 if (r->type == RUNE_DGLYPH) |
7057 { | 6159 { |
7058 if (!NILP (r->object.dglyph.glyph)) | 6160 if (!NILP (r->object.dglyph.glyph)) |
7059 mark_object (r->object.dglyph.glyph); | 6161 markobj (r->object.dglyph.glyph); |
7060 if (!NILP (r->object.dglyph.extent)) | 6162 if (!NILP (r->object.dglyph.extent)) |
7061 mark_object (r->object.dglyph.extent); | 6163 markobj (r->object.dglyph.extent); |
7062 } | 6164 } |
7063 } | 6165 } |
7064 } | 6166 } |
7065 | 6167 |
7066 mark_glyph_block_dynarr (dl->left_glyphs); | 6168 mark_glyph_block_dynarr (dl->left_glyphs, markobj); |
7067 mark_glyph_block_dynarr (dl->right_glyphs); | 6169 mark_glyph_block_dynarr (dl->right_glyphs, markobj); |
7068 } | 6170 } |
7069 } | 6171 } |
7070 | 6172 |
7071 static void | 6173 static void |
7072 mark_window_mirror (struct window_mirror *mir) | 6174 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object)) |
7073 { | 6175 { |
7074 mark_redisplay_structs (mir->current_display_lines); | 6176 mark_redisplay_structs (mir->current_display_lines, markobj); |
7075 mark_redisplay_structs (mir->desired_display_lines); | 6177 mark_redisplay_structs (mir->desired_display_lines, markobj); |
7076 | 6178 |
7077 if (mir->next) | 6179 if (mir->next) |
7078 mark_window_mirror (mir->next); | 6180 mark_window_mirror (mir->next, markobj); |
7079 | 6181 |
7080 if (mir->hchild) | 6182 if (mir->hchild) |
7081 mark_window_mirror (mir->hchild); | 6183 mark_window_mirror (mir->hchild, markobj); |
7082 else if (mir->vchild) | 6184 else if (mir->vchild) |
7083 mark_window_mirror (mir->vchild); | 6185 mark_window_mirror (mir->vchild, markobj); |
7084 } | 6186 } |
7085 | 6187 |
7086 void | 6188 void |
7087 mark_redisplay (void) | 6189 mark_redisplay (void (*markobj)(Lisp_Object)) |
7088 { | 6190 { |
7089 Lisp_Object frmcons, devcons, concons; | 6191 Lisp_Object frmcons, devcons, concons; |
7090 | 6192 |
7091 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) | 6193 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons) |
7092 { | 6194 { |
7093 struct frame *f = XFRAME (XCAR (frmcons)); | 6195 struct frame *f = XFRAME (XCAR (frmcons)); |
7094 update_frame_window_mirror (f); | 6196 update_frame_window_mirror (f); |
7095 mark_window_mirror (f->root_mirror); | 6197 mark_window_mirror (f->root_mirror, markobj); |
7096 mark_gutters (f); | |
7097 } | 6198 } |
7098 } | 6199 } |
7099 | 6200 |
7100 /***************************************************************************** | 6201 /***************************************************************************** |
7101 Line Start Cache Description and Rationale | 6202 Line Start Cache Description and Rationale |
7155 applicable. | 6256 applicable. |
7156 ****************************************************************************/ | 6257 ****************************************************************************/ |
7157 | 6258 |
7158 /* This will get used quite a bit so we don't want to be constantly | 6259 /* This will get used quite a bit so we don't want to be constantly |
7159 allocating and freeing it. */ | 6260 allocating and freeing it. */ |
7160 static line_start_cache_dynarr *internal_cache; | 6261 line_start_cache_dynarr *internal_cache; |
7161 | 6262 |
7162 /* Makes internal_cache represent the TYPE display structs and only | 6263 /* Makes internal_cache represent the TYPE display structs and only |
7163 the TYPE display structs. */ | 6264 the TYPE display structs. */ |
7164 | 6265 |
7165 static void | 6266 static void |
7176 if (dl->modeline) | 6277 if (dl->modeline) |
7177 continue; | 6278 continue; |
7178 else | 6279 else |
7179 { | 6280 { |
7180 struct line_start_cache lsc; | 6281 struct line_start_cache lsc; |
7181 | 6282 |
7182 lsc.start = dl->bufpos; | 6283 lsc.start = dl->bufpos; |
7183 lsc.end = dl->end_bufpos; | 6284 lsc.end = dl->end_bufpos; |
7184 lsc.height = dl->ascent + dl->descent; | 6285 lsc.height = dl->ascent + dl->descent; |
7185 | 6286 |
7186 Dynarr_add (internal_cache, lsc); | 6287 Dynarr_add (internal_cache, lsc); |
7449 | 6550 |
7450 int | 6551 int |
7451 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point) | 6552 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point) |
7452 { | 6553 { |
7453 struct buffer *b = XBUFFER (w->buffer); | 6554 struct buffer *b = XBUFFER (w->buffer); |
7454 int pixpos = -WINDOW_TEXT_TOP_CLIP(w); | 6555 int pixpos = 0; |
7455 int bottom = WINDOW_TEXT_HEIGHT (w); | 6556 int bottom = WINDOW_TEXT_HEIGHT (w); |
7456 int start_elt; | 6557 int start_elt; |
7457 | 6558 |
7458 /* If point is before the intended start it obviously can't be visible. */ | 6559 /* If point is before the intended start it obviously can't be visible. */ |
7459 if (point < startp) | 6560 if (point < startp) |
7528 /* For the given window W, if display starts at STARTP, what will be | 6629 /* For the given window W, if display starts at STARTP, what will be |
7529 the buffer position at the beginning or end of the last line | 6630 the buffer position at the beginning or end of the last line |
7530 displayed. The end of the last line is also know as the window end | 6631 displayed. The end of the last line is also know as the window end |
7531 position. | 6632 position. |
7532 | 6633 |
7533 WARNING: It is possible that rediplay failed to layout any lines for the | |
7534 windows. Under normal circumstances this is rare. However it seems that it | |
7535 does occur in the following situation: A mouse event has come in and we | |
7536 need to compute its location in a window. That code (in | |
7537 pixel_to_glyph_translation) already can handle 0 as an error return value. | |
7538 | |
7539 #### With a little work this could probably be reworked as just a | 6634 #### With a little work this could probably be reworked as just a |
7540 call to start_with_line_at_pixpos. */ | 6635 call to start_with_line_at_pixpos. */ |
7541 | 6636 |
7542 static Bufpos | 6637 static Bufpos |
7543 start_end_of_last_line (struct window *w, Bufpos startp, int end, | 6638 start_end_of_last_line (struct window *w, Bufpos startp, int end) |
7544 int may_error) | |
7545 { | 6639 { |
7546 struct buffer *b = XBUFFER (w->buffer); | 6640 struct buffer *b = XBUFFER (w->buffer); |
7547 line_start_cache_dynarr *cache = w->line_start_cache; | 6641 line_start_cache_dynarr *cache = w->line_start_cache; |
7548 int pixpos = 0; | 6642 int pixpos = 0; |
7549 int bottom = WINDOW_TEXT_HEIGHT (w); | 6643 int bottom = WINDOW_TEXT_HEIGHT (w); |
7559 startp = BUF_ZV (b); | 6653 startp = BUF_ZV (b); |
7560 cur_start = startp; | 6654 cur_start = startp; |
7561 | 6655 |
7562 start_elt = point_in_line_start_cache (w, cur_start, 0); | 6656 start_elt = point_in_line_start_cache (w, cur_start, 0); |
7563 if (start_elt == -1) | 6657 if (start_elt == -1) |
7564 return may_error ? 0 : startp; | 6658 abort (); /* this had better never happen */ |
7565 | 6659 |
7566 while (1) | 6660 while (1) |
7567 { | 6661 { |
7568 int height = Dynarr_atp (cache, start_elt)->height; | 6662 int height = Dynarr_atp (cache, start_elt)->height; |
7569 | 6663 |
7623 the buffer position at the beginning of the last line displayed. */ | 6717 the buffer position at the beginning of the last line displayed. */ |
7624 | 6718 |
7625 Bufpos | 6719 Bufpos |
7626 start_of_last_line (struct window *w, Bufpos startp) | 6720 start_of_last_line (struct window *w, Bufpos startp) |
7627 { | 6721 { |
7628 return start_end_of_last_line (w, startp, 0 , 0); | 6722 return start_end_of_last_line (w, startp, 0); |
7629 } | 6723 } |
7630 | 6724 |
7631 /* For the given window W, if display starts at STARTP, what will be | 6725 /* For the given window W, if display starts at STARTP, what will be |
7632 the buffer position at the end of the last line displayed. This is | 6726 the buffer position at the end of the last line displayed. This is |
7633 also know as the window end position. */ | 6727 also know as the window end position. */ |
7634 | 6728 |
7635 Bufpos | 6729 Bufpos |
7636 end_of_last_line (struct window *w, Bufpos startp) | 6730 end_of_last_line (struct window *w, Bufpos startp) |
7637 { | 6731 { |
7638 return start_end_of_last_line (w, startp, 1, 0); | 6732 return start_end_of_last_line (w, startp, 1); |
7639 } | 6733 } |
7640 | |
7641 static Bufpos | |
7642 end_of_last_line_may_error (struct window *w, Bufpos startp) | |
7643 { | |
7644 return start_end_of_last_line (w, startp, 1, 1); | |
7645 } | |
7646 | |
7647 | 6734 |
7648 /* For window W, what does the starting position have to be so that | 6735 /* For window W, what does the starting position have to be so that |
7649 the line containing POINT will cover pixel position PIXPOS. */ | 6736 the line containing POINT will cover pixel position PIXPOS. */ |
7650 | 6737 |
7651 Bufpos | 6738 Bufpos |
7688 else | 6775 else |
7689 return cur_pos; | 6776 return cur_pos; |
7690 } | 6777 } |
7691 | 6778 |
7692 cur_elt--; | 6779 cur_elt--; |
7693 while (cur_elt < 0) | 6780 if (cur_elt < 0) |
7694 { | 6781 { |
7695 Bufpos from, to; | 6782 Bufpos from, to; |
7696 int win_char_height; | 6783 int win_char_height; |
7697 | 6784 |
7698 if (cur_pos <= BUF_BEGV (b)) | 6785 if (cur_pos <= BUF_BEGV (b)) |
7708 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); | 6795 from = find_next_newline_no_quit (b, cur_pos, -win_char_height); |
7709 to = line_start_cache_end (w); | 6796 to = line_start_cache_end (w); |
7710 update_line_start_cache (w, from, to, point, 0); | 6797 update_line_start_cache (w, from, to, point, 0); |
7711 | 6798 |
7712 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; | 6799 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; |
7713 assert (cur_elt >= -1); | 6800 assert (cur_elt >= 0); |
7714 /* This used to be cur_elt>=0 under the assumption that if | |
7715 point is in the top line and not at BUF_BEGV, then | |
7716 setting the window_start to a newline before the start of | |
7717 the first line will always cause scrolling. | |
7718 | |
7719 However in my (jv) opinion this is wrong. That new line | |
7720 can be hidden in various ways: invisible extents, an | |
7721 explicit window-start not at a newline character etc. | |
7722 The existence of those are indeed known to create crashes | |
7723 on that assert. So we have no option but to continue the | |
7724 search if we found point at the top of the line_start_cache | |
7725 again. */ | |
7726 cur_pos = Dynarr_atp (w->line_start_cache,0)->start; | |
7727 } | 6801 } |
7728 prev_pos = cur_pos; | 6802 prev_pos = cur_pos; |
7729 } | 6803 } |
7730 } | 6804 } |
7731 | 6805 |
7826 line_start_cache_dynarr *cache = w->line_start_cache; | 6900 line_start_cache_dynarr *cache = w->line_start_cache; |
7827 Bufpos low_bound, high_bound; | 6901 Bufpos low_bound, high_bound; |
7828 | 6902 |
7829 validate_line_start_cache (w); | 6903 validate_line_start_cache (w); |
7830 w->line_cache_validation_override++; | 6904 w->line_cache_validation_override++; |
6905 updating_line_start_cache = 1; | |
7831 | 6906 |
7832 if (from < BUF_BEGV (b)) | 6907 if (from < BUF_BEGV (b)) |
7833 from = BUF_BEGV (b); | 6908 from = BUF_BEGV (b); |
7834 if (to > BUF_ZV (b)) | 6909 if (to > BUF_ZV (b)) |
7835 to = BUF_ZV (b); | 6910 to = BUF_ZV (b); |
7836 | 6911 |
7837 if (from > to) | 6912 if (from > to) |
7838 { | 6913 { |
6914 updating_line_start_cache = 0; | |
7839 w->line_cache_validation_override--; | 6915 w->line_cache_validation_override--; |
7840 return; | 6916 return; |
7841 } | 6917 } |
7842 | 6918 |
7843 if (Dynarr_length (cache)) | 6919 if (Dynarr_length (cache)) |
7846 high_bound = line_start_cache_end (w); | 6922 high_bound = line_start_cache_end (w); |
7847 | 6923 |
7848 /* Check to see if the desired range is already in the cache. */ | 6924 /* Check to see if the desired range is already in the cache. */ |
7849 if (from >= low_bound && to <= high_bound) | 6925 if (from >= low_bound && to <= high_bound) |
7850 { | 6926 { |
6927 updating_line_start_cache = 0; | |
7851 w->line_cache_validation_override--; | 6928 w->line_cache_validation_override--; |
7852 return; | 6929 return; |
7853 } | 6930 } |
7854 | 6931 |
7855 /* Check to make sure that the desired range is adjacent to the | 6932 /* Check to make sure that the desired range is adjacent to the |
7874 Bufpos start, end; | 6951 Bufpos start, end; |
7875 | 6952 |
7876 update_internal_cache_list (w, DESIRED_DISP); | 6953 update_internal_cache_list (w, DESIRED_DISP); |
7877 if (!Dynarr_length (internal_cache)) | 6954 if (!Dynarr_length (internal_cache)) |
7878 { | 6955 { |
6956 updating_line_start_cache = 0; | |
7879 w->line_cache_validation_override--; | 6957 w->line_cache_validation_override--; |
7880 return; | 6958 return; |
7881 } | 6959 } |
7882 | 6960 |
7883 start = Dynarr_atp (internal_cache, 0)->start; | 6961 start = Dynarr_atp (internal_cache, 0)->start; |
7901 | 6979 |
7902 if (!Dynarr_length (cache)) | 6980 if (!Dynarr_length (cache)) |
7903 { | 6981 { |
7904 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), | 6982 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), |
7905 Dynarr_length (internal_cache)); | 6983 Dynarr_length (internal_cache)); |
6984 updating_line_start_cache = 0; | |
7906 w->line_cache_validation_override--; | 6985 w->line_cache_validation_override--; |
7907 return; | 6986 return; |
7908 } | 6987 } |
7909 | 6988 |
7910 /* An extra check just in case the calling function didn't pass in | 6989 /* An extra check just in case the calling function didn't pass in |
7911 the bounds of the DESIRED structs in the first place. */ | 6990 the bounds of the DESIRED structs in the first place. */ |
7912 if (start >= low_bound && end <= high_bound) | 6991 if (start >= low_bound && end <= high_bound) |
7913 { | 6992 { |
6993 updating_line_start_cache = 0; | |
7914 w->line_cache_validation_override--; | 6994 w->line_cache_validation_override--; |
7915 return; | 6995 return; |
7916 } | 6996 } |
7917 | 6997 |
7918 /* At this point we know that the internal cache partially overlaps | 6998 /* At this point we know that the internal cache partially overlaps |
7931 if (!(ic_elt >= 0)) | 7011 if (!(ic_elt >= 0)) |
7932 { | 7012 { |
7933 Dynarr_reset (cache); | 7013 Dynarr_reset (cache); |
7934 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), | 7014 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), |
7935 Dynarr_length (internal_cache)); | 7015 Dynarr_length (internal_cache)); |
7016 updating_line_start_cache = 0; | |
7936 w->line_cache_validation_override--; | 7017 w->line_cache_validation_override--; |
7937 return; | 7018 return; |
7938 } | 7019 } |
7939 | 7020 |
7940 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0), | 7021 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0), |
7956 if (!(ic_elt < Dynarr_length (internal_cache))) | 7037 if (!(ic_elt < Dynarr_length (internal_cache))) |
7957 { | 7038 { |
7958 Dynarr_reset (cache); | 7039 Dynarr_reset (cache); |
7959 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), | 7040 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0), |
7960 Dynarr_length (internal_cache)); | 7041 Dynarr_length (internal_cache)); |
7042 updating_line_start_cache = 0; | |
7961 w->line_cache_validation_override--; | 7043 w->line_cache_validation_override--; |
7962 return; | 7044 return; |
7963 } | 7045 } |
7964 | 7046 |
7965 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), | 7047 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt), |
7966 Dynarr_length (internal_cache) - ic_elt); | 7048 Dynarr_length (internal_cache) - ic_elt); |
7967 } | 7049 } |
7968 | 7050 |
7051 updating_line_start_cache = 0; | |
7969 w->line_cache_validation_override--; | 7052 w->line_cache_validation_override--; |
7970 return; | 7053 return; |
7971 } | 7054 } |
7972 | 7055 |
7973 if (!Dynarr_length (cache) || from < low_bound) | 7056 if (!Dynarr_length (cache) || from < low_bound) |
7983 | 7066 |
7984 regenerate_window (w, startp, point, CMOTION_DISP); | 7067 regenerate_window (w, startp, point, CMOTION_DISP); |
7985 update_internal_cache_list (w, CMOTION_DISP); | 7068 update_internal_cache_list (w, CMOTION_DISP); |
7986 | 7069 |
7987 /* If this assert is triggered then regenerate_window failed | 7070 /* If this assert is triggered then regenerate_window failed |
7988 to layout a single line. This is not possible since we | 7071 to layout a single line. That is not supposed to be |
7989 force at least a single line to be layout for CMOTION_DISP */ | 7072 possible because we impose a minimum height on the buffer |
7990 assert (Dynarr_length (internal_cache)); | 7073 and override vertical clip when we are in here. */ |
7074 /* #### Ah, but it is because the window may temporarily | |
7075 exist but not have any lines at all if the minibuffer is | |
7076 real big. Look into that situation better. */ | |
7077 if (!Dynarr_length (internal_cache)) | |
7078 { | |
7079 if (old_lb == -1 && low_bound == -1) | |
7080 { | |
7081 updating_line_start_cache = 0; | |
7082 w->line_cache_validation_override--; | |
7083 return; | |
7084 } | |
7085 | |
7086 assert (Dynarr_length (internal_cache)); | |
7087 } | |
7991 assert (startp == Dynarr_atp (internal_cache, 0)->start); | 7088 assert (startp == Dynarr_atp (internal_cache, 0)->start); |
7992 | 7089 |
7993 ic_elt = Dynarr_length (internal_cache) - 1; | 7090 ic_elt = Dynarr_length (internal_cache) - 1; |
7994 if (low_bound != -1) | 7091 if (low_bound != -1) |
7995 { | 7092 { |
8031 if (startp < low_bound || low_bound == -1) | 7128 if (startp < low_bound || low_bound == -1) |
8032 low_bound = startp; | 7129 low_bound = startp; |
8033 startp = new_startp; | 7130 startp = new_startp; |
8034 if (startp > BUF_ZV (b)) | 7131 if (startp > BUF_ZV (b)) |
8035 { | 7132 { |
7133 updating_line_start_cache = 0; | |
8036 w->line_cache_validation_override--; | 7134 w->line_cache_validation_override--; |
8037 return; | 7135 return; |
8038 } | 7136 } |
8039 } | 7137 } |
8040 } | 7138 } |
8064 startp = high_bound + 1; | 7162 startp = high_bound + 1; |
8065 } | 7163 } |
8066 while (to > high_bound); | 7164 while (to > high_bound); |
8067 } | 7165 } |
8068 | 7166 |
7167 updating_line_start_cache = 0; | |
8069 w->line_cache_validation_override--; | 7168 w->line_cache_validation_override--; |
8070 assert (to <= high_bound); | 7169 assert (to <= high_bound); |
8071 } | 7170 } |
8072 | 7171 |
8073 | 7172 |
8771 /* #### This should be checked out some more to determine what | 7870 /* #### This should be checked out some more to determine what |
8772 should really be going on. */ | 7871 should really be going on. */ |
8773 if (!MARKERP ((*w)->start[CURRENT_DISP])) | 7872 if (!MARKERP ((*w)->start[CURRENT_DISP])) |
8774 *closest = 0; | 7873 *closest = 0; |
8775 else | 7874 else |
8776 *closest = end_of_last_line_may_error (*w, | 7875 *closest = end_of_last_line (*w, |
8777 marker_position ((*w)->start[CURRENT_DISP])); | 7876 marker_position ((*w)->start[CURRENT_DISP])); |
8778 *col = 0; | 7877 *col = 0; |
8779 UPDATE_CACHE_RETURN; | 7878 UPDATE_CACHE_RETURN; |
8780 } | 7879 } |
8781 #undef UPDATE_CACHE_RETURN | 7880 #undef UPDATE_CACHE_RETURN |
8804 struct frame *f = XFRAME (XCAR (frmcons)); | 7903 struct frame *f = XFRAME (XCAR (frmcons)); |
8805 | 7904 |
8806 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) | 7905 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f)) |
8807 { | 7906 { |
8808 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); | 7907 Lisp_Object window = FRAME_MINIBUF_WINDOW (f); |
8809 | |
8810 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
8811 | |
8812 /* | 7908 /* |
8813 * If the frame size has changed, there may be random | 7909 * If the frame size has changed, there may be random |
8814 * chud on the screen left from previous messages | 7910 * chud on the screen left from previous messages |
8815 * because redisplay_frame hasn't been called yet. | 7911 * because redisplay_frame hasn't been called yet. |
8816 * Clear the screen to get rid of the potential mess. | 7912 * Clear the screen to get rid of the potential mess. |
8817 */ | 7913 */ |
8818 if (f->echo_area_garbaged) | 7914 if (f->echo_area_garbaged) |
8819 { | 7915 { |
8820 MAYBE_DEVMETH (d, clear_frame, (f)); | 7916 DEVMETH (d, clear_frame, (f)); |
8821 f->echo_area_garbaged = 0; | 7917 f->echo_area_garbaged = 0; |
8822 } | 7918 } |
8823 redisplay_window (window, 0); | 7919 redisplay_window (window, 0); |
8824 MAYBE_DEVMETH (d, frame_output_end, (f)); | |
8825 | |
8826 call_redisplay_end_triggers (XWINDOW (window), 0); | 7920 call_redisplay_end_triggers (XWINDOW (window), 0); |
8827 } | 7921 } |
8828 } | 7922 } |
7923 | |
7924 /* We now call the output_end routine for tty frames. We delay | |
7925 doing so in order to avoid cursor flicker. So much for 100% | |
7926 encapsulation. */ | |
7927 if (DEVICE_TTY_P (d)) | |
7928 DEVMETH (d, output_end, (d)); | |
8829 } | 7929 } |
8830 | 7930 |
8831 return Qnil; | 7931 return Qnil; |
8832 } | 7932 } |
8833 | 7933 |
8857 disable_preemption++; | 7957 disable_preemption++; |
8858 } | 7958 } |
8859 | 7959 |
8860 f->clear = 1; | 7960 f->clear = 1; |
8861 redisplay_frame (f, 1); | 7961 redisplay_frame (f, 1); |
8862 | |
8863 /* See the comment in Fredisplay_frame. */ | |
8864 RESET_CHANGED_SET_FLAGS; | |
8865 | 7962 |
8866 return unbind_to (count, Qnil); | 7963 return unbind_to (count, Qnil); |
8867 } | 7964 } |
8868 | 7965 |
8869 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* | 7966 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /* |
8888 disable_preemption++; | 7985 disable_preemption++; |
8889 } | 7986 } |
8890 | 7987 |
8891 redisplay_frame (f, 1); | 7988 redisplay_frame (f, 1); |
8892 | 7989 |
8893 /* If we don't reset the global redisplay flafs here, subsequent | |
8894 changes to the display will not get registered by redisplay | |
8895 because it thinks it already has registered changes. If you | |
8896 really knew what you were doing you could confuse redisplay by | |
8897 calling Fredisplay_frame while updating another frame. We assume | |
8898 that if you know what you are doing you will not be that | |
8899 stupid. */ | |
8900 RESET_CHANGED_SET_FLAGS; | |
8901 | |
8902 return unbind_to (count, Qnil); | 7990 return unbind_to (count, Qnil); |
8903 } | 7991 } |
8904 | 7992 |
8905 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* | 7993 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /* |
8906 Clear device DEVICE and output again what is supposed to appear on it. | 7994 Clear device DEVICE and output again what is supposed to appear on it. |
8924 | 8012 |
8925 DEVICE_FRAME_LOOP (frmcons, d) | 8013 DEVICE_FRAME_LOOP (frmcons, d) |
8926 { | 8014 { |
8927 XFRAME (XCAR (frmcons))->clear = 1; | 8015 XFRAME (XCAR (frmcons))->clear = 1; |
8928 } | 8016 } |
8929 redisplay_device (d, 0); | 8017 redisplay_device (d); |
8930 | |
8931 /* See the comment in Fredisplay_frame. */ | |
8932 RESET_CHANGED_SET_FLAGS; | |
8933 | 8018 |
8934 return unbind_to (count, Qnil); | 8019 return unbind_to (count, Qnil); |
8935 } | 8020 } |
8936 | 8021 |
8937 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* | 8022 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /* |
8954 record_unwind_protect (restore_disable_preemption_value, | 8039 record_unwind_protect (restore_disable_preemption_value, |
8955 make_int (disable_preemption)); | 8040 make_int (disable_preemption)); |
8956 disable_preemption++; | 8041 disable_preemption++; |
8957 } | 8042 } |
8958 | 8043 |
8959 redisplay_device (d, 0); | 8044 redisplay_device (d); |
8960 | |
8961 /* See the comment in Fredisplay_frame. */ | |
8962 RESET_CHANGED_SET_FLAGS; | |
8963 | 8045 |
8964 return unbind_to (count, Qnil); | 8046 return unbind_to (count, Qnil); |
8965 } | 8047 } |
8966 | 8048 |
8967 /* Big lie. Big lie. This will force all modelines to be updated | 8049 /* Big lie. Big lie. This will force all modelines to be updated |
9009 global_redisplay_change. */ | 8091 global_redisplay_change. */ |
9010 MARK_CLIP_CHANGED; | 8092 MARK_CLIP_CHANGED; |
9011 return 0; | 8093 return 0; |
9012 } | 8094 } |
9013 | 8095 |
9014 /* This is called if the built-in glyphs have their properties | |
9015 changed. */ | |
9016 void | 8096 void |
9017 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property, | 8097 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property, |
9018 Lisp_Object locale) | 8098 Lisp_Object locale) |
9019 { | 8099 { |
9020 if (WINDOWP (locale)) | 8100 if (WINDOWP (locale)) |
9133 { | 8213 { |
9134 disable_preemption = 0; | 8214 disable_preemption = 0; |
9135 preemption_count = 0; | 8215 preemption_count = 0; |
9136 max_preempts = INIT_MAX_PREEMPTS; | 8216 max_preempts = INIT_MAX_PREEMPTS; |
9137 | 8217 |
9138 #ifndef PDUMP | |
9139 if (!initialized) | 8218 if (!initialized) |
9140 #endif | 8219 { |
9141 { | 8220 cmotion_display_lines = Dynarr_new (display_line); |
9142 if (!cmotion_display_lines) | 8221 mode_spec_bufbyte_string = Dynarr_new (Bufbyte); |
9143 cmotion_display_lines = Dynarr_new (display_line); | 8222 formatted_string_emchar_dynarr = Dynarr_new (Emchar); |
9144 if (!mode_spec_bufbyte_string) | 8223 formatted_string_extent_dynarr = Dynarr_new (EXTENT); |
9145 mode_spec_bufbyte_string = Dynarr_new (Bufbyte); | 8224 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); |
9146 if (!formatted_string_extent_dynarr) | 8225 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); |
9147 formatted_string_extent_dynarr = Dynarr_new (EXTENT); | 8226 internal_cache = Dynarr_new (line_start_cache); |
9148 if (!formatted_string_extent_start_dynarr) | 8227 xzero (formatted_string_display_line); |
9149 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount); | |
9150 if (!formatted_string_extent_end_dynarr) | |
9151 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount); | |
9152 if (!internal_cache) | |
9153 internal_cache = Dynarr_new (line_start_cache); | |
9154 } | 8228 } |
9155 | 8229 |
9156 /* window system is nil when in -batch mode */ | 8230 /* window system is nil when in -batch mode */ |
9157 if (!initialized || noninteractive) | 8231 if (!initialized || noninteractive) |
9158 return; | 8232 return; |
9219 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook"); | 8293 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook"); |
9220 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook"); | 8294 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook"); |
9221 #endif /* INHIBIT_REDISPLAY_HOOKS */ | 8295 #endif /* INHIBIT_REDISPLAY_HOOKS */ |
9222 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer"); | 8296 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer"); |
9223 defsymbol (&Qbar_cursor, "bar-cursor"); | 8297 defsymbol (&Qbar_cursor, "bar-cursor"); |
8298 defsymbol (&Qwindow_scroll_functions, "window-scroll-functions"); | |
9224 defsymbol (&Qredisplay_end_trigger_functions, | 8299 defsymbol (&Qredisplay_end_trigger_functions, |
9225 "redisplay-end-trigger-functions"); | 8300 "redisplay-end-trigger-functions"); |
9226 defsymbol (&Qtop_bottom, "top-bottom"); | |
9227 defsymbol (&Qbuffer_list_changed_hook, "buffer-list-changed-hook"); | |
9228 | 8301 |
9229 DEFSUBR (Fredisplay_echo_area); | 8302 DEFSUBR (Fredisplay_echo_area); |
9230 DEFSUBR (Fredraw_frame); | 8303 DEFSUBR (Fredraw_frame); |
9231 DEFSUBR (Fredisplay_frame); | 8304 DEFSUBR (Fredisplay_frame); |
9232 DEFSUBR (Fredraw_device); | 8305 DEFSUBR (Fredraw_device); |
9236 } | 8309 } |
9237 | 8310 |
9238 void | 8311 void |
9239 vars_of_redisplay (void) | 8312 vars_of_redisplay (void) |
9240 { | 8313 { |
9241 | |
9242 #if 0 | 8314 #if 0 |
9243 staticpro (&last_arrow_position); | 8315 staticpro (&last_arrow_position); |
9244 staticpro (&last_arrow_string); | 8316 staticpro (&last_arrow_string); |
9245 last_arrow_position = Qnil; | 8317 last_arrow_position = Qnil; |
9246 last_arrow_string = Qnil; | 8318 last_arrow_string = Qnil; |
9247 #endif /* 0 */ | 8319 #endif /* 0 */ |
8320 | |
8321 updating_line_start_cache = 0; | |
9248 | 8322 |
9249 /* #### Probably temporary */ | 8323 /* #### Probably temporary */ |
9250 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* | 8324 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* |
9251 \(Temporary) Setting this will impact the performance of the internal | 8325 \(Temporary) Setting this will impact the performance of the internal |
9252 line start cache. | 8326 line start cache. |
9280 */ , | 8354 */ , |
9281 redisplay_variable_changed); | 8355 redisplay_variable_changed); |
9282 Voverlay_arrow_position = Qnil; | 8356 Voverlay_arrow_position = Qnil; |
9283 | 8357 |
9284 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* | 8358 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /* |
9285 String or glyph to display as an arrow. See also `overlay-arrow-position'. | 8359 String to display as an arrow. See also `overlay-arrow-position'. |
9286 (Note that despite the name of this variable, it can be set to a glyph as | |
9287 well as a string.) | |
9288 */ , | 8360 */ , |
9289 redisplay_variable_changed); | 8361 redisplay_variable_changed); |
9290 Voverlay_arrow_string = Qnil; | 8362 Voverlay_arrow_string = Qnil; |
9291 | 8363 |
9292 DEFVAR_INT ("scroll-step", &scroll_step /* | 8364 DEFVAR_INT ("scroll-step", &scroll_step /* |
9306 *Non-nil means truncate lines in all windows less than full frame wide. | 8378 *Non-nil means truncate lines in all windows less than full frame wide. |
9307 */ , | 8379 */ , |
9308 redisplay_variable_changed); | 8380 redisplay_variable_changed); |
9309 truncate_partial_width_windows = 1; | 8381 truncate_partial_width_windows = 1; |
9310 | 8382 |
9311 DEFVAR_LISP ("visible-bell", &Vvisible_bell /* | 8383 DEFVAR_BOOL ("visible-bell", &visible_bell /* |
9312 *Non-nil substitutes a visual signal for the audible bell. | 8384 *Non-nil means try to flash the frame to represent a bell. |
9313 | |
9314 Default behavior is to flash the whole screen. On some platforms, | |
9315 special effects are available using the following values: | |
9316 | |
9317 'display Flash the whole screen (ie, the default behavior). | |
9318 'top-bottom Flash only the top and bottom lines of the selected frame. | |
9319 | |
9320 When effects are unavailable on a platform, the visual bell is the | |
9321 default, whole screen. (Currently only X supports any special effects.) | |
9322 */ ); | 8385 */ ); |
9323 Vvisible_bell = Qnil; | 8386 visible_bell = 0; |
9324 | 8387 |
9325 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* | 8388 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /* |
9326 *Non-nil means no need to redraw entire frame after suspending. | 8389 *Non-nil means no need to redraw entire frame after suspending. |
9327 A non-nil value is useful if the terminal can automatically preserve | 8390 A non-nil value is useful if the terminal can automatically preserve |
9328 Emacs's frame display when you reenter Emacs. | 8391 Emacs's frame display when you reenter Emacs. |
9339 instead. | 8402 instead. |
9340 */ ); | 8403 */ ); |
9341 Vwindow_system = Qnil; | 8404 Vwindow_system = Qnil; |
9342 | 8405 |
9343 /* #### Temporary shit until window-system is eliminated. */ | 8406 /* #### Temporary shit until window-system is eliminated. */ |
9344 DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /* | 8407 DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /* |
9345 DON'T TOUCH | 8408 DON'T TOUCH |
9346 */ ); | 8409 */ ); |
9347 Vinitial_window_system = Qnil; | 8410 Vinitial_window_system = Qnil; |
9348 | 8411 |
9349 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* | 8412 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /* |
9369 Vbar_cursor = Qnil; | 8432 Vbar_cursor = Qnil; |
9370 | 8433 |
9371 #ifndef INHIBIT_REDISPLAY_HOOKS | 8434 #ifndef INHIBIT_REDISPLAY_HOOKS |
9372 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /* | 8435 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /* |
9373 Function or functions to run before every redisplay. | 8436 Function or functions to run before every redisplay. |
8437 Functions on this hook must be careful to avoid signalling errors! | |
9374 */ ); | 8438 */ ); |
9375 Vpre_redisplay_hook = Qnil; | 8439 Vpre_redisplay_hook = Qnil; |
9376 | 8440 |
9377 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /* | 8441 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /* |
9378 Function or functions to run after every redisplay. | 8442 Function or functions to run after every redisplay. |
8443 Functions on this hook must be careful to avoid signalling errors! | |
9379 */ ); | 8444 */ ); |
9380 Vpost_redisplay_hook = Qnil; | 8445 Vpost_redisplay_hook = Qnil; |
9381 #endif /* INHIBIT_REDISPLAY_HOOKS */ | 8446 #endif /* INHIBIT_REDISPLAY_HOOKS */ |
9382 | |
9383 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /* | |
9384 Function or functions to call when a frame's buffer list has changed. | |
9385 This is called during redisplay, before redisplaying each frame. | |
9386 Functions on this hook are called with one argument, the frame. | |
9387 */ ); | |
9388 Vbuffer_list_changed_hook = Qnil; | |
9389 | 8447 |
9390 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* | 8448 DEFVAR_INT ("display-warning-tick", &display_warning_tick /* |
9391 Bump this to tell the C code to call `display-warning-buffer' | 8449 Bump this to tell the C code to call `display-warning-buffer' |
9392 at next redisplay. You should not normally change this; the function | 8450 at next redisplay. You should not normally change this; the function |
9393 `display-warning' automatically does this at appropriate times. | 8451 `display-warning' automatically does this at appropriate times. |
9443 This is a specifier; use `set-specifier' to change it. | 8501 This is a specifier; use `set-specifier' to change it. |
9444 */ ); | 8502 */ ); |
9445 Vleft_margin_width = Fmake_specifier (Qnatnum); | 8503 Vleft_margin_width = Fmake_specifier (Qnatnum); |
9446 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); | 8504 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero))); |
9447 set_specifier_caching (Vleft_margin_width, | 8505 set_specifier_caching (Vleft_margin_width, |
9448 offsetof (struct window, left_margin_width), | 8506 slot_offset (struct window, left_margin_width), |
9449 some_window_value_changed, | 8507 some_window_value_changed, |
9450 offsetof (struct frame, left_margin_width), | 8508 slot_offset (struct frame, left_margin_width), |
9451 margin_width_changed_in_frame); | 8509 margin_width_changed_in_frame); |
9452 | 8510 |
9453 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* | 8511 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /* |
9454 *Width of right margin. | 8512 *Width of right margin. |
9455 This is a specifier; use `set-specifier' to change it. | 8513 This is a specifier; use `set-specifier' to change it. |
9456 */ ); | 8514 */ ); |
9457 Vright_margin_width = Fmake_specifier (Qnatnum); | 8515 Vright_margin_width = Fmake_specifier (Qnatnum); |
9458 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); | 8516 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero))); |
9459 set_specifier_caching (Vright_margin_width, | 8517 set_specifier_caching (Vright_margin_width, |
9460 offsetof (struct window, right_margin_width), | 8518 slot_offset (struct window, right_margin_width), |
9461 some_window_value_changed, | 8519 some_window_value_changed, |
9462 offsetof (struct frame, right_margin_width), | 8520 slot_offset (struct frame, right_margin_width), |
9463 margin_width_changed_in_frame); | 8521 margin_width_changed_in_frame); |
9464 | 8522 |
9465 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* | 8523 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /* |
9466 *Minimum ascent height of lines. | 8524 *Minimum ascent height of lines. |
9467 This is a specifier; use `set-specifier' to change it. | 8525 This is a specifier; use `set-specifier' to change it. |
9468 */ ); | 8526 */ ); |
9469 Vminimum_line_ascent = Fmake_specifier (Qnatnum); | 8527 Vminimum_line_ascent = Fmake_specifier (Qnatnum); |
9470 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); | 8528 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero))); |
9471 set_specifier_caching (Vminimum_line_ascent, | 8529 set_specifier_caching (Vminimum_line_ascent, |
9472 offsetof (struct window, minimum_line_ascent), | 8530 slot_offset (struct window, minimum_line_ascent), |
9473 some_window_value_changed, | 8531 some_window_value_changed, |
9474 0, 0); | 8532 0, 0); |
9475 | 8533 |
9476 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* | 8534 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /* |
9477 *Minimum descent height of lines. | 8535 *Minimum descent height of lines. |
9478 This is a specifier; use `set-specifier' to change it. | 8536 This is a specifier; use `set-specifier' to change it. |
9479 */ ); | 8537 */ ); |
9480 Vminimum_line_descent = Fmake_specifier (Qnatnum); | 8538 Vminimum_line_descent = Fmake_specifier (Qnatnum); |
9481 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); | 8539 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero))); |
9482 set_specifier_caching (Vminimum_line_descent, | 8540 set_specifier_caching (Vminimum_line_descent, |
9483 offsetof (struct window, minimum_line_descent), | 8541 slot_offset (struct window, minimum_line_descent), |
9484 some_window_value_changed, | 8542 some_window_value_changed, |
9485 0, 0); | 8543 0, 0); |
9486 | 8544 |
9487 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* | 8545 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /* |
9488 *Non-nil means use the left outside margin as extra whitespace when | 8546 *Non-nil means use the left outside margin as extra whitespace when |
9490 This is a specifier; use `set-specifier' to change it. | 8548 This is a specifier; use `set-specifier' to change it. |
9491 */ ); | 8549 */ ); |
9492 Vuse_left_overflow = Fmake_specifier (Qboolean); | 8550 Vuse_left_overflow = Fmake_specifier (Qboolean); |
9493 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); | 8551 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil))); |
9494 set_specifier_caching (Vuse_left_overflow, | 8552 set_specifier_caching (Vuse_left_overflow, |
9495 offsetof (struct window, use_left_overflow), | 8553 slot_offset (struct window, use_left_overflow), |
9496 some_window_value_changed, | 8554 some_window_value_changed, |
9497 0, 0); | 8555 0, 0); |
9498 | 8556 |
9499 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* | 8557 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /* |
9500 *Non-nil means use the right outside margin as extra whitespace when | 8558 *Non-nil means use the right outside margin as extra whitespace when |
9502 This is a specifier; use `set-specifier' to change it. | 8560 This is a specifier; use `set-specifier' to change it. |
9503 */ ); | 8561 */ ); |
9504 Vuse_right_overflow = Fmake_specifier (Qboolean); | 8562 Vuse_right_overflow = Fmake_specifier (Qboolean); |
9505 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); | 8563 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil))); |
9506 set_specifier_caching (Vuse_right_overflow, | 8564 set_specifier_caching (Vuse_right_overflow, |
9507 offsetof (struct window, use_right_overflow), | 8565 slot_offset (struct window, use_right_overflow), |
9508 some_window_value_changed, | 8566 some_window_value_changed, |
9509 0, 0); | 8567 0, 0); |
9510 | 8568 |
9511 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* | 8569 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /* |
9512 *Non-nil means the text cursor is visible (this is usually the case). | 8570 *Non-nil means the text cursor is visible (this is usually the case). |
9513 This is a specifier; use `set-specifier' to change it. | 8571 This is a specifier; use `set-specifier' to change it. |
9514 */ ); | 8572 */ ); |
9515 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); | 8573 Vtext_cursor_visible_p = Fmake_specifier (Qboolean); |
9516 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); | 8574 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt))); |
9517 set_specifier_caching (Vtext_cursor_visible_p, | 8575 set_specifier_caching (Vtext_cursor_visible_p, |
9518 offsetof (struct window, text_cursor_visible_p), | 8576 slot_offset (struct window, text_cursor_visible_p), |
9519 text_cursor_visible_p_changed, | 8577 text_cursor_visible_p_changed, |
9520 0, 0); | 8578 0, 0); |
9521 | 8579 |
9522 } | 8580 } |