1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Free Software Foundation, Inc.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1995 Sun Microsystems, Inc.
6 Copyright (C) 1996 Chuck Thompson.
8 This file is part of XEmacs.
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 /* Synched up with: Not in FSF. */
27 /* Author: Chuck Thompson */
29 /* Fixed up by Ben Wing for Mule */
31 /* This file has been Mule-ized. */
33 /*****************************************************************************
34 The Golden Rules of Redisplay
36 First: It Is Better To Be Correct Than Fast
37 Second: Thou Shalt Not Run Elisp From Within Redisplay
38 Third: It Is Better To Be Fast Than Not To Be
39 ****************************************************************************/
58 #include "redisplay.h"
61 #include "line-number.h"
63 #include "file-coding.h"
67 #include "console-tty.h"
69 #include <unistd.h> /* for isatty() */
73 /* Note: We have to be careful throughout this code to properly handle
74 and differentiate between Bufbytes and Emchars.
76 Since strings are generally composed of Bufbytes, I've taken the tack
77 that any contiguous set of Bufbytes is called a "string", while
78 any contiguous set of Emchars is called an "array". */
80 /* Return value to indicate a failure by an add_*_rune routine to add
81 a rune, but no propagation information needs to be returned. */
82 #define ADD_FAILED (prop_block_dynarr *) 1
84 #define BEGIN_GLYPHS 0
87 #define RIGHT_GLYPHS 3
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
93 #define VERTICAL_CLIP(w, display) \
94 (updating_line_start_cache \
96 : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
100 /* The following structures are completely private to redisplay.c so
101 we put them here instead of in a header file, for modularity. */
103 /* NOTE: Bytinds not Bufpos's in this structure. */
105 typedef struct position_redisplay_data_type
107 /* This information is normally filled in by the create_*_block
108 routines and is used by the add_*_rune routines. */
111 struct display_block *db;
112 struct display_line *dl;
113 Emchar ch; /* Character that is to be added. This is
114 used to communicate this information to
115 add_emchar_rune(). */
116 Lisp_Object last_charset; /* The charset of the previous character.
117 Used to optimize some lookups -- we
118 only have to do some things when
119 the charset changes. */
120 face_index last_findex; /* The face index of the previous character.
121 Needed to ensure the validity of the
122 last_charset optimization. */
124 int last_char_width; /* The width of the previous character. */
125 int font_is_bogus; /* If true, it means we couldn't instantiate
126 the font for this charset, so we substitute
127 ~'s from the ASCII charset. */
132 int blank_width; /* Width of the blank that is to be added.
133 This is used to communicate this information
136 This is also used rather cheesily to
137 communicate the width of the eol-cursor-size
138 blank that exists at the end of the line.
139 add_emchar_rune() is called cheesily with
140 the non-printing char '\n', which is stuck
141 in the output routines with its width being
143 Bytind bi_cursor_bufpos;/* This stores the buffer position of the cursor. */
144 unsigned int cursor_type :3;
145 int cursor_x; /* rune block cursor is at */
146 int start_col; /* Number of character columns (each column has
147 a width of the default char width) that still
148 need to be skipped. This is used for horizontal
149 scrolling, where a certain number of columns
150 (those off the left side of the screen) need
151 to be skipped before anything is displayed. */
152 Bytind bi_start_col_enabled;
154 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
155 glyph differs from space_width (w).
156 0 if no hscroll glyph was used,
157 i.e. the window is not scrolled
158 horizontally. Used in tab
161 /* Information about the face the text should be displayed in and
162 any begin-glyphs and end-glyphs. */
163 struct extent_fragment *ef;
166 /* The height of a pixmap may either be predetermined if the user
167 has set a baseline value, or it may be dependent on whatever the
168 line ascent and descent values end up being, based just on font
169 information. In the first case we can immediately update the
170 values, thus their inclusion here. In the last case we cannot
171 determine the actual contribution to the line height until we
172 have finished laying out all text on the line. Thus we propagate
173 the max height of such pixmaps and do a final calculation after
174 all text has been added to the line. */
177 int max_pixmap_height;
179 Lisp_Object result_str; /* String where we put the result of
180 generating a formatted string in the modeline. */
181 int is_modeline; /* Non-zero if we're generating the modeline. */
182 Charcount modeline_charpos; /* Number of chars used in result_str so far;
183 corresponds to bytepos. */
184 Bytecount bytepos; /* Number of bytes used in result_str so far.
185 We don't actually copy the bytes into result_str
186 until the end because we don't know how big the
187 string is going to be until then. */
198 /* Data that should be propagated to the next line. Either a single
199 Emchar or a string of Bufbyte's.
201 The actual data that is propagated ends up as a Dynarr of these
204 #### It's unclean that both Emchars and Bufbytes are here.
207 typedef struct prop_block prop_block;
217 Bytecount len; /* length of the string. */
223 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
224 unsigned int cursor_type :3;
237 Dynarr_declare (prop_block);
241 static void generate_formatted_string_db (Lisp_Object format_str,
242 Lisp_Object result_str,
244 struct display_line *dl,
245 struct display_block *db,
246 face_index findex, int min_pixpos,
247 int max_pixpos, int type);
248 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
249 Charcount pos, Charcount min_pos,
250 Charcount max_pos, Lisp_Object elt,
251 int depth, int max_pixsize,
252 face_index findex, int type);
253 static prop_block_dynarr *add_glyph_rune (pos_data *data,
254 struct glyph_block *gb,
255 int pos_type, int allow_cursor,
256 struct glyph_cachel *cachel);
257 static Bytind create_text_block (struct window *w, struct display_line *dl,
258 Bytind bi_start_pos, int start_col,
259 prop_block_dynarr **prop, int type);
260 static int create_overlay_glyph_block (struct window *w,
261 struct display_line *dl);
262 static void create_left_glyph_block (struct window *w,
263 struct display_line *dl,
265 static void create_right_glyph_block (struct window *w,
266 struct display_line *dl);
267 static void redisplay_windows (Lisp_Object window, int skip_selected);
268 static void decode_mode_spec (struct window *w, Emchar spec, int type);
269 static void free_display_line (struct display_line *dl);
270 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
271 Bufpos point, int no_regen);
272 static int point_visible (struct window *w, Bufpos point, int type);
274 /* This used to be 10 but 30 seems to give much better performance. */
275 #define INIT_MAX_PREEMPTS 30
276 static int max_preempts;
278 #define REDISPLAY_PREEMPTION_CHECK \
281 (!disable_preemption && \
282 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
283 (!INTERACTIVE || detect_input_pending ()))))
286 * Redisplay global variables.
289 /* We need a third set of display structures for the cursor motion
290 routines. We used to just give each window a third set. However,
291 we always fully regenerate the structures when needed so there
292 isn't any reason we need more than a single set. */
293 display_line_dynarr *cmotion_display_lines;
295 /* Used by generate_formatted_string. Global because they get used so
296 much that the dynamic allocation time adds up. */
297 Emchar_dynarr *formatted_string_emchar_dynarr;
298 struct display_line formatted_string_display_line;
299 /* We store the extents that we need to generate in a Dynarr and then
300 frob them all on at the end of generating the string. We do it
301 this way rather than adding them as we generate the string because
302 we don't store the text into the resulting string until we're done
303 (to avoid having to resize the string multiple times), and we don't
304 want to go around adding extents to a string when the extents might
305 stretch off the end of the string. */
306 EXTENT_dynarr *formatted_string_extent_dynarr;
307 Bytecount_dynarr *formatted_string_extent_start_dynarr;
308 Bytecount_dynarr *formatted_string_extent_end_dynarr;
311 /* #### probably temporary */
312 int cache_adjustment;
314 /* This holds a string representing the text corresponding to a single
316 static Bufbyte_dynarr *mode_spec_bufbyte_string;
318 int in_display; /* 1 if in redisplay. */
320 int disable_preemption; /* Used for debugging redisplay and for
323 /* We only allow max_preempts preemptions before we force a redisplay. */
324 static int preemption_count;
326 /* Minimum pixel height of clipped bottom display line. */
329 /* Minimum visible pixel width of clipped glyphs at right margin. */
332 /* Set if currently inside update_line_start_cache. */
333 int updating_line_start_cache;
335 /* Nonzero means reading single-character input with prompt
336 so put cursor on minibuffer after the prompt. */
337 int cursor_in_echo_area;
338 Lisp_Object Qcursor_in_echo_area;
340 /* Nonzero means truncate lines in all windows less wide than the frame */
341 int truncate_partial_width_windows;
343 /* non-nil if a buffer has changed since the last time redisplay completed */
345 int buffers_changed_set;
347 /* non-nil if hscroll has changed somewhere or a buffer has been
348 narrowed or widened */
350 int clip_changed_set;
352 /* non-nil if any extent has changed since the last time redisplay completed */
354 int extents_changed_set;
356 /* non-nil if any face has changed since the last time redisplay completed */
359 /* Nonzero means some frames have been marked as garbaged */
362 /* non-zero if any of the builtin display glyphs (continuation,
363 hscroll, control-arrow, etc) is in need of updating
366 int glyphs_changed_set;
368 /* This variable is 1 if the icon has to be updated.
369 It is set to 1 when `frame-icon-glyph' changes. */
371 int icon_changed_set;
373 /* This variable is 1 if the menubar widget has to be updated.
374 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
377 int menubar_changed_set;
379 /* true iff we should redraw the modelines on the next redisplay */
380 int modeline_changed;
381 int modeline_changed_set;
383 /* non-nil if point has changed in some buffer since the last time
384 redisplay completed */
386 int point_changed_set;
388 /* non-nil if some frame has changed its size */
391 /* non-nil if some device has signaled that it wants to change size */
392 int asynch_device_change_pending;
394 /* non-nil if any toolbar has changed */
396 int toolbar_changed_set;
398 /* non-nil if any window has changed since the last time redisplay completed */
401 /* non-nil if any frame's window structure has changed since the last
402 time redisplay completed */
403 int windows_structure_changed;
405 /* If non-nil, use vertical bar cursor. */
406 Lisp_Object Vbar_cursor;
407 Lisp_Object Qbar_cursor;
410 int visible_bell; /* If true and the terminal will support it
411 then the frame will flash instead of
412 beeping when an error occurs */
414 /* Nonzero means no need to redraw the entire frame on resuming
415 a suspended Emacs. This is useful on terminals with multiple pages,
416 where one page is used for Emacs and another for all else. */
417 int no_redraw_on_reenter;
419 Lisp_Object Vwindow_system; /* nil or a symbol naming the window system
420 under which emacs is running
421 ('x is the only current possibility) */
422 Lisp_Object Vinitial_window_system;
424 Lisp_Object Vglobal_mode_string;
426 /* The number of lines scroll a window by when point leaves the window; if
427 it is <=0 then point is centered in the window */
430 /* Scroll up to this many lines, to bring point back on screen. */
431 int scroll_conservatively;
433 /* Marker for where to display an arrow on top of the buffer text. */
434 Lisp_Object Voverlay_arrow_position;
435 /* String to display for the arrow. */
436 Lisp_Object Voverlay_arrow_string;
438 Lisp_Object Vwindow_size_change_functions;
439 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
440 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
442 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
444 #ifndef INHIBIT_REDISPLAY_HOOKS
445 /* #### Chuck says: I think this needs more thought.
446 Think about this for 19.14. */
447 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
448 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
449 #endif /* INHIBIT_REDISPLAY_HOOKS */
451 int last_display_warning_tick, display_warning_tick;
452 Lisp_Object Qdisplay_warning_buffer;
453 int inhibit_warning_display;
455 Lisp_Object Vleft_margin_width, Vright_margin_width;
456 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
457 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
458 Lisp_Object Vtext_cursor_visible_p;
460 int column_number_start_at_one;
462 /***************************************************************************/
464 /* low-level interfaces onto device routines */
466 /***************************************************************************/
469 redisplay_text_width_emchar_string (struct window *w, int findex,
470 Emchar *str, Charcount len)
472 unsigned char charsets[NUM_LEADING_BYTES];
475 find_charsets_in_emchar_string (charsets, str, len);
476 XSETWINDOW (window, w);
477 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
479 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))),
480 text_width, (XFRAME (WINDOW_FRAME (w)),
481 WINDOW_FACE_CACHEL (w, findex), str, len));
484 static Emchar_dynarr *rtw_emchar_dynarr;
487 redisplay_text_width_string (struct window *w, int findex,
488 Bufbyte *nonreloc, Lisp_Object reloc,
489 Bytecount offset, Bytecount len)
491 if (!rtw_emchar_dynarr)
492 rtw_emchar_dynarr = Dynarr_new (Emchar);
493 Dynarr_reset (rtw_emchar_dynarr);
495 fixup_internal_substring (nonreloc, reloc, offset, &len);
497 nonreloc = XSTRING_DATA (reloc);
498 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
499 return redisplay_text_width_emchar_string
500 (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
501 Dynarr_length (rtw_emchar_dynarr));
505 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face,
506 Bufbyte *nonreloc, Lisp_Object reloc,
507 Bytecount offset, Bytecount len)
509 unsigned char charsets[NUM_LEADING_BYTES];
511 struct face_cachel cachel;
513 if (!rtw_emchar_dynarr)
514 rtw_emchar_dynarr = Dynarr_new (Emchar);
515 Dynarr_reset (rtw_emchar_dynarr);
517 fixup_internal_substring (nonreloc, reloc, offset, &len);
519 nonreloc = XSTRING_DATA (reloc);
520 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
521 find_charsets_in_bufbyte_string (charsets, nonreloc, len);
522 reset_face_cachel (&cachel);
524 XSETFRAME (frame, f);
525 ensure_face_cachel_complete (&cachel, frame, charsets);
526 return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
527 text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
528 Dynarr_length (rtw_emchar_dynarr)));
531 /* Return the display block from DL of the given TYPE. A display line
532 can have only one display block of each possible type. If DL does
533 not have a block of type TYPE, one will be created and added to DL. */
535 struct display_block *
536 get_display_block_from_line (struct display_line *dl, enum display_type type)
539 struct display_block db;
541 /* Check if this display line already has a block of the desired type and
543 if (dl->display_blocks)
545 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++)
547 if (Dynarr_at (dl->display_blocks, elt).type == type)
548 return Dynarr_atp (dl->display_blocks, elt);
551 /* There isn't an active block of the desired type, but there
552 might still be allocated blocks we need to reuse. */
553 if (elt < Dynarr_largest (dl->display_blocks))
555 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
557 /* 'add' the block to the list */
558 Dynarr_increment (dl->display_blocks);
560 /* initialize and return */
567 /* This line doesn't have any display blocks, so initialize the display
569 dl->display_blocks = Dynarr_new (display_block);
572 /* The line doesn't have a block of the desired type so go ahead and create
573 one and add it to the line. */
576 db.runes = Dynarr_new (rune);
577 Dynarr_add (dl->display_blocks, db);
579 /* Return the newly added display block. */
580 elt = Dynarr_length (dl->display_blocks) - 1;
582 return Dynarr_atp (dl->display_blocks, elt);
586 tab_char_width (struct window *w)
588 struct buffer *b = XBUFFER (w->buffer);
589 int char_tab_width = XINT (b->tab_width);
591 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8;
593 return char_tab_width;
597 space_width (struct window *w)
599 /* While tabs are traditional composed of spaces, for variable-width
600 fonts the space character tends to give too narrow a value. So
601 we use 'n' instead. Except that we don't. We use the default
602 character width for the default face. If this is actually
603 defined by the font then it is probably the best thing to
604 actually use. If it isn't, we have assumed it is 'n' and have
605 already calculated its width. Thus we can avoid a call to
606 XTextWidth on X frames by just querying the default width. */
607 return XFONT_INSTANCE
608 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width;
612 tab_pix_width (struct window *w)
614 return space_width (w) * tab_char_width (w);
617 /* Given a pixel position in a window, return the pixel location of
618 the next tabstop. Tabs are calculated from the left window edge in
619 terms of spaces displayed in the default face. Formerly the space
620 width was determined using the currently active face. That method
621 leads to tabstops which do not line up. */
624 next_tab_position (struct window *w, int start_pixpos, int left_pixpos)
626 int n_pos = left_pixpos;
627 int pix_tab_width = tab_pix_width (w);
629 /* Adjust n_pos for any hscrolling which has happened. */
631 n_pos -= space_width (w) * (w->hscroll - 1);
633 while (n_pos <= start_pixpos)
634 n_pos += pix_tab_width;
639 /* For the given window, calculate the outside and margin boundaries for a
640 display line. The whitespace boundaries must be calculated by the text
644 calculate_display_line_boundaries (struct window *w, int modeline)
646 layout_bounds bounds;
648 /* Set the outermost boundaries which are the boundaries of the
649 window itself minus the gutters (and minus the scrollbars if this
650 is for the modeline). */
653 bounds.left_out = WINDOW_TEXT_LEFT (w);
654 bounds.right_out = WINDOW_TEXT_RIGHT (w);
658 bounds.left_out = WINDOW_MODELINE_LEFT (w);
659 bounds.right_out = WINDOW_MODELINE_RIGHT (w);
662 /* The inner boundaries mark where the glyph margins are located. */
663 bounds.left_in = bounds.left_out + window_left_margin_width (w);
664 bounds.right_in = bounds.right_out - window_right_margin_width (w);
666 /* We cannot fully calculate the whitespace boundaries as they
667 depend on the contents of the line being displayed. */
668 bounds.left_white = bounds.left_in;
669 bounds.right_white = bounds.right_in;
674 /* Given a display line and a starting position, ensure that the
675 contents of the display line accurately represent the visual
676 representation of the buffer contents starting from the given
677 position when displayed in the given window. The display line ends
678 when the contents of the line reach the right boundary of the given
682 generate_display_line (struct window *w, struct display_line *dl, int bounds,
683 Bufpos start_pos, int start_col,
684 prop_block_dynarr **prop, int type)
688 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
690 /* If our caller hasn't already set the boundaries, then do so now. */
692 dl->bounds = calculate_display_line_boundaries (w, 0);
694 /* Reset what this line is using. */
695 if (dl->display_blocks)
696 Dynarr_reset (dl->display_blocks);
699 Dynarr_free (dl->left_glyphs);
702 if (dl->right_glyphs)
704 Dynarr_free (dl->right_glyphs);
705 dl->right_glyphs = 0;
708 /* We aren't generating a modeline at the moment. */
711 /* Create a display block for the text region of the line. */
713 /* #### urk urk urk!!! Chuck fix this shit! */
714 Bytind hacked_up_bytind =
715 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
716 start_col, prop, type);
717 if (hacked_up_bytind > BI_BUF_ZV (b))
718 ret_bufpos = BUF_ZV (b) + 1;
720 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
722 dl->bufpos = start_pos;
723 if (dl->end_bufpos < dl->bufpos)
724 dl->end_bufpos = dl->bufpos;
726 if (MARKERP (Voverlay_arrow_position)
727 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
728 && start_pos == marker_position (Voverlay_arrow_position)
729 && (STRINGP (Voverlay_arrow_string)
730 || GLYPHP (Voverlay_arrow_string)))
732 overlay_width = create_overlay_glyph_block (w, dl);
737 /* If there are left glyphs associated with any character in the
738 text block, then create a display block to handle them. */
739 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
740 create_left_glyph_block (w, dl, overlay_width);
742 /* If there are right glyphs associated with any character in the
743 text block, then create a display block to handle them. */
744 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
745 create_right_glyph_block (w, dl);
747 /* In the future additional types of display blocks may be generated
750 w->last_redisplay_pos = ret_bufpos;
755 /* Adds an hscroll glyph to a display block. If this is called, then
756 the block had better be empty.
758 Yes, there are multiple places where this function is called but
759 that is the way it has to be. Each calling function has to deal
760 with bi_start_col_enabled a little differently depending on the
761 object being worked with. */
763 static prop_block_dynarr *
764 add_hscroll_rune (pos_data *data)
766 struct glyph_block gb;
767 prop_block_dynarr *retval;
768 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
769 unsigned int old_cursor_type = data->cursor_type;
770 Bytind bi_old_bufpos = data->bi_bufpos;
772 if (data->cursor_type == CURSOR_ON
773 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
774 && data->bi_cursor_bufpos <= data->bi_bufpos)
776 data->bi_cursor_bufpos = data->bi_start_col_enabled;
780 data->cursor_type = NO_CURSOR;
783 data->bi_endpos = data->bi_bufpos;
784 data->bi_bufpos = data->bi_start_col_enabled;
787 gb.glyph = Vhscroll_glyph;
789 int oldpixpos = data->pixpos;
790 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
791 GLYPH_CACHEL (XWINDOW (data->window),
792 HSCROLL_GLYPH_INDEX));
793 data->hscroll_glyph_width_adjust =
794 data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
797 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
798 data->cursor_type = old_cursor_type;
799 data->bi_bufpos = bi_old_bufpos;
801 data->bi_start_col_enabled = 0;
805 /* Adds a character rune to a display block. If there is not enough
806 room to fit the rune on the display block (as determined by the
807 MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
809 static prop_block_dynarr *
810 add_emchar_rune (pos_data *data)
812 struct rune rb, *crb;
823 if (data->bi_start_col_enabled)
825 return add_hscroll_rune (data);
828 if (data->ch == '\n')
830 data->font_is_bogus = 0;
831 /* Cheesy end-of-line pseudo-character. */
832 width = data->blank_width;
836 Lisp_Object charset = CHAR_CHARSET (data->ch);
837 if (!EQ (charset, data->last_charset) ||
838 data->findex != data->last_findex)
840 /* OK, we need to do things the hard way. */
841 struct window *w = XWINDOW (data->window);
842 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
843 Lisp_Object font_instance =
844 ensure_face_cachel_contains_charset (cachel, data->window,
846 struct Lisp_Font_Instance *fi;
848 if (EQ (font_instance, Vthe_null_font_instance))
850 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
851 data->font_is_bogus = 1;
854 data->font_is_bogus = 0;
856 fi = XFONT_INSTANCE (font_instance);
857 if (!fi->proportional_p)
858 /* sweetness and light. */
859 data->last_char_width = fi->width;
861 data->last_char_width = -1;
862 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
863 data->new_descent = max (data->new_descent, (int) fi->descent);
864 data->last_charset = charset;
865 data->last_findex = data->findex;
868 width = data->last_char_width;
871 /* bummer. Proportional fonts. */
872 width = redisplay_text_width_emchar_string (XWINDOW (data->window),
878 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
883 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
885 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
894 crb->findex = data->findex;
895 crb->xpos = data->pixpos;
899 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
901 else if (data->is_modeline)
902 crb->bufpos = data->modeline_charpos;
904 /* fuckme if this shouldn't be an abort. */
905 /* abort (); fuckme harder, this abort gets tripped quite often,
906 in propagation and whatnot. #### fixme */
908 crb->type = RUNE_CHAR;
909 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
912 if (data->cursor_type == CURSOR_ON)
914 if (data->bi_bufpos == data->bi_cursor_bufpos)
916 crb->cursor_type = CURSOR_ON;
917 data->cursor_x = Dynarr_length (data->db->runes);
920 crb->cursor_type = CURSOR_OFF;
922 else if (data->cursor_type == NEXT_CURSOR)
924 crb->cursor_type = CURSOR_ON;
925 data->cursor_x = Dynarr_length (data->db->runes);
926 data->cursor_type = NO_CURSOR;
928 else if (data->cursor_type == IGNORE_CURSOR)
929 crb->cursor_type = IGNORE_CURSOR;
931 crb->cursor_type = CURSOR_OFF;
934 Dynarr_add (data->db->runes, *crb);
936 Dynarr_increment (data->db->runes);
938 data->pixpos += width;
943 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
944 for each character in the string. Propagate any left-over data
945 unless NO_PROP is non-zero. */
947 static prop_block_dynarr *
948 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
949 Bytecount c_length, int no_prop)
951 Bufbyte *pos, *end = c_string + c_length;
952 prop_block_dynarr *prop;
954 /* #### This function is too simplistic. It needs to do the same
955 sort of character interpretation (display-table lookup,
956 ctl-arrow checking), etc. that create_text_block() does.
957 The functionality to do this in that routine needs to be
960 for (pos = c_string; pos < end;)
962 data->ch = charptr_emchar (pos);
964 prop = add_emchar_rune (data);
972 struct prop_block pb;
973 Bytecount len = end - pos;
974 prop = Dynarr_new (prop_block);
976 pb.type = PROP_STRING;
977 pb.data.p_string.str = xnew_array (Bufbyte, len);
978 strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
979 pb.data.p_string.len = len;
981 Dynarr_add (prop, pb);
992 /* Add a single rune of the specified width. The area covered by this
993 rune will be displayed in the foreground color of the associated
996 static prop_block_dynarr *
997 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1001 /* If data->start_col is not 0 then this call to add_blank_rune must have
1002 been to add it as a tab. */
1003 if (data->start_col)
1005 /* assert (w != NULL) */
1006 prop_block_dynarr *retval;
1008 /* If we have still not fully scrolled horizontally, subtract
1009 the width of this tab and return. */
1010 if (char_tab_width < data->start_col)
1012 data->start_col -= char_tab_width;
1015 else if (char_tab_width == data->start_col)
1016 data->blank_width = 0;
1019 int spcwid = space_width (w);
1021 if (spcwid >= data->blank_width)
1022 data->blank_width = 0;
1024 data->blank_width -= spcwid;
1027 data->start_col = 0;
1028 retval = add_hscroll_rune (data);
1030 /* Could be caused by the handling of the hscroll rune. */
1031 if (retval != NULL || !data->blank_width)
1035 /* Blank runes are always calculated to fit. */
1036 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1038 rb.findex = data->findex;
1039 rb.xpos = data->pixpos;
1040 rb.width = data->blank_width;
1041 if (data->bi_bufpos)
1043 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1046 /* #### and this is really correct too? */
1049 rb.type = RUNE_BLANK;
1051 if (data->cursor_type == CURSOR_ON)
1053 if (data->bi_bufpos == data->bi_cursor_bufpos)
1055 rb.cursor_type = CURSOR_ON;
1056 data->cursor_x = Dynarr_length (data->db->runes);
1059 rb.cursor_type = CURSOR_OFF;
1061 else if (data->cursor_type == NEXT_CURSOR)
1063 rb.cursor_type = CURSOR_ON;
1064 data->cursor_x = Dynarr_length (data->db->runes);
1065 data->cursor_type = NO_CURSOR;
1068 rb.cursor_type = CURSOR_OFF;
1070 Dynarr_add (data->db->runes, rb);
1071 data->pixpos += data->blank_width;
1076 /* Add runes representing a character in octal. */
1078 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1080 if (add_failed || (add_failed = add_emchar_rune (data))) \
1082 struct prop_block pb; \
1084 prop = Dynarr_new (prop_block); \
1086 pb.type = PROP_CHAR; \
1087 pb.data.p_char.ch = data->ch; \
1088 pb.data.p_char.cursor_type = data->cursor_type; \
1089 Dynarr_add (prop, pb); \
1093 static prop_block_dynarr *
1094 add_octal_runes (pos_data *data)
1096 prop_block_dynarr *prop, *add_failed;
1097 Emchar orig_char = data->ch;
1098 unsigned int orig_cursor_type = data->cursor_type;
1104 if (data->start_col)
1107 if (!data->start_col)
1109 if (data->bi_start_col_enabled)
1111 add_failed = add_hscroll_rune (data);
1115 struct glyph_block gb;
1116 struct window *w = XWINDOW (data->window);
1119 gb.glyph = Voctal_escape_glyph;
1121 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1122 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1126 /* We only propagate information if the glyph was partially
1131 data->cursor_type = IGNORE_CURSOR;
1133 if (data->ch >= 0x100)
1135 /* If the character is an extended Mule character, it could have
1136 up to 19 bits. For the moment, we treat it as a seven-digit
1137 octal number. This is not that pretty, but whatever. */
1138 data->ch = (7 & (orig_char >> 18)) + '0';
1139 ADD_NEXT_OCTAL_RUNE_CHAR;
1141 data->ch = (7 & (orig_char >> 15)) + '0';
1142 ADD_NEXT_OCTAL_RUNE_CHAR;
1144 data->ch = (7 & (orig_char >> 12)) + '0';
1145 ADD_NEXT_OCTAL_RUNE_CHAR;
1147 data->ch = (7 & (orig_char >> 9)) + '0';
1148 ADD_NEXT_OCTAL_RUNE_CHAR;
1151 data->ch = (7 & (orig_char >> 6)) + '0';
1152 ADD_NEXT_OCTAL_RUNE_CHAR;
1154 data->ch = (7 & (orig_char >> 3)) + '0';
1155 ADD_NEXT_OCTAL_RUNE_CHAR;
1157 data->ch = (7 & orig_char) + '0';
1158 ADD_NEXT_OCTAL_RUNE_CHAR;
1160 data->cursor_type = orig_cursor_type;
1164 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1166 /* Add runes representing a control character to a display block. */
1168 static prop_block_dynarr *
1169 add_control_char_runes (pos_data *data, struct buffer *b)
1171 if (!NILP (b->ctl_arrow))
1173 prop_block_dynarr *prop;
1174 Emchar orig_char = data->ch;
1175 unsigned int old_cursor_type = data->cursor_type;
1180 if (data->start_col)
1183 if (!data->start_col)
1185 if (data->bi_start_col_enabled)
1187 prop_block_dynarr *retval;
1189 retval = add_hscroll_rune (data);
1195 struct glyph_block gb;
1196 struct window *w = XWINDOW (data->window);
1199 gb.glyph = Vcontrol_arrow_glyph;
1201 /* We only propagate information if the glyph was partially
1203 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1204 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1209 if (orig_char == 0177)
1212 data->ch = orig_char ^ 0100;
1213 data->cursor_type = IGNORE_CURSOR;
1215 if (add_emchar_rune (data))
1217 struct prop_block pb;
1219 prop = Dynarr_new (prop_block);
1221 pb.type = PROP_CHAR;
1222 pb.data.p_char.ch = data->ch;
1223 pb.data.p_char.cursor_type = data->cursor_type;
1224 Dynarr_add (prop, pb);
1227 data->cursor_type = old_cursor_type;
1232 return add_octal_runes (data);
1236 /* Given a display table entry, call the appropriate functions to
1237 display each element of the entry. */
1239 static prop_block_dynarr *
1240 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1242 prop_block_dynarr *prop = NULL;
1244 if (VECTORP (entry))
1246 struct Lisp_Vector *de = XVECTOR (entry);
1247 long len = vector_length (de);
1250 for (elt = 0; elt < len; elt++)
1252 if (NILP (de->contents[elt]))
1254 else if (STRINGP (de->contents[elt]))
1257 add_bufbyte_string_runes
1259 XSTRING_DATA (de->contents[elt]),
1260 XSTRING_LENGTH (de->contents[elt]),
1263 else if (GLYPHP (de->contents[elt]))
1265 if (data->start_col)
1268 if (!data->start_col && data->bi_start_col_enabled)
1270 prop = add_hscroll_rune (data);
1274 struct glyph_block gb;
1276 gb.glyph = de->contents[elt];
1278 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1281 else if (CHAR_OR_CHAR_INTP (de->contents[elt]))
1283 data->ch = XCHAR_OR_CHAR_INT (de->contents[elt]);
1284 prop = add_emchar_rune (data);
1286 /* Else blow it off because someone added a bad entry and we
1287 don't have any safe way of signaling an error. */
1289 /* #### Still need to add any remaining elements to the
1290 propagation information. */
1295 else if (STRINGP (entry))
1297 prop = add_bufbyte_string_runes (data,
1298 XSTRING_DATA (entry),
1299 XSTRING_LENGTH (entry),
1302 else if (GLYPHP (entry))
1304 if (data->start_col)
1307 if (!data->start_col && data->bi_start_col_enabled)
1309 prop = add_hscroll_rune (data);
1313 struct glyph_block gb;
1317 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1320 else if (CHAR_OR_CHAR_INTP (entry))
1322 data->ch = XCHAR_OR_CHAR_INT (entry);
1323 prop = add_emchar_rune (data);
1326 /* Else blow it off because someone added a bad entry and we don't
1327 have any safe way of signaling an error. Hey, this comment
1332 /* Add runes which were propagated from the previous line. */
1334 static prop_block_dynarr *
1335 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1337 /* #### Remember to handle start_col parameter of data when the rest of
1338 this is finished. */
1339 /* #### Chuck -- I've redone this function a bit. It looked like the
1340 case of not all the propagation blocks being added was not handled
1342 /* #### Chuck -- I also think the double indirection of PROP is kind
1343 of bogus. A cleaner solution is just to check for
1344 Dynarr_length (prop) > 0. */
1345 /* #### This function also doesn't even pay attention to ADD_FAILED!
1346 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1349 prop_block_dynarr *add_failed;
1350 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1351 unsigned int old_cursor_type = data->cursor_type;
1353 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1355 struct prop_block *pb = Dynarr_atp (*prop, elt);
1360 data->ch = pb->data.p_char.ch;
1361 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1362 data->cursor_type = pb->data.p_char.cursor_type;
1363 add_failed = add_emchar_rune (data);
1366 goto oops_no_more_space;
1369 if (pb->data.p_string.str)
1370 xfree (pb->data.p_string.str);
1371 /* #### bogus bogus -- this doesn't do anything!
1372 Should probably call add_bufbyte_string_runes(),
1373 once that function is fixed. */
1375 case PROP_MINIBUF_PROMPT:
1377 face_index old_findex = data->findex;
1378 Bytind bi_old_bufpos = data->bi_bufpos;
1380 data->findex = DEFAULT_INDEX;
1381 data->bi_bufpos = 0;
1382 data->cursor_type = NO_CURSOR;
1384 while (pb->data.p_string.len > 0)
1386 data->ch = charptr_emchar (pb->data.p_string.str);
1387 add_failed = add_emchar_rune (data);
1391 data->findex = old_findex;
1392 data->bi_bufpos = bi_old_bufpos;
1393 goto oops_no_more_space;
1397 /* Complicated equivalent of ptr++, len-- */
1398 Bufbyte *oldpos = pb->data.p_string.str;
1399 INC_CHARPTR (pb->data.p_string.str);
1400 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1404 data->findex = old_findex;
1405 /* ##### FIXME FIXME FIXME -- Upon successful return from
1406 this function, data->bi_bufpos is automatically incremented.
1407 However, we don't want that to happen if we were adding
1408 the minibuffer prompt. */
1410 struct buffer *buf =
1411 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1412 /* #### Chuck fix this shit or I'm gonna scream! */
1413 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1414 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1416 /* #### is this correct? Does anyone know?
1417 Does anyone care? Is this a cheesy hack or what? */
1418 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1424 /* #### I think it's unnecessary and misleading to preserve
1425 the blank_width, as it implies that the value carries
1426 over from one rune to the next, which is wrong. */
1427 int old_width = data->blank_width;
1428 face_index old_findex = data->findex;
1430 data->findex = pb->data.p_blank.findex;
1431 data->blank_width = pb->data.p_blank.width;
1432 data->bi_cursor_bufpos = 0;
1433 data->cursor_type = IGNORE_CURSOR;
1435 if (data->pixpos + data->blank_width > data->max_pixpos)
1436 data->blank_width = data->max_pixpos - data->pixpos;
1438 /* We pass a bogus value of char_tab_width. It shouldn't
1439 matter because unless something is really screwed up
1440 this call won't cause that arg to be used. */
1441 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1443 /* This can happen in the case where we have a tab which
1444 is wider than the window. */
1445 if (data->blank_width != pb->data.p_blank.width)
1447 pb->data.p_blank.width -= data->blank_width;
1448 add_failed = ADD_FAILED;
1451 data->findex = old_findex;
1452 data->blank_width = old_width;
1455 goto oops_no_more_space;
1465 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1466 data->cursor_type = old_cursor_type;
1467 if (elt < Dynarr_length (*prop))
1469 Dynarr_delete_many (*prop, 0, elt);
1474 Dynarr_free (*prop);
1479 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1480 the display block, but add all other types to the appropriate list
1481 of the display line. They will be added later by different
1484 static prop_block_dynarr *
1485 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1486 int allow_cursor, struct glyph_cachel *cachel)
1488 struct window *w = XWINDOW (data->window);
1490 /* A nil extent indicates a special glyph (ex. truncator). */
1491 if (NILP (gb->extent)
1492 || (pos_type == BEGIN_GLYPHS &&
1493 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1494 || (pos_type == END_GLYPHS &&
1495 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
1500 int ascent, descent;
1501 Lisp_Object baseline;
1505 width = cachel->width;
1507 width = glyph_width (gb->glyph, Qnil, data->findex, data->window);
1512 if (data->start_col)
1514 prop_block_dynarr *retval;
1515 int glyph_char_width = width / space_width (w);
1517 /* If we still have not fully scrolled horizontally after
1518 taking into account the width of the glyph, subtract its
1519 width and return. */
1520 if (glyph_char_width < data->start_col)
1522 data->start_col -= glyph_char_width;
1525 else if (glyph_char_width == data->start_col)
1529 xoffset = space_width (w) * data->start_col;
1532 /* #### Can this happen? */
1537 data->start_col = 0;
1538 retval = add_hscroll_rune (data);
1540 /* Could be caused by the handling of the hscroll rune. */
1541 if (retval != NULL || !width)
1547 if (data->pixpos + width > data->max_pixpos)
1549 /* If this is the first object we are attempting to add to
1550 the line then we ignore the horizontal_clip threshold.
1551 Otherwise we will loop until the bottom of the window
1552 continually failing to add this glyph because it is wider
1553 than the window. We could alternatively just completely
1554 ignore the glyph and proceed from there but I think that
1555 this is a better solution. */
1556 if (Dynarr_length (data->db->runes)
1557 && data->max_pixpos - data->pixpos < horizontal_clip)
1560 width = data->max_pixpos - data->pixpos;
1565 ascent = cachel->ascent;
1566 descent = cachel->descent;
1570 ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window);
1571 descent = glyph_descent (gb->glyph, Qnil, data->findex,
1575 baseline = glyph_baseline (gb->glyph, data->window);
1577 if (glyph_contrib_p (gb->glyph, data->window))
1579 /* A pixmap that has not had a baseline explicitly set. Its
1580 contribution will be determined later. */
1581 if (NILP (baseline))
1583 int height = ascent + descent;
1584 data->max_pixmap_height = max (data->max_pixmap_height, height);
1587 /* A string so determine contribution normally. */
1588 else if (EQ (baseline, Qt))
1590 data->new_ascent = max (data->new_ascent, ascent);
1591 data->new_descent = max (data->new_descent, descent);
1594 /* A pixmap with an explicitly set baseline. We determine the
1595 contribution here. */
1596 else if (INTP (baseline))
1598 int height = ascent + descent;
1599 int pix_ascent, pix_descent;
1601 pix_ascent = height * XINT (baseline) / 100;
1602 pix_descent = height - pix_ascent;
1604 data->new_ascent = max (data->new_ascent, pix_ascent);
1605 data->new_descent = max (data->new_descent, pix_descent);
1608 /* Otherwise something is screwed up. */
1613 face = glyph_face (gb->glyph, data->window);
1615 rb.findex = data->findex;
1617 rb.findex = get_builtin_face_cache_index (w, face);
1619 rb.xpos = data->pixpos;
1621 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1622 if (data->bi_endpos)
1623 /* #### is this necessary at all? */
1624 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1628 rb.type = RUNE_DGLYPH;
1629 /* #### Ben sez: this is way bogus if the glyph is a string.
1630 You should not make the output routines have to cope with
1631 this. The string could contain Mule characters, or non-
1632 printable characters, or characters to be passed through
1633 the display table, or non-character objects (when this gets
1634 implemented), etc. Instead, this routine here should parse
1635 the string into a series of runes. */
1636 rb.object.dglyph.glyph = gb->glyph;
1637 rb.object.dglyph.extent = gb->extent;
1638 rb.object.dglyph.xoffset = xoffset;
1642 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1645 if (data->cursor_type == CURSOR_ON)
1647 if (data->bi_bufpos == data->bi_cursor_bufpos)
1649 rb.cursor_type = CURSOR_ON;
1650 data->cursor_x = Dynarr_length (data->db->runes);
1653 rb.cursor_type = CURSOR_OFF;
1655 else if (data->cursor_type == NEXT_CURSOR)
1657 rb.cursor_type = CURSOR_ON;
1658 data->cursor_x = Dynarr_length (data->db->runes);
1659 data->cursor_type = NO_CURSOR;
1661 else if (data->cursor_type == IGNORE_CURSOR)
1662 rb.cursor_type = IGNORE_CURSOR;
1663 else if (data->cursor_type == NO_CURSOR)
1664 rb.cursor_type = NO_CURSOR;
1666 rb.cursor_type = CURSOR_OFF;
1669 rb.cursor_type = CURSOR_OFF;
1671 Dynarr_add (data->db->runes, rb);
1672 data->pixpos += width;
1678 if (!NILP (glyph_face (gb->glyph, data->window)))
1680 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1683 gb->findex = data->findex;
1685 if (pos_type == BEGIN_GLYPHS)
1687 if (!data->dl->left_glyphs)
1688 data->dl->left_glyphs = Dynarr_new (glyph_block);
1689 Dynarr_add (data->dl->left_glyphs, *gb);
1692 else if (pos_type == END_GLYPHS)
1694 if (!data->dl->right_glyphs)
1695 data->dl->right_glyphs = Dynarr_new (glyph_block);
1696 Dynarr_add (data->dl->right_glyphs, *gb);
1700 abort (); /* there are no unknown types */
1703 return NULL; /* shut up compiler */
1706 /* Add all glyphs at position POS_TYPE that are contained in the given
1709 static prop_block_dynarr *
1710 add_glyph_runes (pos_data *data, int pos_type)
1712 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1713 why didn't you just modify add_glyph_rune in the first place? */
1715 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1716 ? data->ef->begin_glyphs
1717 : data->ef->end_glyphs);
1718 prop_block_dynarr *prop;
1720 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1722 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1727 /* #### Add some propagation information. */
1732 Dynarr_reset (glyph_arr);
1737 /* Given a position for a buffer in a window, ensure that the given
1738 display line DL accurately represents the text on a line starting
1739 at the given position.
1741 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1742 You must do appropriate conversion. */
1745 create_text_block (struct window *w, struct display_line *dl,
1746 Bytind bi_start_pos, int start_col,
1747 prop_block_dynarr **prop, int type)
1749 struct frame *f = XFRAME (w->frame);
1750 struct buffer *b = XBUFFER (w->buffer);
1751 struct device *d = XDEVICE (f->device);
1754 struct Lisp_Vector *dt = 0;
1756 /* Don't display anything in the minibuffer if this window is not on
1757 a selected frame. We consider all other windows to be active
1758 minibuffers as it simplifies the coding. */
1759 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1760 (f == device_selected_frame (d)) ||
1761 is_surrogate_for_selected_frame (f));
1763 int truncate_win = window_truncation_on (w);
1764 int end_glyph_width;
1766 /* If the buffer's value of selective_display is an integer then
1767 only lines that start with less than selective_display columns of
1768 space will be displayed. If selective_display is t then all text
1769 after a ^M is invisible. */
1770 int selective = (INTP (b->selective_display)
1771 ? XINT (b->selective_display)
1772 : ((!NILP (b->selective_display) ? -1 : 0)));
1774 /* The variable ctl-arrow allows the user to specify what characters
1775 can actually be displayed and which octal should be used for.
1776 #### This variable should probably have some rethought done to
1779 #### It would also be really nice if you could specify that
1780 the characters come out in hex instead of in octal. Mule
1781 does that by adding a ctl-hexa variable similar to ctl-arrow,
1782 but that's bogus -- we need a more general solution. I
1783 think you need to extend the concept of display tables
1784 into a more general conversion mechanism. Ideally you
1785 could specify a Lisp function that converts characters,
1786 but this violates the Second Golden Rule and besides would
1787 make things way way way way slow. An idea I like is to
1788 be able to specify multiple display tables instead of just
1789 one. Each display table can specify conversions for some
1790 characters and leave others unchanged. The way the
1791 character gets displayed is determined by the first display
1792 table with a binding for that character. This way, you
1793 could call a function `enable-hex-display' that adds a
1794 pre-defined hex display-table (or maybe computes one if
1795 you give weird parameters to the function) and adds it
1796 to the list of display tables for the current buffer.
1798 Unfortunately there are still problems dealing with Mule
1799 characters. For example, maybe I want to specify that
1800 all extended characters (i.e. >= 256) are displayed in hex.
1801 It's not reasonable to create a mapping for all possible
1802 such characters, because there are about 2^19 of them.
1803 One way of dealing with this is to extend the concept
1804 of what a display table is. Currently it's only allowed
1805 to be a 256-entry vector. Instead, it should be something
1808 a) A 256-entry vector, for backward compatibility
1809 b) Some sort of hash table, mapping characters to values
1810 c) A list that specifies a range of values and the
1811 mapping to provide for those values.
1813 Also, extend the concept of "mapping" to include a
1814 printf-like spec. Then, you could make all extended
1815 characters show up as hex with a display table like
1817 ((256 . 524288) . "%x")
1819 Since more than one display table is possible, you have
1820 great flexibility in mapping ranges of characters.
1822 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1823 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1824 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1827 /* The text display block for this display line. */
1828 struct display_block *db = get_display_block_from_line (dl, TEXT);
1830 /* The first time through the main loop we need to force the glyph
1831 data to be updated. */
1834 /* Apparently the new extent_fragment_update returns an end position
1835 equal to the position passed in if there are no more runs to be
1837 int no_more_frags = 0;
1839 Lisp_Object synch_minibuffers_value =
1840 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1842 dl->used_prop_data = 0;
1846 data.ef = extent_fragment_new (w->buffer, f);
1848 /* These values are used by all of the rune addition routines. We add
1849 them to this structure for ease of passing. */
1851 XSETWINDOW (data.window, w);
1855 data.bi_bufpos = bi_start_pos;
1856 data.pixpos = dl->bounds.left_in;
1857 data.last_charset = Qunbound;
1858 data.last_findex = DEFAULT_INDEX;
1859 data.result_str = Qnil;
1861 /* Set the right boundary adjusting it to take into account any end
1862 glyph. Save the width of the end glyph for later use. */
1863 data.max_pixpos = dl->bounds.right_in;
1865 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1867 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1868 data.max_pixpos -= end_glyph_width;
1870 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1872 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1873 data.cursor_type = CURSOR_ON;
1875 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1876 data.cursor_type = NO_CURSOR;
1877 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1878 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1879 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1880 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1882 data.bi_cursor_bufpos = BI_BUF_PT (b);
1883 data.cursor_type = CURSOR_ON;
1885 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1887 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1888 data.cursor_type = CURSOR_ON;
1891 data.cursor_type = NO_CURSOR;
1894 data.start_col = w->hscroll;
1895 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1896 data.hscroll_glyph_width_adjust = 0;
1898 /* We regenerate the line from the very beginning. */
1899 Dynarr_reset (db->runes);
1901 /* Why is this less than or equal and not just less than? If the
1902 starting position is already equal to the maximum we can't add
1903 anything else, right? Wrong. We might still have a newline to
1904 add. A newline can use the room allocated for an end glyph since
1905 if we add it we know we aren't going to be adding any end
1908 /* #### Chuck -- I think this condition should be while (1).
1909 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1910 and the begin-glyph ends exactly at the end of the window, the
1911 end-glyph and text might not be displayed. while (1) ensures
1912 that the loop terminates only when either (a) there is
1913 propagation data or (b) the end-of-line or end-of-buffer is hit.
1915 #### Also I think you need to ensure that the operation
1916 "add begin glyphs; add end glyphs; add text" is atomic and
1917 can't get interrupted in the middle. If you run off the end
1918 of the line during that operation, then you keep accumulating
1919 propagation data until you're done. Otherwise, if the (e.g.)
1920 there's a begin glyph at a particular position and attempting
1921 to display that glyph results in window-end being hit and
1922 propagation data being generated, then the character at that
1923 position won't be displayed.
1925 #### See also the comment after the end of this loop, below.
1927 while (data.pixpos <= data.max_pixpos
1928 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1930 /* #### This check probably should not be necessary. */
1931 if (data.bi_bufpos > BI_BUF_ZV (b))
1933 /* #### urk! More of this lossage! */
1938 /* If selective display was an integer and we aren't working on
1939 a continuation line then find the next line we are actually
1940 supposed to display. */
1942 && (data.bi_bufpos == BI_BUF_BEGV (b)
1943 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
1945 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
1948 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
1949 if (data.bi_bufpos >= BI_BUF_ZV (b))
1951 data.bi_bufpos = BI_BUF_ZV (b);
1957 /* Check for face changes. */
1958 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
1960 /* Now compute the face and begin/end-glyph information. */
1962 /* Remember that the extent-fragment routines deal in Bytind's. */
1963 extent_fragment_update (w, data.ef, data.bi_bufpos);
1965 if (data.bi_bufpos == data.ef->end)
1968 dt = get_display_table (w, data.findex);
1972 /* Determine what is next to be displayed. We first handle any
1973 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
1974 display then we determine what to do based on the character at the
1975 current buffer position. */
1977 /* If the current position is covered by an invisible extent, do
1978 nothing (except maybe add some ellipses).
1980 #### The behavior of begin and end-glyphs at the edge of an
1981 invisible extent should be investigated further. This is
1982 fairly low priority though. */
1983 if (data.ef->invisible)
1985 /* #### Chuck, perhaps you could look at this code? I don't
1986 really know what I'm doing. */
1989 Dynarr_free (*prop);
1993 /* The extent fragment code only sets this when we should
1994 really display the ellipses. It makes sure the ellipses
1995 don't get displayed more than once in a row. */
1996 if (data.ef->invisible_ellipses)
1998 struct glyph_block gb;
2000 data.ef->invisible_ellipses_already_displayed = 1;
2001 data.ef->invisible_ellipses = 0;
2003 gb.glyph = Vinvisible_text_glyph;
2004 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2005 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2006 /* Perhaps they shouldn't propagate if the very next thing
2007 is to display a newline (for compatibility with
2008 selective-display-ellipses)? Maybe that's too
2014 /* If point is in an invisible region we place it on the
2015 next visible character. */
2016 if (data.cursor_type == CURSOR_ON
2017 && data.bi_bufpos == data.bi_cursor_bufpos)
2019 data.cursor_type = NEXT_CURSOR;
2022 /* #### What if we we're dealing with a display table? */
2026 if (data.bi_bufpos == BI_BUF_ZV (b))
2029 INC_BYTIND (b, data.bi_bufpos);
2032 /* If there is propagation data, then it represents the current
2033 buffer position being displayed. Add them and advance the
2034 position counter. This might also add the minibuffer
2038 dl->used_prop_data = 1;
2039 *prop = add_propagation_runes (prop, &data);
2042 goto done; /* gee, a really narrow window */
2043 else if (data.bi_bufpos == BI_BUF_ZV (b))
2045 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2046 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2047 data.bi_bufpos = BI_BUF_BEGV (b);
2049 INC_BYTIND (b, data.bi_bufpos);
2052 /* If there are end glyphs, add them to the line. These are
2053 the end glyphs for the previous run of text. We add them
2054 here rather than doing them at the end of handling the
2055 previous run so that glyphs at the beginning and end of
2056 a line are handled correctly. */
2057 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2059 *prop = add_glyph_runes (&data, END_GLYPHS);
2064 /* If there are begin glyphs, add them to the line. */
2065 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2067 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2072 /* If at end-of-buffer, we've already processed begin and
2073 end-glyphs at this point and there's no text to process,
2075 else if (data.bi_bufpos == BI_BUF_ZV (b))
2080 /* Get the character at the current buffer position. */
2081 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2083 /* If there is a display table entry for it, hand it off to
2084 add_disp_table_entry_runes and let it worry about it. */
2085 if (dt && !NILP (DISP_CHAR_ENTRY (dt, data.ch)))
2088 add_disp_table_entry_runes (&data,
2089 DISP_CHAR_ENTRY (dt, data.ch));
2095 /* Check if we have hit a newline character. If so, add a marker
2096 to the line and end this loop. */
2097 else if (data.ch == '\n')
2099 /* We aren't going to be adding an end glyph so give its
2100 space back in order to make sure that the cursor can
2102 data.max_pixpos += end_glyph_width;
2105 && (bi_spaces_at_point
2106 (b, next_bytind (b, data.bi_bufpos))
2109 if (!NILP (b->selective_display_ellipses))
2111 struct glyph_block gb;
2114 gb.glyph = Vinvisible_text_glyph;
2115 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2116 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2120 /* Cheesy, cheesy, cheesy. We mark the end of the
2121 line with a special "character rune" whose width
2122 is the EOL cursor width and whose character is
2123 the non-printing character '\n'. */
2124 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2125 *prop = add_emchar_rune (&data);
2128 /* We need to set data.bi_bufpos to the start of the
2129 next visible region in order to make this line
2130 appear to contain all of the invisible area.
2131 Otherwise, the line cache won't work
2133 INC_BYTIND (b, data.bi_bufpos);
2134 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2137 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2138 if (data.bi_bufpos >= BI_BUF_ZV (b))
2140 data.bi_bufpos = BI_BUF_ZV (b);
2144 if (BI_BUF_FETCH_CHAR
2145 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2146 DEC_BYTIND (b, data.bi_bufpos);
2150 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2151 *prop = add_emchar_rune (&data);
2157 /* If the current character is ^M, and selective display is
2158 enabled, then add the invisible-text-glyph if
2159 selective-display-ellipses is set. In any case, this
2161 else if (data.ch == (('M' & 037)) && selective == -1)
2163 Bytind bi_next_bufpos;
2165 /* Find the buffer position at the end of the line. */
2167 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2168 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2170 DEC_BYTIND (b, bi_next_bufpos);
2172 /* If the cursor is somewhere in the elided text make
2173 sure that the cursor gets drawn appropriately. */
2174 if (data.cursor_type == CURSOR_ON
2175 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2176 data.bi_cursor_bufpos < bi_next_bufpos))
2178 data.cursor_type = NEXT_CURSOR;
2181 /* We won't be adding a truncation or continuation glyph
2182 so give up the room allocated for them. */
2183 data.max_pixpos += end_glyph_width;
2185 if (!NILP (b->selective_display_ellipses))
2187 /* We don't propagate anything from the invisible
2188 text glyph if it fails to fit. This is
2190 struct glyph_block gb;
2193 gb.glyph = Vinvisible_text_glyph;
2194 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2195 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2198 /* Set the buffer position to the end of the line. We
2199 need to do this before potentially adding a newline
2200 so that the cursor flag will get set correctly (if
2202 data.bi_bufpos = bi_next_bufpos;
2204 if (NILP (b->selective_display_ellipses)
2205 || data.bi_cursor_bufpos == bi_next_bufpos)
2207 /* We have to at least add a newline character so
2208 that the cursor shows up properly. */
2210 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2211 data.findex = DEFAULT_INDEX;
2213 data.bi_start_col_enabled = 0;
2215 add_emchar_rune (&data);
2218 /* This had better be a newline but doing it this way
2219 we'll see obvious incorrect results if it isn't. No
2220 need to abort here. */
2221 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2226 /* If the current character is considered to be printable, then
2228 else if (data.ch >= printable_min)
2230 *prop = add_emchar_rune (&data);
2235 /* If the current character is a tab, determine the next tab
2236 starting position and add a blank rune which extends from the
2237 current pixel position to that starting position. */
2238 else if (data.ch == '\t')
2240 int tab_start_pixpos = data.pixpos;
2245 if (data.start_col > 1)
2246 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
2249 next_tab_position (w, tab_start_pixpos,
2250 dl->bounds.left_in +
2251 data.hscroll_glyph_width_adjust);
2252 if (next_tab_start > data.max_pixpos)
2254 prop_width = next_tab_start - data.max_pixpos;
2255 next_tab_start = data.max_pixpos;
2257 data.blank_width = next_tab_start - data.pixpos;
2259 (next_tab_start - tab_start_pixpos) / space_width (w);
2261 *prop = add_blank_rune (&data, w, char_tab_width);
2263 /* add_blank_rune is only supposed to be called with
2264 sizes guaranteed to fit in the available space. */
2269 struct prop_block pb;
2270 *prop = Dynarr_new (prop_block);
2272 pb.type = PROP_BLANK;
2273 pb.data.p_blank.width = prop_width;
2274 pb.data.p_blank.findex = data.findex;
2275 Dynarr_add (*prop, pb);
2281 /* If character is a control character, pass it off to
2282 add_control_char_runes.
2284 The is_*() routines have undefined results on
2285 arguments outside of the range [-1, 255]. (This
2286 often bites people who carelessly use `char' instead
2287 of `unsigned char'.)
2289 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2291 *prop = add_control_char_runes (&data, b);
2297 /* If the character is above the ASCII range and we have not
2298 already handled it, then print it as an octal number. */
2299 else if (data.ch >= 0200)
2301 *prop = add_octal_runes (&data);
2307 /* Assume the current character is considered to be printable,
2308 then just add it. */
2311 *prop = add_emchar_rune (&data);
2316 INC_BYTIND (b, data.bi_bufpos);
2322 /* Determine the starting point of the next line if we did not hit the
2323 end of the buffer. */
2324 if (data.bi_bufpos < BI_BUF_ZV (b)
2325 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2327 /* #### This check is not correct. If the line terminated
2328 due to a begin-glyph or end-glyph hitting window-end, then
2329 data.ch will not point to the character at data.bi_bufpos. If
2330 you make the two changes mentioned at the top of this loop,
2331 you should be able to say '(if (*prop))'. That should also
2332 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2335 /* The common case is that the line ended because we hit a newline.
2336 In that case, the next character is just the next buffer
2338 if (data.ch == '\n')
2340 /* If data.start_col_enabled is still true, then the window is
2341 scrolled far enough so that nothing on this line is visible.
2342 We need to stick a truncation glyph at the beginning of the
2343 line in that case unless the line is completely blank. */
2344 if (data.bi_start_col_enabled)
2346 if (data.cursor_type == CURSOR_ON)
2348 if (data.bi_cursor_bufpos >= bi_start_pos
2349 && data.bi_cursor_bufpos <= data.bi_bufpos)
2350 data.bi_cursor_bufpos = data.bi_bufpos;
2352 data.findex = DEFAULT_INDEX;
2354 data.bi_start_col_enabled = 0;
2356 if (data.bi_bufpos != bi_start_pos)
2358 struct glyph_block gb;
2361 gb.glyph = Vhscroll_glyph;
2362 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2363 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2367 /* This duplicates code down below to add a newline to
2368 the end of an otherwise empty line.*/
2370 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2372 add_emchar_rune (&data);
2376 INC_BYTIND (b, data.bi_bufpos);
2379 /* Otherwise we have a buffer line which cannot fit on one display
2383 struct glyph_block gb;
2384 struct glyph_cachel *cachel;
2386 /* If the line is to be truncated then we actually have to look
2387 for the next newline. We also add the end-of-line glyph which
2388 we know will fit because we adjusted the right border before
2389 we starting laying out the line. */
2390 data.max_pixpos += end_glyph_width;
2391 data.findex = DEFAULT_INDEX;
2398 /* Now find the start of the next line. */
2399 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2401 /* If the cursor is past the truncation line then we
2402 make it appear on the truncation glyph. If we've hit
2403 the end of the buffer then we also make the cursor
2404 appear unless eob is immediately preceded by a
2405 newline. In that case the cursor should actually
2406 appear on the next line. */
2407 if (data.cursor_type == CURSOR_ON
2408 && data.bi_cursor_bufpos >= data.bi_bufpos
2409 && (data.bi_cursor_bufpos < bi_pos ||
2410 (bi_pos == BI_BUF_ZV (b)
2411 && (bi_pos == BI_BUF_BEGV (b)
2412 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2414 data.bi_cursor_bufpos = bi_pos;
2416 data.cursor_type = NO_CURSOR;
2418 data.bi_bufpos = bi_pos;
2419 gb.glyph = Vtruncation_glyph;
2420 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2424 /* The cursor can never be on the continuation glyph. */
2425 data.cursor_type = NO_CURSOR;
2427 /* data.bi_bufpos is already at the start of the next line. */
2429 gb.glyph = Vcontinuation_glyph;
2430 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2433 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
2435 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2436 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2437 /* #### Damn this losing shit. */
2441 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2442 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2444 /* We need to add a marker to the end of the line since there is no
2445 newline character in order for the cursor to get drawn. We label
2446 it as a newline so that it gets handled correctly by the
2447 whitespace routines below. */
2450 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2451 data.findex = DEFAULT_INDEX;
2453 data.bi_start_col_enabled = 0;
2455 data.max_pixpos += data.blank_width;
2456 add_emchar_rune (&data);
2457 data.max_pixpos -= data.blank_width;
2459 /* #### urk! Chuck, this shit is bad news. Going around
2460 manipulating invalid positions is guaranteed to result in
2461 trouble sooner or later. */
2462 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2465 /* Calculate left whitespace boundary. */
2469 /* Whitespace past a newline is considered right whitespace. */
2470 while (elt < Dynarr_length (db->runes))
2472 struct rune *rb = Dynarr_atp (db->runes, elt);
2474 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2475 || rb->type == RUNE_BLANK)
2477 dl->bounds.left_white += rb->width;
2481 elt = Dynarr_length (db->runes);
2485 /* Calculate right whitespace boundary. */
2487 int elt = Dynarr_length (db->runes) - 1;
2490 while (!done && elt >= 0)
2492 struct rune *rb = Dynarr_atp (db->runes, elt);
2494 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2495 && isspace (rb->object.chr.ch))
2496 && !rb->type == RUNE_BLANK)
2498 dl->bounds.right_white = rb->xpos + rb->width;
2506 /* The line is blank so everything is considered to be right
2509 dl->bounds.right_white = dl->bounds.left_in;
2512 /* Set the display blocks bounds. */
2513 db->start_pos = dl->bounds.left_in;
2514 if (Dynarr_length (db->runes))
2516 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2518 db->end_pos = rb->xpos + rb->width;
2521 db->end_pos = dl->bounds.right_white;
2523 /* update line height parameters */
2524 if (!data.new_ascent && !data.new_descent)
2526 /* We've got a blank line so initialize these values from the default
2528 default_face_font_info (data.window, &data.new_ascent,
2529 &data.new_descent, 0, 0, 0);
2532 if (data.max_pixmap_height)
2534 int height = data.new_ascent + data.new_descent;
2535 int pix_ascent, pix_descent;
2537 pix_descent = data.max_pixmap_height * data.new_descent / height;
2538 pix_ascent = data.max_pixmap_height - pix_descent;
2540 data.new_ascent = max (data.new_ascent, pix_ascent);
2541 data.new_descent = max (data.new_descent, pix_descent);
2544 dl->ascent = data.new_ascent;
2545 dl->descent = data.new_descent;
2548 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2550 if (dl->ascent < ascent)
2551 dl->ascent = ascent;
2554 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2556 if (dl->descent < descent)
2557 dl->descent = descent;
2560 dl->cursor_elt = data.cursor_x;
2561 /* #### lossage lossage lossage! Fix this shit! */
2562 if (data.bi_bufpos > BI_BUF_ZV (b))
2563 dl->end_bufpos = BUF_ZV (b);
2565 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2567 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2569 /* This doesn't correctly take into account tabs and control
2570 characters but if the window isn't being truncated then this
2571 value isn't going to end up being used anyhow. */
2572 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2574 /* #### handle horizontally scrolled line with text none of which
2575 was actually laid out. */
2577 /* #### handle any remainder of overlay arrow */
2579 if (*prop == ADD_FAILED)
2582 if (truncate_win && *prop)
2584 Dynarr_free (*prop);
2588 extent_fragment_delete (data.ef);
2590 /* #### If we started at EOB, then make sure we return a value past
2591 it so that regenerate_window will exit properly. This is bogus.
2592 The main loop should get fixed so that it isn't necessary to call
2593 this function if we are already at EOB. */
2595 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2596 return data.bi_bufpos + 1; /* Yuck! */
2598 return data.bi_bufpos;
2601 /* Display the overlay arrow at the beginning of the given line. */
2604 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2606 struct frame *f = XFRAME (w->frame);
2607 struct device *d = XDEVICE (f->device);
2610 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2611 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2617 XSETWINDOW (data.window, w);
2618 data.db = get_display_block_from_line (dl, OVERWRITE);
2620 data.pixpos = dl->bounds.left_in;
2621 data.max_pixpos = dl->bounds.right_in;
2622 data.cursor_type = NO_CURSOR;
2624 data.findex = DEFAULT_INDEX;
2625 data.last_charset = Qunbound;
2626 data.last_findex = DEFAULT_INDEX;
2627 data.result_str = Qnil;
2629 Dynarr_reset (data.db->runes);
2631 if (STRINGP (Voverlay_arrow_string))
2633 add_bufbyte_string_runes
2635 XSTRING_DATA (Voverlay_arrow_string),
2636 XSTRING_LENGTH (Voverlay_arrow_string),
2639 else if (GLYPHP (Voverlay_arrow_string))
2641 struct glyph_block gb;
2643 gb.glyph = Voverlay_arrow_string;
2645 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2648 if (data.max_pixmap_height)
2650 int height = data.new_ascent + data.new_descent;
2651 int pix_ascent, pix_descent;
2653 pix_descent = data.max_pixmap_height * data.new_descent / height;
2654 pix_ascent = data.max_pixmap_height - pix_descent;
2656 data.new_ascent = max (data.new_ascent, pix_ascent);
2657 data.new_descent = max (data.new_descent, pix_descent);
2660 dl->ascent = data.new_ascent;
2661 dl->descent = data.new_descent;
2663 data.db->start_pos = dl->bounds.left_in;
2664 data.db->end_pos = data.pixpos;
2666 return data.pixpos - dl->bounds.left_in;
2669 /* Add a type of glyph to a margin display block. */
2672 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2673 int count, enum glyph_layout layout, int side, Lisp_Object window)
2675 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2677 : dl->right_glyphs);
2682 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2683 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2686 elt = Dynarr_length (gbd) - 1;
2693 end = Dynarr_length (gbd);
2696 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2698 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2700 if (NILP (gb->extent))
2701 abort (); /* these should have been handled in add_glyph_rune */
2704 ((side == LEFT_GLYPHS &&
2705 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2706 || (side == RIGHT_GLYPHS &&
2707 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2711 rb.width = gb->width;
2712 rb.findex = gb->findex;
2716 rb.type = RUNE_DGLYPH;
2717 rb.object.dglyph.glyph = gb->glyph;
2718 rb.object.dglyph.extent = gb->extent;
2719 rb.object.dglyph.xoffset = 0;
2720 rb.cursor_type = CURSOR_OFF;
2722 Dynarr_add (db->runes, rb);
2727 if (glyph_contrib_p (gb->glyph, window))
2729 unsigned short ascent, descent;
2730 Lisp_Object baseline = glyph_baseline (gb->glyph, window);
2732 ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window);
2733 descent = glyph_descent (gb->glyph, Qnil, gb->findex, window);
2735 /* A pixmap that has not had a baseline explicitly set.
2736 We use the existing ascent / descent ratio of the
2738 if (NILP (baseline))
2740 int gheight = ascent + descent;
2741 int line_height = dl->ascent + dl->descent;
2742 int pix_ascent, pix_descent;
2744 pix_descent = (int) (gheight * dl->descent) / line_height;
2745 pix_ascent = gheight - pix_descent;
2747 dl->ascent = max ((int) dl->ascent, pix_ascent);
2748 dl->descent = max ((int) dl->descent, pix_descent);
2751 /* A string so determine contribution normally. */
2752 else if (EQ (baseline, Qt))
2754 dl->ascent = max (dl->ascent, ascent);
2755 dl->descent = max (dl->descent, descent);
2758 /* A pixmap with an explicitly set baseline. We determine the
2759 contribution here. */
2760 else if (INTP (baseline))
2762 int height = ascent + descent;
2763 int pix_ascent, pix_descent;
2765 pix_ascent = height * XINT (baseline) / 100;
2766 pix_descent = height - pix_ascent;
2768 dl->ascent = max ((int) dl->ascent, pix_ascent);
2769 dl->descent = max ((int) dl->descent, pix_descent);
2772 /* Otherwise something is screwed up. */
2778 (reverse ? elt-- : elt++);
2784 /* Add a blank to a margin display block. */
2787 add_margin_blank (struct display_line *dl, struct display_block *db,
2788 struct window *w, int xpos, int width, int side)
2792 rb.findex = (side == LEFT_GLYPHS
2793 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2794 : get_builtin_face_cache_index (w, Vright_margin_face));
2799 rb.type = RUNE_BLANK;
2800 rb.cursor_type = CURSOR_OFF;
2802 Dynarr_add (db->runes, rb);
2805 /* Display glyphs in the left outside margin, left inside margin and
2806 left whitespace area. */
2809 create_left_glyph_block (struct window *w, struct display_line *dl,
2814 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2816 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2817 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2818 int left_in_start = dl->bounds.left_in;
2819 int left_in_end = dl->bounds.left_in + overlay_width;
2821 struct display_block *odb, *idb;
2823 XSETWINDOW (window, w);
2825 /* We have to add the glyphs to the line in the order outside,
2826 inside, whitespace. However the precedence dictates that we
2827 determine how many will fit in the reverse order. */
2829 /* Determine how many whitespace glyphs we can display and where
2830 they should start. */
2831 white_in_start = dl->bounds.left_white;
2832 white_out_start = left_in_start;
2833 white_out_cnt = white_in_cnt = 0;
2836 while (elt < Dynarr_length (dl->left_glyphs))
2838 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2840 if (NILP (gb->extent))
2841 abort (); /* these should have been handled in add_glyph_rune */
2843 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2847 width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2849 if (white_in_start - width >= left_in_end)
2852 white_in_start -= width;
2856 else if (use_overflow
2857 && (white_out_start - width > dl->bounds.left_out))
2860 white_out_start -= width;
2871 /* Determine how many inside margin glyphs we can display and where
2872 they should start. The inside margin glyphs get whatever space
2873 is left after the whitespace glyphs have been displayed. These
2874 are tricky to calculate since if we decide to use the overflow
2875 area we basically have to start over. So for these we build up a
2876 list of just the inside margin glyphs and manipulate it to
2877 determine the needed info. */
2879 glyph_block_dynarr *ib;
2880 int avail_in, avail_out;
2883 int used_in, used_out;
2886 used_in = used_out = 0;
2887 ib = Dynarr_new (glyph_block);
2888 while (elt < Dynarr_length (dl->left_glyphs))
2890 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2892 if (NILP (gb->extent))
2893 abort (); /* these should have been handled in add_glyph_rune */
2895 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2898 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2899 used_in += gb->width;
2900 Dynarr_add (ib, *gb);
2910 avail_in = white_in_start - left_in_end;
2918 avail_out = white_out_start - dl->bounds.left_out;
2921 while (!done && marker < Dynarr_length (ib))
2923 int width = Dynarr_atp (ib, marker)->width;
2925 /* If everything now fits in the available inside margin
2926 space, we're done. */
2927 if (used_in <= avail_in)
2931 /* Otherwise see if we have room to move a glyph to the
2933 if (used_out + width <= avail_out)
2946 /* At this point we now know that everything from marker on goes in
2947 the inside margin and everything before it goes in the outside
2948 margin. The stuff going into the outside margin is guaranteed
2949 to fit, but we may have to trim some stuff from the inside. */
2951 in_in_end = left_in_end;
2952 in_out_start = white_out_start;
2953 in_out_cnt = in_in_cnt = 0;
2957 while (elt < Dynarr_length (dl->left_glyphs))
2959 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2961 if (NILP (gb->extent))
2962 abort (); /* these should have been handled in add_glyph_rune */
2964 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2967 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2972 in_out_start -= width;
2977 else if (in_in_end + width < white_in_start)
2992 /* Determine how many outside margin glyphs we can display. They
2993 always start at the left outside margin and can only use the
2994 outside margin space. */
2995 out_end = dl->bounds.left_out;
2999 while (elt < Dynarr_length (dl->left_glyphs))
3001 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3003 if (NILP (gb->extent))
3004 abort (); /* these should have been handled in add_glyph_rune */
3006 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3009 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3011 if (out_end + width <= in_out_start)
3025 /* Now that we know where everything goes, we add the glyphs as
3026 runes to the appropriate display blocks. */
3027 if (out_cnt || in_out_cnt || white_out_cnt)
3029 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3030 odb->start_pos = dl->bounds.left_out;
3031 /* #### We should stop adding a blank to account for the space
3032 between the end of the glyphs and the margin and instead set
3033 this accordingly. */
3034 odb->end_pos = dl->bounds.left_in;
3035 Dynarr_reset (odb->runes);
3040 if (in_in_cnt || white_in_cnt)
3042 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3043 idb->start_pos = dl->bounds.left_in;
3044 /* #### See above comment for odb->end_pos */
3045 idb->end_pos = dl->bounds.left_white;
3046 Dynarr_reset (idb->runes);
3051 /* First add the outside margin glyphs. */
3053 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3054 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3056 end_xpos = dl->bounds.left_out;
3058 /* There may be blank space between the outside margin glyphs and
3059 the inside margin glyphs. If so, add a blank. */
3060 if (in_out_cnt && (in_out_start - end_xpos))
3062 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3066 /* Next add the inside margin glyphs which are actually in the
3070 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3071 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3074 /* If we didn't add any inside margin glyphs to the outside margin,
3075 but are adding whitespace glyphs, then we need to add a blank
3077 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3079 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3083 /* Next add the whitespace margin glyphs which are actually in the
3087 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3088 GL_WHITESPACE, LEFT_GLYPHS, window);
3091 /* We take care of clearing between the end of the glyphs and the
3092 start of the inside margin for lines which have glyphs. */
3093 if (odb && (left_in_start - end_xpos))
3095 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3099 /* Next add the inside margin glyphs which are actually in the
3103 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3104 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3107 end_xpos = left_in_end;
3109 /* Make sure that the area between the end of the inside margin
3110 glyphs and the whitespace glyphs is cleared. */
3111 if (idb && (white_in_start - end_xpos > 0))
3113 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3117 /* Next add the whitespace margin glyphs which are actually in the
3121 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3122 LEFT_GLYPHS, window);
3125 /* Whitespace glyphs always end right next to the text block so
3126 there is nothing we have to make sure is cleared after them. */
3129 /* Display glyphs in the right outside margin, right inside margin and
3130 right whitespace area. */
3133 create_right_glyph_block (struct window *w, struct display_line *dl)
3137 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3139 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3140 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3142 struct display_block *odb, *idb;
3144 XSETWINDOW (window, w);
3146 /* We have to add the glyphs to the line in the order outside,
3147 inside, whitespace. However the precedence dictates that we
3148 determine how many will fit in the reverse order. */
3150 /* Determine how many whitespace glyphs we can display and where
3151 they should start. */
3152 white_in_end = dl->bounds.right_white;
3153 white_out_end = dl->bounds.right_in;
3154 white_out_cnt = white_in_cnt = 0;
3157 while (elt < Dynarr_length (dl->right_glyphs))
3159 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3161 if (NILP (gb->extent))
3162 abort (); /* these should have been handled in add_glyph_rune */
3164 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3166 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3168 if (white_in_end + width <= dl->bounds.right_in)
3171 white_in_end += width;
3175 else if (use_overflow
3176 && (white_out_end + width <= dl->bounds.right_out))
3179 white_out_end += width;
3190 /* Determine how many inside margin glyphs we can display and where
3191 they should start. The inside margin glyphs get whatever space
3192 is left after the whitespace glyphs have been displayed. These
3193 are tricky to calculate since if we decide to use the overflow
3194 area we basically have to start over. So for these we build up a
3195 list of just the inside margin glyphs and manipulate it to
3196 determine the needed info. */
3198 glyph_block_dynarr *ib;
3199 int avail_in, avail_out;
3202 int used_in, used_out;
3205 used_in = used_out = 0;
3206 ib = Dynarr_new (glyph_block);
3207 while (elt < Dynarr_length (dl->right_glyphs))
3209 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3211 if (NILP (gb->extent))
3212 abort (); /* these should have been handled in add_glyph_rune */
3214 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3216 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3217 used_in += gb->width;
3218 Dynarr_add (ib, *gb);
3227 avail_in = dl->bounds.right_in - white_in_end;
3232 avail_out = dl->bounds.right_out - white_out_end;
3235 while (!done && marker < Dynarr_length (ib))
3237 int width = Dynarr_atp (ib, marker)->width;
3239 /* If everything now fits in the available inside margin
3240 space, we're done. */
3241 if (used_in <= avail_in)
3245 /* Otherwise see if we have room to move a glyph to the
3247 if (used_out + width <= avail_out)
3260 /* At this point we now know that everything from marker on goes in
3261 the inside margin and everything before it goes in the outside
3262 margin. The stuff going into the outside margin is guaranteed
3263 to fit, but we may have to trim some stuff from the inside. */
3265 in_in_start = dl->bounds.right_in;
3266 in_out_end = dl->bounds.right_in;
3267 in_out_cnt = in_in_cnt = 0;
3271 while (elt < Dynarr_length (dl->right_glyphs))
3273 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3275 if (NILP (gb->extent))
3276 abort (); /* these should have been handled in add_glyph_rune */
3278 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3280 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3285 in_out_end += width;
3290 else if (in_in_start - width >= white_in_end)
3293 in_in_start -= width;
3305 /* Determine how many outside margin glyphs we can display. They
3306 always start at the right outside margin and can only use the
3307 outside margin space. */
3308 out_start = dl->bounds.right_out;
3312 while (elt < Dynarr_length (dl->right_glyphs))
3314 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3316 if (NILP (gb->extent))
3317 abort (); /* these should have been handled in add_glyph_rune */
3319 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3321 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3323 if (out_start - width >= in_out_end)
3337 /* Now that we now where everything goes, we add the glyphs as runes
3338 to the appropriate display blocks. */
3339 if (out_cnt || in_out_cnt || white_out_cnt)
3341 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3342 /* #### See comments before odb->start_pos init in
3343 create_left_glyph_block */
3344 odb->start_pos = dl->bounds.right_in;
3345 odb->end_pos = dl->bounds.right_out;
3346 Dynarr_reset (odb->runes);
3351 if (in_in_cnt || white_in_cnt)
3353 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3354 idb->start_pos = dl->bounds.right_white;
3355 /* #### See comments before odb->start_pos init in
3356 create_left_glyph_block */
3357 idb->end_pos = dl->bounds.right_in;
3358 Dynarr_reset (idb->runes);
3363 /* First add the whitespace margin glyphs which are actually in the
3367 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3368 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3372 end_xpos = dl->bounds.right_white;
3374 /* Make sure that the area between the end of the whitespace glyphs
3375 and the inside margin glyphs is cleared. */
3376 if (in_in_cnt && (in_in_start - end_xpos))
3378 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3382 /* Next add the inside margin glyphs which are actually in the
3386 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3387 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3390 /* If we didn't add any inside margin glyphs then make sure the rest
3391 of the inside margin area gets cleared. */
3392 if (idb && (dl->bounds.right_in - end_xpos))
3394 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3398 /* Next add any whitespace glyphs in the outside margin. */
3401 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3402 GL_WHITESPACE, RIGHT_GLYPHS, window);
3405 end_xpos = dl->bounds.right_in;
3407 /* Next add any inside margin glyphs in the outside margin. */
3410 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3411 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3414 /* There may be space between any whitespace or inside margin glyphs
3415 in the outside margin and the actual outside margin glyphs. */
3416 if (odb && (out_start - end_xpos))
3418 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3422 /* Finally, add the outside margin glyphs. */
3425 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3426 RIGHT_GLYPHS, window);
3431 /***************************************************************************/
3433 /* modeline routines */
3435 /***************************************************************************/
3437 /* Ensure that the given display line DL accurately represents the
3438 modeline for the given window. */
3441 generate_modeline (struct window *w, struct display_line *dl, int type)
3443 struct buffer *b = XBUFFER (w->buffer);
3444 struct frame *f = XFRAME (w->frame);
3445 struct device *d = XDEVICE (f->device);
3447 /* Unlike display line and rune pointers, this one can't change underneath
3449 struct display_block *db = get_display_block_from_line (dl, TEXT);
3450 int max_pixpos, min_pixpos, ypos_adj;
3451 Lisp_Object font_inst;
3453 /* This will actually determine incorrect inside boundaries for the
3454 modeline since it ignores the margins. However being aware of this fact
3455 we never use those values anywhere so it doesn't matter. */
3456 dl->bounds = calculate_display_line_boundaries (w, 1);
3458 /* We are generating a modeline. */
3460 dl->cursor_elt = -1;
3462 /* Reset the runes on the modeline. */
3463 Dynarr_reset (db->runes);
3465 if (!WINDOW_HAS_MODELINE_P (w))
3469 /* If there is a horizontal scrollbar, don't add anything. */
3470 if (window_scrollbar_height (w))
3473 dl->ascent = DEVMETH (d, divider_height, ());
3475 /* The modeline is at the bottom of the gutters. */
3476 dl->ypos = WINDOW_BOTTOM (w);
3478 rb.findex = MODELINE_INDEX;
3479 rb.xpos = dl->bounds.left_out;
3480 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3483 rb.type = RUNE_HLINE;
3484 rb.object.hline.thickness = 1;
3485 rb.object.hline.yoffset = 0;
3486 rb.cursor_type = NO_CURSOR;
3488 if (!EQ (Qzero, w->modeline_shadow_thickness)
3491 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3493 dl->ypos -= shadow_thickness;
3494 rb.xpos += shadow_thickness;
3495 rb.width -= 2 * shadow_thickness;
3498 Dynarr_add (db->runes, rb);
3502 /* !!#### not right; needs to compute the max height of
3504 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3506 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3507 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3509 min_pixpos = dl->bounds.left_out;
3510 max_pixpos = dl->bounds.right_out;
3512 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3514 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3516 ypos_adj = shadow_thickness;
3517 min_pixpos += shadow_thickness;
3518 max_pixpos -= shadow_thickness;
3523 generate_formatted_string_db (b->modeline_format,
3524 b->generated_modeline_string, w, dl, db,
3525 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3527 /* The modeline is at the bottom of the gutters. We have to wait to
3528 set this until we've generated the modeline in order to account
3529 for any embedded faces. */
3530 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3534 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3535 struct window *w, struct display_line *dl,
3536 struct display_block *db, face_index findex,
3537 int min_pixpos, int max_pixpos, int type)
3539 struct frame *f = XFRAME (w->frame);
3540 struct device *d = XDEVICE (f->device);
3549 data.findex = findex;
3550 data.pixpos = min_pixpos;
3551 data.max_pixpos = max_pixpos;
3552 data.cursor_type = NO_CURSOR;
3553 data.last_charset = Qunbound;
3554 data.last_findex = DEFAULT_INDEX;
3555 data.result_str = result_str;
3556 data.is_modeline = 1;
3557 XSETWINDOW (data.window, w);
3559 Dynarr_reset (formatted_string_extent_dynarr);
3560 Dynarr_reset (formatted_string_extent_start_dynarr);
3561 Dynarr_reset (formatted_string_extent_end_dynarr);
3563 /* This recursively builds up the modeline. */
3564 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3565 max_pixpos - min_pixpos, findex, type);
3567 if (Dynarr_length (db->runes))
3570 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3571 c_pixpos = rb->xpos + rb->width;
3574 c_pixpos = min_pixpos;
3576 /* If we don't reach the right side of the window, add a blank rune
3577 to make up the difference. This usually only occurs if the
3578 modeline face is using a proportional width font or a fixed width
3579 font of a different size from the default face font. */
3581 if (c_pixpos < max_pixpos)
3583 data.pixpos = c_pixpos;
3584 data.blank_width = max_pixpos - data.pixpos;
3586 add_blank_rune (&data, NULL, 0);
3589 /* Now create the result string and frob the extents into it. */
3590 if (!NILP (result_str))
3595 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3597 detach_all_extents (result_str);
3598 resize_string (XSTRING (result_str), -1,
3599 data.bytepos - XSTRING_LENGTH (result_str));
3601 strdata = XSTRING_DATA (result_str);
3603 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3605 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3607 len += (set_charptr_emchar
3608 (strdata + len, Dynarr_atp (db->runes,
3609 elt)->object.chr.ch));
3613 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3616 Lisp_Object extent = Qnil;
3619 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3620 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3623 child = Fmake_extent (Qnil, Qnil, result_str);
3624 Fputhash (extent, child, buf->modeline_extent_table);
3626 Fset_extent_parent (child, extent);
3627 set_extent_endpoints
3629 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3630 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3637 add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
3638 Charcount pos, Charcount min_pos, Charcount max_pos)
3640 /* This function has been Mule-ized. */
3642 CONST Bufbyte *cur_pos = str;
3643 struct display_block *db = data->db;
3645 data->blank_width = space_width (XWINDOW (data->window));
3646 while (Dynarr_length (db->runes) < pos)
3647 add_blank_rune (data, NULL, 0);
3649 end = (Dynarr_length (db->runes) +
3650 bytecount_to_charcount (str, strlen ((CONST char *) str)));
3652 end = min (max_pos, end);
3654 while (pos < end && *cur_pos)
3656 CONST Bufbyte *old_cur_pos = cur_pos;
3659 data->ch = charptr_emchar (cur_pos);
3660 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3661 INC_CHARPTR (cur_pos);
3665 data->modeline_charpos++;
3666 data->bytepos += cur_pos - old_cur_pos;
3670 while (Dynarr_length (db->runes) < min_pos &&
3671 (data->pixpos + data->blank_width <= data->max_pixpos))
3672 add_blank_rune (data, NULL, 0);
3674 return Dynarr_length (db->runes);
3677 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3678 modeline extents. */
3680 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3681 Charcount pos, Charcount min_pos, Charcount max_pos)
3683 /* This function has been Mule-ized. */
3685 struct display_block *db = data->db;
3686 struct glyph_block gb;
3688 data->blank_width = space_width (XWINDOW (data->window));
3689 while (Dynarr_length (db->runes) < pos)
3690 add_blank_rune (data, NULL, 0);
3692 end = Dynarr_length (db->runes) + 1;
3694 end = min (max_pos, end);
3698 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3701 while (Dynarr_length (db->runes) < pos &&
3702 (data->pixpos + data->blank_width <= data->max_pixpos))
3703 add_blank_rune (data, NULL, 0);
3705 return Dynarr_length (db->runes);
3708 /* If max_pos is == -1, it is considered to be infinite. The same is
3709 true of max_pixsize. */
3710 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3711 if (Dynarr_length (data->db->runes)) \
3712 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3716 /* Note that this function does "positions" in terms of characters and
3717 not in terms of columns. This is necessary to make the formatting
3718 work correctly when proportional width fonts are used in the
3721 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3722 Charcount min_pos, Charcount max_pos,
3723 Lisp_Object elt, int depth, int max_pixsize,
3724 face_index findex, int type)
3726 /* This function has been Mule-ized. */
3727 /* #### The other losing things in this function are:
3729 -- C zero-terminated-string lossage.
3730 -- Non-printable characters should be converted into something
3731 appropriate (e.g. ^F) instead of blindly being printed anyway.
3742 /* A string. Add to the display line and check for %-constructs
3745 Bufbyte *this = XSTRING_DATA (elt);
3747 while ((pos < max_pos || max_pos == -1) && *this)
3749 Bufbyte *last = this;
3751 while (*this && *this != '%')
3756 /* The string is just a string. */
3758 bytecount_to_charcount (last, this - last) + pos;
3759 Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos));
3761 pos = add_string_to_fstring_db_runes (data, last, pos, pos,
3764 else /* *this == '%' */
3766 Charcount spec_width = 0;
3768 this++; /* skip over '%' */
3770 /* We can't allow -ve args due to the "%-" construct.
3771 * Argument specifies minwidth but not maxwidth
3772 * (maxwidth can be specified by
3773 * (<negative-number> . <stuff>) modeline elements)
3775 while (isdigit (*this))
3777 spec_width = spec_width * 10 + (*this - '0');
3784 pos = generate_fstring_runes (w, data, pos, spec_width,
3785 max_pos, Vglobal_mode_string,
3786 depth, max_pixsize, findex,
3789 else if (*this == '-')
3791 Charcount num_to_add;
3793 if (max_pixsize < 0)
3795 else if (max_pos != -1)
3796 num_to_add = max_pos - pos;
3802 SET_CURRENT_MODE_CHARS_PIXSIZE;
3805 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3808 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3812 while (num_to_add--)
3813 pos = add_string_to_fstring_db_runes
3814 (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
3816 else if (*this != 0)
3819 Emchar ch = charptr_emchar (this);
3820 decode_mode_spec (w, ch, type);
3822 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3823 pos = add_string_to_fstring_db_runes (data,str, pos, pos,
3827 /* NOT this++. There could be any sort of character at
3828 the current position. */
3832 if (max_pixsize > 0)
3835 SET_CURRENT_MODE_CHARS_PIXSIZE;
3837 if (cur_pixsize >= max_pixsize)
3842 else if (SYMBOLP (elt))
3844 /* A symbol: process the value of the symbol recursively
3845 as if it appeared here directly. */
3846 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3848 if (!UNBOUNDP (tem))
3850 /* If value is a string, output that string literally:
3851 don't check for % within it. */
3855 add_string_to_fstring_db_runes
3856 (data, XSTRING_DATA (tem), pos, min_pos, max_pos);
3858 /* Give up right away for nil or t. */
3859 else if (!EQ (tem, elt))
3866 else if (GENERIC_SPECIFIERP (elt))
3868 Lisp_Object window, tem;
3869 XSETWINDOW (window, w);
3870 tem = specifier_instance_no_quit (elt, Qunbound, window,
3871 ERROR_ME_NOT, 0, Qzero);
3872 if (!UNBOUNDP (tem))
3878 else if (CONSP (elt))
3880 /* A cons cell: four distinct cases.
3881 * If first element is a string or a cons, process all the elements
3882 * and effectively concatenate them.
3883 * If first element is a negative number, truncate displaying cdr to
3884 * at most that many characters. If positive, pad (with spaces)
3885 * to at least that many characters.
3886 * If first element is a symbol, process the cadr or caddr recursively
3887 * according to whether the symbol's value is non-nil or nil.
3888 * If first element is a face, process the cdr recursively
3889 * without altering the depth.
3891 Lisp_Object car, tem;
3899 tem = symbol_value_in_buffer (car, w->buffer);
3900 /* elt is now the cdr, and we know it is a cons cell.
3901 Use its car if CAR has a non-nil value. */
3902 if (!UNBOUNDP (tem))
3910 /* Symbol's value is nil (or symbol is unbound)
3911 * Get the cddr of the original list
3912 * and if possible find the caddr and use that.
3917 else if (!CONSP (elt))
3925 else if (INTP (car))
3927 Charcount lim = XINT (car);
3933 /* Negative int means reduce maximum width.
3934 * DO NOT change MIN_PIXPOS here!
3935 * (20 -10 . foo) should truncate foo to 10 col
3936 * and then pad to 20.
3939 max_pos = pos - lim;
3941 max_pos = min (max_pos, pos - lim);
3945 /* Padding specified. Don't let it be more than
3949 if (max_pos != -1 && lim > max_pos)
3951 /* If that's more padding than already wanted, queue it.
3952 * But don't reduce padding already specified even if
3953 * that is beyond the current truncation point.
3960 else if (STRINGP (car) || CONSP (car))
3963 /* LIMIT is to protect against circular lists. */
3964 while (CONSP (elt) && --limit > 0
3965 && (pos < max_pos || max_pos == -1))
3967 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
3969 max_pixsize, findex, type);
3973 else if (EXTENTP (car))
3975 struct extent *ext = XEXTENT (car);
3977 if (EXTENT_LIVE_P (ext))
3979 face_index old_findex = data->findex;
3981 Lisp_Object font_inst;
3982 face_index new_findex;
3983 Bytecount start = data->bytepos;
3985 face = extent_face (ext);
3988 /* #### needs to merge faces, sigh */
3989 /* #### needs to handle list of faces */
3990 new_findex = get_builtin_face_cache_index (w, face);
3991 /* !!#### not right; needs to compute the max height of
3993 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
3996 data->dl->ascent = max (data->dl->ascent,
3997 XFONT_INSTANCE (font_inst)->ascent);
3998 data->dl->descent = max (data->dl->descent,
3999 XFONT_INSTANCE (font_inst)->
4003 new_findex = old_findex;
4005 data->findex = new_findex;
4006 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4007 XCDR (elt), depth - 1,
4008 max_pixsize, new_findex, type);
4009 data->findex = old_findex;
4010 Dynarr_add (formatted_string_extent_dynarr, ext);
4011 Dynarr_add (formatted_string_extent_start_dynarr, start);
4012 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4016 else if (GLYPHP (elt))
4018 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos);
4024 add_string_to_fstring_db_runes
4025 (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos,
4031 add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos,
4038 /* The caller is responsible for freeing the returned string. */
4040 generate_formatted_string (struct window *w, Lisp_Object format_str,
4041 Lisp_Object result_str, face_index findex, int type)
4043 struct display_line *dl;
4044 struct display_block *db;
4047 dl = &formatted_string_display_line;
4048 db = get_display_block_from_line (dl, TEXT);
4049 Dynarr_reset (db->runes);
4051 generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
4054 Dynarr_reset (formatted_string_emchar_dynarr);
4055 while (elt < Dynarr_length (db->runes))
4057 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
4058 Dynarr_add (formatted_string_emchar_dynarr,
4059 Dynarr_atp (db->runes, elt)->object.chr.ch);
4064 convert_emchar_string_into_malloced_string
4065 ( Dynarr_atp (formatted_string_emchar_dynarr, 0),
4066 Dynarr_length (formatted_string_emchar_dynarr), 0);
4069 /* Update just the modeline. Assumes the desired display structs. If
4070 they do not have a modeline block, it does nothing. */
4072 regenerate_modeline (struct window *w)
4074 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4076 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4080 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4081 redisplay_update_line (w, 0, 0, 0);
4085 /* Make sure that modeline display line is present in the given
4086 display structs if the window has a modeline and update that
4087 line. Returns true if a modeline was needed. */
4089 ensure_modeline_generated (struct window *w, int type)
4093 /* minibuffer windows don't have modelines */
4094 if (MINI_WINDOW_P (w))
4096 /* windows which haven't had it turned off do */
4097 else if (WINDOW_HAS_MODELINE_P (w))
4099 /* windows which have it turned off don't have a divider if there is
4100 a horizontal scrollbar */
4101 else if (window_scrollbar_height (w))
4103 /* and in this case there is none */
4109 display_line_dynarr *dla;
4111 dla = window_display_lines (w, type);
4113 /* We don't care if there is a display line which is not
4114 currently a modeline because it is definitely going to become
4115 one if we have gotten to this point. */
4116 if (Dynarr_length (dla) == 0)
4118 if (Dynarr_largest (dla) > 0)
4120 struct display_line *mlp = Dynarr_atp (dla, 0);
4121 Dynarr_add (dla, *mlp);
4125 struct display_line modeline;
4127 Dynarr_add (dla, modeline);
4131 /* If we're adding a new place marker go ahead and generate the
4132 modeline so that it is available for use by
4133 window_modeline_height. */
4134 generate_modeline (w, Dynarr_atp (dla, 0), type);
4137 return need_modeline;
4140 /* #### Kludge or not a kludge. I tend towards the former. */
4142 real_current_modeline_height (struct window *w)
4144 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4145 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4147 if (ensure_modeline_generated (w, CMOTION_DISP))
4149 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4151 if (Dynarr_length (dla))
4153 if (Dynarr_atp (dla, 0)->modeline)
4154 return (Dynarr_atp (dla, 0)->ascent +
4155 Dynarr_atp (dla, 0)->descent);
4162 /***************************************************************************/
4164 /* window-regeneration routines */
4166 /***************************************************************************/
4168 /* For a given window and starting position in the buffer it contains,
4169 ensure that the TYPE display lines accurately represent the
4170 presentation of the window. We pass the buffer instead of getting
4171 it from the window since redisplay_window may have temporarily
4172 changed it to the echo area buffer. */
4175 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
4177 struct frame *f = XFRAME (w->frame);
4178 struct buffer *b = XBUFFER (w->buffer);
4179 int ypos = WINDOW_TEXT_TOP (w);
4180 int yend; /* set farther down */
4182 prop_block_dynarr *prop;
4183 layout_bounds bounds;
4184 display_line_dynarr *dla;
4187 /* The lines had better exist by this point. */
4188 if (!(dla = window_display_lines (w, type)))
4191 w->max_line_len = 0;
4193 /* Normally these get updated in redisplay_window but it is possible
4194 for this function to get called from some other points where that
4195 update may not have occurred. This acts as a safety check. */
4196 if (!Dynarr_length (w->face_cachels))
4197 reset_face_cachels (w);
4198 if (!Dynarr_length (w->glyph_cachels))
4199 reset_glyph_cachels (w);
4201 Fset_marker (w->start[type], make_int (start_pos), w->buffer);
4202 Fset_marker (w->pointm[type], make_int (point), w->buffer);
4203 w->last_point_x[type] = -1;
4204 w->last_point_y[type] = -1;
4206 /* Make sure a modeline is in the structs if needed. */
4207 need_modeline = ensure_modeline_generated (w, type);
4209 /* Wait until here to set this so that the structs have a modeline
4210 generated in the case where one didn't exist. */
4211 yend = WINDOW_TEXT_BOTTOM (w);
4213 bounds = calculate_display_line_boundaries (w, 0);
4215 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
4216 if (MINI_WINDOW_P (w)
4217 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
4218 && !echo_area_active (f)
4219 && start_pos == BUF_BEGV (b))
4221 struct prop_block pb;
4223 prop = Dynarr_new (prop_block);
4225 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
4226 pb.type = PROP_MINIBUF_PROMPT;
4227 pb.data.p_string.str = XSTRING_DATA(string);
4228 pb.data.p_string.len = XSTRING_LENGTH(string);
4229 Dynarr_add (prop, pb);
4236 struct display_line dl;
4237 struct display_line *dlp;
4240 if (Dynarr_length (dla) < Dynarr_largest (dla))
4242 dlp = Dynarr_atp (dla, Dynarr_length (dla));
4252 dlp->bounds = bounds;
4254 start_pos = generate_display_line (w, dlp, 1, start_pos,
4255 w->hscroll, &prop, type);
4256 dlp->ypos = ypos + dlp->ascent;
4257 ypos = dlp->ypos + dlp->descent;
4261 int visible_height = dlp->ascent + dlp->descent;
4263 dlp->clip = (ypos - yend);
4264 visible_height -= dlp->clip;
4266 if (visible_height < VERTICAL_CLIP (w, 1))
4269 free_display_line (dlp);
4276 if (dlp->cursor_elt != -1)
4278 /* #### This check is steaming crap. Have to get things
4279 fixed so when create_text_block hits EOB, we're done,
4281 if (w->last_point_x[type] == -1)
4283 w->last_point_x[type] = dlp->cursor_elt;
4284 w->last_point_y[type] = Dynarr_length (dla);
4288 /* #### This means that we've added a cursor at EOB
4289 twice. Yuck oh yuck. */
4290 struct display_block *db =
4291 get_display_block_from_line (dlp, TEXT);
4293 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
4294 dlp->cursor_elt = -1;
4298 if (dlp->num_chars > w->max_line_len)
4299 w->max_line_len = dlp->num_chars;
4301 Dynarr_add (dla, *dlp);
4303 /* #### This isn't right, but it is close enough for now. */
4304 w->window_end_pos[type] = start_pos;
4306 /* #### This type of check needs to be done down in the
4307 generate_display_line call. */
4308 if (start_pos > BUF_ZV (b))
4315 /* #### More not quite right, but close enough. */
4316 /* #### Ben sez: apparently window_end_pos[] is measured
4317 as the number of characters between the window end and the
4318 end of the buffer? This seems rather weirdo. What's
4319 the justification for this? */
4320 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
4324 /* We know that this is the right thing to use because we put it
4325 there when we first started working in this function. */
4326 generate_modeline (w, Dynarr_atp (dla, 0), type);
4330 #define REGEN_INC_FIND_START_END \
4332 /* Determine start and end of lines. */ \
4333 if (!Dynarr_length (cdla)) \
4337 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
4341 else if (!Dynarr_atp (cdla, 0)->modeline \
4342 && !Dynarr_atp (ddla, 0)->modeline) \
4347 abort (); /* structs differ */ \
4349 dla_end = Dynarr_length (cdla) - 1; \
4352 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
4353 + Dynarr_atp (cdla, dla_start)->offset); \
4354 /* If this isn't true, then startp has changed and we need to do a \
4356 if (startp != start_pos) \
4359 /* Point is outside the visible region so give up. */ \
4360 if (pointm < start_pos) \
4365 /* This attempts to incrementally update the display structures. It
4366 returns a boolean indicating success or failure. This function is
4367 very similar to regenerate_window_incrementally and is in fact only
4368 called from that function. However, because of the nature of the
4369 changes it deals with it sometimes makes different assumptions
4370 which can lead to success which are much more difficult to make
4371 when dealing with buffer changes. */
4374 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
4376 Charcount beg_unchanged,
4377 Charcount end_unchanged)
4379 struct buffer *b = XBUFFER (w->buffer);
4380 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
4381 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
4385 int first_line, last_line;
4387 /* Don't define this in the loop where it is used because we
4388 definitely want its value to survive between passes. */
4389 prop_block_dynarr *prop = NULL;
4391 /* If we don't have any buffer change recorded but the modiff flag has
4392 been incremented, then fail. I'm not sure of the exact circumstances
4393 under which this can happen, but I believe that it is probably a
4394 reasonable happening. */
4395 if (!point_visible (w, pointm, CURRENT_DISP)
4396 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
4399 /* If the cursor is moved we attempt to update it. If we succeed we
4400 go ahead and proceed with the optimization attempt. */
4401 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
4402 || pointm != marker_position (w->last_point[CURRENT_DISP]))
4404 struct frame *f = XFRAME (w->frame);
4405 struct device *d = XDEVICE (f->device);
4406 struct frame *sel_f = device_selected_frame (d);
4409 if (w->last_point_x[CURRENT_DISP] != -1
4410 && w->last_point_y[CURRENT_DISP] != -1)
4413 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
4415 /* Always regenerate the modeline in case it is
4416 displaying the current line or column. */
4417 regenerate_modeline (w);
4421 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
4423 if (f->modeline_changed)
4424 regenerate_modeline (w);
4432 if (beg_unchanged == -1 && end_unchanged == -1)
4435 /* assert: There are no buffer modifications or they are all below the
4436 visible region. We assume that regenerate_window_incrementally has
4437 not called us unless this is true. */
4439 REGEN_INC_FIND_START_END;
4441 /* If the changed are starts before the visible area, give up. */
4442 if (beg_unchanged < startp)
4445 /* Find what display line the extent changes first affect. */
4447 while (line <= dla_end)
4449 struct display_line *dl = Dynarr_atp (cdla, line);
4450 Bufpos lstart = dl->bufpos + dl->offset;
4451 Bufpos lend = dl->end_bufpos + dl->offset;
4453 if (beg_unchanged >= lstart && beg_unchanged <= lend)
4459 /* If the changes are below the visible area then if point hasn't
4460 moved return success otherwise fail in order to be safe. */
4463 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
4464 && pointm == marker_position (w->last_point[CURRENT_DISP]))
4470 /* At this point we know what line the changes first affect. We now
4471 begin redrawing lines as long as we are still in the affected
4472 region and the line's size and positioning don't change.
4473 Otherwise we fail. If we fail we will have altered the desired
4474 structs which could lead to an assertion failure. However, if we
4475 fail the next thing that is going to happen is a full regen so we
4476 will actually end up being safe. */
4477 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
4478 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
4479 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
4480 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
4482 first_line = last_line = line;
4483 while (line <= dla_end)
4485 Bufpos old_start, old_end, new_start;
4486 struct display_line *cdl = Dynarr_atp (cdla, line);
4487 struct display_line *ddl = Dynarr_atp (ddla, line);
4488 struct display_block *db;
4491 assert (cdl->bufpos == ddl->bufpos);
4492 assert (cdl->end_bufpos == ddl->end_bufpos);
4493 assert (cdl->offset == ddl->offset);
4495 db = get_display_block_from_line (ddl, TEXT);
4496 initial_size = Dynarr_length (db->runes);
4497 old_start = ddl->bufpos + ddl->offset;
4498 old_end = ddl->end_bufpos + ddl->offset;
4500 /* If this is the first line being updated and it used
4501 propagation data, fail. Otherwise we'll be okay because
4502 we'll have the necessary propagation data. */
4503 if (line == first_line && ddl->used_prop_data)
4506 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
4507 w->hscroll, &prop, DESIRED_DISP);
4510 /* #### If there is propagated stuff the fail. We could
4511 probably actually deal with this if the line had propagated
4512 information when originally created by a full
4520 /* If any line position parameters have changed or a
4521 cursor has disappeared or disappeared, fail. */
4522 db = get_display_block_from_line (ddl, TEXT);
4523 if (cdl->ypos != ddl->ypos
4524 || cdl->ascent != ddl->ascent
4525 || cdl->descent != ddl->descent
4526 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
4527 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
4528 || old_start != ddl->bufpos
4529 || old_end != ddl->end_bufpos
4530 || initial_size != Dynarr_length (db->runes))
4535 if (ddl->cursor_elt != -1)
4537 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
4538 w->last_point_y[DESIRED_DISP] = line;
4543 /* If the extent changes end on the line we just updated then
4544 we're done. Otherwise go on to the next line. */
4545 if (end_unchanged <= ddl->end_bufpos)
4551 redisplay_update_line (w, first_line, last_line, 1);
4555 /* Attempt to update the display data structures based on knowledge of
4556 the changed region in the buffer. Returns a boolean indicating
4557 success or failure. If this function returns a failure then a
4558 regenerate_window _must_ be performed next in order to maintain
4559 invariants located here. */
4562 regenerate_window_incrementally (struct window *w, Bufpos startp,
4565 struct buffer *b = XBUFFER (w->buffer);
4566 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
4567 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
4568 Charcount beg_unchanged, end_unchanged;
4569 Charcount extent_beg_unchanged, extent_end_unchanged;
4575 /* If this function is called, the current and desired structures
4576 had better be identical. If they are not, then that is a bug. */
4577 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
4579 /* We don't handle minibuffer windows yet. The minibuffer prompt
4581 if (MINI_WINDOW_P (w))
4584 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
4585 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
4587 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
4589 /* If nothing has changed in the buffer, then make sure point is ok
4591 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
4592 return regenerate_window_extents_only_changed (w, startp, pointm,
4593 extent_beg_unchanged,
4594 extent_end_unchanged);
4596 /* We can't deal with deleted newlines. */
4597 if (BUF_NEWLINE_WAS_DELETED (b))
4600 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
4601 end_unchanged = (BUF_END_UNCHANGED (b) == -1
4603 : BUF_Z (b) - BUF_END_UNCHANGED (b));
4605 REGEN_INC_FIND_START_END;
4607 /* If the changed area starts before the visible area, give up. */
4608 if (beg_unchanged < startp)
4611 /* Find what display line the buffer changes first affect. */
4613 while (line <= dla_end)
4615 struct display_line *dl = Dynarr_atp (cdla, line);
4616 Bufpos lstart = dl->bufpos + dl->offset;
4617 Bufpos lend = dl->end_bufpos + dl->offset;
4619 if (beg_unchanged >= lstart && beg_unchanged <= lend)
4625 /* If the changes are below the visible area then if point hasn't
4626 moved return success otherwise fail in order to be safe. */
4629 return regenerate_window_extents_only_changed (w, startp, pointm,
4630 extent_beg_unchanged,
4631 extent_end_unchanged);
4634 /* At this point we know what line the changes first affect. We
4635 now redraw that line. If the changes are contained within it
4636 we are going to succeed and can update just that one line.
4637 Otherwise we fail. If we fail we will have altered the desired
4638 structs which could lead to an assertion failure. However, if
4639 we fail the next thing that is going to happen is a full regen
4640 so we will actually end up being safe. */
4643 prop_block_dynarr *prop = NULL;
4644 struct display_line *cdl = Dynarr_atp (cdla, line);
4645 struct display_line *ddl = Dynarr_atp (ddla, line);
4647 assert (cdl->bufpos == ddl->bufpos);
4648 assert (cdl->end_bufpos == ddl->end_bufpos);
4649 assert (cdl->offset == ddl->offset);
4651 /* If the last rune is already a continuation glyph, fail.
4652 #### We should be able to handle this better. */
4654 struct display_block *db = get_display_block_from_line (ddl, TEXT);
4655 if (Dynarr_length (db->runes))
4658 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4660 if (rb->type == RUNE_DGLYPH
4661 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
4666 /* If the line was generated using propagation data, fail. */
4667 if (ddl->used_prop_data)
4670 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
4671 w->hscroll, &prop, DESIRED_DISP);
4674 /* If there is propagated stuff then it is pretty much a
4675 guarantee that more than just the one line is affected. */
4682 /* If the last rune is now a continuation glyph, fail. */
4684 struct display_block *db = get_display_block_from_line (ddl, TEXT);
4685 if (Dynarr_length (db->runes))
4688 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4690 if (rb->type == RUNE_DGLYPH
4691 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
4696 /* If any line position parameters have changed or a
4697 cursor has disappeared or disappeared, fail. */
4698 if (cdl->ypos != ddl->ypos
4699 || cdl->ascent != ddl->ascent
4700 || cdl->descent != ddl->descent
4701 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
4702 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
4707 /* If the changed area also ends on this line, then we may be in
4708 business. Update everything and return success. */
4709 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
4711 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
4712 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
4713 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
4715 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
4718 if (ddl->cursor_elt != -1)
4720 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
4721 w->last_point_y[DESIRED_DISP] = line;
4724 redisplay_update_line (w, line, line, 1);
4725 regenerate_modeline (w);
4727 /* #### For now we just flush the cache until this has been
4728 tested. After that is done, this should correct the
4730 Dynarr_reset (w->line_start_cache);
4732 /* Adjust the extent changed boundaries to remove any
4733 overlap with the buffer changes since we've just
4734 successfully updated that area. */
4735 if (extent_beg_unchanged != -1
4736 && extent_beg_unchanged >= beg_unchanged
4737 && extent_beg_unchanged < end_unchanged)
4738 extent_beg_unchanged = end_unchanged;
4740 if (extent_end_unchanged != -1
4741 && extent_end_unchanged >= beg_unchanged
4742 && extent_end_unchanged < end_unchanged)
4743 extent_end_unchanged = beg_unchanged - 1;
4745 if (extent_end_unchanged <= extent_beg_unchanged)
4746 extent_beg_unchanged = extent_end_unchanged = -1;
4748 /* This could lead to odd results if it fails, but since the
4749 buffer changes update succeeded this probably will to.
4750 We already know that the extent changes start at or after
4751 the line because we checked before entering the loop. */
4752 if (extent_beg_unchanged != -1
4753 && extent_end_unchanged != -1
4754 && ((extent_beg_unchanged < ddl->bufpos)
4755 || (extent_end_unchanged > ddl->end_bufpos)))
4758 regenerate_window_extents_only_changed (w, startp, pointm,
4759 extent_beg_unchanged,
4760 extent_end_unchanged);
4771 /* Given a window and a point, update the given display lines such
4772 that point is displayed in the middle of the window.
4773 Return the window's new start position. */
4776 regenerate_window_point_center (struct window *w, Bufpos point, int type)
4780 /* We need to make sure that the modeline is generated so that the
4781 window height can be calculated correctly. */
4782 ensure_modeline_generated (w, type);
4784 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
4785 regenerate_window (w, startp, point, type);
4786 Fset_marker (w->start[type], make_int (startp), w->buffer);
4791 /* Given a window and a set of display lines, return a boolean
4792 indicating whether the given point is contained within. */
4795 point_visible (struct window *w, Bufpos point, int type)
4797 struct buffer *b = XBUFFER (w->buffer);
4798 display_line_dynarr *dla = window_display_lines (w, type);
4801 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
4806 if (Dynarr_length (dla) > first_line)
4809 struct display_line *dl = Dynarr_atp (dla, first_line);
4812 end = BUF_Z (b) - w->window_end_pos[type] - 1;
4814 if (point >= start && point <= end)
4816 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
4818 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
4820 if (point >= (dl->bufpos + dl->offset)
4821 && point <= (dl->end_bufpos + dl->offset))
4836 /* Return pixel position the middle of the window, not including the
4837 modeline and any potential horizontal scrollbar. */
4840 window_half_pixpos (struct window *w)
4842 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
4845 /* Return the display line which is currently in the middle of the
4846 window W for display lines TYPE. */
4849 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
4851 display_line_dynarr *dla;
4854 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
4856 if (type == CMOTION_DISP)
4857 regenerate_window (w, start, point, type);
4859 dla = window_display_lines (w, type);
4860 half = window_half_pixpos (w);
4862 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
4864 struct display_line *dl = Dynarr_atp (dla, elt);
4865 int line_bot = dl->ypos + dl->descent;
4867 if (line_bot > half)
4871 /* We may not have a line at the middle if the end of the buffer is
4876 /* Return a value for point that would place it at the beginning of
4877 the line which is in the middle of the window. */
4880 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
4882 /* line_at_center will regenerate the display structures, if necessary. */
4883 int line = line_at_center (w, type, start, point);
4886 return BUF_ZV (XBUFFER (w->buffer));
4889 display_line_dynarr *dla = window_display_lines (w, type);
4890 struct display_line *dl = Dynarr_atp (dla, line);
4896 /* For a given window, ensure that the current visual representation
4900 redisplay_window (Lisp_Object window, int skip_selected)
4902 struct window *w = XWINDOW (window);
4903 struct frame *f = XFRAME (w->frame);
4904 struct device *d = XDEVICE (f->device);
4905 Lisp_Object old_buffer = w->buffer;
4906 Lisp_Object the_buffer = w->buffer;
4908 int echo_active = 0;
4913 int selected_in_its_frame;
4914 int selected_globally;
4915 int skip_output = 0;
4916 int truncation_changed;
4917 int inactive_minibuffer =
4918 (MINI_WINDOW_P (w) &&
4919 (f != device_selected_frame (d)) &&
4920 !is_surrogate_for_selected_frame (f));
4922 /* #### In the new world this function actually does a bunch of
4923 optimizations such as buffer-based scrolling, but none of that is
4926 /* If this is a combination window, do its children; that's all.
4927 The selected window is always a leaf so we don't check for
4928 skip_selected here. */
4929 if (!NILP (w->vchild))
4931 redisplay_windows (w->vchild, skip_selected);
4934 if (!NILP (w->hchild))
4936 redisplay_windows (w->hchild, skip_selected);
4940 /* Is this window the selected window on its frame? */
4941 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
4943 selected_in_its_frame &&
4944 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
4945 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
4946 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
4947 if (skip_selected && selected_in_its_frame)
4950 /* It is possible that the window is not fully initialized yet. */
4951 if (NILP (w->buffer))
4954 if (MINI_WINDOW_P (w) && echo_area_active (f))
4956 w->buffer = the_buffer = Vecho_area_buffer;
4960 b = XBUFFER (w->buffer);
4964 old_pointm = selected_globally
4966 : marker_position (w->pointm[CURRENT_DISP]);
4971 if (selected_globally)
4973 pointm = BUF_PT (b);
4977 pointm = marker_position (w->pointm[CURRENT_DISP]);
4979 if (pointm < BUF_BEGV (b))
4980 pointm = BUF_BEGV (b);
4981 else if (pointm > BUF_ZV (b))
4982 pointm = BUF_ZV (b);
4985 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
4987 /* If the buffer has changed we have to invalid all of our face
4989 if ((!echo_active && b != window_display_buffer (w))
4990 || !Dynarr_length (w->face_cachels)
4991 || f->faces_changed)
4992 reset_face_cachels (w);
4994 mark_face_cachels_as_not_updated (w);
4996 /* Ditto the glyph cache elements. */
4997 if ((!echo_active && b != window_display_buffer (w))
4998 || !Dynarr_length (w->glyph_cachels)
4999 || f->glyphs_changed)
5000 reset_glyph_cachels (w);
5002 mark_glyph_cachels_as_not_updated (w);
5004 /* If the marker's buffer is not the window's buffer, then we need
5005 to find a new starting position. */
5006 if (!MINI_WINDOW_P (w)
5007 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5009 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5011 goto regeneration_done;
5016 old_startp = marker_position (w->start[CURRENT_DISP]);
5021 startp = marker_position (w->start[CURRENT_DISP]);
5022 if (startp < BUF_BEGV (b))
5023 startp = BUF_BEGV (b);
5024 else if (startp > BUF_ZV (b))
5025 startp = BUF_ZV (b);
5027 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5029 truncation_changed = (find_window_mirror (w)->truncate_win !=
5030 window_truncation_on (w));
5032 /* If w->force_start is set, then some function set w->start and we
5033 should display from there and change point, if necessary, to
5034 ensure that it is visible. */
5035 if (w->force_start || inactive_minibuffer)
5038 w->last_modified[DESIRED_DISP] = Qzero;
5039 w->last_facechange[DESIRED_DISP] = Qzero;
5041 regenerate_window (w, startp, pointm, DESIRED_DISP);
5043 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5045 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5047 if (selected_globally)
5048 BUF_SET_PT (b, pointm);
5050 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5053 /* #### BUFU amounts of overkill just to get the cursor
5054 location marked properly. FIX ME FIX ME FIX ME */
5055 regenerate_window (w, startp, pointm, DESIRED_DISP);
5058 goto regeneration_done;
5061 /* If nothing has changed since the last redisplay, then we just
5062 need to make sure that point is still visible. */
5063 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5064 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
5066 /* This check is to make sure we restore the minibuffer after a
5067 temporary change to the echo area. */
5068 && !(MINI_WINDOW_P (w) && f->buffers_changed)
5069 && !f->frame_changed
5070 && !truncation_changed
5071 /* check whether start is really at the begining of a line GE */
5072 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
5075 /* Check if the cursor has actually moved. */
5076 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5077 && pointm == marker_position (w->last_point[CURRENT_DISP])
5078 && selected_globally
5079 && !w->windows_changed
5081 && !f->extents_changed
5082 && !f->faces_changed
5083 && !f->glyphs_changed
5084 && !f->point_changed
5085 && !f->windows_structure_changed)
5087 /* If not, we're done. */
5088 if (f->modeline_changed)
5089 regenerate_modeline (w);
5092 goto regeneration_done;
5096 /* If the new point is visible in the redisplay structures,
5097 then let the output update routines handle it, otherwise
5098 do things the hard way. */
5099 if (!w->windows_changed
5101 && !f->extents_changed
5102 && !f->faces_changed
5103 && !f->glyphs_changed
5104 && !f->windows_structure_changed)
5106 if (point_visible (w, pointm, CURRENT_DISP)
5107 && w->last_point_x[CURRENT_DISP] != -1
5108 && w->last_point_y[CURRENT_DISP] != -1)
5110 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
5112 /* Always regenerate in case it is displaying
5113 the current line or column. */
5114 regenerate_modeline (w);
5117 goto regeneration_done;
5120 else if (!selected_in_its_frame && !f->point_changed)
5122 if (f->modeline_changed)
5123 regenerate_modeline (w);
5126 goto regeneration_done;
5130 /* If we weren't able to take the shortcut method, then use
5131 the brute force method. */
5132 regenerate_window (w, startp, pointm, DESIRED_DISP);
5134 if (point_visible (w, pointm, DESIRED_DISP))
5135 goto regeneration_done;
5139 /* Check if the starting point is no longer at the beginning of a
5140 line, in which case find a new starting point. We also recenter
5141 if our start position is equal to point-max. Otherwise we'll end
5142 up with a blank window. */
5143 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
5144 && !(startp == BUF_BEGV (b)
5145 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
5146 || (pointm == startp &&
5147 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
5148 startp < marker_position (w->last_start[CURRENT_DISP]))
5149 || (startp == BUF_ZV (b)))
5151 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5153 goto regeneration_done;
5155 /* See if we can update the data structures locally based on
5156 knowledge of what changed in the buffer. */
5157 else if (!w->windows_changed
5159 && !f->faces_changed
5160 && !f->glyphs_changed
5161 && !f->windows_structure_changed
5162 && !f->frame_changed
5163 && !truncation_changed
5165 && regenerate_window_incrementally (w, startp, pointm))
5167 if (f->modeline_changed
5168 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
5169 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
5170 regenerate_modeline (w);
5173 goto regeneration_done;
5175 /* #### This is where a check for structure based scrolling would go. */
5176 /* If all else fails, try just regenerating and see what happens. */
5179 regenerate_window (w, startp, pointm, DESIRED_DISP);
5181 if (point_visible (w, pointm, DESIRED_DISP))
5182 goto regeneration_done;
5185 /* We still haven't gotten the window regenerated with point
5186 visible. Next we try scrolling a little and see if point comes
5187 back onto the screen. */
5188 if (scroll_step > 0)
5190 int scrolled = scroll_conservatively;
5191 for (; scrolled >= 0; scrolled -= scroll_step)
5193 startp = vmotion (w, startp,
5194 (pointm < startp) ? -scroll_step : scroll_step, 0);
5195 regenerate_window (w, startp, pointm, DESIRED_DISP);
5197 if (point_visible (w, pointm, DESIRED_DISP))
5198 goto regeneration_done;
5202 /* We still haven't managed to get the screen drawn with point on
5203 the screen, so just center it and be done with it. */
5204 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5209 /* If the window's frame is changed then reset the current display
5210 lines in order to force a full repaint. */
5211 if (f->frame_changed)
5213 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
5218 /* Must do this before calling redisplay_output_window because it
5219 sets some markers on the window. */
5222 w->buffer = old_buffer;
5223 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
5224 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
5227 /* These also have to be set before calling redisplay_output_window
5228 since it sets the CURRENT_DISP values based on them. */
5229 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5230 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5231 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5232 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5236 Bufpos start = marker_position (w->start[DESIRED_DISP]);
5237 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
5239 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
5241 update_line_start_cache (w, start, end, pointm, 1);
5242 redisplay_output_window (w);
5244 * If we just displayed the echo area, the line start cache is
5245 * no longer valid, because the minibuffer window is associated
5246 * with the window now.
5249 w->line_cache_last_updated = make_int (-1);
5252 /* #### This should be dependent on face changes and will need to be
5253 somewhere else once tty updates occur on a per-frame basis. */
5254 mark_face_cachels_as_clean (w);
5256 w->windows_changed = 0;
5259 /* Call buffer_reset_changes for all buffers present in any window
5260 currently visible in all frames on all devices. #### There has to
5261 be a better way to do this. */
5264 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
5266 buffer_reset_changes (XBUFFER (w->buffer));
5271 reset_buffer_changes (void)
5273 Lisp_Object frmcons, devcons, concons;
5275 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
5277 struct frame *f = XFRAME (XCAR (frmcons));
5279 if (FRAME_REPAINT_P (f))
5280 map_windows (f, reset_buffer_changes_mapfun, 0);
5284 /* Ensure that all windows underneath the given window in the window
5285 hierarchy are correctly displayed. */
5288 redisplay_windows (Lisp_Object window, int skip_selected)
5290 for (; !NILP (window) ; window = XWINDOW (window)->next)
5292 redisplay_window (window, skip_selected);
5297 call_redisplay_end_triggers (struct window *w, void *closure)
5299 Bufpos lrpos = w->last_redisplay_pos;
5300 w->last_redisplay_pos = 0;
5301 if (!NILP (w->buffer)
5302 && !NILP (w->redisplay_end_trigger)
5307 if (MARKERP (w->redisplay_end_trigger)
5308 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
5309 pos = marker_position (w->redisplay_end_trigger);
5310 else if (INTP (w->redisplay_end_trigger))
5311 pos = XINT (w->redisplay_end_trigger);
5314 w->redisplay_end_trigger = Qnil;
5321 XSETWINDOW (window, w);
5322 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
5323 Qredisplay_end_trigger_functions,
5325 w->redisplay_end_trigger);
5326 w->redisplay_end_trigger = Qnil;
5333 /* Ensure that all windows on the given frame are correctly displayed. */
5336 redisplay_frame (struct frame *f, int preemption_check)
5338 struct device *d = XDEVICE (f->device);
5340 if (preemption_check)
5342 /* The preemption check itself takes a lot of time,
5343 so normally don't do it here. We do it if called
5344 from Lisp, though (`redisplay-frame'). */
5347 REDISPLAY_PREEMPTION_CHECK;
5352 /* Before we put a hold on frame size changes, attempt to process
5353 any which are already pending. */
5354 if (f->size_change_pending)
5355 change_frame_size (f, f->new_height, f->new_width, 0);
5357 /* If frame size might need to be changed, due to changed size
5358 of toolbars, scrollbars etc, change it now */
5359 if (f->size_slipped)
5361 adjust_frame_size (f);
5362 assert (!f->size_slipped);
5365 /* The menubar, toolbar, and icon updates must be done before
5366 hold_frame_size_changes is called and we are officially
5367 'in_display'. They may eval lisp code which may call Fsignal.
5368 If in_display is set Fsignal will abort. */
5370 #ifdef HAVE_MENUBARS
5371 /* Update the menubar. It is done first since it could change
5372 the menubar's visibility. This way we avoid having flashing
5373 caused by an Expose event generated by the visibility change
5375 update_frame_menubars (f);
5376 #endif /* HAVE_MENUBARS */
5378 #ifdef HAVE_TOOLBARS
5379 /* Update the toolbars. */
5380 update_frame_toolbars (f);
5381 #endif /* HAVE_TOOLBARS */
5383 hold_frame_size_changes ();
5385 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
5386 /* Within this section, we are defenseless and assume that the
5387 following cannot happen:
5389 1) garbage collection
5390 2) Lisp code evaluation
5391 3) frame size changes
5393 We ensure (3) by calling hold_frame_size_changes(), which
5394 will cause any pending frame size changes to get put on hold
5395 till after the end of the critical section. (1) follows
5396 automatically if (2) is met. #### Unfortunately, there are
5397 some places where Lisp code can be called within this section.
5398 We need to remove them.
5400 If Fsignal() is called during this critical section, we
5403 If garbage collection is called during this critical section,
5404 we simply return. #### We should abort instead.
5406 #### If a frame-size change does occur we should probably
5407 actually be preempting redisplay. */
5409 /* If we clear the frame we have to force its contents to be redrawn. */
5411 f->frame_changed = 1;
5413 /* Erase the frame before outputting its contents. */
5415 DEVMETH (d, clear_frame, (f));
5417 /* Do the selected window first. */
5418 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
5420 /* Then do the rest. */
5421 redisplay_windows (f->root_window, 1);
5423 /* We now call the output_end routine for tty frames. We delay
5424 doing so in order to avoid cursor flicker. So much for 100%
5426 if (FRAME_TTY_P (f))
5427 DEVMETH (d, output_end, (d));
5429 update_frame_title (f);
5431 f->buffers_changed = 0;
5432 f->clip_changed = 0;
5433 f->extents_changed = 0;
5434 f->faces_changed = 0;
5435 f->frame_changed = 0;
5436 f->glyphs_changed = 0;
5437 f->icon_changed = 0;
5438 f->menubar_changed = 0;
5439 f->modeline_changed = 0;
5440 f->point_changed = 0;
5441 f->toolbar_changed = 0;
5442 f->windows_changed = 0;
5443 f->windows_structure_changed = 0;
5444 f->window_face_cache_reset = 0;
5445 f->echo_area_garbaged = 0;
5449 if (!f->size_change_pending)
5450 f->size_changed = 0;
5452 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
5454 /* Allow frame size changes to occur again.
5456 #### what happens if changes to other frames happen? */
5457 unhold_one_frame_size_changes (f);
5459 map_windows (f, call_redisplay_end_triggers, 0);
5463 /* Ensure that all frames on the given device are correctly displayed. */
5466 redisplay_device (struct device *d)
5468 Lisp_Object frame, frmcons;
5470 int size_change_failed = 0;
5473 if (DEVICE_STREAM_P (d)) /* nothing to do */
5476 /* It is possible that redisplay has been called before the
5477 device is fully initialized. If so then continue with the
5479 if (NILP (DEVICE_SELECTED_FRAME (d)))
5482 REDISPLAY_PREEMPTION_CHECK;
5486 /* Always do the selected frame first. */
5487 frame = DEVICE_SELECTED_FRAME (d);
5491 if (f->icon_changed || f->windows_changed)
5492 update_frame_icon (f);
5494 if (FRAME_REPAINT_P (f))
5496 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
5497 f->faces_changed || f->frame_changed || f->menubar_changed ||
5498 f->modeline_changed || f->point_changed || f->size_changed ||
5499 f->toolbar_changed || f->windows_changed || f->size_slipped ||
5500 f->windows_structure_changed || f->glyphs_changed)
5502 preempted = redisplay_frame (f, 0);
5508 /* If the frame redisplay did not get preempted, then this flag
5509 should have gotten set to 0. It might be possible for that
5510 not to happen if a size change event were to occur at an odd
5511 time. To make sure we don't miss anything we simply don't
5512 reset the top level flags until the condition ends up being
5513 in the right state. */
5514 if (f->size_changed)
5515 size_change_failed = 1;
5518 DEVICE_FRAME_LOOP (frmcons, d)
5520 f = XFRAME (XCAR (frmcons));
5522 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
5525 if (f->icon_changed || f->windows_changed)
5526 update_frame_icon (f);
5528 if (FRAME_REPAINT_P (f))
5530 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
5531 f->faces_changed || f->frame_changed || f->menubar_changed ||
5532 f->modeline_changed || f->point_changed || f->size_changed ||
5533 f->toolbar_changed || f->windows_changed ||
5534 f->windows_structure_changed ||
5537 preempted = redisplay_frame (f, 0);
5543 if (f->size_change_pending)
5544 size_change_failed = 1;
5548 /* If we get here then we redisplayed all of our frames without
5549 getting preempted so mark ourselves as clean. */
5550 d->buffers_changed = 0;
5551 d->clip_changed = 0;
5552 d->extents_changed = 0;
5553 d->faces_changed = 0;
5554 d->frame_changed = 0;
5555 d->glyphs_changed = 0;
5556 d->icon_changed = 0;
5557 d->menubar_changed = 0;
5558 d->modeline_changed = 0;
5559 d->point_changed = 0;
5560 d->toolbar_changed = 0;
5561 d->windows_changed = 0;
5562 d->windows_structure_changed = 0;
5564 if (!size_change_failed)
5565 d->size_changed = 0;
5571 restore_profiling_redisplay_flag (Lisp_Object val)
5573 profiling_redisplay_flag = XINT (val);
5577 /* Ensure that all windows on all frames on all devices are displaying
5578 the current contents of their respective buffers. */
5581 redisplay_without_hooks (void)
5583 Lisp_Object devcons, concons;
5584 int size_change_failed = 0;
5585 int count = specpdl_depth ();
5587 if (profiling_active)
5589 record_unwind_protect (restore_profiling_redisplay_flag,
5590 make_int (profiling_redisplay_flag));
5591 profiling_redisplay_flag = 1;
5594 if (asynch_device_change_pending)
5595 handle_asynch_device_change ();
5597 if (!buffers_changed && !clip_changed && !extents_changed &&
5598 !faces_changed && !frame_changed && !icon_changed &&
5599 !menubar_changed && !modeline_changed && !point_changed &&
5600 !size_changed && !toolbar_changed && !windows_changed &&
5602 !windows_structure_changed && !disable_preemption &&
5603 preemption_count < max_preempts)
5606 DEVICE_LOOP_NO_BREAK (devcons, concons)
5608 struct device *d = XDEVICE (XCAR (devcons));
5611 if (d->buffers_changed || d->clip_changed || d->extents_changed ||
5612 d->faces_changed || d->frame_changed || d->icon_changed ||
5613 d->menubar_changed || d->modeline_changed || d->point_changed ||
5614 d->size_changed || d->toolbar_changed || d->windows_changed ||
5615 d->windows_structure_changed ||
5618 preempted = redisplay_device (d);
5623 RESET_CHANGED_SET_FLAGS;
5627 /* See comment in redisplay_device. */
5628 if (d->size_changed)
5629 size_change_failed = 1;
5632 preemption_count = 0;
5634 /* Mark redisplay as accurate */
5635 buffers_changed = 0;
5637 extents_changed = 0;
5641 menubar_changed = 0;
5642 modeline_changed = 0;
5644 toolbar_changed = 0;
5645 windows_changed = 0;
5646 windows_structure_changed = 0;
5647 RESET_CHANGED_SET_FLAGS;
5651 mark_all_faces_as_clean ();
5655 if (!size_change_failed)
5658 reset_buffer_changes ();
5661 unbind_to (count, Qnil);
5667 if (last_display_warning_tick != display_warning_tick &&
5668 !inhibit_warning_display)
5670 /* If an error occurs during this function, oh well.
5671 If we report another warning, we could get stuck in an
5672 infinite loop reporting warnings. */
5673 call0_trapping_errors (0, Qdisplay_warning_buffer);
5674 last_display_warning_tick = display_warning_tick;
5676 /* The run_hook_trapping_errors functions are smart enough not
5677 to do any evalling if the hook function is empty, so there
5678 should not be any significant time loss. All places in the
5679 C code that call redisplay() are prepared to handle GCing,
5680 so we should be OK. */
5681 #ifndef INHIBIT_REDISPLAY_HOOKS
5682 run_hook_trapping_errors ("Error in pre-redisplay-hook",
5683 Qpre_redisplay_hook);
5684 #endif /* INHIBIT_REDISPLAY_HOOKS */
5686 redisplay_without_hooks ();
5688 #ifndef INHIBIT_REDISPLAY_HOOKS
5689 run_hook_trapping_errors ("Error in post-redisplay-hook",
5690 Qpost_redisplay_hook);
5691 #endif /* INHIBIT_REDISPLAY_HOOKS */
5695 static char window_line_number_buf[32];
5697 /* Efficiently determine the window line number, and return a pointer
5698 to its printed representation. Do this regardless of whether
5699 line-number-mode is on. The first line in the buffer is counted as
5700 1. If narrowing is in effect, the lines are counted from the
5701 beginning of the visible portion of the buffer. */
5703 window_line_number (struct window *w, int type)
5705 struct device *d = XDEVICE (XFRAME (w->frame)->device);
5706 struct buffer *b = XBUFFER (w->buffer);
5707 /* Be careful in the order of these tests. The first clause will
5708 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
5709 This can occur when the frame title is computed really early */
5711 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
5712 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
5713 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5714 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
5716 : marker_position (w->pointm[type]));
5719 line = buffer_line_number (b, pos, 1);
5721 long_to_string (window_line_number_buf, line + 1);
5723 return window_line_number_buf;
5727 /* Given a character representing an object in a modeline
5728 specification, return a string (stored into the global array
5729 `mode_spec_bufbyte_string') with the information that object
5732 This function is largely unchanged from previous versions of the
5735 Warning! This code is also used for frame titles and can be called
5736 very early in the device/frame update process! JV
5740 decode_mode_spec (struct window *w, Emchar spec, int type)
5742 Lisp_Object obj = Qnil;
5743 CONST char *str = NULL;
5744 struct buffer *b = XBUFFER (w->buffer);
5746 Dynarr_reset (mode_spec_bufbyte_string);
5750 /* print buffer name */
5755 /* print visited file name */
5760 /* print the current column */
5763 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
5765 : marker_position (w->pointm[type]);
5766 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
5769 long_to_string (buf, col);
5771 Dynarr_add_many (mode_spec_bufbyte_string,
5772 (CONST Bufbyte *) buf, strlen (buf));
5774 goto decode_mode_spec_done;
5776 /* print the file coding system */
5780 Lisp_Object codesys = b->buffer_file_coding_system;
5781 /* Be very careful here not to get an error. */
5782 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
5784 codesys = Ffind_coding_system (codesys);
5785 if (CODING_SYSTEMP (codesys))
5786 obj = XCODING_SYSTEM_MNEMONIC (codesys);
5789 #endif /* FILE_CODING */
5792 /* print the current line number */
5794 str = window_line_number (w, type);
5797 /* print value of mode-name (obsolete) */
5802 /* print hyphen and frame number, if != 1 */
5806 struct frame *f = XFRAME (w->frame);
5807 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
5809 /* Naughty, naughty */
5810 char * writable_str = alloca_array (char, 10);
5811 sprintf (writable_str, "-%d", f->order_count);
5815 #endif /* HAVE_TTY */
5818 /* print Narrow if appropriate */
5820 if (BUF_BEGV (b) > BUF_BEG (b)
5821 || BUF_ZV (b) < BUF_Z (b))
5825 /* print %, * or hyphen, if buffer is read-only, modified or neither */
5827 str = (!NILP (b->read_only)
5829 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5834 /* print * or hyphen -- XEmacs change to allow a buffer to be
5835 read-only but still indicate whether it is modified. */
5837 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5839 : (!NILP (b->read_only)
5844 /* #### defined in 19.29 decode_mode_spec, but not in
5845 modeline-format doc string. */
5846 /* This differs from %* in that it ignores read-only-ness. */
5848 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5853 /* print process status */
5855 obj = Fget_buffer_process (w->buffer);
5857 str = GETTEXT ("no process");
5859 obj = Fsymbol_name (Fprocess_status (obj));
5862 /* Print name of selected frame. */
5864 obj = XFRAME (w->frame)->name;
5867 /* indicate TEXT or BINARY */
5869 /* #### NT does not use this any more. Now what? */
5873 /* print percent of buffer above top of window, or Top, Bot or All */
5876 Bufpos pos = marker_position (w->start[type]);
5877 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5879 /* This had better be while the desired lines are being done. */
5880 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
5882 if (pos <= BUF_BEGV (b))
5887 else if (pos <= BUF_BEGV (b))
5891 /* This hard limit is ok since the string it will hold has a
5892 fixed maximum length of 3. But just to be safe... */
5895 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
5897 /* We can't normally display a 3-digit number, so get us a
5898 2-digit number that is close. */
5902 sprintf (buf, "%2d%%", total);
5903 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5906 goto decode_mode_spec_done;
5911 /* print percent of buffer above bottom of window, perhaps plus
5912 Top, or print Bottom or All */
5915 Bufpos toppos = marker_position (w->start[type]);
5916 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
5917 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5919 /* botpos is only accurate as of the last redisplay, so we can
5920 only treat it as a hint. In particular, after erase-buffer,
5921 botpos may be negative. */
5922 if (botpos < toppos)
5925 if (botpos >= BUF_ZV (b))
5927 if (toppos <= BUF_BEGV (b))
5934 /* This hard limit is ok since the string it will hold has a
5935 fixed maximum length of around 6. But just to be safe... */
5938 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
5940 /* We can't normally display a 3-digit number, so get us a
5941 2-digit number that is close. */
5945 if (toppos <= BUF_BEGV (b))
5946 sprintf (buf, "Top%2d%%", total);
5948 sprintf (buf, "%2d%%", total);
5950 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5953 goto decode_mode_spec_done;
5963 /* print one [ for each recursive editing level. */
5968 if (command_loop_level > 5)
5974 for (i = 0; i < command_loop_level; i++)
5975 Dynarr_add (mode_spec_bufbyte_string, '[');
5977 goto decode_mode_spec_done;
5980 /* print one ] for each recursive editing level. */
5985 if (command_loop_level > 5)
5991 for (i = 0; i < command_loop_level; i++)
5992 Dynarr_add (mode_spec_bufbyte_string, ']');
5994 goto decode_mode_spec_done;
5997 /* print infinitely many dashes -- handle at top level now */
6004 Dynarr_add_many (mode_spec_bufbyte_string,
6006 XSTRING_LENGTH (obj));
6008 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6010 decode_mode_spec_done:
6011 Dynarr_add (mode_spec_bufbyte_string, '\0');
6014 /* Given a display line, free all of its data structures. */
6017 free_display_line (struct display_line *dl)
6021 if (dl->display_blocks)
6023 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6025 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6027 Dynarr_free (db->runes);
6030 Dynarr_free (dl->display_blocks);
6031 dl->display_blocks = NULL;
6034 if (dl->left_glyphs)
6036 Dynarr_free (dl->left_glyphs);
6037 dl->left_glyphs = NULL;
6040 if (dl->right_glyphs)
6042 Dynarr_free (dl->right_glyphs);
6043 dl->right_glyphs = NULL;
6048 /* Given an array of display lines, free them and all data structures
6049 contained within them. */
6052 free_display_lines (display_line_dynarr *dla)
6056 for (line = 0; line < Dynarr_largest (dla); line++)
6058 free_display_line (Dynarr_atp (dla, line));
6064 /* Call internal free routine for each set of display lines. */
6067 free_display_structs (struct window_mirror *mir)
6069 if (mir->current_display_lines)
6071 free_display_lines (mir->current_display_lines);
6072 mir->current_display_lines = 0;
6075 if (mir->desired_display_lines)
6077 free_display_lines (mir->desired_display_lines);
6078 mir->desired_display_lines = 0;
6084 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object))
6088 glyph_block *gb = Dynarr_atp (gba, 0);
6089 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
6091 for (; gb < gb_last; gb++)
6093 if (!NILP (gb->glyph))
6094 markobj (gb->glyph);
6095 if (!NILP (gb->extent))
6096 markobj (gb->extent);
6102 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object))
6104 display_line *dl = Dynarr_atp (dla, 0);
6105 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
6107 for (; dl < dl_last; dl++)
6109 display_block_dynarr *dba = dl->display_blocks;
6110 display_block *db = Dynarr_atp (dba, 0);
6111 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
6113 for (; db < db_last; db++)
6115 rune_dynarr *ra = db->runes;
6116 rune *r = Dynarr_atp (ra, 0);
6117 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
6119 for (; r < r_last; r++)
6121 if (r->type == RUNE_DGLYPH)
6123 if (!NILP (r->object.dglyph.glyph))
6124 markobj (r->object.dglyph.glyph);
6125 if (!NILP (r->object.dglyph.extent))
6126 markobj (r->object.dglyph.extent);
6131 mark_glyph_block_dynarr (dl->left_glyphs, markobj);
6132 mark_glyph_block_dynarr (dl->right_glyphs, markobj);
6137 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object))
6139 mark_redisplay_structs (mir->current_display_lines, markobj);
6140 mark_redisplay_structs (mir->desired_display_lines, markobj);
6143 mark_window_mirror (mir->next, markobj);
6146 mark_window_mirror (mir->hchild, markobj);
6147 else if (mir->vchild)
6148 mark_window_mirror (mir->vchild, markobj);
6152 mark_redisplay (void (*markobj)(Lisp_Object))
6154 Lisp_Object frmcons, devcons, concons;
6156 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6158 struct frame *f = XFRAME (XCAR (frmcons));
6159 update_frame_window_mirror (f);
6160 mark_window_mirror (f->root_mirror, markobj);
6164 /*****************************************************************************
6165 Line Start Cache Description and Rationale
6167 The traditional scrolling code in Emacs breaks in a variable height world.
6168 It depends on the key assumption that the number of lines that can be
6169 displayed at any given time is fixed. This led to a complete separation
6170 of the scrolling code from the redisplay code. In order to fully support
6171 variable height lines, the scrolling code must actually be tightly
6172 integrated with redisplay. Only redisplay can determine how many lines
6173 will be displayed on a screen for any given starting point.
6175 What is ideally wanted is a complete list of the starting buffer position
6176 for every possible display line of a buffer along with the height of that
6177 display line. Maintaining such a full list would be very expensive. We
6178 settle for having it include information for all areas which we happen to
6179 generate anyhow (i.e. the region currently being displayed) and for those
6180 areas we need to work with.
6182 In order to ensure that the cache accurately represents what redisplay
6183 would actually show, it is necessary to invalidate it in many situations.
6184 If the buffer changes, the starting positions may no longer be correct.
6185 If a face or an extent has changed then the line heights may have altered.
6186 These events happen frequently enough that the cache can end up being
6187 constantly disabled. With this potentially constant invalidation when is
6188 the cache ever useful?
6190 Even if the cache is invalidated before every single usage, it is
6191 necessary. Scrolling often requires knowledge about display lines which
6192 are actually above or below the visible region. The cache provides a
6193 convenient light-weight method of storing this information for multiple
6194 display regions. This knowledge is necessary for the scrolling code to
6195 always obey the First Golden Rule of Redisplay.
6197 If the cache already contains all of the information that the scrolling
6198 routines happen to need so that it doesn't have to go generate it, then we
6199 are able to obey the Third Golden Rule of Redisplay. The first thing we
6200 do to help out the cache is to always add the displayed region. This
6201 region had to be generated anyway, so the cache ends up getting the
6202 information basically for free. In those cases where a user is simply
6203 scrolling around viewing a buffer there is a high probability that this is
6204 sufficient to always provide the needed information. The second thing we
6205 can do is be smart about invalidating the cache.
6207 TODO -- Be smart about invalidating the cache. Potential places:
6209 + Insertions at end-of-line which don't cause line-wraps do not alter the
6210 starting positions of any display lines. These types of buffer
6211 modifications should not invalidate the cache. This is actually a large
6212 optimization for redisplay speed as well.
6214 + Buffer modifications frequently only affect the display of lines at and
6215 below where they occur. In these situations we should only invalidate
6216 the part of the cache starting at where the modification occurs.
6218 In case you're wondering, the Second Golden Rule of Redisplay is not
6220 ****************************************************************************/
6222 /* This will get used quite a bit so we don't want to be constantly
6223 allocating and freeing it. */
6224 line_start_cache_dynarr *internal_cache;
6226 /* Makes internal_cache represent the TYPE display structs and only
6227 the TYPE display structs. */
6230 update_internal_cache_list (struct window *w, int type)
6233 display_line_dynarr *dla = window_display_lines (w, type);
6235 Dynarr_reset (internal_cache);
6236 for (line = 0; line < Dynarr_length (dla); line++)
6238 struct display_line *dl = Dynarr_atp (dla, line);
6244 struct line_start_cache lsc;
6246 lsc.start = dl->bufpos;
6247 lsc.end = dl->end_bufpos;
6248 lsc.height = dl->ascent + dl->descent;
6250 Dynarr_add (internal_cache, lsc);
6255 /* Reset the line cache if necessary. This should be run at the
6256 beginning of any function which access the cache. */
6259 validate_line_start_cache (struct window *w)
6261 struct buffer *b = XBUFFER (w->buffer);
6262 struct frame *f = XFRAME (w->frame);
6264 if (!w->line_cache_validation_override)
6266 /* f->extents_changed used to be in here because extent face and
6267 size changes can cause text shifting. However, the extent
6268 covering the region is constantly having its face set and
6269 priority altered by the mouse code. This means that the line
6270 start cache is constantly being invalidated. This is bad
6271 since the mouse code also triggers heavy usage of the cache.
6272 Since it is an unlikely that f->extents being changed
6273 indicates that the cache really needs to be updated and if it
6274 does redisplay will catch it pretty quickly we no longer
6275 invalidate the cache if it is set. This greatly speeds up
6276 dragging out regions with the mouse. */
6277 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
6281 Dynarr_reset (w->line_start_cache);
6286 /* Return the very first buffer position contained in the given
6287 window's cache, or -1 if the cache is empty. Assumes that the
6291 line_start_cache_start (struct window *w)
6293 line_start_cache_dynarr *cache = w->line_start_cache;
6295 if (!Dynarr_length (cache))
6298 return Dynarr_atp (cache, 0)->start;
6301 /* Return the very last buffer position contained in the given
6302 window's cache, or -1 if the cache is empty. Assumes that the
6306 line_start_cache_end (struct window *w)
6308 line_start_cache_dynarr *cache = w->line_start_cache;
6310 if (!Dynarr_length (cache))
6313 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
6316 /* Return the index of the line POINT is contained within in window
6317 W's line start cache. It will enlarge the cache or move the cache
6318 window in order to have POINT be present in the cache. MIN_PAST is
6319 a guarantee of the number of entries in the cache present on either
6320 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
6321 then it will be treated as 0, but the cache window will not be
6322 allowed to shift. Returns -1 if POINT cannot be found in the cache
6326 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
6328 struct buffer *b = XBUFFER (w->buffer);
6329 line_start_cache_dynarr *cache = w->line_start_cache;
6330 unsigned int top, bottom, pos;
6332 validate_line_start_cache (w);
6333 w->line_cache_validation_override++;
6335 /* Let functions pass in negative values, but we still treat -1
6337 /* #### bogosity alert */
6338 if (min_past < 0 && min_past != -1)
6339 min_past = -min_past;
6341 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
6342 || line_start_cache_end (w) < point)
6345 int win_char_height = window_char_height (w, 1);
6347 /* Occasionally we get here with a 0 height
6348 window. find_next_newline_no_quit will abort if we pass it a
6349 count of 0 so handle that case. */
6350 if (!win_char_height)
6351 win_char_height = 1;
6353 if (!Dynarr_length (cache))
6355 Bufpos from = find_next_newline_no_quit (b, point, -1);
6356 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
6358 update_line_start_cache (w, from, to, point, 0);
6360 if (!Dynarr_length (cache))
6362 w->line_cache_validation_override--;
6367 assert (Dynarr_length (cache));
6370 while (line_start_cache_start (w) > point
6371 && (loop < cache_adjustment || min_past == -1))
6375 from = line_start_cache_start (w);
6376 if (from <= BUF_BEGV (b))
6379 from = find_next_newline_no_quit (b, from, -win_char_height);
6380 to = line_start_cache_end (w);
6382 update_line_start_cache (w, from, to, point, 0);
6386 if (line_start_cache_start (w) > point)
6390 from = find_next_newline_no_quit (b, point, -1);
6391 if (from >= BUF_ZV (b))
6393 to = find_next_newline_no_quit (b, from, -win_char_height);
6398 to = find_next_newline_no_quit (b, from, win_char_height);
6400 update_line_start_cache (w, from, to, point, 0);
6404 while (line_start_cache_end (w) < point
6405 && (loop < cache_adjustment || min_past == -1))
6409 to = line_start_cache_end (w);
6410 if (to >= BUF_ZV (b))
6413 from = line_start_cache_end (w);
6414 to = find_next_newline_no_quit (b, from, win_char_height);
6416 update_line_start_cache (w, from, to, point, 0);
6420 if (line_start_cache_end (w) < point)
6424 from = find_next_newline_no_quit (b, point, -1);
6425 if (from >= BUF_ZV (b))
6427 to = find_next_newline_no_quit (b, from, -win_char_height);
6432 to = find_next_newline_no_quit (b, from, win_char_height);
6434 update_line_start_cache (w, from, to, point, 0);
6438 assert (Dynarr_length (cache));
6443 /* This could happen if the buffer is narrowed. */
6444 if (line_start_cache_start (w) > point
6445 || line_start_cache_end (w) < point)
6447 w->line_cache_validation_override--;
6453 top = Dynarr_length (cache) - 1;
6458 unsigned int new_pos;
6461 pos = (bottom + top + 1) >> 1;
6462 start = Dynarr_atp (cache, pos)->start;
6463 end = Dynarr_atp (cache, pos)->end;
6465 if (point >= start && point <= end)
6467 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
6470 find_next_newline_no_quit (b, line_start_cache_start (w),
6472 Bufpos to = line_start_cache_end (w);
6474 update_line_start_cache (w, from, to, point, 0);
6475 goto find_point_loop;
6477 else if ((Dynarr_length (cache) - pos - 1) < min_past
6478 && line_start_cache_end (w) < BUF_ZV (b))
6480 Bufpos from = line_start_cache_end (w);
6481 Bufpos to = find_next_newline_no_quit (b, from,
6486 update_line_start_cache (w, from, to, point, 0);
6487 goto find_point_loop;
6491 w->line_cache_validation_override--;
6495 else if (point > end)
6497 else if (point < start)
6502 new_pos = (bottom + top + 1) >> 1;
6505 w->line_cache_validation_override--;
6511 /* Return a boolean indicating if POINT would be visible in window W
6512 if display of the window was to begin at STARTP. */
6515 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
6517 struct buffer *b = XBUFFER (w->buffer);
6519 int bottom = WINDOW_TEXT_HEIGHT (w);
6522 /* If point is before the intended start it obviously can't be visible. */
6526 /* If point or start are not in the accessible buffer range, then
6528 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
6529 || point < BUF_BEGV (b) || point > BUF_ZV (b))
6532 validate_line_start_cache (w);
6533 w->line_cache_validation_override++;
6535 start_elt = point_in_line_start_cache (w, startp, 0);
6536 if (start_elt == -1)
6538 w->line_cache_validation_override--;
6542 assert (line_start_cache_start (w) <= startp
6543 && line_start_cache_end (w) >= startp);
6549 /* Expand the cache if necessary. */
6550 if (start_elt == Dynarr_length (w->line_start_cache))
6553 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
6555 start_elt = point_in_line_start_cache (w, old_startp,
6556 window_char_height (w, 0));
6558 /* We've already actually processed old_startp, so increment
6562 /* If this happens we didn't add any extra elements. Bummer. */
6563 if (start_elt == Dynarr_length (w->line_start_cache))
6565 w->line_cache_validation_override--;
6570 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
6572 if (pixpos + height > bottom)
6574 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6576 w->line_cache_validation_override--;
6582 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
6584 w->line_cache_validation_override--;
6592 /* For the given window W, if display starts at STARTP, what will be
6593 the buffer position at the beginning or end of the last line
6594 displayed. The end of the last line is also know as the window end
6597 #### With a little work this could probably be reworked as just a
6598 call to start_with_line_at_pixpos. */
6601 start_end_of_last_line (struct window *w, Bufpos startp, int end)
6603 struct buffer *b = XBUFFER (w->buffer);
6604 line_start_cache_dynarr *cache = w->line_start_cache;
6606 int bottom = WINDOW_TEXT_HEIGHT (w);
6610 validate_line_start_cache (w);
6611 w->line_cache_validation_override++;
6613 if (startp < BUF_BEGV (b))
6614 startp = BUF_BEGV (b);
6615 else if (startp > BUF_ZV (b))
6616 startp = BUF_ZV (b);
6619 start_elt = point_in_line_start_cache (w, cur_start, 0);
6620 if (start_elt == -1)
6621 abort (); /* this had better never happen */
6625 int height = Dynarr_atp (cache, start_elt)->height;
6627 cur_start = Dynarr_atp (cache, start_elt)->start;
6629 if (pixpos + height > bottom)
6631 /* Adjust for any possible clip. */
6632 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6637 w->line_cache_validation_override--;
6641 return BUF_BEGV (b);
6645 w->line_cache_validation_override--;
6647 return Dynarr_atp (cache, start_elt)->end;
6649 return Dynarr_atp (cache, start_elt)->start;
6655 if (start_elt == Dynarr_length (cache))
6657 Bufpos from = line_start_cache_end (w);
6658 int win_char_height = window_char_height (w, 0);
6659 Bufpos to = find_next_newline_no_quit (b, from,
6664 /* We've hit the end of the bottom so that's what it is. */
6665 if (from >= BUF_ZV (b))
6667 w->line_cache_validation_override--;
6671 update_line_start_cache (w, from, to, BUF_PT (b), 0);
6673 /* Updating the cache invalidates any current indexes. */
6674 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
6679 /* For the given window W, if display starts at STARTP, what will be
6680 the buffer position at the beginning of the last line displayed. */
6683 start_of_last_line (struct window *w, Bufpos startp)
6685 return start_end_of_last_line (w, startp, 0);
6688 /* For the given window W, if display starts at STARTP, what will be
6689 the buffer position at the end of the last line displayed. This is
6690 also know as the window end position. */
6693 end_of_last_line (struct window *w, Bufpos startp)
6695 return start_end_of_last_line (w, startp, 1);
6698 /* For window W, what does the starting position have to be so that
6699 the line containing POINT will cover pixel position PIXPOS. */
6702 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
6704 struct buffer *b = XBUFFER (w->buffer);
6706 Bufpos cur_pos, prev_pos = point;
6707 int point_line_height;
6708 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
6710 validate_line_start_cache (w);
6711 w->line_cache_validation_override++;
6713 cur_elt = point_in_line_start_cache (w, point, 0);
6714 /* #### See comment in update_line_start_cache about big minibuffers. */
6717 w->line_cache_validation_override--;
6721 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
6725 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6727 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6729 /* Do not take into account the value of vertical_clip here.
6730 That is the responsibility of the calling functions. */
6733 w->line_cache_validation_override--;
6734 if (-pixheight > point_line_height)
6735 /* We can't make the target line cover pixpos, so put it
6736 above pixpos. That way it will at least be visible. */
6746 int win_char_height;
6748 if (cur_pos <= BUF_BEGV (b))
6750 w->line_cache_validation_override--;
6751 return BUF_BEGV (b);
6754 win_char_height = window_char_height (w, 0);
6755 if (!win_char_height)
6756 win_char_height = 1;
6758 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
6759 to = line_start_cache_end (w);
6760 update_line_start_cache (w, from, to, point, 0);
6762 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
6763 assert (cur_elt >= 0);
6769 /* For window W, what does the starting position have to be so that
6770 the line containing point is on display line LINE. If LINE is
6771 positive it is considered to be the number of lines from the top of
6772 the window (0 is the top line). If it is negative the number is
6773 considered to be the number of lines from the bottom (-1 is the
6777 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
6779 validate_line_start_cache (w);
6780 w->line_cache_validation_override++;
6784 int cur_elt = point_in_line_start_cache (w, point, line);
6786 if (cur_elt - line < 0)
6787 cur_elt = 0; /* Hit the top */
6791 w->line_cache_validation_override--;
6792 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
6796 /* The calculated value of pixpos is correct for the bottom line
6797 or what we want when line is -1. Therefore we subtract one
6798 because we have already handled one line. */
6799 int new_line = -line - 1;
6800 int cur_elt = point_in_line_start_cache (w, point, new_line);
6801 int pixpos = WINDOW_TEXT_BOTTOM (w);
6802 Bufpos retval, search_point;
6804 /* If scroll_on_clipped_lines is false, the last "visible" line of
6805 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
6806 If s_o_c_l is true, then we don't want to count a clipped
6807 line, so back up from the bottom by the height of the line
6808 containing point. */
6809 if (scroll_on_clipped_lines)
6810 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6814 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
6816 /* Hit the bottom of the buffer. */
6818 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
6822 XSETWINDOW (window, w);
6823 default_face_height_and_width (window, &defheight, 0);
6825 cur_elt = Dynarr_length (w->line_start_cache) - 1;
6827 pixpos -= (adjustment * defheight);
6828 if (pixpos < WINDOW_TEXT_TOP (w))
6829 pixpos = WINDOW_TEXT_TOP (w);
6832 cur_elt = cur_elt + new_line;
6834 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6836 retval = start_with_line_at_pixpos (w, search_point, pixpos);
6837 w->line_cache_validation_override--;
6842 /* This is used to speed up vertical scrolling by caching the known
6843 buffer starting positions for display lines. This allows the
6844 scrolling routines to avoid costly calls to regenerate_window. If
6845 NO_REGEN is true then it will only add the values in the DESIRED
6846 display structs which are in the given range.
6848 Note also that the FROM/TO values are minimums. It is possible
6849 that this function will actually add information outside of the
6850 lines containing those positions. This can't hurt but it could
6853 #### We currently force the cache to have only 1 contiguous region.
6854 It might help to make the cache a dynarr of caches so that we can
6855 cover more areas. This might, however, turn out to be a lot of
6856 overhead for too little gain. */
6859 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
6860 Bufpos point, int no_regen)
6862 struct buffer *b = XBUFFER (w->buffer);
6863 line_start_cache_dynarr *cache = w->line_start_cache;
6864 Bufpos low_bound, high_bound;
6866 validate_line_start_cache (w);
6867 w->line_cache_validation_override++;
6868 updating_line_start_cache = 1;
6870 if (from < BUF_BEGV (b))
6871 from = BUF_BEGV (b);
6872 if (to > BUF_ZV (b))
6877 updating_line_start_cache = 0;
6878 w->line_cache_validation_override--;
6882 if (Dynarr_length (cache))
6884 low_bound = line_start_cache_start (w);
6885 high_bound = line_start_cache_end (w);
6887 /* Check to see if the desired range is already in the cache. */
6888 if (from >= low_bound && to <= high_bound)
6890 updating_line_start_cache = 0;
6891 w->line_cache_validation_override--;
6895 /* Check to make sure that the desired range is adjacent to the
6896 current cache. If not, invalidate the cache. */
6897 if (to < low_bound || from > high_bound)
6899 Dynarr_reset (cache);
6900 low_bound = high_bound = -1;
6905 low_bound = high_bound = -1;
6908 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
6910 /* This could be integrated into the next two sections, but it is easier
6911 to follow what's going on by having it separate. */
6916 update_internal_cache_list (w, DESIRED_DISP);
6917 if (!Dynarr_length (internal_cache))
6919 updating_line_start_cache = 0;
6920 w->line_cache_validation_override--;
6924 start = Dynarr_atp (internal_cache, 0)->start;
6926 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
6928 /* We aren't allowed to generate additional information to fill in
6929 gaps, so if the DESIRED structs don't overlap the cache, reset the
6931 if (Dynarr_length (cache))
6933 if (end < low_bound || start > high_bound)
6934 Dynarr_reset (cache);
6936 /* #### What should really happen if what we are doing is
6937 extending a line (the last line)? */
6938 if (Dynarr_length (cache) == 1
6939 && Dynarr_length (internal_cache) == 1)
6940 Dynarr_reset (cache);
6943 if (!Dynarr_length (cache))
6945 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
6946 Dynarr_length (internal_cache));
6947 updating_line_start_cache = 0;
6948 w->line_cache_validation_override--;
6952 /* An extra check just in case the calling function didn't pass in
6953 the bounds of the DESIRED structs in the first place. */
6954 if (start >= low_bound && end <= high_bound)
6956 updating_line_start_cache = 0;
6957 w->line_cache_validation_override--;
6961 /* At this point we know that the internal cache partially overlaps
6963 if (start < low_bound)
6965 int ic_elt = Dynarr_length (internal_cache) - 1;
6968 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
6976 Dynarr_reset (cache);
6977 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
6978 Dynarr_length (internal_cache));
6979 updating_line_start_cache = 0;
6980 w->line_cache_validation_override--;
6984 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
6988 if (end > high_bound)
6992 while (ic_elt < Dynarr_length (internal_cache))
6994 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7000 if (!(ic_elt < Dynarr_length (internal_cache)))
7002 Dynarr_reset (cache);
7003 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7004 Dynarr_length (internal_cache));
7005 updating_line_start_cache = 0;
7006 w->line_cache_validation_override--;
7010 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7011 Dynarr_length (internal_cache) - ic_elt);
7014 updating_line_start_cache = 0;
7015 w->line_cache_validation_override--;
7019 if (!Dynarr_length (cache) || from < low_bound)
7021 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7023 int old_lb = low_bound;
7025 while (startp < old_lb || low_bound == -1)
7030 regenerate_window (w, startp, point, CMOTION_DISP);
7031 update_internal_cache_list (w, CMOTION_DISP);
7033 /* If this assert is triggered then regenerate_window failed
7034 to layout a single line. That is not supposed to be
7035 possible because we impose a minimum height on the buffer
7036 and override vertical clip when we are in here. */
7037 /* #### Ah, but it is because the window may temporarily
7038 exist but not have any lines at all if the minibuffer is
7039 real big. Look into that situation better. */
7040 if (!Dynarr_length (internal_cache))
7042 if (old_lb == -1 && low_bound == -1)
7044 updating_line_start_cache = 0;
7045 w->line_cache_validation_override--;
7049 assert (Dynarr_length (internal_cache));
7051 assert (startp == Dynarr_atp (internal_cache, 0)->start);
7053 ic_elt = Dynarr_length (internal_cache) - 1;
7054 if (low_bound != -1)
7058 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
7064 assert (ic_elt >= 0);
7066 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
7069 * Handle invisible text properly:
7070 * If the last line we're inserting has the same end as the
7071 * line before which it will be added, merge the two lines.
7073 if (Dynarr_length (cache) &&
7074 Dynarr_atp (internal_cache, ic_elt)->end ==
7075 Dynarr_atp (cache, marker)->end)
7077 Dynarr_atp (cache, marker)->start
7078 = Dynarr_atp (internal_cache, ic_elt)->start;
7079 Dynarr_atp (cache, marker)->height
7080 = Dynarr_atp (internal_cache, ic_elt)->height;
7084 if (ic_elt >= 0) /* we still have lines to add.. */
7086 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
7087 ic_elt + 1, marker);
7088 marker += (ic_elt + 1);
7091 if (startp < low_bound || low_bound == -1)
7093 startp = new_startp;
7094 if (startp > BUF_ZV (b))
7096 updating_line_start_cache = 0;
7097 w->line_cache_validation_override--;
7103 assert (Dynarr_length (cache));
7104 assert (from >= low_bound);
7106 /* Readjust the high_bound to account for any changes made while
7107 correcting the low_bound. */
7108 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7110 if (to > high_bound)
7112 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
7116 regenerate_window (w, startp, point, CMOTION_DISP);
7117 update_internal_cache_list (w, CMOTION_DISP);
7119 /* See comment above about regenerate_window failing. */
7120 assert (Dynarr_length (internal_cache));
7122 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7123 Dynarr_length (internal_cache));
7124 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7125 startp = high_bound + 1;
7127 while (to > high_bound);
7130 updating_line_start_cache = 0;
7131 w->line_cache_validation_override--;
7132 assert (to <= high_bound);
7136 /* Given x and y coordinates in characters, relative to a window,
7137 return the pixel location corresponding to those coordinates. The
7138 pixel location returned is the center of the given character
7139 position. The pixel values are generated relative to the window,
7142 The modeline is considered to be part of the window. */
7145 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
7146 int *pix_x, int *pix_y)
7148 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
7149 int num_disp_lines, modeline;
7151 int defheight, defwidth;
7153 XSETWINDOW (window, w);
7154 default_face_height_and_width (window, &defheight, &defwidth);
7156 /* If we get a bogus value indicating somewhere above or to the left of
7157 the window, use the first window line or character position
7164 num_disp_lines = Dynarr_length (dla);
7168 if (Dynarr_atp (dla, 0)->modeline)
7175 /* First check if the y position intersects the display lines. */
7176 if (char_y < num_disp_lines)
7178 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
7179 struct display_block *db = get_display_block_from_line (dl, TEXT);
7181 *pix_y = (dl->ypos - dl->ascent +
7182 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
7184 if (char_x < Dynarr_length (db->runes))
7186 struct rune *rb = Dynarr_atp (db->runes, char_x);
7188 *pix_x = rb->xpos + (rb->width >> 1);
7192 int last_rune = Dynarr_length (db->runes) - 1;
7193 struct rune *rb = Dynarr_atp (db->runes, last_rune);
7195 char_x -= last_rune;
7197 *pix_x = rb->xpos + rb->width;
7198 *pix_x += ((char_x - 1) * defwidth);
7199 *pix_x += (defwidth >> 1);
7204 /* It didn't intersect, so extrapolate. #### For now, we include the
7205 modeline in this since we don't have true character positions in
7208 if (!Dynarr_length (w->face_cachels))
7209 reset_face_cachels (w);
7211 char_y -= num_disp_lines;
7213 if (Dynarr_length (dla))
7215 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
7216 *pix_y = dl->ypos + dl->descent - dl->clip;
7219 *pix_y = WINDOW_TEXT_TOP (w);
7221 *pix_y += (char_y * defheight);
7222 *pix_y += (defheight >> 1);
7224 *pix_x = WINDOW_TEXT_LEFT (w);
7225 /* Don't adjust by one because this is still the unadjusted value. */
7226 *pix_x += (char_x * defwidth);
7227 *pix_x += (defwidth >> 1);
7230 if (*pix_x > w->pixel_left + w->pixel_width)
7231 *pix_x = w->pixel_left + w->pixel_width;
7232 if (*pix_y > w->pixel_top + w->pixel_height)
7233 *pix_y = w->pixel_top + w->pixel_height;
7235 *pix_x -= w->pixel_left;
7236 *pix_y -= w->pixel_top;
7239 /* Given a display line and a position, determine if there is a glyph
7240 there and return information about it if there is. */
7243 get_position_object (struct display_line *dl, Lisp_Object *obj1,
7244 Lisp_Object *obj2, int x_coord, int *low_x_coord,
7247 struct display_block *db;
7250 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
7252 /* We use get_next_display_block to get the actual display block
7253 that would be displayed at x_coord. */
7255 if (block == NO_BLOCK)
7258 db = Dynarr_atp (dl->display_blocks, block);
7260 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
7262 struct rune *rb = Dynarr_atp (db->runes, elt);
7264 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
7266 if (rb->type == RUNE_DGLYPH)
7268 *obj1 = rb->object.dglyph.glyph;
7269 *obj2 = rb->object.dglyph.extent;
7278 *low_x_coord = rb->xpos;
7280 *high_x_coord = rb->xpos + rb->width;
7287 #define UPDATE_CACHE_RETURN \
7289 d->pixel_to_glyph_cache.valid = 1; \
7290 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
7291 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
7292 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
7293 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
7294 d->pixel_to_glyph_cache.frame = f; \
7295 d->pixel_to_glyph_cache.col = *col; \
7296 d->pixel_to_glyph_cache.row = *row; \
7297 d->pixel_to_glyph_cache.obj_x = *obj_x; \
7298 d->pixel_to_glyph_cache.obj_y = *obj_y; \
7299 d->pixel_to_glyph_cache.w = *w; \
7300 d->pixel_to_glyph_cache.bufpos = *bufpos; \
7301 d->pixel_to_glyph_cache.closest = *closest; \
7302 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
7303 d->pixel_to_glyph_cache.obj1 = *obj1; \
7304 d->pixel_to_glyph_cache.obj2 = *obj2; \
7305 d->pixel_to_glyph_cache.retval = position; \
7306 RETURN_SANS_WARNINGS position; \
7309 /* Given x and y coordinates in pixels relative to a frame, return
7310 information about what is located under those coordinates.
7312 The return value will be one of:
7314 OVER_TOOLBAR: over one of the 4 frame toolbars
7315 OVER_MODELINE: over a modeline
7316 OVER_BORDER: over an internal border
7317 OVER_NOTHING: over the text area, but not over text
7318 OVER_OUTSIDE: outside of the frame border
7319 OVER_TEXT: over text in the text area
7325 -- nil if the coordinates are not over a glyph or a toolbar button.
7329 -- an extent, if the coordinates are over a glyph in the text area
7332 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
7333 equivalent coordinates relative to the upper-left corner of the glyph.
7335 If the coordinates are over a character, OBJ_X and OBJ_Y give the
7336 equivalent coordinates relative to the upper-left corner of the character.
7338 Otherwise, OBJ_X and OBJ_Y are undefined.
7342 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
7343 int *col, int *row, int *obj_x, int *obj_y,
7344 struct window **w, Bufpos *bufpos,
7345 Bufpos *closest, Charcount *modeline_closest,
7346 Lisp_Object *obj1, Lisp_Object *obj2)
7349 struct pixel_to_glyph_translation_cache *cache;
7351 int frm_left, frm_right, frm_top, frm_bottom;
7352 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
7353 int position = OVER_NOTHING;
7354 int device_check_failed = 0;
7355 display_line_dynarr *dla;
7357 /* This is a safety valve in case this got called with a frame in
7358 the middle of being deleted. */
7359 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
7361 device_check_failed = 1;
7362 d = NULL, cache = NULL; /* Warning suppression */
7366 d = XDEVICE (f->device);
7367 cache = &d->pixel_to_glyph_cache;
7370 if (!device_check_failed
7372 && cache->frame == f
7373 && cache->low_x_coord <= x_coord
7374 && cache->high_x_coord > x_coord
7375 && cache->low_y_coord <= y_coord
7376 && cache->high_y_coord > y_coord)
7380 *obj_x = cache->obj_x;
7381 *obj_y = cache->obj_y;
7383 *bufpos = cache->bufpos;
7384 *closest = cache->closest;
7385 *modeline_closest = cache->modeline_closest;
7386 *obj1 = cache->obj1;
7387 *obj2 = cache->obj2;
7389 return cache->retval;
7400 *modeline_closest = -1;
7404 low_x_coord = x_coord;
7405 high_x_coord = x_coord + 1;
7406 low_y_coord = y_coord;
7407 high_y_coord = y_coord + 1;
7410 if (device_check_failed)
7411 return OVER_NOTHING;
7413 frm_left = FRAME_LEFT_BORDER_END (f);
7414 frm_right = FRAME_RIGHT_BORDER_START (f);
7415 frm_top = FRAME_TOP_BORDER_END (f);
7416 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
7418 /* Check if the mouse is outside of the text area actually used by
7420 if (y_coord < frm_top)
7422 if (y_coord >= FRAME_TOP_BORDER_START (f))
7424 low_y_coord = FRAME_TOP_BORDER_START (f);
7425 high_y_coord = frm_top;
7426 position = OVER_BORDER;
7428 else if (y_coord >= 0)
7431 high_y_coord = FRAME_TOP_BORDER_START (f);
7432 position = OVER_TOOLBAR;
7436 low_y_coord = y_coord;
7438 position = OVER_OUTSIDE;
7441 else if (y_coord >= frm_bottom)
7443 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
7445 low_y_coord = frm_bottom;
7446 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
7447 position = OVER_BORDER;
7449 else if (y_coord < FRAME_PIXHEIGHT (f))
7451 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
7452 high_y_coord = FRAME_PIXHEIGHT (f);
7453 position = OVER_TOOLBAR;
7457 low_y_coord = FRAME_PIXHEIGHT (f);
7458 high_y_coord = y_coord;
7459 position = OVER_OUTSIDE;
7463 if (position != OVER_TOOLBAR && position != OVER_BORDER)
7465 if (x_coord < frm_left)
7467 if (x_coord >= FRAME_LEFT_BORDER_START (f))
7469 low_x_coord = FRAME_LEFT_BORDER_START (f);
7470 high_x_coord = frm_left;
7471 position = OVER_BORDER;
7473 else if (x_coord >= 0)
7476 high_x_coord = FRAME_LEFT_BORDER_START (f);
7477 position = OVER_TOOLBAR;
7481 low_x_coord = x_coord;
7483 position = OVER_OUTSIDE;
7486 else if (x_coord >= frm_right)
7488 if (x_coord < FRAME_RIGHT_BORDER_END (f))
7490 low_x_coord = frm_right;
7491 high_x_coord = FRAME_RIGHT_BORDER_END (f);
7492 position = OVER_BORDER;
7494 else if (x_coord < FRAME_PIXWIDTH (f))
7496 low_x_coord = FRAME_RIGHT_BORDER_END (f);
7497 high_x_coord = FRAME_PIXWIDTH (f);
7498 position = OVER_TOOLBAR;
7502 low_x_coord = FRAME_PIXWIDTH (f);
7503 high_x_coord = x_coord;
7504 position = OVER_OUTSIDE;
7509 #ifdef HAVE_TOOLBARS
7510 if (position == OVER_TOOLBAR)
7512 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
7515 UPDATE_CACHE_RETURN;
7517 #endif /* HAVE_TOOLBARS */
7519 /* We still have to return the window the pointer is next to and its
7520 relative y position even if it is outside the x boundary. */
7521 if (x_coord < frm_left)
7523 else if (x_coord > frm_right)
7524 x_coord = frm_right;
7526 /* Same in reverse. */
7527 if (y_coord < frm_top)
7529 else if (y_coord > frm_bottom)
7530 y_coord = frm_bottom;
7532 /* Find what window the given coordinates are actually in. */
7533 window = f->root_window;
7534 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
7536 /* If we didn't find a window, we're done. */
7539 UPDATE_CACHE_RETURN;
7541 else if (position != OVER_NOTHING)
7544 *modeline_closest = -1;
7546 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
7549 UPDATE_CACHE_RETURN;
7553 /* Check if the window is a minibuffer but isn't active. */
7554 if (MINI_WINDOW_P (*w) && !minibuf_level)
7556 /* Must reset the window value since some callers will ignore
7557 the return value if it is set. */
7559 UPDATE_CACHE_RETURN;
7562 /* See if the point is over window vertical divider */
7563 if (window_needs_vertical_divider (*w))
7565 int div_x_high = WINDOW_RIGHT (*w);
7566 int div_x_low = div_x_high - window_divider_width (*w);
7567 int div_y_high = WINDOW_BOTTOM (*w);
7568 int div_y_low = WINDOW_TOP (*w);
7570 if (div_x_low < x_coord && x_coord <= div_x_high &&
7571 div_y_low < y_coord && y_coord <= div_y_high)
7573 low_x_coord = div_x_low;
7574 high_x_coord = div_x_high;
7575 low_y_coord = div_y_low;
7576 high_y_coord = div_y_high;
7577 position = OVER_V_DIVIDER;
7578 UPDATE_CACHE_RETURN;
7582 dla = window_display_lines (*w, CURRENT_DISP);
7584 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
7586 int really_over_nothing = 0;
7587 struct display_line *dl = Dynarr_atp (dla, *row);
7589 if ((int) (dl->ypos - dl->ascent) <= y_coord
7590 && y_coord <= (int) (dl->ypos + dl->descent))
7592 int check_margin_glyphs = 0;
7593 struct display_block *db = get_display_block_from_line (dl, TEXT);
7594 struct rune *rb = 0;
7596 if (x_coord < dl->bounds.left_white
7597 || x_coord >= dl->bounds.right_white)
7598 check_margin_glyphs = 1;
7600 low_y_coord = dl->ypos - dl->ascent;
7601 high_y_coord = dl->ypos + dl->descent + 1;
7603 if (position == OVER_BORDER
7604 || position == OVER_OUTSIDE
7605 || check_margin_glyphs)
7607 int x_check, left_bound;
7609 if (check_margin_glyphs)
7612 left_bound = dl->bounds.left_white;
7616 x_check = high_x_coord;
7617 left_bound = frm_left;
7620 if (Dynarr_length (db->runes))
7622 if (x_check <= left_bound)
7625 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
7627 *closest = Dynarr_atp (db->runes, 0)->bufpos;
7633 Dynarr_atp (db->runes,
7634 Dynarr_length (db->runes) - 1)->bufpos;
7637 Dynarr_atp (db->runes,
7638 Dynarr_length (db->runes) - 1)->bufpos;
7642 *modeline_closest += dl->offset;
7644 *closest += dl->offset;
7648 /* #### What should be here. */
7650 *modeline_closest = 0;
7655 if (check_margin_glyphs)
7657 if (x_coord < dl->bounds.left_in
7658 || x_coord >= dl->bounds.right_in)
7660 /* If we are over the outside margins then we
7661 know the loop over the text block isn't going
7662 to accomplish anything. So we go ahead and
7663 set what information we can right here and
7666 *obj_y = y_coord - (dl->ypos - dl->ascent);
7667 get_position_object (dl, obj1, obj2, x_coord,
7668 &low_x_coord, &high_x_coord);
7670 UPDATE_CACHE_RETURN;
7674 UPDATE_CACHE_RETURN;
7677 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
7679 int past_end = (*col == Dynarr_length (db->runes));
7682 rb = Dynarr_atp (db->runes, *col);
7685 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
7690 rb = Dynarr_atp (db->runes, *col);
7693 *bufpos = rb->bufpos + dl->offset;
7694 low_x_coord = rb->xpos;
7695 high_x_coord = rb->xpos + rb->width;
7697 if (rb->type == RUNE_DGLYPH)
7701 /* Find the first character after the glyph. */
7702 while (elt < Dynarr_length (db->runes))
7704 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
7708 (Dynarr_atp (db->runes, elt)->bufpos +
7712 (Dynarr_atp (db->runes, elt)->bufpos +
7720 /* In this case we failed to find a non-glyph
7721 character so we return the last position
7722 displayed on the line. */
7723 if (elt == Dynarr_length (db->runes))
7726 *modeline_closest = dl->end_bufpos + dl->offset;
7728 *closest = dl->end_bufpos + dl->offset;
7729 really_over_nothing = 1;
7735 *modeline_closest = rb->bufpos + dl->offset;
7737 *closest = rb->bufpos + dl->offset;
7742 *row = window_displayed_height (*w);
7744 if (position == OVER_NOTHING)
7745 position = OVER_MODELINE;
7747 if (rb->type == RUNE_DGLYPH)
7749 *obj1 = rb->object.dglyph.glyph;
7750 *obj2 = rb->object.dglyph.extent;
7752 else if (rb->type == RUNE_CHAR)
7763 UPDATE_CACHE_RETURN;
7766 || (rb->type == RUNE_CHAR
7767 && rb->object.chr.ch == '\n'))
7770 /* At this point we may have glyphs in the right
7772 if (check_margin_glyphs)
7773 get_position_object (dl, obj1, obj2, x_coord,
7774 &low_x_coord, &high_x_coord);
7775 UPDATE_CACHE_RETURN;
7780 if (rb->type == RUNE_DGLYPH)
7782 *obj1 = rb->object.dglyph.glyph;
7783 *obj2 = rb->object.dglyph.extent;
7785 else if (rb->type == RUNE_CHAR)
7796 *obj_x = x_coord - rb->xpos;
7797 *obj_y = y_coord - (dl->ypos - dl->ascent);
7799 /* At this point we may have glyphs in the left
7801 if (check_margin_glyphs)
7802 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
7804 if (position == OVER_NOTHING && !really_over_nothing)
7805 position = OVER_TEXT;
7807 UPDATE_CACHE_RETURN;
7814 *row = Dynarr_length (dla) - 1;
7815 if (FRAME_WIN_P (f))
7817 int bot_elt = Dynarr_length (dla) - 1;
7821 struct display_line *dl = Dynarr_atp (dla, bot_elt);
7822 int adj_area = y_coord - (dl->ypos + dl->descent);
7826 XSETWINDOW (lwin, *w);
7827 default_face_height_and_width (lwin, 0, &defheight);
7829 *row += (adj_area / defheight);
7833 /* #### This should be checked out some more to determine what
7834 should really be going on. */
7835 if (!MARKERP ((*w)->start[CURRENT_DISP]))
7838 *closest = end_of_last_line (*w,
7839 marker_position ((*w)->start[CURRENT_DISP]));
7841 UPDATE_CACHE_RETURN;
7843 #undef UPDATE_CACHE_RETURN
7846 /***************************************************************************/
7848 /* Lisp functions */
7850 /***************************************************************************/
7852 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
7853 Ensure that all minibuffers are correctly showing the echo area.
7857 Lisp_Object devcons, concons;
7859 DEVICE_LOOP_NO_BREAK (devcons, concons)
7861 struct device *d = XDEVICE (XCAR (devcons));
7862 Lisp_Object frmcons;
7864 DEVICE_FRAME_LOOP (frmcons, d)
7866 struct frame *f = XFRAME (XCAR (frmcons));
7868 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
7870 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
7872 * If the frame size has changed, there may be random
7873 * chud on the screen left from previous messages
7874 * because redisplay_frame hasn't been called yet.
7875 * Clear the screen to get rid of the potential mess.
7877 if (f->echo_area_garbaged)
7879 DEVMETH (d, clear_frame, (f));
7880 f->echo_area_garbaged = 0;
7882 redisplay_window (window, 0);
7883 call_redisplay_end_triggers (XWINDOW (window), 0);
7887 /* We now call the output_end routine for tty frames. We delay
7888 doing so in order to avoid cursor flicker. So much for 100%
7890 if (DEVICE_TTY_P (d))
7891 DEVMETH (d, output_end, (d));
7898 restore_disable_preemption_value (Lisp_Object value)
7900 disable_preemption = XINT (value);
7904 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
7905 Clear frame FRAME and output again what is supposed to appear on it.
7906 FRAME defaults to the selected frame if omitted.
7907 Normally, redisplay is preempted as normal if input arrives. However,
7908 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7909 input and is guaranteed to proceed to completion.
7911 (frame, no_preempt))
7913 struct frame *f = decode_frame (frame);
7914 int count = specpdl_depth ();
7916 if (!NILP (no_preempt))
7918 record_unwind_protect (restore_disable_preemption_value,
7919 make_int (disable_preemption));
7920 disable_preemption++;
7924 redisplay_frame (f, 1);
7926 return unbind_to (count, Qnil);
7929 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
7930 Ensure that FRAME's contents are correctly displayed.
7931 This differs from `redraw-frame' in that it only redraws what needs to
7932 be updated, as opposed to unconditionally clearing and redrawing
7934 FRAME defaults to the selected frame if omitted.
7935 Normally, redisplay is preempted as normal if input arrives. However,
7936 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7937 input and is guaranteed to proceed to completion.
7939 (frame, no_preempt))
7941 struct frame *f = decode_frame (frame);
7942 int count = specpdl_depth ();
7944 if (!NILP (no_preempt))
7946 record_unwind_protect (restore_disable_preemption_value,
7947 make_int (disable_preemption));
7948 disable_preemption++;
7951 redisplay_frame (f, 1);
7953 return unbind_to (count, Qnil);
7956 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
7957 Clear device DEVICE and output again what is supposed to appear on it.
7958 DEVICE defaults to the selected device if omitted.
7959 Normally, redisplay is preempted as normal if input arrives. However,
7960 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7961 input and is guaranteed to proceed to completion.
7963 (device, no_preempt))
7965 struct device *d = decode_device (device);
7966 Lisp_Object frmcons;
7967 int count = specpdl_depth ();
7969 if (!NILP (no_preempt))
7971 record_unwind_protect (restore_disable_preemption_value,
7972 make_int (disable_preemption));
7973 disable_preemption++;
7976 DEVICE_FRAME_LOOP (frmcons, d)
7978 XFRAME (XCAR (frmcons))->clear = 1;
7980 redisplay_device (d);
7982 return unbind_to (count, Qnil);
7985 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
7986 Ensure that DEVICE's contents are correctly displayed.
7987 This differs from `redraw-device' in that it only redraws what needs to
7988 be updated, as opposed to unconditionally clearing and redrawing
7990 DEVICE defaults to the selected device if omitted.
7991 Normally, redisplay is preempted as normal if input arrives. However,
7992 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7993 input and is guaranteed to proceed to completion.
7995 (device, no_preempt))
7997 struct device *d = decode_device (device);
7998 int count = specpdl_depth ();
8000 if (!NILP (no_preempt))
8002 record_unwind_protect (restore_disable_preemption_value,
8003 make_int (disable_preemption));
8004 disable_preemption++;
8007 redisplay_device (d);
8009 return unbind_to (count, Qnil);
8012 /* Big lie. Big lie. This will force all modelines to be updated
8013 regardless if the all flag is set or not. It remains in existence
8014 solely for backwards compatibility. */
8015 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8016 Force the modeline of the current buffer to be redisplayed.
8017 With optional non-nil ALL, force redisplay of all modelines.
8021 MARK_MODELINE_CHANGED;
8025 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8026 Force an immediate update of the cursor on FRAME.
8027 FRAME defaults to the selected frame if omitted.
8031 redisplay_redraw_cursor (decode_frame (frame), 1);
8036 /***************************************************************************/
8038 /* Lisp-variable change triggers */
8040 /***************************************************************************/
8043 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
8046 /* Nothing to be done? */
8050 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
8051 Lisp_Object in_object, int flags)
8053 /* #### clip_changed should really be renamed something like
8054 global_redisplay_change. */
8060 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8063 if (WINDOWP (locale))
8065 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
8067 else if (FRAMEP (locale))
8069 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
8071 else if (DEVICEP (locale))
8073 Lisp_Object frmcons;
8074 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
8075 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8077 else if (CONSOLEP (locale))
8079 Lisp_Object frmcons, devcons;
8080 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
8081 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8083 else /* global or buffer */
8085 Lisp_Object frmcons, devcons, concons;
8086 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
8087 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8092 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
8095 if (XFRAME (w->frame)->init_finished)
8096 Fforce_cursor_redisplay (w->frame);
8099 #ifdef MEMORY_USAGE_STATS
8102 /***************************************************************************/
8104 /* memory usage computation */
8106 /***************************************************************************/
8109 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
8111 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8115 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
8116 struct overhead_stats *ovstats)
8123 total = Dynarr_memory_usage (dyn, ovstats);
8124 for (i = 0; i < Dynarr_largest (dyn); i++)
8125 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
8131 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
8132 struct overhead_stats *ovstats)
8134 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8138 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
8139 struct overhead_stats *ovstats)
8146 total = Dynarr_memory_usage (dyn, ovstats);
8147 for (i = 0; i < Dynarr_largest (dyn); i++)
8149 struct display_line *dl = &Dynarr_at (dyn, i);
8150 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
8151 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
8152 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
8159 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
8160 struct overhead_stats *ovstats)
8162 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8165 #endif /* MEMORY_USAGE_STATS */
8168 /***************************************************************************/
8170 /* initialization */
8172 /***************************************************************************/
8175 init_redisplay (void)
8177 disable_preemption = 0;
8178 preemption_count = 0;
8179 max_preempts = INIT_MAX_PREEMPTS;
8183 cmotion_display_lines = Dynarr_new (display_line);
8184 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
8185 formatted_string_emchar_dynarr = Dynarr_new (Emchar);
8186 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
8187 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
8188 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
8189 internal_cache = Dynarr_new (line_start_cache);
8190 xzero (formatted_string_display_line);
8193 /* window system is nil when in -batch mode */
8194 if (!initialized || noninteractive)
8197 /* If the user wants to use a window system, we shouldn't bother
8198 initializing the terminal. This is especially important when the
8199 terminal is so dumb that emacs gives up before and doesn't bother
8200 using the window system.
8202 If the DISPLAY environment variable is set, try to use X, and die
8203 with an error message if that doesn't work. */
8205 #ifdef HAVE_X_WINDOWS
8206 if (!strcmp (display_use, "x"))
8208 /* Some stuff checks this way early. */
8209 Vwindow_system = Qx;
8210 Vinitial_window_system = Qx;
8213 #endif /* HAVE_X_WINDOWS */
8215 #ifdef HAVE_MS_WINDOWS
8216 if (!strcmp (display_use, "mswindows"))
8218 /* Some stuff checks this way early. */
8219 Vwindow_system = Qmswindows;
8220 Vinitial_window_system = Qmswindows;
8223 #endif /* HAVE_MS_WINDOWS */
8226 /* If no window system has been specified, try to use the terminal. */
8229 stderr_out ("XEmacs: standard input is not a tty\n");
8233 /* Look at the TERM variable */
8234 if (!getenv ("TERM"))
8236 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
8240 Vinitial_window_system = Qtty;
8242 #else /* not HAVE_TTY */
8243 /* No DISPLAY specified, and no TTY support. */
8244 stderr_out ("XEmacs: Cannot open display.\n\
8245 Please set the environmental variable DISPLAY to an appropriate value.\n");
8252 syms_of_redisplay (void)
8254 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
8255 #ifndef INHIBIT_REDISPLAY_HOOKS
8256 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
8257 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
8258 #endif /* INHIBIT_REDISPLAY_HOOKS */
8259 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
8260 defsymbol (&Qbar_cursor, "bar-cursor");
8261 defsymbol (&Qwindow_scroll_functions, "window-scroll-functions");
8262 defsymbol (&Qredisplay_end_trigger_functions,
8263 "redisplay-end-trigger-functions");
8265 DEFSUBR (Fredisplay_echo_area);
8266 DEFSUBR (Fredraw_frame);
8267 DEFSUBR (Fredisplay_frame);
8268 DEFSUBR (Fredraw_device);
8269 DEFSUBR (Fredisplay_device);
8270 DEFSUBR (Fredraw_modeline);
8271 DEFSUBR (Fforce_cursor_redisplay);
8275 vars_of_redisplay (void)
8278 staticpro (&last_arrow_position);
8279 staticpro (&last_arrow_string);
8280 last_arrow_position = Qnil;
8281 last_arrow_string = Qnil;
8284 updating_line_start_cache = 0;
8286 /* #### Probably temporary */
8287 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
8288 \(Temporary) Setting this will impact the performance of the internal
8291 cache_adjustment = 2;
8293 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
8294 Minimum pixel height for clipped bottom display line.
8295 A clipped line shorter than this won't be displayed.
8297 redisplay_variable_changed);
8300 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
8301 Minimum visible area for clipped glyphs at right boundary.
8302 Clipped glyphs shorter than this won't be displayed.
8303 Only pixmap glyph instances are currently allowed to be clipped.
8305 redisplay_variable_changed);
8306 horizontal_clip = 5;
8308 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
8309 String displayed by modeline-format's "%m" specification.
8311 Vglobal_mode_string = Qnil;
8313 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
8314 Marker for where to display an arrow on top of the buffer text.
8315 This must be the beginning of a line in order to work.
8316 See also `overlay-arrow-string'.
8318 redisplay_variable_changed);
8319 Voverlay_arrow_position = Qnil;
8321 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
8322 String to display as an arrow. See also `overlay-arrow-position'.
8324 redisplay_variable_changed);
8325 Voverlay_arrow_string = Qnil;
8327 DEFVAR_INT ("scroll-step", &scroll_step /*
8328 *The number of lines to try scrolling a window by when point moves out.
8329 If that fails to bring point back on frame, point is centered instead.
8330 If this is zero, point is always centered after it moves off screen.
8334 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
8335 *Scroll up to this many lines, to bring point back on screen.
8337 scroll_conservatively = 0;
8339 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
8340 &truncate_partial_width_windows /*
8341 *Non-nil means truncate lines in all windows less than full frame wide.
8343 redisplay_variable_changed);
8344 truncate_partial_width_windows = 1;
8346 DEFVAR_BOOL ("visible-bell", &visible_bell /*
8347 *Non-nil means try to flash the frame to represent a bell.
8351 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
8352 *Non-nil means no need to redraw entire frame after suspending.
8353 A non-nil value is useful if the terminal can automatically preserve
8354 Emacs's frame display when you reenter Emacs.
8355 It is up to you to set this variable if your terminal can do that.
8357 no_redraw_on_reenter = 0;
8359 DEFVAR_LISP ("window-system", &Vwindow_system /*
8360 A symbol naming the window-system under which Emacs is running,
8361 such as `x', or nil if emacs is running on an ordinary terminal.
8363 Do not use this variable, except for GNU Emacs compatibility, as it
8364 gives wrong values in a multi-device environment. Use `console-type'
8367 Vwindow_system = Qnil;
8369 /* #### Temporary shit until window-system is eliminated. */
8370 DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /*
8373 Vinitial_window_system = Qnil;
8375 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
8376 Non-nil means put cursor in minibuffer, at end of any message there.
8378 cursor_in_echo_area = 0;
8380 /* #### Shouldn't this be generalized as follows:
8382 if nil, use block cursor.
8383 if a number, use a bar cursor of that width.
8384 Otherwise, use a 1-pixel bar cursor.
8386 #### Or better yet, this variable should be trashed entirely
8387 (use a Lisp-magic variable to maintain compatibility)
8388 and a specifier `cursor-shape' added, which allows a block
8389 cursor, a bar cursor, a flashing block or bar cursor,
8390 maybe a caret cursor, etc. */
8392 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
8393 Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
8397 #ifndef INHIBIT_REDISPLAY_HOOKS
8398 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
8399 Function or functions to run before every redisplay.
8400 Functions on this hook must be careful to avoid signalling errors!
8402 Vpre_redisplay_hook = Qnil;
8404 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
8405 Function or functions to run after every redisplay.
8406 Functions on this hook must be careful to avoid signalling errors!
8408 Vpost_redisplay_hook = Qnil;
8409 #endif /* INHIBIT_REDISPLAY_HOOKS */
8411 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
8412 Bump this to tell the C code to call `display-warning-buffer'
8413 at next redisplay. You should not normally change this; the function
8414 `display-warning' automatically does this at appropriate times.
8416 display_warning_tick = 0;
8418 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
8419 Non-nil means inhibit display of warning messages.
8420 You should *bind* this, not set it. Any pending warning messages
8421 will be displayed when the binding no longer applies.
8423 /* reset to 0 by startup.el after the splash screen has displayed.
8424 This way, the warnings don't obliterate the splash screen. */
8425 inhibit_warning_display = 1;
8427 DEFVAR_LISP ("window-size-change-functions",
8428 &Vwindow_size_change_functions /*
8429 Not currently implemented.
8430 Functions called before redisplay, if window sizes have changed.
8431 The value should be a list of functions that take one argument.
8432 Just before redisplay, for each frame, if any of its windows have changed
8433 size since the last redisplay, or have been split or deleted,
8434 all the functions in the list are called, with the frame as argument.
8436 Vwindow_size_change_functions = Qnil;
8438 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
8439 Not currently implemented.
8440 Functions to call before redisplaying a window with scrolling.
8441 Each function is called with two arguments, the window
8442 and its new display-start position. Note that the value of `window-end'
8443 is not valid when these functions are called.
8445 Vwindow_scroll_functions = Qnil;
8447 DEFVAR_LISP ("redisplay-end-trigger-functions",
8448 &Vredisplay_end_trigger_functions /*
8449 See `set-window-redisplay-end-trigger'.
8451 Vredisplay_end_trigger_functions = Qnil;
8453 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
8454 *Non-nil means column display number starts at 1.
8456 column_number_start_at_one = 0;
8460 specifier_vars_of_redisplay (void)
8462 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
8463 *Width of left margin.
8464 This is a specifier; use `set-specifier' to change it.
8466 Vleft_margin_width = Fmake_specifier (Qnatnum);
8467 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
8468 set_specifier_caching (Vleft_margin_width,
8469 slot_offset (struct window, left_margin_width),
8470 some_window_value_changed,
8471 slot_offset (struct frame, left_margin_width),
8472 margin_width_changed_in_frame);
8474 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
8475 *Width of right margin.
8476 This is a specifier; use `set-specifier' to change it.
8478 Vright_margin_width = Fmake_specifier (Qnatnum);
8479 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
8480 set_specifier_caching (Vright_margin_width,
8481 slot_offset (struct window, right_margin_width),
8482 some_window_value_changed,
8483 slot_offset (struct frame, right_margin_width),
8484 margin_width_changed_in_frame);
8486 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
8487 *Minimum ascent height of lines.
8488 This is a specifier; use `set-specifier' to change it.
8490 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
8491 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
8492 set_specifier_caching (Vminimum_line_ascent,
8493 slot_offset (struct window, minimum_line_ascent),
8494 some_window_value_changed,
8497 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
8498 *Minimum descent height of lines.
8499 This is a specifier; use `set-specifier' to change it.
8501 Vminimum_line_descent = Fmake_specifier (Qnatnum);
8502 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
8503 set_specifier_caching (Vminimum_line_descent,
8504 slot_offset (struct window, minimum_line_descent),
8505 some_window_value_changed,
8508 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
8509 *Non-nil means use the left outside margin as extra whitespace when
8510 displaying 'whitespace or 'inside-margin glyphs.
8511 This is a specifier; use `set-specifier' to change it.
8513 Vuse_left_overflow = Fmake_specifier (Qboolean);
8514 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
8515 set_specifier_caching (Vuse_left_overflow,
8516 slot_offset (struct window, use_left_overflow),
8517 some_window_value_changed,
8520 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
8521 *Non-nil means use the right outside margin as extra whitespace when
8522 displaying 'whitespace or 'inside-margin glyphs.
8523 This is a specifier; use `set-specifier' to change it.
8525 Vuse_right_overflow = Fmake_specifier (Qboolean);
8526 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
8527 set_specifier_caching (Vuse_right_overflow,
8528 slot_offset (struct window, use_right_overflow),
8529 some_window_value_changed,
8532 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
8533 *Non-nil means the text cursor is visible (this is usually the case).
8534 This is a specifier; use `set-specifier' to change it.
8536 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
8537 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
8538 set_specifier_caching (Vtext_cursor_visible_p,
8539 slot_offset (struct window, text_cursor_visible_p),
8540 text_cursor_visible_p_changed,