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 ****************************************************************************/
57 #include "redisplay.h"
60 #include "line-number.h"
62 #include "file-coding.h"
66 #include "console-tty.h"
68 #include <unistd.h> /* for isatty() */
72 /* Note: We have to be careful throughout this code to properly handle
73 and differentiate between Bufbytes and Emchars.
75 Since strings are generally composed of Bufbytes, I've taken the tack
76 that any contiguous set of Bufbytes is called a "string", while
77 any contiguous set of Emchars is called an "array". */
79 /* Return value to indicate a failure by an add_*_rune routine to add
80 a rune, but no propagation information needs to be returned. */
81 #define ADD_FAILED (prop_block_dynarr *) 1
83 #define BEGIN_GLYPHS 0
86 #define RIGHT_GLYPHS 3
88 /* Set the vertical clip to 0 if we are currently updating the line
89 start cache. Otherwise for buffers of line height 1 it may fail to
90 be able to work properly because regenerate_window will not layout
92 #define VERTICAL_CLIP(w, display) \
93 (updating_line_start_cache \
95 : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
99 /* The following structures are completely private to redisplay.c so
100 we put them here instead of in a header file, for modularity. */
102 /* NOTE: Bytinds not Bufpos's in this structure. */
104 typedef struct position_redisplay_data_type
106 /* This information is normally filled in by the create_*_block
107 routines and is used by the add_*_rune routines. */
110 struct display_block *db;
111 struct display_line *dl;
112 Emchar ch; /* Character that is to be added. This is
113 used to communicate this information to
114 add_emchar_rune(). */
115 Lisp_Object last_charset; /* The charset of the previous character.
116 Used to optimize some lookups -- we
117 only have to do some things when
118 the charset changes. */
119 face_index last_findex; /* The face index of the previous character.
120 Needed to ensure the validity of the
121 last_charset optimization. */
123 int last_char_width; /* The width of the previous character. */
124 int font_is_bogus; /* If true, it means we couldn't instantiate
125 the font for this charset, so we substitute
126 ~'s from the ASCII charset. */
131 int blank_width; /* Width of the blank that is to be added.
132 This is used to communicate this information
135 This is also used rather cheesily to
136 communicate the width of the eol-cursor-size
137 blank that exists at the end of the line.
138 add_emchar_rune() is called cheesily with
139 the non-printing char '\n', which is stuck
140 in the output routines with its width being
142 Bytind bi_cursor_bufpos;/* This stores the buffer position of the cursor. */
143 unsigned int cursor_type :3;
144 int cursor_x; /* rune block cursor is at */
145 int start_col; /* Number of character columns (each column has
146 a width of the default char width) that still
147 need to be skipped. This is used for horizontal
148 scrolling, where a certain number of columns
149 (those off the left side of the screen) need
150 to be skipped before anything is displayed. */
151 Bytind bi_start_col_enabled;
153 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
154 glyph differs from space_width (w).
155 0 if no hscroll glyph was used,
156 i.e. the window is not scrolled
157 horizontally. Used in tab
160 /* Information about the face the text should be displayed in and
161 any begin-glyphs and end-glyphs. */
162 struct extent_fragment *ef;
165 /* The height of a pixmap may either be predetermined if the user
166 has set a baseline value, or it may be dependent on whatever the
167 line ascent and descent values end up being, based just on font
168 information. In the first case we can immediately update the
169 values, thus their inclusion here. In the last case we cannot
170 determine the actual contribution to the line height until we
171 have finished laying out all text on the line. Thus we propagate
172 the max height of such pixmaps and do a final calculation after
173 all text has been added to the line. */
176 int max_pixmap_height;
178 Lisp_Object result_str; /* String where we put the result of
179 generating a formatted string in the modeline. */
180 int is_modeline; /* Non-zero if we're generating the modeline. */
181 Charcount modeline_charpos; /* Number of chars used in result_str so far;
182 corresponds to bytepos. */
183 Bytecount bytepos; /* Number of bytes used in result_str so far.
184 We don't actually copy the bytes into result_str
185 until the end because we don't know how big the
186 string is going to be until then. */
197 /* Data that should be propagated to the next line. Either a single
198 Emchar or a string of Bufbyte's.
200 The actual data that is propagated ends up as a Dynarr of these
203 #### It's unclean that both Emchars and Bufbytes are here.
206 typedef struct prop_block prop_block;
216 Bytecount len; /* length of the string. */
222 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
223 unsigned int cursor_type :3;
236 Dynarr_declare (prop_block);
240 static void generate_formatted_string_db (Lisp_Object format_str,
241 Lisp_Object result_str,
243 struct display_line *dl,
244 struct display_block *db,
245 face_index findex, int min_pixpos,
246 int max_pixpos, int type);
247 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
248 Charcount pos, Charcount min_pos,
249 Charcount max_pos, Lisp_Object elt,
250 int depth, int max_pixsize,
251 face_index findex, int type);
252 static prop_block_dynarr *add_glyph_rune (pos_data *data,
253 struct glyph_block *gb,
254 int pos_type, int allow_cursor,
255 struct glyph_cachel *cachel);
256 static Bytind create_text_block (struct window *w, struct display_line *dl,
257 Bytind bi_start_pos, int start_col,
258 prop_block_dynarr **prop, int type);
259 static int create_overlay_glyph_block (struct window *w,
260 struct display_line *dl);
261 static void create_left_glyph_block (struct window *w,
262 struct display_line *dl,
264 static void create_right_glyph_block (struct window *w,
265 struct display_line *dl);
266 static void redisplay_windows (Lisp_Object window, int skip_selected);
267 static void decode_mode_spec (struct window *w, Emchar spec, int type);
268 static void free_display_line (struct display_line *dl);
269 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
270 Bufpos point, int no_regen);
271 static int point_visible (struct window *w, Bufpos point, int type);
273 /* This used to be 10 but 30 seems to give much better performance. */
274 #define INIT_MAX_PREEMPTS 30
275 static int max_preempts;
277 #define REDISPLAY_PREEMPTION_CHECK \
280 (!disable_preemption && \
281 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
282 (!INTERACTIVE || detect_input_pending ()))))
285 * Redisplay global variables.
288 /* We need a third set of display structures for the cursor motion
289 routines. We used to just give each window a third set. However,
290 we always fully regenerate the structures when needed so there
291 isn't any reason we need more than a single set. */
292 display_line_dynarr *cmotion_display_lines;
294 /* Used by generate_formatted_string. Global because they get used so
295 much that the dynamic allocation time adds up. */
296 Emchar_dynarr *formatted_string_emchar_dynarr;
297 struct display_line formatted_string_display_line;
298 /* We store the extents that we need to generate in a Dynarr and then
299 frob them all on at the end of generating the string. We do it
300 this way rather than adding them as we generate the string because
301 we don't store the text into the resulting string until we're done
302 (to avoid having to resize the string multiple times), and we don't
303 want to go around adding extents to a string when the extents might
304 stretch off the end of the string. */
305 EXTENT_dynarr *formatted_string_extent_dynarr;
306 Bytecount_dynarr *formatted_string_extent_start_dynarr;
307 Bytecount_dynarr *formatted_string_extent_end_dynarr;
310 /* #### probably temporary */
311 int cache_adjustment;
313 /* This holds a string representing the text corresponding to a single
315 static Bufbyte_dynarr *mode_spec_bufbyte_string;
317 int in_display; /* 1 if in redisplay. */
319 int disable_preemption; /* Used for debugging redisplay and for
322 /* We only allow max_preempts preemptions before we force a redisplay. */
323 static int preemption_count;
325 /* Minimum pixel height of clipped bottom display line. */
328 /* Minimum visible pixel width of clipped glyphs at right margin. */
331 /* Set if currently inside update_line_start_cache. */
332 int updating_line_start_cache;
334 /* Nonzero means reading single-character input with prompt
335 so put cursor on minibuffer after the prompt. */
336 int cursor_in_echo_area;
337 Lisp_Object Qcursor_in_echo_area;
339 /* Nonzero means truncate lines in all windows less wide than the frame */
340 int truncate_partial_width_windows;
342 /* non-nil if a buffer has changed since the last time redisplay completed */
344 int buffers_changed_set;
346 /* non-nil if hscroll has changed somewhere or a buffer has been
347 narrowed or widened */
349 int clip_changed_set;
351 /* non-nil if any extent has changed since the last time redisplay completed */
353 int extents_changed_set;
355 /* non-nil if any face has changed since the last time redisplay completed */
358 /* Nonzero means some frames have been marked as garbaged */
361 /* non-zero if any of the builtin display glyphs (continuation,
362 hscroll, control-arrow, etc) is in need of updating
365 int glyphs_changed_set;
367 /* This variable is 1 if the icon has to be updated.
368 It is set to 1 when `frame-icon-glyph' changes. */
370 int icon_changed_set;
372 /* This variable is 1 if the menubar widget has to be updated.
373 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
376 int menubar_changed_set;
378 /* true iff we should redraw the modelines on the next redisplay */
379 int modeline_changed;
380 int modeline_changed_set;
382 /* non-nil if point has changed in some buffer since the last time
383 redisplay completed */
385 int point_changed_set;
387 /* non-nil if some frame has changed its size */
390 /* non-nil if some device has signaled that it wants to change size */
391 int asynch_device_change_pending;
393 /* non-nil if any toolbar has changed */
395 int toolbar_changed_set;
397 /* non-nil if any window has changed since the last time redisplay completed */
400 /* non-nil if any frame's window structure has changed since the last
401 time redisplay completed */
402 int windows_structure_changed;
404 /* If non-nil, use vertical bar cursor. */
405 Lisp_Object Vbar_cursor;
406 Lisp_Object Qbar_cursor;
409 int visible_bell; /* If true and the terminal will support it
410 then the frame will flash instead of
411 beeping when an error occurs */
413 /* Nonzero means no need to redraw the entire frame on resuming
414 a suspended Emacs. This is useful on terminals with multiple pages,
415 where one page is used for Emacs and another for all else. */
416 int no_redraw_on_reenter;
418 Lisp_Object Vwindow_system; /* nil or a symbol naming the window system
419 under which emacs is running
420 ('x is the only current possibility) */
421 Lisp_Object Vinitial_window_system;
423 Lisp_Object Vglobal_mode_string;
425 /* The number of lines scroll a window by when point leaves the window; if
426 it is <=0 then point is centered in the window */
429 /* Scroll up to this many lines, to bring point back on screen. */
430 int scroll_conservatively;
432 /* Marker for where to display an arrow on top of the buffer text. */
433 Lisp_Object Voverlay_arrow_position;
434 /* String to display for the arrow. */
435 Lisp_Object Voverlay_arrow_string;
437 Lisp_Object Vwindow_size_change_functions;
438 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
439 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
441 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
443 #ifndef INHIBIT_REDISPLAY_HOOKS
444 /* #### Chuck says: I think this needs more thought.
445 Think about this for 19.14. */
446 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
447 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
448 #endif /* INHIBIT_REDISPLAY_HOOKS */
450 int last_display_warning_tick, display_warning_tick;
451 Lisp_Object Qdisplay_warning_buffer;
452 int inhibit_warning_display;
454 Lisp_Object Vleft_margin_width, Vright_margin_width;
455 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
456 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
457 Lisp_Object Vtext_cursor_visible_p;
459 int column_number_start_at_one;
461 /***************************************************************************/
463 /* low-level interfaces onto device routines */
465 /***************************************************************************/
468 redisplay_text_width_emchar_string (struct window *w, int findex,
469 Emchar *str, Charcount len)
471 unsigned char charsets[NUM_LEADING_BYTES];
474 find_charsets_in_emchar_string (charsets, str, len);
475 XSETWINDOW (window, w);
476 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
478 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))),
479 text_width, (XFRAME (WINDOW_FRAME (w)),
480 WINDOW_FACE_CACHEL (w, findex), str, len));
483 static Emchar_dynarr *rtw_emchar_dynarr;
486 redisplay_text_width_string (struct window *w, int findex,
487 Bufbyte *nonreloc, Lisp_Object reloc,
488 Bytecount offset, Bytecount len)
490 if (!rtw_emchar_dynarr)
491 rtw_emchar_dynarr = Dynarr_new (Emchar);
492 Dynarr_reset (rtw_emchar_dynarr);
494 fixup_internal_substring (nonreloc, reloc, offset, &len);
496 nonreloc = XSTRING_DATA (reloc);
497 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
498 return redisplay_text_width_emchar_string
499 (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
500 Dynarr_length (rtw_emchar_dynarr));
504 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face,
505 Bufbyte *nonreloc, Lisp_Object reloc,
506 Bytecount offset, Bytecount len)
508 unsigned char charsets[NUM_LEADING_BYTES];
510 struct face_cachel cachel;
512 if (!rtw_emchar_dynarr)
513 rtw_emchar_dynarr = Dynarr_new (Emchar);
514 Dynarr_reset (rtw_emchar_dynarr);
516 fixup_internal_substring (nonreloc, reloc, offset, &len);
518 nonreloc = XSTRING_DATA (reloc);
519 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
520 find_charsets_in_bufbyte_string (charsets, nonreloc, len);
521 reset_face_cachel (&cachel);
523 XSETFRAME (frame, f);
524 ensure_face_cachel_complete (&cachel, frame, charsets);
525 return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
526 text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
527 Dynarr_length (rtw_emchar_dynarr)));
530 /* Return the display block from DL of the given TYPE. A display line
531 can have only one display block of each possible type. If DL does
532 not have a block of type TYPE, one will be created and added to DL. */
534 struct display_block *
535 get_display_block_from_line (struct display_line *dl, enum display_type type)
538 struct display_block db;
540 /* Check if this display line already has a block of the desired type and
542 if (dl->display_blocks)
544 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++)
546 if (Dynarr_at (dl->display_blocks, elt).type == type)
547 return Dynarr_atp (dl->display_blocks, elt);
550 /* There isn't an active block of the desired type, but there
551 might still be allocated blocks we need to reuse. */
552 if (elt < Dynarr_largest (dl->display_blocks))
554 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
556 /* 'add' the block to the list */
557 Dynarr_increment (dl->display_blocks);
559 /* initialize and return */
566 /* This line doesn't have any display blocks, so initialize the display
568 dl->display_blocks = Dynarr_new (display_block);
571 /* The line doesn't have a block of the desired type so go ahead and create
572 one and add it to the line. */
575 db.runes = Dynarr_new (rune);
576 Dynarr_add (dl->display_blocks, db);
578 /* Return the newly added display block. */
579 elt = Dynarr_length (dl->display_blocks) - 1;
581 return Dynarr_atp (dl->display_blocks, elt);
585 tab_char_width (struct window *w)
587 struct buffer *b = XBUFFER (w->buffer);
588 int char_tab_width = XINT (b->tab_width);
590 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8;
592 return char_tab_width;
596 space_width (struct window *w)
598 /* While tabs are traditional composed of spaces, for variable-width
599 fonts the space character tends to give too narrow a value. So
600 we use 'n' instead. Except that we don't. We use the default
601 character width for the default face. If this is actually
602 defined by the font then it is probably the best thing to
603 actually use. If it isn't, we have assumed it is 'n' and have
604 already calculated its width. Thus we can avoid a call to
605 XTextWidth on X frames by just querying the default width. */
606 return XFONT_INSTANCE
607 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width;
611 tab_pix_width (struct window *w)
613 return space_width (w) * tab_char_width (w);
616 /* Given a pixel position in a window, return the pixel location of
617 the next tabstop. Tabs are calculated from the left window edge in
618 terms of spaces displayed in the default face. Formerly the space
619 width was determined using the currently active face. That method
620 leads to tabstops which do not line up. */
623 next_tab_position (struct window *w, int start_pixpos, int left_pixpos)
625 int n_pos = left_pixpos;
626 int pix_tab_width = tab_pix_width (w);
628 /* Adjust n_pos for any hscrolling which has happened. */
630 n_pos -= space_width (w) * (w->hscroll - 1);
632 while (n_pos <= start_pixpos)
633 n_pos += pix_tab_width;
638 /* For the given window, calculate the outside and margin boundaries for a
639 display line. The whitespace boundaries must be calculated by the text
643 calculate_display_line_boundaries (struct window *w, int modeline)
645 layout_bounds bounds;
647 /* Set the outermost boundaries which are the boundaries of the
648 window itself minus the gutters (and minus the scrollbars if this
649 is for the modeline). */
652 bounds.left_out = WINDOW_TEXT_LEFT (w);
653 bounds.right_out = WINDOW_TEXT_RIGHT (w);
657 bounds.left_out = WINDOW_MODELINE_LEFT (w);
658 bounds.right_out = WINDOW_MODELINE_RIGHT (w);
661 /* The inner boundaries mark where the glyph margins are located. */
662 bounds.left_in = bounds.left_out + window_left_margin_width (w);
663 bounds.right_in = bounds.right_out - window_right_margin_width (w);
665 /* We cannot fully calculate the whitespace boundaries as they
666 depend on the contents of the line being displayed. */
667 bounds.left_white = bounds.left_in;
668 bounds.right_white = bounds.right_in;
673 /* Given a display line and a starting position, ensure that the
674 contents of the display line accurately represent the visual
675 representation of the buffer contents starting from the given
676 position when displayed in the given window. The display line ends
677 when the contents of the line reach the right boundary of the given
681 generate_display_line (struct window *w, struct display_line *dl, int bounds,
682 Bufpos start_pos, int start_col,
683 prop_block_dynarr **prop, int type)
687 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
689 /* If our caller hasn't already set the boundaries, then do so now. */
691 dl->bounds = calculate_display_line_boundaries (w, 0);
693 /* Reset what this line is using. */
694 if (dl->display_blocks)
695 Dynarr_reset (dl->display_blocks);
698 Dynarr_free (dl->left_glyphs);
701 if (dl->right_glyphs)
703 Dynarr_free (dl->right_glyphs);
704 dl->right_glyphs = 0;
707 /* We aren't generating a modeline at the moment. */
710 /* Create a display block for the text region of the line. */
712 /* #### urk urk urk!!! Chuck fix this shit! */
713 Bytind hacked_up_bytind =
714 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
715 start_col, prop, type);
716 if (hacked_up_bytind > BI_BUF_ZV (b))
717 ret_bufpos = BUF_ZV (b) + 1;
719 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
721 dl->bufpos = start_pos;
722 if (dl->end_bufpos < dl->bufpos)
723 dl->end_bufpos = dl->bufpos;
725 if (MARKERP (Voverlay_arrow_position)
726 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
727 && start_pos == marker_position (Voverlay_arrow_position)
728 && (STRINGP (Voverlay_arrow_string)
729 || GLYPHP (Voverlay_arrow_string)))
731 overlay_width = create_overlay_glyph_block (w, dl);
736 /* If there are left glyphs associated with any character in the
737 text block, then create a display block to handle them. */
738 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
739 create_left_glyph_block (w, dl, overlay_width);
741 /* If there are right glyphs associated with any character in the
742 text block, then create a display block to handle them. */
743 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
744 create_right_glyph_block (w, dl);
746 /* In the future additional types of display blocks may be generated
749 w->last_redisplay_pos = ret_bufpos;
754 /* Adds an hscroll glyph to a display block. If this is called, then
755 the block had better be empty.
757 Yes, there are multiple places where this function is called but
758 that is the way it has to be. Each calling function has to deal
759 with bi_start_col_enabled a little differently depending on the
760 object being worked with. */
762 static prop_block_dynarr *
763 add_hscroll_rune (pos_data *data)
765 struct glyph_block gb;
766 prop_block_dynarr *retval;
767 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
768 unsigned int old_cursor_type = data->cursor_type;
769 Bytind bi_old_bufpos = data->bi_bufpos;
771 if (data->cursor_type == CURSOR_ON
772 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
773 && data->bi_cursor_bufpos <= data->bi_bufpos)
775 data->bi_cursor_bufpos = data->bi_start_col_enabled;
779 data->cursor_type = NO_CURSOR;
782 data->bi_endpos = data->bi_bufpos;
783 data->bi_bufpos = data->bi_start_col_enabled;
786 gb.glyph = Vhscroll_glyph;
788 int oldpixpos = data->pixpos;
789 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
790 GLYPH_CACHEL (XWINDOW (data->window),
791 HSCROLL_GLYPH_INDEX));
792 data->hscroll_glyph_width_adjust =
793 data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
796 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
797 data->cursor_type = old_cursor_type;
798 data->bi_bufpos = bi_old_bufpos;
800 data->bi_start_col_enabled = 0;
804 /* Adds a character rune to a display block. If there is not enough
805 room to fit the rune on the display block (as determined by the
806 MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
808 static prop_block_dynarr *
809 add_emchar_rune (pos_data *data)
811 struct rune rb, *crb;
822 if (data->bi_start_col_enabled)
824 return add_hscroll_rune (data);
827 if (data->ch == '\n')
829 data->font_is_bogus = 0;
830 /* Cheesy end-of-line pseudo-character. */
831 width = data->blank_width;
835 Lisp_Object charset = CHAR_CHARSET (data->ch);
836 if (!EQ (charset, data->last_charset) ||
837 data->findex != data->last_findex)
839 /* OK, we need to do things the hard way. */
840 struct window *w = XWINDOW (data->window);
841 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
842 Lisp_Object font_instance =
843 ensure_face_cachel_contains_charset (cachel, data->window,
845 struct Lisp_Font_Instance *fi;
847 if (EQ (font_instance, Vthe_null_font_instance))
849 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
850 data->font_is_bogus = 1;
853 data->font_is_bogus = 0;
855 fi = XFONT_INSTANCE (font_instance);
856 if (!fi->proportional_p)
857 /* sweetness and light. */
858 data->last_char_width = fi->width;
860 data->last_char_width = -1;
861 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
862 data->new_descent = max (data->new_descent, (int) fi->descent);
863 data->last_charset = charset;
864 data->last_findex = data->findex;
867 width = data->last_char_width;
870 /* bummer. Proportional fonts. */
871 width = redisplay_text_width_emchar_string (XWINDOW (data->window),
877 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
882 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
884 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
893 crb->findex = data->findex;
894 crb->xpos = data->pixpos;
898 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
900 else if (data->is_modeline)
901 crb->bufpos = data->modeline_charpos;
903 /* fuckme if this shouldn't be an abort. */
904 /* abort (); fuckme harder, this abort gets tripped quite often,
905 in propagation and whatnot. #### fixme */
907 crb->type = RUNE_CHAR;
908 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
911 if (data->cursor_type == CURSOR_ON)
913 if (data->bi_bufpos == data->bi_cursor_bufpos)
915 crb->cursor_type = CURSOR_ON;
916 data->cursor_x = Dynarr_length (data->db->runes);
919 crb->cursor_type = CURSOR_OFF;
921 else if (data->cursor_type == NEXT_CURSOR)
923 crb->cursor_type = CURSOR_ON;
924 data->cursor_x = Dynarr_length (data->db->runes);
925 data->cursor_type = NO_CURSOR;
927 else if (data->cursor_type == IGNORE_CURSOR)
928 crb->cursor_type = IGNORE_CURSOR;
930 crb->cursor_type = CURSOR_OFF;
933 Dynarr_add (data->db->runes, *crb);
935 Dynarr_increment (data->db->runes);
937 data->pixpos += width;
942 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
943 for each character in the string. Propagate any left-over data
944 unless NO_PROP is non-zero. */
946 static prop_block_dynarr *
947 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
948 Bytecount c_length, int no_prop)
950 Bufbyte *pos, *end = c_string + c_length;
951 prop_block_dynarr *prop;
953 /* #### This function is too simplistic. It needs to do the same
954 sort of character interpretation (display-table lookup,
955 ctl-arrow checking), etc. that create_text_block() does.
956 The functionality to do this in that routine needs to be
959 for (pos = c_string; pos < end;)
961 data->ch = charptr_emchar (pos);
963 prop = add_emchar_rune (data);
971 struct prop_block pb;
972 Bytecount len = end - pos;
973 prop = Dynarr_new (prop_block);
975 pb.type = PROP_STRING;
976 pb.data.p_string.str = xnew_array (Bufbyte, len);
977 strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
978 pb.data.p_string.len = len;
980 Dynarr_add (prop, pb);
991 /* Add a single rune of the specified width. The area covered by this
992 rune will be displayed in the foreground color of the associated
995 static prop_block_dynarr *
996 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1000 /* If data->start_col is not 0 then this call to add_blank_rune must have
1001 been to add it as a tab. */
1002 if (data->start_col)
1004 /* assert (w != NULL) */
1005 prop_block_dynarr *retval;
1007 /* If we have still not fully scrolled horizontally, subtract
1008 the width of this tab and return. */
1009 if (char_tab_width < data->start_col)
1011 data->start_col -= char_tab_width;
1014 else if (char_tab_width == data->start_col)
1015 data->blank_width = 0;
1018 int spcwid = space_width (w);
1020 if (spcwid >= data->blank_width)
1021 data->blank_width = 0;
1023 data->blank_width -= spcwid;
1026 data->start_col = 0;
1027 retval = add_hscroll_rune (data);
1029 /* Could be caused by the handling of the hscroll rune. */
1030 if (retval != NULL || !data->blank_width)
1034 /* Blank runes are always calculated to fit. */
1035 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1037 rb.findex = data->findex;
1038 rb.xpos = data->pixpos;
1039 rb.width = data->blank_width;
1040 if (data->bi_bufpos)
1042 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1045 /* #### and this is really correct too? */
1048 rb.type = RUNE_BLANK;
1050 if (data->cursor_type == CURSOR_ON)
1052 if (data->bi_bufpos == data->bi_cursor_bufpos)
1054 rb.cursor_type = CURSOR_ON;
1055 data->cursor_x = Dynarr_length (data->db->runes);
1058 rb.cursor_type = CURSOR_OFF;
1060 else if (data->cursor_type == NEXT_CURSOR)
1062 rb.cursor_type = CURSOR_ON;
1063 data->cursor_x = Dynarr_length (data->db->runes);
1064 data->cursor_type = NO_CURSOR;
1067 rb.cursor_type = CURSOR_OFF;
1069 Dynarr_add (data->db->runes, rb);
1070 data->pixpos += data->blank_width;
1075 /* Add runes representing a character in octal. */
1077 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1079 if (add_failed || (add_failed = add_emchar_rune (data))) \
1081 struct prop_block pb; \
1083 prop = Dynarr_new (prop_block); \
1085 pb.type = PROP_CHAR; \
1086 pb.data.p_char.ch = data->ch; \
1087 pb.data.p_char.cursor_type = data->cursor_type; \
1088 Dynarr_add (prop, pb); \
1092 static prop_block_dynarr *
1093 add_octal_runes (pos_data *data)
1095 prop_block_dynarr *prop, *add_failed;
1096 Emchar orig_char = data->ch;
1097 unsigned int orig_cursor_type = data->cursor_type;
1103 if (data->start_col)
1106 if (!data->start_col)
1108 if (data->bi_start_col_enabled)
1110 add_failed = add_hscroll_rune (data);
1114 struct glyph_block gb;
1115 struct window *w = XWINDOW (data->window);
1118 gb.glyph = Voctal_escape_glyph;
1120 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1121 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1125 /* We only propagate information if the glyph was partially
1130 data->cursor_type = IGNORE_CURSOR;
1132 if (data->ch >= 0x100)
1134 /* If the character is an extended Mule character, it could have
1135 up to 19 bits. For the moment, we treat it as a seven-digit
1136 octal number. This is not that pretty, but whatever. */
1137 data->ch = (7 & (orig_char >> 18)) + '0';
1138 ADD_NEXT_OCTAL_RUNE_CHAR;
1140 data->ch = (7 & (orig_char >> 15)) + '0';
1141 ADD_NEXT_OCTAL_RUNE_CHAR;
1143 data->ch = (7 & (orig_char >> 12)) + '0';
1144 ADD_NEXT_OCTAL_RUNE_CHAR;
1146 data->ch = (7 & (orig_char >> 9)) + '0';
1147 ADD_NEXT_OCTAL_RUNE_CHAR;
1150 data->ch = (7 & (orig_char >> 6)) + '0';
1151 ADD_NEXT_OCTAL_RUNE_CHAR;
1153 data->ch = (7 & (orig_char >> 3)) + '0';
1154 ADD_NEXT_OCTAL_RUNE_CHAR;
1156 data->ch = (7 & orig_char) + '0';
1157 ADD_NEXT_OCTAL_RUNE_CHAR;
1159 data->cursor_type = orig_cursor_type;
1163 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1165 /* Add runes representing a control character to a display block. */
1167 static prop_block_dynarr *
1168 add_control_char_runes (pos_data *data, struct buffer *b)
1170 if (!NILP (b->ctl_arrow))
1172 prop_block_dynarr *prop;
1173 Emchar orig_char = data->ch;
1174 unsigned int old_cursor_type = data->cursor_type;
1179 if (data->start_col)
1182 if (!data->start_col)
1184 if (data->bi_start_col_enabled)
1186 prop_block_dynarr *retval;
1188 retval = add_hscroll_rune (data);
1194 struct glyph_block gb;
1195 struct window *w = XWINDOW (data->window);
1198 gb.glyph = Vcontrol_arrow_glyph;
1200 /* We only propagate information if the glyph was partially
1202 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1203 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1208 if (orig_char == 0177)
1211 data->ch = orig_char ^ 0100;
1212 data->cursor_type = IGNORE_CURSOR;
1214 if (add_emchar_rune (data))
1216 struct prop_block pb;
1218 prop = Dynarr_new (prop_block);
1220 pb.type = PROP_CHAR;
1221 pb.data.p_char.ch = data->ch;
1222 pb.data.p_char.cursor_type = data->cursor_type;
1223 Dynarr_add (prop, pb);
1226 data->cursor_type = old_cursor_type;
1231 return add_octal_runes (data);
1235 /* Given a display table entry, call the appropriate functions to
1236 display each element of the entry. */
1238 static prop_block_dynarr *
1239 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1241 prop_block_dynarr *prop = NULL;
1243 if (VECTORP (entry))
1245 struct Lisp_Vector *de = XVECTOR (entry);
1246 long len = vector_length (de);
1249 for (elt = 0; elt < len; elt++)
1251 if (NILP (de->contents[elt]))
1253 else if (STRINGP (de->contents[elt]))
1256 add_bufbyte_string_runes
1258 XSTRING_DATA (de->contents[elt]),
1259 XSTRING_LENGTH (de->contents[elt]),
1262 else if (GLYPHP (de->contents[elt]))
1264 if (data->start_col)
1267 if (!data->start_col && data->bi_start_col_enabled)
1269 prop = add_hscroll_rune (data);
1273 struct glyph_block gb;
1275 gb.glyph = de->contents[elt];
1277 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1280 else if (CHAR_OR_CHAR_INTP (de->contents[elt]))
1282 data->ch = XCHAR_OR_CHAR_INT (de->contents[elt]);
1283 prop = add_emchar_rune (data);
1285 /* Else blow it off because someone added a bad entry and we
1286 don't have any safe way of signaling an error. */
1288 /* #### Still need to add any remaining elements to the
1289 propagation information. */
1294 else if (STRINGP (entry))
1296 prop = add_bufbyte_string_runes (data,
1297 XSTRING_DATA (entry),
1298 XSTRING_LENGTH (entry),
1301 else if (GLYPHP (entry))
1303 if (data->start_col)
1306 if (!data->start_col && data->bi_start_col_enabled)
1308 prop = add_hscroll_rune (data);
1312 struct glyph_block gb;
1316 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1319 else if (CHAR_OR_CHAR_INTP (entry))
1321 data->ch = XCHAR_OR_CHAR_INT (entry);
1322 prop = add_emchar_rune (data);
1325 /* Else blow it off because someone added a bad entry and we don't
1326 have any safe way of signaling an error. Hey, this comment
1331 /* Add runes which were propagated from the previous line. */
1333 static prop_block_dynarr *
1334 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1336 /* #### Remember to handle start_col parameter of data when the rest of
1337 this is finished. */
1338 /* #### Chuck -- I've redone this function a bit. It looked like the
1339 case of not all the propagation blocks being added was not handled
1341 /* #### Chuck -- I also think the double indirection of PROP is kind
1342 of bogus. A cleaner solution is just to check for
1343 Dynarr_length (prop) > 0. */
1344 /* #### This function also doesn't even pay attention to ADD_FAILED!
1345 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1348 prop_block_dynarr *add_failed;
1349 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1350 unsigned int old_cursor_type = data->cursor_type;
1352 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1354 struct prop_block *pb = Dynarr_atp (*prop, elt);
1359 data->ch = pb->data.p_char.ch;
1360 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1361 data->cursor_type = pb->data.p_char.cursor_type;
1362 add_failed = add_emchar_rune (data);
1365 goto oops_no_more_space;
1368 if (pb->data.p_string.str)
1369 xfree (pb->data.p_string.str);
1370 /* #### bogus bogus -- this doesn't do anything!
1371 Should probably call add_bufbyte_string_runes(),
1372 once that function is fixed. */
1374 case PROP_MINIBUF_PROMPT:
1376 face_index old_findex = data->findex;
1377 Bytind bi_old_bufpos = data->bi_bufpos;
1379 data->findex = DEFAULT_INDEX;
1380 data->bi_bufpos = 0;
1381 data->cursor_type = NO_CURSOR;
1383 while (pb->data.p_string.len > 0)
1385 data->ch = charptr_emchar (pb->data.p_string.str);
1386 add_failed = add_emchar_rune (data);
1390 data->findex = old_findex;
1391 data->bi_bufpos = bi_old_bufpos;
1392 goto oops_no_more_space;
1396 /* Complicated equivalent of ptr++, len-- */
1397 Bufbyte *oldpos = pb->data.p_string.str;
1398 INC_CHARPTR (pb->data.p_string.str);
1399 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1403 data->findex = old_findex;
1404 /* ##### FIXME FIXME FIXME -- Upon successful return from
1405 this function, data->bi_bufpos is automatically incremented.
1406 However, we don't want that to happen if we were adding
1407 the minibuffer prompt. */
1409 struct buffer *buf =
1410 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1411 /* #### Chuck fix this shit or I'm gonna scream! */
1412 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1413 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1415 /* #### is this correct? Does anyone know?
1416 Does anyone care? Is this a cheesy hack or what? */
1417 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1423 /* #### I think it's unnecessary and misleading to preserve
1424 the blank_width, as it implies that the value carries
1425 over from one rune to the next, which is wrong. */
1426 int old_width = data->blank_width;
1427 face_index old_findex = data->findex;
1429 data->findex = pb->data.p_blank.findex;
1430 data->blank_width = pb->data.p_blank.width;
1431 data->bi_cursor_bufpos = 0;
1432 data->cursor_type = IGNORE_CURSOR;
1434 if (data->pixpos + data->blank_width > data->max_pixpos)
1435 data->blank_width = data->max_pixpos - data->pixpos;
1437 /* We pass a bogus value of char_tab_width. It shouldn't
1438 matter because unless something is really screwed up
1439 this call won't cause that arg to be used. */
1440 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1442 /* This can happen in the case where we have a tab which
1443 is wider than the window. */
1444 if (data->blank_width != pb->data.p_blank.width)
1446 pb->data.p_blank.width -= data->blank_width;
1447 add_failed = ADD_FAILED;
1450 data->findex = old_findex;
1451 data->blank_width = old_width;
1454 goto oops_no_more_space;
1464 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1465 data->cursor_type = old_cursor_type;
1466 if (elt < Dynarr_length (*prop))
1468 Dynarr_delete_many (*prop, 0, elt);
1473 Dynarr_free (*prop);
1478 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1479 the display block, but add all other types to the appropriate list
1480 of the display line. They will be added later by different
1483 static prop_block_dynarr *
1484 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1485 int allow_cursor, struct glyph_cachel *cachel)
1487 struct window *w = XWINDOW (data->window);
1489 /* A nil extent indicates a special glyph (ex. truncator). */
1490 if (NILP (gb->extent)
1491 || (pos_type == BEGIN_GLYPHS &&
1492 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1493 || (pos_type == END_GLYPHS &&
1494 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
1499 int ascent, descent;
1500 Lisp_Object baseline;
1504 width = cachel->width;
1506 width = glyph_width (gb->glyph, Qnil, data->findex, data->window);
1511 if (data->start_col)
1513 prop_block_dynarr *retval;
1514 int glyph_char_width = width / space_width (w);
1516 /* If we still have not fully scrolled horizontally after
1517 taking into account the width of the glyph, subtract its
1518 width and return. */
1519 if (glyph_char_width < data->start_col)
1521 data->start_col -= glyph_char_width;
1524 else if (glyph_char_width == data->start_col)
1528 xoffset = space_width (w) * data->start_col;
1531 /* #### Can this happen? */
1536 data->start_col = 0;
1537 retval = add_hscroll_rune (data);
1539 /* Could be caused by the handling of the hscroll rune. */
1540 if (retval != NULL || !width)
1546 if (data->pixpos + width > data->max_pixpos)
1548 /* If this is the first object we are attempting to add to
1549 the line then we ignore the horizontal_clip threshold.
1550 Otherwise we will loop until the bottom of the window
1551 continually failing to add this glyph because it is wider
1552 than the window. We could alternatively just completely
1553 ignore the glyph and proceed from there but I think that
1554 this is a better solution. */
1555 if (Dynarr_length (data->db->runes)
1556 && data->max_pixpos - data->pixpos < horizontal_clip)
1559 width = data->max_pixpos - data->pixpos;
1564 ascent = cachel->ascent;
1565 descent = cachel->descent;
1569 ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window);
1570 descent = glyph_descent (gb->glyph, Qnil, data->findex,
1574 baseline = glyph_baseline (gb->glyph, data->window);
1576 if (glyph_contrib_p (gb->glyph, data->window))
1578 /* A pixmap that has not had a baseline explicitly set. Its
1579 contribution will be determined later. */
1580 if (NILP (baseline))
1582 int height = ascent + descent;
1583 data->max_pixmap_height = max (data->max_pixmap_height, height);
1586 /* A string so determine contribution normally. */
1587 else if (EQ (baseline, Qt))
1589 data->new_ascent = max (data->new_ascent, ascent);
1590 data->new_descent = max (data->new_descent, descent);
1593 /* A pixmap with an explicitly set baseline. We determine the
1594 contribution here. */
1595 else if (INTP (baseline))
1597 int height = ascent + descent;
1598 int pix_ascent, pix_descent;
1600 pix_ascent = height * XINT (baseline) / 100;
1601 pix_descent = height - pix_ascent;
1603 data->new_ascent = max (data->new_ascent, pix_ascent);
1604 data->new_descent = max (data->new_descent, pix_descent);
1607 /* Otherwise something is screwed up. */
1612 face = glyph_face (gb->glyph, data->window);
1614 rb.findex = data->findex;
1616 rb.findex = get_builtin_face_cache_index (w, face);
1618 rb.xpos = data->pixpos;
1620 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1621 if (data->bi_endpos)
1622 /* #### is this necessary at all? */
1623 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1627 rb.type = RUNE_DGLYPH;
1628 /* #### Ben sez: this is way bogus if the glyph is a string.
1629 You should not make the output routines have to cope with
1630 this. The string could contain Mule characters, or non-
1631 printable characters, or characters to be passed through
1632 the display table, or non-character objects (when this gets
1633 implemented), etc. Instead, this routine here should parse
1634 the string into a series of runes. */
1635 rb.object.dglyph.glyph = gb->glyph;
1636 rb.object.dglyph.extent = gb->extent;
1637 rb.object.dglyph.xoffset = xoffset;
1641 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1644 if (data->cursor_type == CURSOR_ON)
1646 if (data->bi_bufpos == data->bi_cursor_bufpos)
1648 rb.cursor_type = CURSOR_ON;
1649 data->cursor_x = Dynarr_length (data->db->runes);
1652 rb.cursor_type = CURSOR_OFF;
1654 else if (data->cursor_type == NEXT_CURSOR)
1656 rb.cursor_type = CURSOR_ON;
1657 data->cursor_x = Dynarr_length (data->db->runes);
1658 data->cursor_type = NO_CURSOR;
1660 else if (data->cursor_type == IGNORE_CURSOR)
1661 rb.cursor_type = IGNORE_CURSOR;
1662 else if (data->cursor_type == NO_CURSOR)
1663 rb.cursor_type = NO_CURSOR;
1665 rb.cursor_type = CURSOR_OFF;
1668 rb.cursor_type = CURSOR_OFF;
1670 Dynarr_add (data->db->runes, rb);
1671 data->pixpos += width;
1677 if (!NILP (glyph_face (gb->glyph, data->window)))
1679 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1682 gb->findex = data->findex;
1684 if (pos_type == BEGIN_GLYPHS)
1686 if (!data->dl->left_glyphs)
1687 data->dl->left_glyphs = Dynarr_new (glyph_block);
1688 Dynarr_add (data->dl->left_glyphs, *gb);
1691 else if (pos_type == END_GLYPHS)
1693 if (!data->dl->right_glyphs)
1694 data->dl->right_glyphs = Dynarr_new (glyph_block);
1695 Dynarr_add (data->dl->right_glyphs, *gb);
1699 abort (); /* there are no unknown types */
1702 return NULL; /* shut up compiler */
1705 /* Add all glyphs at position POS_TYPE that are contained in the given
1708 static prop_block_dynarr *
1709 add_glyph_runes (pos_data *data, int pos_type)
1711 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1712 why didn't you just modify add_glyph_rune in the first place? */
1714 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1715 ? data->ef->begin_glyphs
1716 : data->ef->end_glyphs);
1717 prop_block_dynarr *prop;
1719 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1721 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1726 /* #### Add some propagation information. */
1731 Dynarr_reset (glyph_arr);
1736 /* Given a position for a buffer in a window, ensure that the given
1737 display line DL accurately represents the text on a line starting
1738 at the given position.
1740 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1741 You must do appropriate conversion. */
1744 create_text_block (struct window *w, struct display_line *dl,
1745 Bytind bi_start_pos, int start_col,
1746 prop_block_dynarr **prop, int type)
1748 struct frame *f = XFRAME (w->frame);
1749 struct buffer *b = XBUFFER (w->buffer);
1750 struct device *d = XDEVICE (f->device);
1753 struct Lisp_Vector *dt = 0;
1755 /* Don't display anything in the minibuffer if this window is not on
1756 a selected frame. We consider all other windows to be active
1757 minibuffers as it simplifies the coding. */
1758 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1759 (f == device_selected_frame (d)) ||
1760 is_surrogate_for_selected_frame (f));
1762 int truncate_win = window_truncation_on (w);
1763 int end_glyph_width;
1765 /* If the buffer's value of selective_display is an integer then
1766 only lines that start with less than selective_display columns of
1767 space will be displayed. If selective_display is t then all text
1768 after a ^M is invisible. */
1769 int selective = (INTP (b->selective_display)
1770 ? XINT (b->selective_display)
1771 : ((!NILP (b->selective_display) ? -1 : 0)));
1773 /* The variable ctl-arrow allows the user to specify what characters
1774 can actually be displayed and which octal should be used for.
1775 #### This variable should probably have some rethought done to
1778 #### It would also be really nice if you could specify that
1779 the characters come out in hex instead of in octal. Mule
1780 does that by adding a ctl-hexa variable similar to ctl-arrow,
1781 but that's bogus -- we need a more general solution. I
1782 think you need to extend the concept of display tables
1783 into a more general conversion mechanism. Ideally you
1784 could specify a Lisp function that converts characters,
1785 but this violates the Second Golden Rule and besides would
1786 make things way way way way slow. An idea I like is to
1787 be able to specify multiple display tables instead of just
1788 one. Each display table can specify conversions for some
1789 characters and leave others unchanged. The way the
1790 character gets displayed is determined by the first display
1791 table with a binding for that character. This way, you
1792 could call a function `enable-hex-display' that adds a
1793 pre-defined hex display-table (or maybe computes one if
1794 you give weird parameters to the function) and adds it
1795 to the list of display tables for the current buffer.
1797 Unfortunately there are still problems dealing with Mule
1798 characters. For example, maybe I want to specify that
1799 all extended characters (i.e. >= 256) are displayed in hex.
1800 It's not reasonable to create a mapping for all possible
1801 such characters, because there are about 2^19 of them.
1802 One way of dealing with this is to extend the concept
1803 of what a display table is. Currently it's only allowed
1804 to be a 256-entry vector. Instead, it should be something
1807 a) A 256-entry vector, for backward compatibility
1808 b) Some sort of hashtable, mapping characters to values
1809 c) A list that specifies a range of values and the
1810 mapping to provide for those values.
1812 Also, extend the concept of "mapping" to include a
1813 printf-like spec. Then, you could make all extended
1814 characters show up as hex with a display table like
1816 ((256 . 524288) . "%x")
1818 Since more than one display table is possible, you have
1819 great flexibility in mapping ranges of characters.
1821 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1822 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1823 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1826 /* The text display block for this display line. */
1827 struct display_block *db = get_display_block_from_line (dl, TEXT);
1829 /* The first time through the main loop we need to force the glyph
1830 data to be updated. */
1833 /* Apparently the new extent_fragment_update returns an end position
1834 equal to the position passed in if there are no more runs to be
1836 int no_more_frags = 0;
1838 Lisp_Object synch_minibuffers_value =
1839 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1841 dl->used_prop_data = 0;
1845 data.ef = extent_fragment_new (w->buffer, f);
1847 /* These values are used by all of the rune addition routines. We add
1848 them to this structure for ease of passing. */
1850 XSETWINDOW (data.window, w);
1854 data.bi_bufpos = bi_start_pos;
1855 data.pixpos = dl->bounds.left_in;
1856 data.last_charset = Qunbound;
1857 data.last_findex = DEFAULT_INDEX;
1858 data.result_str = Qnil;
1860 /* Set the right boundary adjusting it to take into account any end
1861 glyph. Save the width of the end glyph for later use. */
1862 data.max_pixpos = dl->bounds.right_in;
1864 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1866 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1867 data.max_pixpos -= end_glyph_width;
1869 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1871 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1872 data.cursor_type = CURSOR_ON;
1874 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1875 data.cursor_type = NO_CURSOR;
1876 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1877 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1878 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1879 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1881 data.bi_cursor_bufpos = BI_BUF_PT (b);
1882 data.cursor_type = CURSOR_ON;
1884 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1886 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1887 data.cursor_type = CURSOR_ON;
1890 data.cursor_type = NO_CURSOR;
1893 data.start_col = w->hscroll;
1894 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1895 data.hscroll_glyph_width_adjust = 0;
1897 /* We regenerate the line from the very beginning. */
1898 Dynarr_reset (db->runes);
1900 /* Why is this less than or equal and not just less than? If the
1901 starting position is already equal to the maximum we can't add
1902 anything else, right? Wrong. We might still have a newline to
1903 add. A newline can use the room allocated for an end glyph since
1904 if we add it we know we aren't going to be adding any end
1907 /* #### Chuck -- I think this condition should be while (1).
1908 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1909 and the begin-glyph ends exactly at the end of the window, the
1910 end-glyph and text might not be displayed. while (1) ensures
1911 that the loop terminates only when either (a) there is
1912 propagation data or (b) the end-of-line or end-of-buffer is hit.
1914 #### Also I think you need to ensure that the operation
1915 "add begin glyphs; add end glyphs; add text" is atomic and
1916 can't get interrupted in the middle. If you run off the end
1917 of the line during that operation, then you keep accumulating
1918 propagation data until you're done. Otherwise, if the (e.g.)
1919 there's a begin glyph at a particular position and attempting
1920 to display that glyph results in window-end being hit and
1921 propagation data being generated, then the character at that
1922 position won't be displayed.
1924 #### See also the comment after the end of this loop, below.
1926 while (data.pixpos <= data.max_pixpos
1927 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1929 /* #### This check probably should not be necessary. */
1930 if (data.bi_bufpos > BI_BUF_ZV (b))
1932 /* #### urk! More of this lossage! */
1937 /* If selective display was an integer and we aren't working on
1938 a continuation line then find the next line we are actually
1939 supposed to display. */
1941 && (data.bi_bufpos == BI_BUF_BEGV (b)
1942 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
1944 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
1947 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
1948 if (data.bi_bufpos >= BI_BUF_ZV (b))
1950 data.bi_bufpos = BI_BUF_ZV (b);
1956 /* Check for face changes. */
1957 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
1959 /* Now compute the face and begin/end-glyph information. */
1961 /* Remember that the extent-fragment routines deal in Bytind's. */
1962 extent_fragment_update (w, data.ef, data.bi_bufpos);
1964 if (data.bi_bufpos == data.ef->end)
1967 dt = get_display_table (w, data.findex);
1971 /* Determine what is next to be displayed. We first handle any
1972 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
1973 display then we determine what to do based on the character at the
1974 current buffer position. */
1976 /* If the current position is covered by an invisible extent, do
1977 nothing (except maybe add some ellipses).
1979 #### The behavior of begin and end-glyphs at the edge of an
1980 invisible extent should be investigated further. This is
1981 fairly low priority though. */
1982 if (data.ef->invisible)
1984 /* #### Chuck, perhaps you could look at this code? I don't
1985 really know what I'm doing. */
1988 Dynarr_free (*prop);
1992 /* The extent fragment code only sets this when we should
1993 really display the ellipses. It makes sure the ellipses
1994 don't get displayed more than once in a row. */
1995 if (data.ef->invisible_ellipses)
1997 struct glyph_block gb;
1999 data.ef->invisible_ellipses_already_displayed = 1;
2000 data.ef->invisible_ellipses = 0;
2002 gb.glyph = Vinvisible_text_glyph;
2003 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2004 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2005 /* Perhaps they shouldn't propagate if the very next thing
2006 is to display a newline (for compatibility with
2007 selective-display-ellipses)? Maybe that's too
2013 /* If point is in an invisible region we place it on the
2014 next visible character. */
2015 if (data.cursor_type == CURSOR_ON
2016 && data.bi_bufpos == data.bi_cursor_bufpos)
2018 data.cursor_type = NEXT_CURSOR;
2021 /* #### What if we we're dealing with a display table? */
2025 if (data.bi_bufpos == BI_BUF_ZV (b))
2028 INC_BYTIND (b, data.bi_bufpos);
2031 /* If there is propagation data, then it represents the current
2032 buffer position being displayed. Add them and advance the
2033 position counter. This might also add the minibuffer
2037 dl->used_prop_data = 1;
2038 *prop = add_propagation_runes (prop, &data);
2041 goto done; /* gee, a really narrow window */
2042 else if (data.bi_bufpos == BI_BUF_ZV (b))
2044 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2045 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2046 data.bi_bufpos = BI_BUF_BEGV (b);
2048 INC_BYTIND (b, data.bi_bufpos);
2051 /* If there are end glyphs, add them to the line. These are
2052 the end glyphs for the previous run of text. We add them
2053 here rather than doing them at the end of handling the
2054 previous run so that glyphs at the beginning and end of
2055 a line are handled correctly. */
2056 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2058 *prop = add_glyph_runes (&data, END_GLYPHS);
2063 /* If there are begin glyphs, add them to the line. */
2064 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2066 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2071 /* If at end-of-buffer, we've already processed begin and
2072 end-glyphs at this point and there's no text to process,
2074 else if (data.bi_bufpos == BI_BUF_ZV (b))
2079 /* Get the character at the current buffer position. */
2080 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2082 /* If there is a display table entry for it, hand it off to
2083 add_disp_table_entry_runes and let it worry about it. */
2084 if (dt && !NILP (DISP_CHAR_ENTRY (dt, data.ch)))
2087 add_disp_table_entry_runes (&data,
2088 DISP_CHAR_ENTRY (dt, data.ch));
2094 /* Check if we have hit a newline character. If so, add a marker
2095 to the line and end this loop. */
2096 else if (data.ch == '\n')
2098 /* We aren't going to be adding an end glyph so give its
2099 space back in order to make sure that the cursor can
2101 data.max_pixpos += end_glyph_width;
2104 && (bi_spaces_at_point
2105 (b, next_bytind (b, data.bi_bufpos))
2108 if (!NILP (b->selective_display_ellipses))
2110 struct glyph_block gb;
2113 gb.glyph = Vinvisible_text_glyph;
2114 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2115 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2119 /* Cheesy, cheesy, cheesy. We mark the end of the
2120 line with a special "character rune" whose width
2121 is the EOL cursor width and whose character is
2122 the non-printing character '\n'. */
2123 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2124 *prop = add_emchar_rune (&data);
2127 /* We need to set data.bi_bufpos to the start of the
2128 next visible region in order to make this line
2129 appear to contain all of the invisible area.
2130 Otherwise, the line cache won't work
2132 INC_BYTIND (b, data.bi_bufpos);
2133 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2136 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2137 if (data.bi_bufpos >= BI_BUF_ZV (b))
2139 data.bi_bufpos = BI_BUF_ZV (b);
2143 if (BI_BUF_FETCH_CHAR
2144 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2145 DEC_BYTIND (b, data.bi_bufpos);
2149 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2150 *prop = add_emchar_rune (&data);
2156 /* If the current character is ^M, and selective display is
2157 enabled, then add the invisible-text-glyph if
2158 selective-display-ellipses is set. In any case, this
2160 else if (data.ch == (('M' & 037)) && selective == -1)
2162 Bytind bi_next_bufpos;
2164 /* Find the buffer position at the end of the line. */
2166 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2167 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2169 DEC_BYTIND (b, bi_next_bufpos);
2171 /* If the cursor is somewhere in the elided text make
2172 sure that the cursor gets drawn appropriately. */
2173 if (data.cursor_type == CURSOR_ON
2174 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2175 data.bi_cursor_bufpos < bi_next_bufpos))
2177 data.cursor_type = NEXT_CURSOR;
2180 /* We won't be adding a truncation or continuation glyph
2181 so give up the room allocated for them. */
2182 data.max_pixpos += end_glyph_width;
2184 if (!NILP (b->selective_display_ellipses))
2186 /* We don't propagate anything from the invisible
2187 text glyph if it fails to fit. This is
2189 struct glyph_block gb;
2192 gb.glyph = Vinvisible_text_glyph;
2193 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2194 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2197 /* Set the buffer position to the end of the line. We
2198 need to do this before potentially adding a newline
2199 so that the cursor flag will get set correctly (if
2201 data.bi_bufpos = bi_next_bufpos;
2203 if (NILP (b->selective_display_ellipses)
2204 || data.bi_cursor_bufpos == bi_next_bufpos)
2206 /* We have to at least add a newline character so
2207 that the cursor shows up properly. */
2209 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2210 data.findex = DEFAULT_INDEX;
2212 data.bi_start_col_enabled = 0;
2214 add_emchar_rune (&data);
2217 /* This had better be a newline but doing it this way
2218 we'll see obvious incorrect results if it isn't. No
2219 need to abort here. */
2220 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2225 /* If the current character is considered to be printable, then
2227 else if (data.ch >= printable_min)
2229 *prop = add_emchar_rune (&data);
2234 /* If the current character is a tab, determine the next tab
2235 starting position and add a blank rune which extends from the
2236 current pixel position to that starting position. */
2237 else if (data.ch == '\t')
2239 int tab_start_pixpos = data.pixpos;
2244 if (data.start_col > 1)
2245 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
2248 next_tab_position (w, tab_start_pixpos,
2249 dl->bounds.left_in +
2250 data.hscroll_glyph_width_adjust);
2251 if (next_tab_start > data.max_pixpos)
2253 prop_width = next_tab_start - data.max_pixpos;
2254 next_tab_start = data.max_pixpos;
2256 data.blank_width = next_tab_start - data.pixpos;
2258 (next_tab_start - tab_start_pixpos) / space_width (w);
2260 *prop = add_blank_rune (&data, w, char_tab_width);
2262 /* add_blank_rune is only supposed to be called with
2263 sizes guaranteed to fit in the available space. */
2268 struct prop_block pb;
2269 *prop = Dynarr_new (prop_block);
2271 pb.type = PROP_BLANK;
2272 pb.data.p_blank.width = prop_width;
2273 pb.data.p_blank.findex = data.findex;
2274 Dynarr_add (*prop, pb);
2280 /* If character is a control character, pass it off to
2281 add_control_char_runes.
2283 The is_*() routines have undefined results on
2284 arguments outside of the range [-1, 255]. (This
2285 often bites people who carelessly use `char' instead
2286 of `unsigned char'.)
2288 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2290 *prop = add_control_char_runes (&data, b);
2296 /* If the character is above the ASCII range and we have not
2297 already handled it, then print it as an octal number. */
2298 else if (data.ch >= 0200)
2300 *prop = add_octal_runes (&data);
2306 /* Assume the current character is considered to be printable,
2307 then just add it. */
2310 *prop = add_emchar_rune (&data);
2315 INC_BYTIND (b, data.bi_bufpos);
2321 /* Determine the starting point of the next line if we did not hit the
2322 end of the buffer. */
2323 if (data.bi_bufpos < BI_BUF_ZV (b)
2324 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2326 /* #### This check is not correct. If the line terminated
2327 due to a begin-glyph or end-glyph hitting window-end, then
2328 data.ch will not point to the character at data.bi_bufpos. If
2329 you make the two changes mentioned at the top of this loop,
2330 you should be able to say '(if (*prop))'. That should also
2331 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2334 /* The common case is that the line ended because we hit a newline.
2335 In that case, the next character is just the next buffer
2337 if (data.ch == '\n')
2339 /* If data.start_col_enabled is still true, then the window is
2340 scrolled far enough so that nothing on this line is visible.
2341 We need to stick a trunctation glyph at the beginning of the
2342 line in that case unless the line is completely blank. */
2343 if (data.bi_start_col_enabled)
2345 if (data.cursor_type == CURSOR_ON)
2347 if (data.bi_cursor_bufpos >= bi_start_pos
2348 && data.bi_cursor_bufpos <= data.bi_bufpos)
2349 data.bi_cursor_bufpos = data.bi_bufpos;
2351 data.findex = DEFAULT_INDEX;
2353 data.bi_start_col_enabled = 0;
2355 if (data.bi_bufpos != bi_start_pos)
2357 struct glyph_block gb;
2360 gb.glyph = Vhscroll_glyph;
2361 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2362 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2366 /* This duplicates code down below to add a newline to
2367 the end of an otherwise empty line.*/
2369 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2371 add_emchar_rune (&data);
2375 INC_BYTIND (b, data.bi_bufpos);
2378 /* Otherwise we have a buffer line which cannot fit on one display
2382 struct glyph_block gb;
2383 struct glyph_cachel *cachel;
2385 /* If the line is to be truncated then we actually have to look
2386 for the next newline. We also add the end-of-line glyph which
2387 we know will fit because we adjusted the right border before
2388 we starting laying out the line. */
2389 data.max_pixpos += end_glyph_width;
2390 data.findex = DEFAULT_INDEX;
2397 /* Now find the start of the next line. */
2398 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2400 /* If the cursor is past the truncation line then we
2401 make it appear on the truncation glyph. If we've hit
2402 the end of the buffer then we also make the cursor
2403 appear unless eob is immediately preceded by a
2404 newline. In that case the cursor should actually
2405 appear on the next line. */
2406 if (data.cursor_type == CURSOR_ON
2407 && data.bi_cursor_bufpos >= data.bi_bufpos
2408 && (data.bi_cursor_bufpos < bi_pos ||
2409 (bi_pos == BI_BUF_ZV (b)
2410 && (bi_pos == BI_BUF_BEGV (b)
2411 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2413 data.bi_cursor_bufpos = bi_pos;
2415 data.cursor_type = NO_CURSOR;
2417 data.bi_bufpos = bi_pos;
2418 gb.glyph = Vtruncation_glyph;
2419 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2423 /* The cursor can never be on the continuation glyph. */
2424 data.cursor_type = NO_CURSOR;
2426 /* data.bi_bufpos is already at the start of the next line. */
2428 gb.glyph = Vcontinuation_glyph;
2429 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2432 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
2434 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2435 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2436 /* #### Damn this losing shit. */
2440 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2441 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2443 /* We need to add a marker to the end of the line since there is no
2444 newline character in order for the cursor to get drawn. We label
2445 it as a newline so that it gets handled correctly by the
2446 whitespace routines below. */
2449 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2450 data.findex = DEFAULT_INDEX;
2452 data.bi_start_col_enabled = 0;
2454 data.max_pixpos += data.blank_width;
2455 add_emchar_rune (&data);
2456 data.max_pixpos -= data.blank_width;
2458 /* #### urk! Chuck, this shit is bad news. Going around
2459 manipulating invalid positions is guaranteed to result in
2460 trouble sooner or later. */
2461 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2464 /* Calculate left whitespace boundary. */
2468 /* Whitespace past a newline is considered right whitespace. */
2469 while (elt < Dynarr_length (db->runes))
2471 struct rune *rb = Dynarr_atp (db->runes, elt);
2473 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2474 || rb->type == RUNE_BLANK)
2476 dl->bounds.left_white += rb->width;
2480 elt = Dynarr_length (db->runes);
2484 /* Calculate right whitespace boundary. */
2486 int elt = Dynarr_length (db->runes) - 1;
2489 while (!done && elt >= 0)
2491 struct rune *rb = Dynarr_atp (db->runes, elt);
2493 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2494 && isspace (rb->object.chr.ch))
2495 && !rb->type == RUNE_BLANK)
2497 dl->bounds.right_white = rb->xpos + rb->width;
2505 /* The line is blank so everything is considered to be right
2508 dl->bounds.right_white = dl->bounds.left_in;
2511 /* Set the display blocks bounds. */
2512 db->start_pos = dl->bounds.left_in;
2513 if (Dynarr_length (db->runes))
2515 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2517 db->end_pos = rb->xpos + rb->width;
2520 db->end_pos = dl->bounds.right_white;
2522 /* update line height parameters */
2523 if (!data.new_ascent && !data.new_descent)
2525 /* We've got a blank line so initialize these values from the default
2527 default_face_font_info (data.window, &data.new_ascent,
2528 &data.new_descent, 0, 0, 0);
2531 if (data.max_pixmap_height)
2533 int height = data.new_ascent + data.new_descent;
2534 int pix_ascent, pix_descent;
2536 pix_descent = data.max_pixmap_height * data.new_descent / height;
2537 pix_ascent = data.max_pixmap_height - pix_descent;
2539 data.new_ascent = max (data.new_ascent, pix_ascent);
2540 data.new_descent = max (data.new_descent, pix_descent);
2543 dl->ascent = data.new_ascent;
2544 dl->descent = data.new_descent;
2547 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2549 if (dl->ascent < ascent)
2550 dl->ascent = ascent;
2553 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2555 if (dl->descent < descent)
2556 dl->descent = descent;
2559 dl->cursor_elt = data.cursor_x;
2560 /* #### lossage lossage lossage! Fix this shit! */
2561 if (data.bi_bufpos > BI_BUF_ZV (b))
2562 dl->end_bufpos = BUF_ZV (b);
2564 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2566 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2568 /* This doesn't correctly take into account tabs and control
2569 characters but if the window isn't being truncated then this
2570 value isn't going to end up being used anyhow. */
2571 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2573 /* #### handle horizontally scrolled line with text none of which
2574 was actually laid out. */
2576 /* #### handle any remainder of overlay arrow */
2578 if (*prop == ADD_FAILED)
2581 if (truncate_win && *prop)
2583 Dynarr_free (*prop);
2587 extent_fragment_delete (data.ef);
2589 /* #### If we started at EOB, then make sure we return a value past
2590 it so that regenerate_window will exit properly. This is bogus.
2591 The main loop should get fixed so that it isn't necessary to call
2592 this function if we are already at EOB. */
2594 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2595 return data.bi_bufpos + 1; /* Yuck! */
2597 return data.bi_bufpos;
2600 /* Display the overlay arrow at the beginning of the given line. */
2603 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2605 struct frame *f = XFRAME (w->frame);
2606 struct device *d = XDEVICE (f->device);
2609 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2610 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2616 XSETWINDOW (data.window, w);
2617 data.db = get_display_block_from_line (dl, OVERWRITE);
2619 data.pixpos = dl->bounds.left_in;
2620 data.max_pixpos = dl->bounds.right_in;
2621 data.cursor_type = NO_CURSOR;
2623 data.findex = DEFAULT_INDEX;
2624 data.last_charset = Qunbound;
2625 data.last_findex = DEFAULT_INDEX;
2626 data.result_str = Qnil;
2628 Dynarr_reset (data.db->runes);
2630 if (STRINGP (Voverlay_arrow_string))
2632 add_bufbyte_string_runes
2634 XSTRING_DATA (Voverlay_arrow_string),
2635 XSTRING_LENGTH (Voverlay_arrow_string),
2638 else if (GLYPHP (Voverlay_arrow_string))
2640 struct glyph_block gb;
2642 gb.glyph = Voverlay_arrow_string;
2644 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2647 if (data.max_pixmap_height)
2649 int height = data.new_ascent + data.new_descent;
2650 int pix_ascent, pix_descent;
2652 pix_descent = data.max_pixmap_height * data.new_descent / height;
2653 pix_ascent = data.max_pixmap_height - pix_descent;
2655 data.new_ascent = max (data.new_ascent, pix_ascent);
2656 data.new_descent = max (data.new_descent, pix_descent);
2659 dl->ascent = data.new_ascent;
2660 dl->descent = data.new_descent;
2662 data.db->start_pos = dl->bounds.left_in;
2663 data.db->end_pos = data.pixpos;
2665 return data.pixpos - dl->bounds.left_in;
2668 /* Add a type of glyph to a margin display block. */
2671 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2672 int count, enum glyph_layout layout, int side, Lisp_Object window)
2674 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2676 : dl->right_glyphs);
2681 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2682 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2685 elt = Dynarr_length (gbd) - 1;
2692 end = Dynarr_length (gbd);
2695 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2697 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2699 if (NILP (gb->extent))
2700 abort (); /* these should have been handled in add_glyph_rune */
2703 ((side == LEFT_GLYPHS &&
2704 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2705 || (side == RIGHT_GLYPHS &&
2706 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2710 rb.width = gb->width;
2711 rb.findex = gb->findex;
2715 rb.type = RUNE_DGLYPH;
2716 rb.object.dglyph.glyph = gb->glyph;
2717 rb.object.dglyph.extent = gb->extent;
2718 rb.object.dglyph.xoffset = 0;
2719 rb.cursor_type = CURSOR_OFF;
2721 Dynarr_add (db->runes, rb);
2726 if (glyph_contrib_p (gb->glyph, window))
2728 unsigned short ascent, descent;
2729 Lisp_Object baseline = glyph_baseline (gb->glyph, window);
2731 ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window);
2732 descent = glyph_descent (gb->glyph, Qnil, gb->findex, window);
2734 /* A pixmap that has not had a baseline explicitly set.
2735 We use the existing ascent / descent ratio of the
2737 if (NILP (baseline))
2739 int gheight = ascent + descent;
2740 int line_height = dl->ascent + dl->descent;
2741 int pix_ascent, pix_descent;
2743 pix_descent = (int) (gheight * dl->descent) / line_height;
2744 pix_ascent = gheight - pix_descent;
2746 dl->ascent = max ((int) dl->ascent, pix_ascent);
2747 dl->descent = max ((int) dl->descent, pix_descent);
2750 /* A string so determine contribution normally. */
2751 else if (EQ (baseline, Qt))
2753 dl->ascent = max (dl->ascent, ascent);
2754 dl->descent = max (dl->descent, descent);
2757 /* A pixmap with an explicitly set baseline. We determine the
2758 contribution here. */
2759 else if (INTP (baseline))
2761 int height = ascent + descent;
2762 int pix_ascent, pix_descent;
2764 pix_ascent = height * XINT (baseline) / 100;
2765 pix_descent = height - pix_ascent;
2767 dl->ascent = max ((int) dl->ascent, pix_ascent);
2768 dl->descent = max ((int) dl->descent, pix_descent);
2771 /* Otherwise something is screwed up. */
2777 (reverse ? elt-- : elt++);
2783 /* Add a blank to a margin display block. */
2786 add_margin_blank (struct display_line *dl, struct display_block *db,
2787 struct window *w, int xpos, int width, int side)
2791 rb.findex = (side == LEFT_GLYPHS
2792 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2793 : get_builtin_face_cache_index (w, Vright_margin_face));
2798 rb.type = RUNE_BLANK;
2799 rb.cursor_type = CURSOR_OFF;
2801 Dynarr_add (db->runes, rb);
2804 /* Display glyphs in the left outside margin, left inside margin and
2805 left whitespace area. */
2808 create_left_glyph_block (struct window *w, struct display_line *dl,
2813 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2815 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2816 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2817 int left_in_start = dl->bounds.left_in;
2818 int left_in_end = dl->bounds.left_in + overlay_width;
2820 struct display_block *odb, *idb;
2822 XSETWINDOW (window, w);
2824 /* We have to add the glyphs to the line in the order outside,
2825 inside, whitespace. However the precedence dictates that we
2826 determine how many will fit in the reverse order. */
2828 /* Determine how many whitespace glyphs we can display and where
2829 they should start. */
2830 white_in_start = dl->bounds.left_white;
2831 white_out_start = left_in_start;
2832 white_out_cnt = white_in_cnt = 0;
2835 while (elt < Dynarr_length (dl->left_glyphs))
2837 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2839 if (NILP (gb->extent))
2840 abort (); /* these should have been handled in add_glyph_rune */
2842 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2846 width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2848 if (white_in_start - width >= left_in_end)
2851 white_in_start -= width;
2855 else if (use_overflow
2856 && (white_out_start - width > dl->bounds.left_out))
2859 white_out_start -= width;
2870 /* Determine how many inside margin glyphs we can display and where
2871 they should start. The inside margin glyphs get whatever space
2872 is left after the whitespace glyphs have been displayed. These
2873 are tricky to calculate since if we decide to use the overflow
2874 area we basicaly have to start over. So for these we build up a
2875 list of just the inside margin glyphs and manipulate it to
2876 determine the needed info. */
2878 glyph_block_dynarr *ib;
2879 int avail_in, avail_out;
2882 int used_in, used_out;
2885 used_in = used_out = 0;
2886 ib = Dynarr_new (glyph_block);
2887 while (elt < Dynarr_length (dl->left_glyphs))
2889 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2891 if (NILP (gb->extent))
2892 abort (); /* these should have been handled in add_glyph_rune */
2894 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2897 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2898 used_in += gb->width;
2899 Dynarr_add (ib, *gb);
2909 avail_in = white_in_start - left_in_end;
2917 avail_out = white_out_start - dl->bounds.left_out;
2920 while (!done && marker < Dynarr_length (ib))
2922 int width = Dynarr_atp (ib, marker)->width;
2924 /* If everything now fits in the available inside margin
2925 space, we're done. */
2926 if (used_in <= avail_in)
2930 /* Otherwise see if we have room to move a glyph to the
2932 if (used_out + width <= avail_out)
2945 /* At this point we now know that everything from marker on goes in
2946 the inside margin and everything before it goes in the outside
2947 margin. The stuff going into the outside margin is guaranteed
2948 to fit, but we may have to trim some stuff from the inside. */
2950 in_in_end = left_in_end;
2951 in_out_start = white_out_start;
2952 in_out_cnt = in_in_cnt = 0;
2956 while (elt < Dynarr_length (dl->left_glyphs))
2958 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2960 if (NILP (gb->extent))
2961 abort (); /* these should have been handled in add_glyph_rune */
2963 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2966 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2971 in_out_start -= width;
2976 else if (in_in_end + width < white_in_start)
2991 /* Determine how many outside margin glyphs we can display. They
2992 always start at the left outside margin and can only use the
2993 outside margin space. */
2994 out_end = dl->bounds.left_out;
2998 while (elt < Dynarr_length (dl->left_glyphs))
3000 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3002 if (NILP (gb->extent))
3003 abort (); /* these should have beeb handled in add_glyph_rune */
3005 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3008 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3010 if (out_end + width <= in_out_start)
3024 /* Now that we know where everything goes, we add the glyphs as
3025 runes to the appropriate display blocks. */
3026 if (out_cnt || in_out_cnt || white_out_cnt)
3028 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3029 odb->start_pos = dl->bounds.left_out;
3030 /* #### We should stop adding a blank to account for the space
3031 between the end of the glyphs and the margin and instead set
3032 this accordingly. */
3033 odb->end_pos = dl->bounds.left_in;
3034 Dynarr_reset (odb->runes);
3039 if (in_in_cnt || white_in_cnt)
3041 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3042 idb->start_pos = dl->bounds.left_in;
3043 /* #### See above comment for odb->end_pos */
3044 idb->end_pos = dl->bounds.left_white;
3045 Dynarr_reset (idb->runes);
3050 /* First add the outside margin glyphs. */
3052 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3053 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3055 end_xpos = dl->bounds.left_out;
3057 /* There may be blank space between the outside margin glyphs and
3058 the inside margin glyphs. If so, add a blank. */
3059 if (in_out_cnt && (in_out_start - end_xpos))
3061 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3065 /* Next add the inside margin glyphs which are actually in the
3069 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3070 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3073 /* If we didn't add any inside margin glyphs to the outside margin,
3074 but are adding whitespace glyphs, then we need to add a blank
3076 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3078 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3082 /* Next add the whitespace margin glyphs which are actually in the
3086 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3087 GL_WHITESPACE, LEFT_GLYPHS, window);
3090 /* We take care of clearing between the end of the glyphs and the
3091 start of the inside margin for lines which have glyphs. */
3092 if (odb && (left_in_start - end_xpos))
3094 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3098 /* Next add the inside margin glyphs which are actually in the
3102 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3103 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3106 end_xpos = left_in_end;
3108 /* Make sure that the area between the end of the inside margin
3109 glyphs and the whitespace glyphs is cleared. */
3110 if (idb && (white_in_start - end_xpos > 0))
3112 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3116 /* Next add the whitespace margin glyphs which are actually in the
3120 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3121 LEFT_GLYPHS, window);
3124 /* Whitespace glyphs always end right next to the text block so
3125 there is nothing we have to make sure is cleared after them. */
3128 /* Display glyphs in the right outside margin, right inside margin and
3129 right whitespace area. */
3132 create_right_glyph_block (struct window *w, struct display_line *dl)
3136 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3138 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3139 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3141 struct display_block *odb, *idb;
3143 XSETWINDOW (window, w);
3145 /* We have to add the glyphs to the line in the order outside,
3146 inside, whitespace. However the precedence dictates that we
3147 determine how many will fit in the reverse order. */
3149 /* Determine how many whitespace glyphs we can display and where
3150 they should start. */
3151 white_in_end = dl->bounds.right_white;
3152 white_out_end = dl->bounds.right_in;
3153 white_out_cnt = white_in_cnt = 0;
3156 while (elt < Dynarr_length (dl->right_glyphs))
3158 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3160 if (NILP (gb->extent))
3161 abort (); /* these should have been handled in add_glyph_rune */
3163 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3165 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3167 if (white_in_end + width <= dl->bounds.right_in)
3170 white_in_end += width;
3174 else if (use_overflow
3175 && (white_out_end + width <= dl->bounds.right_out))
3178 white_out_end += width;
3189 /* Determine how many inside margin glyphs we can display and where
3190 they should start. The inside margin glyphs get whatever space
3191 is left after the whitespace glyphs have been displayed. These
3192 are tricky to calculate since if we decide to use the overflow
3193 area we basicaly have to start over. So for these we build up a
3194 list of just the inside margin glyphs and manipulate it to
3195 determine the needed info. */
3197 glyph_block_dynarr *ib;
3198 int avail_in, avail_out;
3201 int used_in, used_out;
3204 used_in = used_out = 0;
3205 ib = Dynarr_new (glyph_block);
3206 while (elt < Dynarr_length (dl->right_glyphs))
3208 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3210 if (NILP (gb->extent))
3211 abort (); /* these should have been handled in add_glyph_rune */
3213 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3215 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3216 used_in += gb->width;
3217 Dynarr_add (ib, *gb);
3226 avail_in = dl->bounds.right_in - white_in_end;
3231 avail_out = dl->bounds.right_out - white_out_end;
3234 while (!done && marker < Dynarr_length (ib))
3236 int width = Dynarr_atp (ib, marker)->width;
3238 /* If everything now fits in the available inside margin
3239 space, we're done. */
3240 if (used_in <= avail_in)
3244 /* Otherwise see if we have room to move a glyph to the
3246 if (used_out + width <= avail_out)
3259 /* At this point we now know that everything from marker on goes in
3260 the inside margin and everything before it goes in the outside
3261 margin. The stuff going into the outside margin is guaranteed
3262 to fit, but we may have to trim some stuff from the inside. */
3264 in_in_start = dl->bounds.right_in;
3265 in_out_end = dl->bounds.right_in;
3266 in_out_cnt = in_in_cnt = 0;
3270 while (elt < Dynarr_length (dl->right_glyphs))
3272 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3274 if (NILP (gb->extent))
3275 abort (); /* these should have been handled in add_glyph_rune */
3277 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3279 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3284 in_out_end += width;
3289 else if (in_in_start - width >= white_in_end)
3292 in_in_start -= width;
3304 /* Determine how many outside margin glyphs we can display. They
3305 always start at the right outside margin and can only use the
3306 outside margin space. */
3307 out_start = dl->bounds.right_out;
3311 while (elt < Dynarr_length (dl->right_glyphs))
3313 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3315 if (NILP (gb->extent))
3316 abort (); /* these should have beeb handled in add_glyph_rune */
3318 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3320 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3322 if (out_start - width >= in_out_end)
3336 /* Now that we now where everything goes, we add the glyphs as runes
3337 to the appropriate display blocks. */
3338 if (out_cnt || in_out_cnt || white_out_cnt)
3340 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3341 /* #### See comments before odb->start_pos init in
3342 create_left_glyph_block */
3343 odb->start_pos = dl->bounds.right_in;
3344 odb->end_pos = dl->bounds.right_out;
3345 Dynarr_reset (odb->runes);
3350 if (in_in_cnt || white_in_cnt)
3352 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3353 idb->start_pos = dl->bounds.right_white;
3354 /* #### See comments before odb->start_pos init in
3355 create_left_glyph_block */
3356 idb->end_pos = dl->bounds.right_in;
3357 Dynarr_reset (idb->runes);
3362 /* First add the whitespace margin glyphs which are actually in the
3366 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3367 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3371 end_xpos = dl->bounds.right_white;
3373 /* Make sure that the area between the end of the whitespace glyphs
3374 and the inside margin glyphs is cleared. */
3375 if (in_in_cnt && (in_in_start - end_xpos))
3377 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3381 /* Next add the inside margin glyphs which are actually in the
3385 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3386 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3389 /* If we didn't add any inside margin glyphs then make sure the rest
3390 of the inside margin area gets cleared. */
3391 if (idb && (dl->bounds.right_in - end_xpos))
3393 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3397 /* Next add any whitespace glyphs in the outside margin. */
3400 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3401 GL_WHITESPACE, RIGHT_GLYPHS, window);
3404 end_xpos = dl->bounds.right_in;
3406 /* Next add any inside margin glyphs in the outside margin. */
3409 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3410 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3413 /* There may be space between any whitespace or inside margin glyphs
3414 in the outside margin and the actual outside margin glyphs. */
3415 if (odb && (out_start - end_xpos))
3417 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3421 /* Finally, add the outside margin glyphs. */
3424 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3425 RIGHT_GLYPHS, window);
3430 /***************************************************************************/
3432 /* modeline routines */
3434 /***************************************************************************/
3436 /* Ensure that the given display line DL accurately represents the
3437 modeline for the given window. */
3440 generate_modeline (struct window *w, struct display_line *dl, int type)
3442 struct buffer *b = XBUFFER (w->buffer);
3443 struct frame *f = XFRAME (w->frame);
3444 struct device *d = XDEVICE (f->device);
3446 /* Unlike display line and rune pointers, this one can't change underneath
3448 struct display_block *db = get_display_block_from_line (dl, TEXT);
3449 int max_pixpos, min_pixpos, ypos_adj;
3450 Lisp_Object font_inst;
3452 /* This will actually determine incorrect inside boundaries for the
3453 modeline since it ignores the margins. However being aware of this fact
3454 we never use those values anywhere so it doesn't matter. */
3455 dl->bounds = calculate_display_line_boundaries (w, 1);
3457 /* We are generating a modeline. */
3459 dl->cursor_elt = -1;
3461 /* Reset the runes on the modeline. */
3462 Dynarr_reset (db->runes);
3464 if (!WINDOW_HAS_MODELINE_P (w))
3468 /* If there is a horizontal scrollbar, don't add anything. */
3469 if (window_scrollbar_height (w))
3472 dl->ascent = DEVMETH (d, divider_height, ());
3474 /* The modeline is at the bottom of the gutters. */
3475 dl->ypos = WINDOW_BOTTOM (w);
3477 rb.findex = MODELINE_INDEX;
3478 rb.xpos = dl->bounds.left_out;
3479 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3482 rb.type = RUNE_HLINE;
3483 rb.object.hline.thickness = 1;
3484 rb.object.hline.yoffset = 0;
3485 rb.cursor_type = NO_CURSOR;
3487 if (!EQ (Qzero, w->modeline_shadow_thickness)
3490 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3492 dl->ypos -= shadow_thickness;
3493 rb.xpos += shadow_thickness;
3494 rb.width -= 2 * shadow_thickness;
3497 Dynarr_add (db->runes, rb);
3501 /* !!#### not right; needs to compute the max height of
3503 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3505 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3506 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3508 min_pixpos = dl->bounds.left_out;
3509 max_pixpos = dl->bounds.right_out;
3511 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3513 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3515 ypos_adj = shadow_thickness;
3516 min_pixpos += shadow_thickness;
3517 max_pixpos -= shadow_thickness;
3522 generate_formatted_string_db (b->modeline_format,
3523 b->generated_modeline_string, w, dl, db,
3524 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3526 /* The modeline is at the bottom of the gutters. We have to wait to
3527 set this until we've generated teh modeline in order to account
3528 for any embedded faces. */
3529 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3533 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3534 struct window *w, struct display_line *dl,
3535 struct display_block *db, face_index findex,
3536 int min_pixpos, int max_pixpos, int type)
3538 struct frame *f = XFRAME (w->frame);
3539 struct device *d = XDEVICE (f->device);
3548 data.findex = findex;
3549 data.pixpos = min_pixpos;
3550 data.max_pixpos = max_pixpos;
3551 data.cursor_type = NO_CURSOR;
3552 data.last_charset = Qunbound;
3553 data.last_findex = DEFAULT_INDEX;
3554 data.result_str = result_str;
3555 data.is_modeline = 1;
3556 XSETWINDOW (data.window, w);
3558 Dynarr_reset (formatted_string_extent_dynarr);
3559 Dynarr_reset (formatted_string_extent_start_dynarr);
3560 Dynarr_reset (formatted_string_extent_end_dynarr);
3562 /* This recursively builds up the modeline. */
3563 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3564 max_pixpos - min_pixpos, findex, type);
3566 if (Dynarr_length (db->runes))
3569 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3570 c_pixpos = rb->xpos + rb->width;
3573 c_pixpos = min_pixpos;
3575 /* If we don't reach the right side of the window, add a blank rune
3576 to make up the difference. This usually only occurs if the
3577 modeline face is using a proportional width font or a fixed width
3578 font of a different size from the default face font. */
3580 if (c_pixpos < max_pixpos)
3582 data.pixpos = c_pixpos;
3583 data.blank_width = max_pixpos - data.pixpos;
3585 add_blank_rune (&data, NULL, 0);
3588 /* Now create the result string and frob the extents into it. */
3589 if (!NILP (result_str))
3594 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3596 detach_all_extents (result_str);
3597 resize_string (XSTRING (result_str), -1,
3598 data.bytepos - XSTRING_LENGTH (result_str));
3600 strdata = XSTRING_DATA (result_str);
3602 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3604 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3606 len += (set_charptr_emchar
3607 (strdata + len, Dynarr_atp (db->runes,
3608 elt)->object.chr.ch));
3612 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3615 Lisp_Object extent = Qnil;
3618 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3619 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3622 child = Fmake_extent (Qnil, Qnil, result_str);
3623 Fputhash (extent, child, buf->modeline_extent_table);
3625 Fset_extent_parent (child, extent);
3626 set_extent_endpoints
3628 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3629 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3636 add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
3637 Charcount pos, Charcount min_pos, Charcount max_pos)
3639 /* This function has been Mule-ized. */
3641 CONST Bufbyte *cur_pos = str;
3642 struct display_block *db = data->db;
3644 data->blank_width = space_width (XWINDOW (data->window));
3645 while (Dynarr_length (db->runes) < pos)
3646 add_blank_rune (data, NULL, 0);
3648 end = (Dynarr_length (db->runes) +
3649 bytecount_to_charcount (str, strlen ((CONST char *) str)));
3651 end = min (max_pos, end);
3653 while (pos < end && *cur_pos)
3655 CONST Bufbyte *old_cur_pos = cur_pos;
3658 data->ch = charptr_emchar (cur_pos);
3659 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3660 INC_CHARPTR (cur_pos);
3664 data->modeline_charpos++;
3665 data->bytepos += cur_pos - old_cur_pos;
3669 while (Dynarr_length (db->runes) < min_pos &&
3670 (data->pixpos + data->blank_width <= data->max_pixpos))
3671 add_blank_rune (data, NULL, 0);
3673 return Dynarr_length (db->runes);
3676 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3677 modeline extents. */
3679 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3680 Charcount pos, Charcount min_pos, Charcount max_pos)
3682 /* This function has been Mule-ized. */
3684 struct display_block *db = data->db;
3685 struct glyph_block gb;
3687 data->blank_width = space_width (XWINDOW (data->window));
3688 while (Dynarr_length (db->runes) < pos)
3689 add_blank_rune (data, NULL, 0);
3691 end = Dynarr_length (db->runes) + 1;
3693 end = min (max_pos, end);
3697 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3700 while (Dynarr_length (db->runes) < pos &&
3701 (data->pixpos + data->blank_width <= data->max_pixpos))
3702 add_blank_rune (data, NULL, 0);
3704 return Dynarr_length (db->runes);
3707 /* If max_pos is == -1, it is considered to be infinite. The same is
3708 true of max_pixsize. */
3709 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3710 if (Dynarr_length (data->db->runes)) \
3711 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3715 /* Note that this function does "positions" in terms of characters and
3716 not in terms of columns. This is necessary to make the formatting
3717 work correctly when proportional width fonts are used in the
3720 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3721 Charcount min_pos, Charcount max_pos,
3722 Lisp_Object elt, int depth, int max_pixsize,
3723 face_index findex, int type)
3725 /* This function has been Mule-ized. */
3726 /* #### The other losing things in this function are:
3728 -- C zero-terminated-string lossage.
3729 -- Non-printable characters should be converted into something
3730 appropriate (e.g. ^F) instead of blindly being printed anyway.
3741 /* A string. Add to the display line and check for %-constructs
3744 Bufbyte *this = XSTRING_DATA (elt);
3746 while ((pos < max_pos || max_pos == -1) && *this)
3748 Bufbyte *last = this;
3750 while (*this && *this != '%')
3755 /* The string is just a string. */
3757 bytecount_to_charcount (last, this - last) + pos;
3758 Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos));
3760 pos = add_string_to_fstring_db_runes (data, last, pos, pos,
3763 else /* *this == '%' */
3765 Charcount spec_width = 0;
3767 this++; /* skip over '%' */
3769 /* We can't allow -ve args due to the "%-" construct.
3770 * Argument specifies minwidth but not maxwidth
3771 * (maxwidth can be specified by
3772 * (<negative-number> . <stuff>) modeline elements)
3774 while (isdigit (*this))
3776 spec_width = spec_width * 10 + (*this - '0');
3783 pos = generate_fstring_runes (w, data, pos, spec_width,
3784 max_pos, Vglobal_mode_string,
3785 depth, max_pixsize, findex,
3788 else if (*this == '-')
3790 Charcount num_to_add;
3792 if (max_pixsize < 0)
3794 else if (max_pos != -1)
3795 num_to_add = max_pos - pos;
3801 SET_CURRENT_MODE_CHARS_PIXSIZE;
3804 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3807 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3811 while (num_to_add--)
3812 pos = add_string_to_fstring_db_runes
3813 (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
3815 else if (*this != 0)
3818 Emchar ch = charptr_emchar (this);
3819 decode_mode_spec (w, ch, type);
3821 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3822 pos = add_string_to_fstring_db_runes (data,str, pos, pos,
3826 /* NOT this++. There could be any sort of character at
3827 the current position. */
3831 if (max_pixsize > 0)
3834 SET_CURRENT_MODE_CHARS_PIXSIZE;
3836 if (cur_pixsize >= max_pixsize)
3841 else if (SYMBOLP (elt))
3843 /* A symbol: process the value of the symbol recursively
3844 as if it appeared here directly. */
3845 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3847 if (!UNBOUNDP (tem))
3849 /* If value is a string, output that string literally:
3850 don't check for % within it. */
3854 add_string_to_fstring_db_runes
3855 (data, XSTRING_DATA (tem), pos, min_pos, max_pos);
3857 /* Give up right away for nil or t. */
3858 else if (!EQ (tem, elt))
3865 else if (GENERIC_SPECIFIERP (elt))
3867 Lisp_Object window, tem;
3868 XSETWINDOW (window, w);
3869 tem = specifier_instance_no_quit (elt, Qunbound, window,
3870 ERROR_ME_NOT, 0, Qzero);
3871 if (!UNBOUNDP (tem))
3877 else if (CONSP (elt))
3879 /* A cons cell: four distinct cases.
3880 * If first element is a string or a cons, process all the elements
3881 * and effectively concatenate them.
3882 * If first element is a negative number, truncate displaying cdr to
3883 * at most that many characters. If positive, pad (with spaces)
3884 * to at least that many characters.
3885 * If first element is a symbol, process the cadr or caddr recursively
3886 * according to whether the symbol's value is non-nil or nil.
3887 * If first element is a face, process the cdr recursively
3888 * without altering the depth.
3890 Lisp_Object car, tem;
3898 tem = symbol_value_in_buffer (car, w->buffer);
3899 /* elt is now the cdr, and we know it is a cons cell.
3900 Use its car if CAR has a non-nil value. */
3901 if (!UNBOUNDP (tem))
3909 /* Symbol's value is nil (or symbol is unbound)
3910 * Get the cddr of the original list
3911 * and if possible find the caddr and use that.
3916 else if (!CONSP (elt))
3924 else if (INTP (car))
3926 Charcount lim = XINT (car);
3932 /* Negative int means reduce maximum width.
3933 * DO NOT change MIN_PIXPOS here!
3934 * (20 -10 . foo) should truncate foo to 10 col
3935 * and then pad to 20.
3938 max_pos = pos - lim;
3940 max_pos = min (max_pos, pos - lim);
3944 /* Padding specified. Don't let it be more than
3948 if (max_pos != -1 && lim > max_pos)
3950 /* If that's more padding than already wanted, queue it.
3951 * But don't reduce padding already specified even if
3952 * that is beyond the current truncation point.
3959 else if (STRINGP (car) || CONSP (car))
3962 /* LIMIT is to protect against circular lists. */
3963 while (CONSP (elt) && --limit > 0
3964 && (pos < max_pos || max_pos == -1))
3966 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
3968 max_pixsize, findex, type);
3972 else if (EXTENTP (car))
3974 struct extent *ext = XEXTENT (car);
3976 if (EXTENT_LIVE_P (ext))
3978 face_index old_findex = data->findex;
3980 Lisp_Object font_inst;
3981 face_index new_findex;
3982 Bytecount start = data->bytepos;
3984 face = extent_face (ext);
3987 /* #### needs to merge faces, sigh */
3988 /* #### needs to handle list of faces */
3989 new_findex = get_builtin_face_cache_index (w, face);
3990 /* !!#### not right; needs to compute the max height of
3992 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
3995 data->dl->ascent = max (data->dl->ascent,
3996 XFONT_INSTANCE (font_inst)->ascent);
3997 data->dl->descent = max (data->dl->descent,
3998 XFONT_INSTANCE (font_inst)->
4002 new_findex = old_findex;
4004 data->findex = new_findex;
4005 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4006 XCDR (elt), depth - 1,
4007 max_pixsize, new_findex, type);
4008 data->findex = old_findex;
4009 Dynarr_add (formatted_string_extent_dynarr, ext);
4010 Dynarr_add (formatted_string_extent_start_dynarr, start);
4011 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4015 else if (GLYPHP (elt))
4017 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos);
4023 add_string_to_fstring_db_runes
4024 (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos,
4030 add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos,
4037 /* The caller is responsible for freeing the returned string. */
4039 generate_formatted_string (struct window *w, Lisp_Object format_str,
4040 Lisp_Object result_str, face_index findex, int type)
4042 struct display_line *dl;
4043 struct display_block *db;
4046 dl = &formatted_string_display_line;
4047 db = get_display_block_from_line (dl, TEXT);
4048 Dynarr_reset (db->runes);
4050 generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
4053 Dynarr_reset (formatted_string_emchar_dynarr);
4054 while (elt < Dynarr_length (db->runes))
4056 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
4057 Dynarr_add (formatted_string_emchar_dynarr,
4058 Dynarr_atp (db->runes, elt)->object.chr.ch);
4063 convert_emchar_string_into_malloced_string
4064 ( Dynarr_atp (formatted_string_emchar_dynarr, 0),
4065 Dynarr_length (formatted_string_emchar_dynarr), 0);
4068 /* Update just the modeline. Assumes the desired display structs. If
4069 they do not have a modeline block, it does nothing. */
4071 regenerate_modeline (struct window *w)
4073 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4075 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4079 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4080 redisplay_update_line (w, 0, 0, 0);
4084 /* Make sure that modeline display line is present in the given
4085 display structs if the window has a modeline and update that
4086 line. Returns true if a modeline was needed. */
4088 ensure_modeline_generated (struct window *w, int type)
4092 /* minibuffer windows don't have modelines */
4093 if (MINI_WINDOW_P (w))
4095 /* windows which haven't had it turned off do */
4096 else if (WINDOW_HAS_MODELINE_P (w))
4098 /* windows which have it turned off don't have a divider if there is
4099 a horizontal scrollbar */
4100 else if (window_scrollbar_height (w))
4102 /* and in this case there is none */
4108 display_line_dynarr *dla;
4110 dla = window_display_lines (w, type);
4112 /* We don't care if there is a display line which is not
4113 currently a modeline because it is definitely going to become
4114 one if we have gotten to this point. */
4115 if (Dynarr_length (dla) == 0)
4117 if (Dynarr_largest (dla) > 0)
4119 struct display_line *mlp = Dynarr_atp (dla, 0);
4120 Dynarr_add (dla, *mlp);
4124 struct display_line modeline;
4126 Dynarr_add (dla, modeline);
4130 /* If we're adding a new place marker go ahead and generate the
4131 modeline so that it is available for use by
4132 window_modeline_height. */
4133 generate_modeline (w, Dynarr_atp (dla, 0), type);
4136 return need_modeline;
4139 /* #### Kludge or not a kludge. I tend towards the former. */
4141 real_current_modeline_height (struct window *w)
4143 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4144 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4146 if (ensure_modeline_generated (w, CMOTION_DISP))
4148 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4150 if (Dynarr_length (dla))
4152 if (Dynarr_atp (dla, 0)->modeline)
4153 return (Dynarr_atp (dla, 0)->ascent +
4154 Dynarr_atp (dla, 0)->descent);
4161 /***************************************************************************/
4163 /* window-regeneration routines */
4165 /***************************************************************************/
4167 /* For a given window and starting position in the buffer it contains,
4168 ensure that the TYPE display lines accurately represent the
4169 presentation of the window. We pass the buffer instead of getting
4170 it from the window since redisplay_window may have temporarily
4171 changed it to the echo area buffer. */
4174 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
4176 struct frame *f = XFRAME (w->frame);
4177 struct buffer *b = XBUFFER (w->buffer);
4178 int ypos = WINDOW_TEXT_TOP (w);
4179 int yend; /* set farther down */
4181 prop_block_dynarr *prop;
4182 layout_bounds bounds;
4183 display_line_dynarr *dla;
4186 /* The lines had better exist by this point. */
4187 if (!(dla = window_display_lines (w, type)))
4190 w->max_line_len = 0;
4192 /* Normally these get updated in redisplay_window but it is possible
4193 for this function to get called from some other points where that
4194 update may not have occurred. This acts as a safety check. */
4195 if (!Dynarr_length (w->face_cachels))
4196 reset_face_cachels (w);
4197 if (!Dynarr_length (w->glyph_cachels))
4198 reset_glyph_cachels (w);
4200 Fset_marker (w->start[type], make_int (start_pos), w->buffer);
4201 Fset_marker (w->pointm[type], make_int (point), w->buffer);
4202 w->last_point_x[type] = -1;
4203 w->last_point_y[type] = -1;
4205 /* Make sure a modeline is in the structs if needed. */
4206 need_modeline = ensure_modeline_generated (w, type);
4208 /* Wait until here to set this so that the structs have a modeline
4209 generated in the case where one didn't exist. */
4210 yend = WINDOW_TEXT_BOTTOM (w);
4212 bounds = calculate_display_line_boundaries (w, 0);
4214 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
4215 if (MINI_WINDOW_P (w)
4216 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
4217 && !echo_area_active (f)
4218 && start_pos == BUF_BEGV (b))
4220 struct prop_block pb;
4222 prop = Dynarr_new (prop_block);
4224 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
4225 pb.type = PROP_MINIBUF_PROMPT;
4226 pb.data.p_string.str = XSTRING_DATA(string);
4227 pb.data.p_string.len = XSTRING_LENGTH(string);
4228 Dynarr_add (prop, pb);
4235 struct display_line dl;
4236 struct display_line *dlp;
4239 if (Dynarr_length (dla) < Dynarr_largest (dla))
4241 dlp = Dynarr_atp (dla, Dynarr_length (dla));
4251 dlp->bounds = bounds;
4253 start_pos = generate_display_line (w, dlp, 1, start_pos,
4254 w->hscroll, &prop, type);
4255 dlp->ypos = ypos + dlp->ascent;
4256 ypos = dlp->ypos + dlp->descent;
4260 int visible_height = dlp->ascent + dlp->descent;
4262 dlp->clip = (ypos - yend);
4263 visible_height -= dlp->clip;
4265 if (visible_height < VERTICAL_CLIP (w, 1))
4268 free_display_line (dlp);
4275 if (dlp->cursor_elt != -1)
4277 /* #### This check is steaming crap. Have to get things
4278 fixed so when create_text_block hits EOB, we're done,
4280 if (w->last_point_x[type] == -1)
4282 w->last_point_x[type] = dlp->cursor_elt;
4283 w->last_point_y[type] = Dynarr_length (dla);
4287 /* #### This means that we've added a cursor at EOB
4288 twice. Yuck oh yuck. */
4289 struct display_block *db =
4290 get_display_block_from_line (dlp, TEXT);
4292 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
4293 dlp->cursor_elt = -1;
4297 if (dlp->num_chars > w->max_line_len)
4298 w->max_line_len = dlp->num_chars;
4300 Dynarr_add (dla, *dlp);
4302 /* #### This isn't right, but it is close enough for now. */
4303 w->window_end_pos[type] = start_pos;
4305 /* #### This type of check needs to be done down in the
4306 generate_display_line call. */
4307 if (start_pos > BUF_ZV (b))
4314 /* #### More not quite right, but close enough. */
4315 /* #### Ben sez: apparently window_end_pos[] is measured
4316 as the number of characters between the window end and the
4317 end of the buffer? This seems rather weirdo. What's
4318 the justification for this? */
4319 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
4323 /* We know that this is the right thing to use because we put it
4324 there when we first started working in this function. */
4325 generate_modeline (w, Dynarr_atp (dla, 0), type);
4329 #define REGEN_INC_FIND_START_END \
4331 /* Determine start and end of lines. */ \
4332 if (!Dynarr_length (cdla)) \
4336 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
4340 else if (!Dynarr_atp (cdla, 0)->modeline \
4341 && !Dynarr_atp (ddla, 0)->modeline) \
4346 abort (); /* structs differ */ \
4348 dla_end = Dynarr_length (cdla) - 1; \
4351 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
4352 + Dynarr_atp (cdla, dla_start)->offset); \
4353 /* If this isn't true, then startp has changed and we need to do a \
4355 if (startp != start_pos) \
4358 /* Point is outside the visible region so give up. */ \
4359 if (pointm < start_pos) \
4364 /* This attempts to incrementally update the display structures. It
4365 returns a boolean indicating success or failure. This function is
4366 very similar to regenerate_window_incrementally and is in fact only
4367 called from that function. However, because of the nature of the
4368 changes it deals with it sometimes makes different assumptions
4369 which can lead to success which are much more difficult to make
4370 when dealing with buffer changes. */
4373 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
4375 Charcount beg_unchanged,
4376 Charcount end_unchanged)
4378 struct buffer *b = XBUFFER (w->buffer);
4379 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
4380 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
4384 int first_line, last_line;
4386 /* Don't define this in the loop where it is used because we
4387 definitely want its value to survive between passes. */
4388 prop_block_dynarr *prop = NULL;
4390 /* If we don't have any buffer change recorded but the modiff flag has
4391 been incremented, then fail. I'm not sure of the exact circumstances
4392 under which this can happen, but I believe that it is probably a
4393 reasonable happening. */
4394 if (!point_visible (w, pointm, CURRENT_DISP)
4395 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
4398 /* If the cursor is moved we attempt to update it. If we succeed we
4399 go ahead and proceed with the optimization attempt. */
4400 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
4401 || pointm != marker_position (w->last_point[CURRENT_DISP]))
4403 struct frame *f = XFRAME (w->frame);
4404 struct device *d = XDEVICE (f->device);
4405 struct frame *sel_f = device_selected_frame (d);
4408 if (w->last_point_x[CURRENT_DISP] != -1
4409 && w->last_point_y[CURRENT_DISP] != -1)
4412 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
4414 /* Always regenerate the modeline in case it is
4415 displaying the current line or column. */
4416 regenerate_modeline (w);
4420 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
4422 if (f->modeline_changed)
4423 regenerate_modeline (w);
4431 if (beg_unchanged == -1 && end_unchanged == -1)
4434 /* assert: There are no buffer modifications or they are all below the
4435 visible region. We assume that regenerate_window_incrementally has
4436 not called us unless this is true. */
4438 REGEN_INC_FIND_START_END;
4440 /* If the changed are starts before the visible area, give up. */
4441 if (beg_unchanged < startp)
4444 /* Find what display line the extent changes first affect. */
4446 while (line <= dla_end)
4448 struct display_line *dl = Dynarr_atp (cdla, line);
4449 Bufpos lstart = dl->bufpos + dl->offset;
4450 Bufpos lend = dl->end_bufpos + dl->offset;
4452 if (beg_unchanged >= lstart && beg_unchanged <= lend)
4458 /* If the changes are below the visible area then if point hasn't
4459 moved return success otherwise fail in order to be safe. */
4462 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
4463 && pointm == marker_position (w->last_point[CURRENT_DISP]))
4469 /* At this point we know what line the changes first affect. We now
4470 begin redrawing lines as long as we are still in the affected
4471 region and the line's size and positioning don't change.
4472 Otherwise we fail. If we fail we will have altered the desired
4473 structs which could lead to an assertion failure. However, if we
4474 fail the next thing that is going to happen is a full regen so we
4475 will actually end up being safe. */
4476 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
4477 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
4478 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
4479 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
4481 first_line = last_line = line;
4482 while (line <= dla_end)
4484 Bufpos old_start, old_end, new_start;
4485 struct display_line *cdl = Dynarr_atp (cdla, line);
4486 struct display_line *ddl = Dynarr_atp (ddla, line);
4487 struct display_block *db;
4490 assert (cdl->bufpos == ddl->bufpos);
4491 assert (cdl->end_bufpos == ddl->end_bufpos);
4492 assert (cdl->offset == ddl->offset);
4494 db = get_display_block_from_line (ddl, TEXT);
4495 initial_size = Dynarr_length (db->runes);
4496 old_start = ddl->bufpos + ddl->offset;
4497 old_end = ddl->end_bufpos + ddl->offset;
4499 /* If this is the first line being updated and it used
4500 propagation data, fail. Otherwise we'll be okay because
4501 we'll have the necessary propagation data. */
4502 if (line == first_line && ddl->used_prop_data)
4505 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
4506 w->hscroll, &prop, DESIRED_DISP);
4509 /* #### If there is propagated stuff the fail. We could
4510 probably actually deal with this if the line had propagated
4511 information when originally created by a full
4519 /* If any line position parameters have changed or a
4520 cursor has disappeared or disappeared, fail. */
4521 db = get_display_block_from_line (ddl, TEXT);
4522 if (cdl->ypos != ddl->ypos
4523 || cdl->ascent != ddl->ascent
4524 || cdl->descent != ddl->descent
4525 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
4526 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
4527 || old_start != ddl->bufpos
4528 || old_end != ddl->end_bufpos
4529 || initial_size != Dynarr_length (db->runes))
4534 if (ddl->cursor_elt != -1)
4536 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
4537 w->last_point_y[DESIRED_DISP] = line;
4542 /* If the extent changes end on the line we just updated then
4543 we're done. Otherwise go on to the next line. */
4544 if (end_unchanged <= ddl->end_bufpos)
4550 redisplay_update_line (w, first_line, last_line, 1);
4554 /* Attempt to update the display data structures based on knowledge of
4555 the changed region in the buffer. Returns a boolean indicating
4556 success or failure. If this function returns a failure then a
4557 regenerate_window _must_ be performed next in order to maintain
4558 invariants located here. */
4561 regenerate_window_incrementally (struct window *w, Bufpos startp,
4564 struct buffer *b = XBUFFER (w->buffer);
4565 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
4566 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
4567 Charcount beg_unchanged, end_unchanged;
4568 Charcount extent_beg_unchanged, extent_end_unchanged;
4574 /* If this function is called, the current and desired structures
4575 had better be identical. If they are not, then that is a bug. */
4576 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
4578 /* We don't handle minibuffer windows yet. The minibuffer prompt
4580 if (MINI_WINDOW_P (w))
4583 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
4584 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
4586 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
4588 /* If nothing has changed in the buffer, then make sure point is ok
4590 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
4591 return regenerate_window_extents_only_changed (w, startp, pointm,
4592 extent_beg_unchanged,
4593 extent_end_unchanged);
4595 /* We can't deal with deleted newlines. */
4596 if (BUF_NEWLINE_WAS_DELETED (b))
4599 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
4600 end_unchanged = (BUF_END_UNCHANGED (b) == -1
4602 : BUF_Z (b) - BUF_END_UNCHANGED (b));
4604 REGEN_INC_FIND_START_END;
4606 /* If the changed area starts before the visible area, give up. */
4607 if (beg_unchanged < startp)
4610 /* Find what display line the buffer changes first affect. */
4612 while (line <= dla_end)
4614 struct display_line *dl = Dynarr_atp (cdla, line);
4615 Bufpos lstart = dl->bufpos + dl->offset;
4616 Bufpos lend = dl->end_bufpos + dl->offset;
4618 if (beg_unchanged >= lstart && beg_unchanged <= lend)
4624 /* If the changes are below the visible area then if point hasn't
4625 moved return success otherwise fail in order to be safe. */
4628 return regenerate_window_extents_only_changed (w, startp, pointm,
4629 extent_beg_unchanged,
4630 extent_end_unchanged);
4633 /* At this point we know what line the changes first affect. We
4634 now redraw that line. If the changes are contained within it
4635 we are going to succeed and can update just that one line.
4636 Otherwise we fail. If we fail we will have altered the desired
4637 structs which could lead to an assertion failure. However, if
4638 we fail the next thing that is going to happen is a full regen
4639 so we will actually end up being safe. */
4642 prop_block_dynarr *prop = NULL;
4643 struct display_line *cdl = Dynarr_atp (cdla, line);
4644 struct display_line *ddl = Dynarr_atp (ddla, line);
4646 assert (cdl->bufpos == ddl->bufpos);
4647 assert (cdl->end_bufpos == ddl->end_bufpos);
4648 assert (cdl->offset == ddl->offset);
4650 /* If the last rune is already a continuation glyph, fail.
4651 #### We should be able to handle this better. */
4653 struct display_block *db = get_display_block_from_line (ddl, TEXT);
4654 if (Dynarr_length (db->runes))
4657 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4659 if (rb->type == RUNE_DGLYPH
4660 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
4665 /* If the line was generated using propagation data, fail. */
4666 if (ddl->used_prop_data)
4669 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
4670 w->hscroll, &prop, DESIRED_DISP);
4673 /* If there is propagated stuff then it is pretty much a
4674 guarantee that more than just the one line is affected. */
4681 /* If the last rune is now a continuation glyph, fail. */
4683 struct display_block *db = get_display_block_from_line (ddl, TEXT);
4684 if (Dynarr_length (db->runes))
4687 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4689 if (rb->type == RUNE_DGLYPH
4690 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
4695 /* If any line position parameters have changed or a
4696 cursor has disappeared or disappeared, fail. */
4697 if (cdl->ypos != ddl->ypos
4698 || cdl->ascent != ddl->ascent
4699 || cdl->descent != ddl->descent
4700 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
4701 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
4706 /* If the changed area also ends on this line, then we may be in
4707 business. Update everything and return success. */
4708 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
4710 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
4711 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
4712 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
4714 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
4717 if (ddl->cursor_elt != -1)
4719 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
4720 w->last_point_y[DESIRED_DISP] = line;
4723 redisplay_update_line (w, line, line, 1);
4724 regenerate_modeline (w);
4726 /* #### For now we just flush the cache until this has been
4727 tested. After that is done, this should correct the
4729 Dynarr_reset (w->line_start_cache);
4731 /* Adjust the extent changed boundaries to remove any
4732 overlap with the buffer changes since we've just
4733 successfully updated that area. */
4734 if (extent_beg_unchanged != -1
4735 && extent_beg_unchanged >= beg_unchanged
4736 && extent_beg_unchanged < end_unchanged)
4737 extent_beg_unchanged = end_unchanged;
4739 if (extent_end_unchanged != -1
4740 && extent_end_unchanged >= beg_unchanged
4741 && extent_end_unchanged < end_unchanged)
4742 extent_end_unchanged = beg_unchanged - 1;
4744 if (extent_end_unchanged <= extent_beg_unchanged)
4745 extent_beg_unchanged = extent_end_unchanged = -1;
4747 /* This could lead to odd results if it fails, but since the
4748 buffer changes update succeeded this probably will to.
4749 We already know that the extent changes start at or after
4750 the line because we checked before entering the loop. */
4751 if (extent_beg_unchanged != -1
4752 && extent_end_unchanged != -1
4753 && ((extent_beg_unchanged < ddl->bufpos)
4754 || (extent_end_unchanged > ddl->end_bufpos)))
4757 regenerate_window_extents_only_changed (w, startp, pointm,
4758 extent_beg_unchanged,
4759 extent_end_unchanged);
4770 /* Given a window and a point, update the given display lines such
4771 that point is displayed in the middle of the window.
4772 Return the window's new start position. */
4775 regenerate_window_point_center (struct window *w, Bufpos point, int type)
4779 /* We need to make sure that the modeline is generated so that the
4780 window height can be calculated correctly. */
4781 ensure_modeline_generated (w, type);
4783 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
4784 regenerate_window (w, startp, point, type);
4785 Fset_marker (w->start[type], make_int (startp), w->buffer);
4790 /* Given a window and a set of display lines, return a boolean
4791 indicating whether the given point is contained within. */
4794 point_visible (struct window *w, Bufpos point, int type)
4796 struct buffer *b = XBUFFER (w->buffer);
4797 display_line_dynarr *dla = window_display_lines (w, type);
4800 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
4805 if (Dynarr_length (dla) > first_line)
4808 struct display_line *dl = Dynarr_atp (dla, first_line);
4811 end = BUF_Z (b) - w->window_end_pos[type] - 1;
4813 if (point >= start && point <= end)
4815 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
4817 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
4819 if (point >= (dl->bufpos + dl->offset)
4820 && point <= (dl->end_bufpos + dl->offset))
4835 /* Return pixel position the middle of the window, not including the
4836 modeline and any potential horizontal scrollbar. */
4839 window_half_pixpos (struct window *w)
4841 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
4844 /* Return the display line which is currently in the middle of the
4845 window W for display lines TYPE. */
4848 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
4850 display_line_dynarr *dla;
4853 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
4855 if (type == CMOTION_DISP)
4856 regenerate_window (w, start, point, type);
4858 dla = window_display_lines (w, type);
4859 half = window_half_pixpos (w);
4861 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
4863 struct display_line *dl = Dynarr_atp (dla, elt);
4864 int line_bot = dl->ypos + dl->descent;
4866 if (line_bot > half)
4870 /* We may not have a line at the middle if the end of the buffer is
4875 /* Return a value for point that would place it at the beginning of
4876 the line which is in the middle of the window. */
4879 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
4881 /* line_at_center will regenerate the display structures, if necessary. */
4882 int line = line_at_center (w, type, start, point);
4885 return BUF_ZV (XBUFFER (w->buffer));
4888 display_line_dynarr *dla = window_display_lines (w, type);
4889 struct display_line *dl = Dynarr_atp (dla, line);
4895 /* For a given window, ensure that the current visual representation
4899 redisplay_window (Lisp_Object window, int skip_selected)
4901 struct window *w = XWINDOW (window);
4902 struct frame *f = XFRAME (w->frame);
4903 struct device *d = XDEVICE (f->device);
4904 Lisp_Object old_buffer = w->buffer;
4905 Lisp_Object the_buffer = w->buffer;
4907 int echo_active = 0;
4912 int selected_in_its_frame;
4913 int selected_globally;
4914 int skip_output = 0;
4915 int truncation_changed;
4916 int inactive_minibuffer =
4917 (MINI_WINDOW_P (w) &&
4918 (f != device_selected_frame (d)) &&
4919 !is_surrogate_for_selected_frame (f));
4921 /* #### In the new world this function actually does a bunch of
4922 optimizations such as buffer-based scrolling, but none of that is
4925 /* If this is a combination window, do its children; that's all.
4926 The selected window is always a leaf so we don't check for
4927 skip_selected here. */
4928 if (!NILP (w->vchild))
4930 redisplay_windows (w->vchild, skip_selected);
4933 if (!NILP (w->hchild))
4935 redisplay_windows (w->hchild, skip_selected);
4939 /* Is this window the selected window on its frame? */
4940 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
4942 selected_in_its_frame &&
4943 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
4944 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
4945 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
4946 if (skip_selected && selected_in_its_frame)
4949 /* It is possible that the window is not fully initialized yet. */
4950 if (NILP (w->buffer))
4953 if (MINI_WINDOW_P (w) && echo_area_active (f))
4955 w->buffer = the_buffer = Vecho_area_buffer;
4959 b = XBUFFER (w->buffer);
4963 old_pointm = selected_globally
4965 : marker_position (w->pointm[CURRENT_DISP]);
4970 if (selected_globally)
4972 pointm = BUF_PT (b);
4976 pointm = marker_position (w->pointm[CURRENT_DISP]);
4978 if (pointm < BUF_BEGV (b))
4979 pointm = BUF_BEGV (b);
4980 else if (pointm > BUF_ZV (b))
4981 pointm = BUF_ZV (b);
4984 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
4986 /* If the buffer has changed we have to invalid all of our face
4988 if ((!echo_active && b != window_display_buffer (w))
4989 || !Dynarr_length (w->face_cachels)
4990 || f->faces_changed)
4991 reset_face_cachels (w);
4993 mark_face_cachels_as_not_updated (w);
4995 /* Ditto the glyph cache elements. */
4996 if ((!echo_active && b != window_display_buffer (w))
4997 || !Dynarr_length (w->glyph_cachels)
4998 || f->glyphs_changed)
4999 reset_glyph_cachels (w);
5001 mark_glyph_cachels_as_not_updated (w);
5003 /* If the marker's buffer is not the window's buffer, then we need
5004 to find a new starting position. */
5005 if (!MINI_WINDOW_P (w)
5006 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5008 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5010 goto regeneration_done;
5015 old_startp = marker_position (w->start[CURRENT_DISP]);
5020 startp = marker_position (w->start[CURRENT_DISP]);
5021 if (startp < BUF_BEGV (b))
5022 startp = BUF_BEGV (b);
5023 else if (startp > BUF_ZV (b))
5024 startp = BUF_ZV (b);
5026 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5028 truncation_changed = (find_window_mirror (w)->truncate_win !=
5029 window_truncation_on (w));
5031 /* If w->force_start is set, then some function set w->start and we
5032 should display from there and change point, if necessary, to
5033 ensure that it is visible. */
5034 if (w->force_start || inactive_minibuffer)
5037 w->last_modified[DESIRED_DISP] = Qzero;
5038 w->last_facechange[DESIRED_DISP] = Qzero;
5040 regenerate_window (w, startp, pointm, DESIRED_DISP);
5042 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5044 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5046 if (selected_globally)
5047 BUF_SET_PT (b, pointm);
5049 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5052 /* #### BUFU amounts of overkil just to get the cursor
5053 location marked properly. FIX ME FIX ME FIX ME */
5054 regenerate_window (w, startp, pointm, DESIRED_DISP);
5057 goto regeneration_done;
5060 /* If nothing has changed since the last redisplay, then we just
5061 need to make sure that point is still visible. */
5062 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5063 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
5065 /* This check is to make sure we restore the minibuffer after a
5066 temporary change to the echo area. */
5067 && !(MINI_WINDOW_P (w) && f->buffers_changed)
5068 && !f->frame_changed
5069 && !truncation_changed
5070 /* check whether start is really at the begining of a line GE */
5071 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
5074 /* Check if the cursor has actually moved. */
5075 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5076 && pointm == marker_position (w->last_point[CURRENT_DISP])
5077 && selected_globally
5078 && !w->windows_changed
5080 && !f->extents_changed
5081 && !f->faces_changed
5082 && !f->glyphs_changed
5083 && !f->point_changed
5084 && !f->windows_structure_changed)
5086 /* If not, we're done. */
5087 if (f->modeline_changed)
5088 regenerate_modeline (w);
5091 goto regeneration_done;
5095 /* If the new point is visible in the redisplay structures,
5096 then let the output update routines handle it, otherwise
5097 do things the hard way. */
5098 if (!w->windows_changed
5100 && !f->extents_changed
5101 && !f->faces_changed
5102 && !f->glyphs_changed
5103 && !f->windows_structure_changed)
5105 if (point_visible (w, pointm, CURRENT_DISP)
5106 && w->last_point_x[CURRENT_DISP] != -1
5107 && w->last_point_y[CURRENT_DISP] != -1)
5109 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
5111 /* Always regenerate in case it is displaying
5112 the current line or column. */
5113 regenerate_modeline (w);
5116 goto regeneration_done;
5119 else if (!selected_in_its_frame && !f->point_changed)
5121 if (f->modeline_changed)
5122 regenerate_modeline (w);
5125 goto regeneration_done;
5129 /* If we weren't able to take the shortcut method, then use
5130 the brute force method. */
5131 regenerate_window (w, startp, pointm, DESIRED_DISP);
5133 if (point_visible (w, pointm, DESIRED_DISP))
5134 goto regeneration_done;
5138 /* Check if the starting point is no longer at the beginning of a
5139 line, in which case find a new starting point. We also recenter
5140 if our start position is equal to point-max. Otherwise we'll end
5141 up with a blank window. */
5142 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
5143 && !(startp == BUF_BEGV (b)
5144 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
5145 || (pointm == startp &&
5146 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
5147 startp < marker_position (w->last_start[CURRENT_DISP]))
5148 || (startp == BUF_ZV (b)))
5150 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5152 goto regeneration_done;
5154 /* See if we can update the data structures locally based on
5155 knowledge of what changed in the buffer. */
5156 else if (!w->windows_changed
5158 && !f->faces_changed
5159 && !f->glyphs_changed
5160 && !f->windows_structure_changed
5161 && !f->frame_changed
5162 && !truncation_changed
5164 && regenerate_window_incrementally (w, startp, pointm))
5166 if (f->modeline_changed
5167 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
5168 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
5169 regenerate_modeline (w);
5172 goto regeneration_done;
5174 /* #### This is where a check for structure based scrolling would go. */
5175 /* If all else fails, try just regenerating and see what happens. */
5178 regenerate_window (w, startp, pointm, DESIRED_DISP);
5180 if (point_visible (w, pointm, DESIRED_DISP))
5181 goto regeneration_done;
5184 /* We still haven't gotten the window regenerated with point
5185 visible. Next we try scrolling a little and see if point comes
5186 back onto the screen. */
5187 if (scroll_step > 0)
5189 int scrolled = scroll_conservatively;
5190 for (; scrolled >= 0; scrolled -= scroll_step)
5192 startp = vmotion (w, startp,
5193 (pointm < startp) ? -scroll_step : scroll_step, 0);
5194 regenerate_window (w, startp, pointm, DESIRED_DISP);
5196 if (point_visible (w, pointm, DESIRED_DISP))
5197 goto regeneration_done;
5201 /* We still haven't managed to get the screen drawn with point on
5202 the screen, so just center it and be done with it. */
5203 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5208 /* If the window's frame is changed then reset the current display
5209 lines in order to force a full repaint. */
5210 if (f->frame_changed)
5212 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
5217 /* Must do this before calling redisplay_output_window because it
5218 sets some markers on the window. */
5221 w->buffer = old_buffer;
5222 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
5223 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
5226 /* These also have to be set before calling redisplay_output_window
5227 since it sets the CURRENT_DISP values based on them. */
5228 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5229 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5230 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5231 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5235 Bufpos start = marker_position (w->start[DESIRED_DISP]);
5236 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
5238 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
5240 update_line_start_cache (w, start, end, pointm, 1);
5241 redisplay_output_window (w);
5243 * If we just displayed the echo area, the line start cache is
5244 * no longer valid, because the minibuffer window is assocaited
5245 * with the window now.
5248 w->line_cache_last_updated = make_int (-1);
5251 /* #### This should be dependent on face changes and will need to be
5252 somewhere else once tty updates occur on a per-frame basis. */
5253 mark_face_cachels_as_clean (w);
5255 w->windows_changed = 0;
5258 /* Call buffer_reset_changes for all buffers present in any window
5259 currently visible in all frames on all devices. #### There has to
5260 be a better way to do this. */
5263 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
5265 buffer_reset_changes (XBUFFER (w->buffer));
5270 reset_buffer_changes (void)
5272 Lisp_Object frmcons, devcons, concons;
5274 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
5276 struct frame *f = XFRAME (XCAR (frmcons));
5278 if (FRAME_REPAINT_P (f))
5279 map_windows (f, reset_buffer_changes_mapfun, 0);
5283 /* Ensure that all windows underneath the given window in the window
5284 hierarchy are correctly displayed. */
5287 redisplay_windows (Lisp_Object window, int skip_selected)
5289 for (; !NILP (window) ; window = XWINDOW (window)->next)
5291 redisplay_window (window, skip_selected);
5296 call_redisplay_end_triggers (struct window *w, void *closure)
5298 Bufpos lrpos = w->last_redisplay_pos;
5299 w->last_redisplay_pos = 0;
5300 if (!NILP (w->buffer)
5301 && !NILP (w->redisplay_end_trigger)
5306 if (MARKERP (w->redisplay_end_trigger)
5307 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
5308 pos = marker_position (w->redisplay_end_trigger);
5309 else if (INTP (w->redisplay_end_trigger))
5310 pos = XINT (w->redisplay_end_trigger);
5313 w->redisplay_end_trigger = Qnil;
5320 XSETWINDOW (window, w);
5321 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
5322 Qredisplay_end_trigger_functions,
5324 w->redisplay_end_trigger);
5325 w->redisplay_end_trigger = Qnil;
5332 /* Ensure that all windows on the given frame are correctly displayed. */
5335 redisplay_frame (struct frame *f, int preemption_check)
5337 struct device *d = XDEVICE (f->device);
5339 if (preemption_check)
5341 /* The preemption check itself takes a lot of time,
5342 so normally don't do it here. We do it if called
5343 from Lisp, though (`redisplay-frame'). */
5346 REDISPLAY_PREEMPTION_CHECK;
5351 /* Before we put a hold on frame size changes, attempt to process
5352 any which are already pending. */
5353 if (f->size_change_pending)
5354 change_frame_size (f, f->new_height, f->new_width, 0);
5356 /* If frame size might need to be changed, due to changed size
5357 of toolbars, scroolabrs etc, change it now */
5358 if (f->size_slipped)
5360 adjust_frame_size (f);
5361 assert (!f->size_slipped);
5364 /* The menubar, toolbar, and icon updates must be done before
5365 hold_frame_size_changes is called and we are officially
5366 'in_display'. They may eval lisp code which may call Fsignal.
5367 If in_display is set Fsignal will abort. */
5369 #ifdef HAVE_MENUBARS
5370 /* Update the menubar. It is done first since it could change
5371 the menubar's visibility. This way we avoid having flashing
5372 caused by an Expose event generated by the visibility change
5374 update_frame_menubars (f);
5375 #endif /* HAVE_MENUBARS */
5377 #ifdef HAVE_TOOLBARS
5378 /* Update the toolbars. */
5379 update_frame_toolbars (f);
5380 #endif /* HAVE_TOOLBARS */
5382 hold_frame_size_changes ();
5384 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
5385 /* Within this section, we are defenseless and assume that the
5386 following cannot happen:
5388 1) garbage collection
5389 2) Lisp code evaluation
5390 3) frame size changes
5392 We ensure (3) by calling hold_frame_size_changes(), which
5393 will cause any pending frame size changes to get put on hold
5394 till after the end of the critical section. (1) follows
5395 automatically if (2) is met. #### Unfortunately, there are
5396 some places where Lisp code can be called within this section.
5397 We need to remove them.
5399 If Fsignal() is called during this critical section, we
5402 If garbage collection is called during this critical section,
5403 we simply return. #### We should abort instead.
5405 #### If a frame-size change does occur we should probably
5406 actually be preempting redisplay. */
5408 /* If we clear the frame we have to force its contents to be redrawn. */
5410 f->frame_changed = 1;
5412 /* Erase the frame before outputting its contents. */
5414 DEVMETH (d, clear_frame, (f));
5416 /* Do the selected window first. */
5417 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
5419 /* Then do the rest. */
5420 redisplay_windows (f->root_window, 1);
5422 /* We now call the output_end routine for tty frames. We delay
5423 doing so in order to avoid cursor flicker. So much for 100%
5425 if (FRAME_TTY_P (f))
5426 DEVMETH (d, output_end, (d));
5428 update_frame_title (f);
5430 f->buffers_changed = 0;
5431 f->clip_changed = 0;
5432 f->extents_changed = 0;
5433 f->faces_changed = 0;
5434 f->frame_changed = 0;
5435 f->glyphs_changed = 0;
5436 f->icon_changed = 0;
5437 f->menubar_changed = 0;
5438 f->modeline_changed = 0;
5439 f->point_changed = 0;
5440 f->toolbar_changed = 0;
5441 f->windows_changed = 0;
5442 f->windows_structure_changed = 0;
5443 f->window_face_cache_reset = 0;
5444 f->echo_area_garbaged = 0;
5448 if (!f->size_change_pending)
5449 f->size_changed = 0;
5451 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
5453 /* Allow frame size changes to occur again.
5455 #### what happens if changes to other frames happen? */
5456 unhold_one_frame_size_changes (f);
5458 map_windows (f, call_redisplay_end_triggers, 0);
5462 /* Ensure that all frames on the given device are correctly displayed. */
5465 redisplay_device (struct device *d)
5467 Lisp_Object frame, frmcons;
5469 int size_change_failed = 0;
5472 if (DEVICE_STREAM_P (d)) /* nothing to do */
5475 /* It is possible that redisplay has been called before the
5476 device is fully initialized. If so then continue with the
5478 if (NILP (DEVICE_SELECTED_FRAME (d)))
5481 REDISPLAY_PREEMPTION_CHECK;
5485 /* Always do the selected frame first. */
5486 frame = DEVICE_SELECTED_FRAME (d);
5490 if (f->icon_changed || f->windows_changed)
5491 update_frame_icon (f);
5493 if (FRAME_REPAINT_P (f))
5495 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
5496 f->faces_changed || f->frame_changed || f->menubar_changed ||
5497 f->modeline_changed || f->point_changed || f->size_changed ||
5498 f->toolbar_changed || f->windows_changed || f->size_slipped ||
5499 f->windows_structure_changed || f->glyphs_changed)
5501 preempted = redisplay_frame (f, 0);
5507 /* If the frame redisplay did not get preempted, then this flag
5508 should have gotten set to 0. It might be possible for that
5509 not to happen if a size change event were to occur at an odd
5510 time. To make sure we don't miss anything we simply don't
5511 reset the top level flags until the condition ends up being
5512 in the right state. */
5513 if (f->size_changed)
5514 size_change_failed = 1;
5517 DEVICE_FRAME_LOOP (frmcons, d)
5519 f = XFRAME (XCAR (frmcons));
5521 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
5524 if (f->icon_changed || f->windows_changed)
5525 update_frame_icon (f);
5527 if (FRAME_REPAINT_P (f))
5529 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
5530 f->faces_changed || f->frame_changed || f->menubar_changed ||
5531 f->modeline_changed || f->point_changed || f->size_changed ||
5532 f->toolbar_changed || f->windows_changed ||
5533 f->windows_structure_changed ||
5536 preempted = redisplay_frame (f, 0);
5542 if (f->size_change_pending)
5543 size_change_failed = 1;
5547 /* If we get here then we redisplayed all of our frames without
5548 getting preempted so mark ourselves as clean. */
5549 d->buffers_changed = 0;
5550 d->clip_changed = 0;
5551 d->extents_changed = 0;
5552 d->faces_changed = 0;
5553 d->frame_changed = 0;
5554 d->glyphs_changed = 0;
5555 d->icon_changed = 0;
5556 d->menubar_changed = 0;
5557 d->modeline_changed = 0;
5558 d->point_changed = 0;
5559 d->toolbar_changed = 0;
5560 d->windows_changed = 0;
5561 d->windows_structure_changed = 0;
5563 if (!size_change_failed)
5564 d->size_changed = 0;
5570 restore_profiling_redisplay_flag (Lisp_Object val)
5572 profiling_redisplay_flag = XINT (val);
5576 /* Ensure that all windows on all frames on all devices are displaying
5577 the current contents of their respective buffers. */
5580 redisplay_without_hooks (void)
5582 Lisp_Object devcons, concons;
5583 int size_change_failed = 0;
5584 int count = specpdl_depth ();
5586 if (profiling_active)
5588 record_unwind_protect (restore_profiling_redisplay_flag,
5589 make_int (profiling_redisplay_flag));
5590 profiling_redisplay_flag = 1;
5593 if (asynch_device_change_pending)
5594 handle_asynch_device_change ();
5596 if (!buffers_changed && !clip_changed && !extents_changed &&
5597 !faces_changed && !frame_changed && !icon_changed &&
5598 !menubar_changed && !modeline_changed && !point_changed &&
5599 !size_changed && !toolbar_changed && !windows_changed &&
5601 !windows_structure_changed && !disable_preemption &&
5602 preemption_count < max_preempts)
5605 DEVICE_LOOP_NO_BREAK (devcons, concons)
5607 struct device *d = XDEVICE (XCAR (devcons));
5610 if (d->buffers_changed || d->clip_changed || d->extents_changed ||
5611 d->faces_changed || d->frame_changed || d->icon_changed ||
5612 d->menubar_changed || d->modeline_changed || d->point_changed ||
5613 d->size_changed || d->toolbar_changed || d->windows_changed ||
5614 d->windows_structure_changed ||
5617 preempted = redisplay_device (d);
5622 RESET_CHANGED_SET_FLAGS;
5626 /* See comment in redisplay_device. */
5627 if (d->size_changed)
5628 size_change_failed = 1;
5631 preemption_count = 0;
5633 /* Mark redisplay as accurate */
5634 buffers_changed = 0;
5636 extents_changed = 0;
5640 menubar_changed = 0;
5641 modeline_changed = 0;
5643 toolbar_changed = 0;
5644 windows_changed = 0;
5645 windows_structure_changed = 0;
5646 RESET_CHANGED_SET_FLAGS;
5650 mark_all_faces_as_clean ();
5654 if (!size_change_failed)
5657 reset_buffer_changes ();
5660 unbind_to (count, Qnil);
5666 if (last_display_warning_tick != display_warning_tick &&
5667 !inhibit_warning_display)
5669 /* If an error occurs during this function, oh well.
5670 If we report another warning, we could get stuck in an
5671 infinite loop reporting warnings. */
5672 call0_trapping_errors (0, Qdisplay_warning_buffer);
5673 last_display_warning_tick = display_warning_tick;
5675 /* The run_hook_trapping_errors functions are smart enough not
5676 to do any evalling if the hook function is empty, so there
5677 should not be any significant time loss. All places in the
5678 C code that call redisplay() are prepared to handle GCing,
5679 so we should be OK. */
5680 #ifndef INHIBIT_REDISPLAY_HOOKS
5681 run_hook_trapping_errors ("Error in pre-redisplay-hook",
5682 Qpre_redisplay_hook);
5683 #endif /* INHIBIT_REDISPLAY_HOOKS */
5685 redisplay_without_hooks ();
5687 #ifndef INHIBIT_REDISPLAY_HOOKS
5688 run_hook_trapping_errors ("Error in post-redisplay-hook",
5689 Qpost_redisplay_hook);
5690 #endif /* INHIBIT_REDISPLAY_HOOKS */
5694 static char window_line_number_buf[32];
5696 /* Efficiently determine the window line number, and return a pointer
5697 to its printed representation. Do this regardless of whether
5698 line-number-mode is on. The first line in the buffer is counted as
5699 1. If narrowing is in effect, the lines are counted from the
5700 beginning of the visible portion of the buffer. */
5702 window_line_number (struct window *w, int type)
5704 struct device *d = XDEVICE (XFRAME (w->frame)->device);
5705 struct buffer *b = XBUFFER (w->buffer);
5706 /* Be careful in the order of these tests. The first clasue will
5707 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
5708 This can occur when the frame title is computed really early */
5710 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
5711 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
5712 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5713 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
5715 : marker_position (w->pointm[type]));
5718 line = buffer_line_number (b, pos, 1);
5720 long_to_string (window_line_number_buf, line + 1);
5722 return window_line_number_buf;
5726 /* Given a character representing an object in a modeline
5727 specification, return a string (stored into the global array
5728 `mode_spec_bufbyte_string') with the information that object
5731 This function is largely unchanged from previous versions of the
5734 Warning! This code is also used for frame titles and can be called
5735 very early in the device/frame update process! JV
5739 decode_mode_spec (struct window *w, Emchar spec, int type)
5741 Lisp_Object obj = Qnil;
5742 CONST char *str = NULL;
5743 struct buffer *b = XBUFFER (w->buffer);
5745 Dynarr_reset (mode_spec_bufbyte_string);
5749 /* print buffer name */
5754 /* print visited file name */
5759 /* print the current column */
5762 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
5764 : marker_position (w->pointm[type]);
5765 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
5768 long_to_string (buf, col);
5770 Dynarr_add_many (mode_spec_bufbyte_string,
5771 (CONST Bufbyte *) buf, strlen (buf));
5773 goto decode_mode_spec_done;
5775 /* print the file coding system */
5779 Lisp_Object codesys = b->buffer_file_coding_system;
5780 /* Be very careful here not to get an error. */
5781 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
5783 codesys = Ffind_coding_system (codesys);
5784 if (CODING_SYSTEMP (codesys))
5785 obj = XCODING_SYSTEM_MNEMONIC (codesys);
5788 #endif /* FILE_CODING */
5791 /* print the current line number */
5793 str = window_line_number (w, type);
5796 /* print value of mode-name (obsolete) */
5801 /* print hyphen and frame number, if != 1 */
5805 struct frame *f = XFRAME (w->frame);
5806 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
5808 /* Naughty, naughty */
5809 char * writable_str = alloca_array (char, 10);
5810 sprintf (writable_str, "-%d", f->order_count);
5814 #endif /* HAVE_TTY */
5817 /* print Narrow if appropriate */
5819 if (BUF_BEGV (b) > BUF_BEG (b)
5820 || BUF_ZV (b) < BUF_Z (b))
5824 /* print %, * or hyphen, if buffer is read-only, modified or neither */
5826 str = (!NILP (b->read_only)
5828 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5833 /* print * or hyphen -- XEmacs change to allow a buffer to be
5834 read-only but still indicate whether it is modified. */
5836 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5838 : (!NILP (b->read_only)
5843 /* #### defined in 19.29 decode_mode_spec, but not in
5844 modeline-format doc string. */
5845 /* This differs from %* in that it ignores read-only-ness. */
5847 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5852 /* print process status */
5854 obj = Fget_buffer_process (w->buffer);
5856 str = GETTEXT ("no process");
5858 obj = Fsymbol_name (Fprocess_status (obj));
5861 /* Print name of selected frame. */
5863 obj = XFRAME (w->frame)->name;
5866 /* indicate TEXT or BINARY */
5868 /* #### NT does not use this any more. Now what? */
5872 /* print percent of buffer above top of window, or Top, Bot or All */
5875 Bufpos pos = marker_position (w->start[type]);
5876 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5878 /* This had better be while the desired lines are being done. */
5879 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
5881 if (pos <= BUF_BEGV (b))
5886 else if (pos <= BUF_BEGV (b))
5890 /* This hard limit is ok since the string it will hold has a
5891 fixed maximum length of 3. But just to be safe... */
5894 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
5896 /* We can't normally display a 3-digit number, so get us a
5897 2-digit number that is close. */
5901 sprintf (buf, "%2d%%", total);
5902 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5905 goto decode_mode_spec_done;
5910 /* print percent of buffer above bottom of window, perhaps plus
5911 Top, or print Bottom or All */
5914 Bufpos toppos = marker_position (w->start[type]);
5915 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
5916 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5918 /* botpos is only accurate as of the last redisplay, so we can
5919 only treat it as a hint. In particular, after erase-buffer,
5920 botpos may be negative. */
5921 if (botpos < toppos)
5924 if (botpos >= BUF_ZV (b))
5926 if (toppos <= BUF_BEGV (b))
5933 /* This hard limit is ok since the string it will hold has a
5934 fixed maximum length of around 6. But just to be safe... */
5937 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
5939 /* We can't normally display a 3-digit number, so get us a
5940 2-digit number that is close. */
5944 if (toppos <= BUF_BEGV (b))
5945 sprintf (buf, "Top%2d%%", total);
5947 sprintf (buf, "%2d%%", total);
5949 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5952 goto decode_mode_spec_done;
5962 /* print one [ for each recursive editing level. */
5967 if (command_loop_level > 5)
5973 for (i = 0; i < command_loop_level; i++)
5974 Dynarr_add (mode_spec_bufbyte_string, '[');
5976 goto decode_mode_spec_done;
5979 /* print one ] for each recursive editing level. */
5984 if (command_loop_level > 5)
5990 for (i = 0; i < command_loop_level; i++)
5991 Dynarr_add (mode_spec_bufbyte_string, ']');
5993 goto decode_mode_spec_done;
5996 /* print infinitely many dashes -- handle at top level now */
6003 Dynarr_add_many (mode_spec_bufbyte_string,
6005 XSTRING_LENGTH (obj));
6007 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6009 decode_mode_spec_done:
6010 Dynarr_add (mode_spec_bufbyte_string, '\0');
6013 /* Given a display line, free all of its data structures. */
6016 free_display_line (struct display_line *dl)
6020 if (dl->display_blocks)
6022 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6024 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6026 Dynarr_free (db->runes);
6029 Dynarr_free (dl->display_blocks);
6030 dl->display_blocks = NULL;
6033 if (dl->left_glyphs)
6035 Dynarr_free (dl->left_glyphs);
6036 dl->left_glyphs = NULL;
6039 if (dl->right_glyphs)
6041 Dynarr_free (dl->right_glyphs);
6042 dl->right_glyphs = NULL;
6047 /* Given an array of display lines, free them and all data structures
6048 contained within them. */
6051 free_display_lines (display_line_dynarr *dla)
6055 for (line = 0; line < Dynarr_largest (dla); line++)
6057 free_display_line (Dynarr_atp (dla, line));
6063 /* Call internal free routine for each set of display lines. */
6066 free_display_structs (struct window_mirror *mir)
6068 if (mir->current_display_lines)
6070 free_display_lines (mir->current_display_lines);
6071 mir->current_display_lines = 0;
6074 if (mir->desired_display_lines)
6076 free_display_lines (mir->desired_display_lines);
6077 mir->desired_display_lines = 0;
6083 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object))
6087 glyph_block *gb = Dynarr_atp (gba, 0);
6088 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
6090 for (; gb < gb_last; gb++)
6092 if (!NILP (gb->glyph)) ((markobj) (gb->glyph));
6093 if (!NILP (gb->extent)) ((markobj) (gb->extent));
6099 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object))
6101 display_line *dl = Dynarr_atp (dla, 0);
6102 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
6104 for (; dl < dl_last; dl++)
6106 display_block_dynarr *dba = dl->display_blocks;
6107 display_block *db = Dynarr_atp (dba, 0);
6108 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
6110 for (; db < db_last; db++)
6112 rune_dynarr *ra = db->runes;
6113 rune *r = Dynarr_atp (ra, 0);
6114 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
6116 for (; r < r_last; r++)
6118 if (r->type == RUNE_DGLYPH)
6120 if (!NILP (r->object.dglyph.glyph))
6121 ((markobj) (r->object.dglyph.glyph));
6122 if (!NILP (r->object.dglyph.extent))
6123 ((markobj) (r->object.dglyph.extent));
6128 mark_glyph_block_dynarr (dl->left_glyphs, markobj);
6129 mark_glyph_block_dynarr (dl->right_glyphs, markobj);
6134 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object))
6136 mark_redisplay_structs (mir->current_display_lines, markobj);
6137 mark_redisplay_structs (mir->desired_display_lines, markobj);
6140 mark_window_mirror (mir->next, markobj);
6143 mark_window_mirror (mir->hchild, markobj);
6144 else if (mir->vchild)
6145 mark_window_mirror (mir->vchild, markobj);
6149 mark_redisplay (void (*markobj)(Lisp_Object))
6151 Lisp_Object frmcons, devcons, concons;
6153 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6155 struct frame *f = XFRAME (XCAR (frmcons));
6156 update_frame_window_mirror (f);
6157 mark_window_mirror (f->root_mirror, markobj);
6161 /*****************************************************************************
6162 Line Start Cache Description and Rationale
6164 The traditional scrolling code in Emacs breaks in a variable height world.
6165 It depends on the key assumption that the number of lines that can be
6166 displayed at any given time is fixed. This led to a complete separation
6167 of the scrolling code from the redisplay code. In order to fully support
6168 variable height lines, the scrolling code must actually be tightly
6169 integrated with redisplay. Only redisplay can determine how many lines
6170 will be displayed on a screen for any given starting point.
6172 What is ideally wanted is a complete list of the starting buffer position
6173 for every possible display line of a buffer along with the height of that
6174 display line. Maintaining such a full list would be very expensive. We
6175 settle for having it include information for all areas which we happen to
6176 generate anyhow (i.e. the region currently being displayed) and for those
6177 areas we need to work with.
6179 In order to ensure that the cache accurately represents what redisplay
6180 would actually show, it is necessary to invalidate it in many situations.
6181 If the buffer changes, the starting positions may no longer be correct.
6182 If a face or an extent has changed then the line heights may have altered.
6183 These events happen frequently enough that the cache can end up being
6184 constantly disabled. With this potentially constant invalidation when is
6185 the cache ever useful?
6187 Even if the cache is invalidated before every single usage, it is
6188 necessary. Scrolling often requires knowledge about display lines which
6189 are actually above or below the visible region. The cache provides a
6190 convenient light-weight method of storing this information for multiple
6191 display regions. This knowledge is necessary for the scrolling code to
6192 always obey the First Golden Rule of Redisplay.
6194 If the cache already contains all of the information that the scrolling
6195 routines happen to need so that it doesn't have to go generate it, then we
6196 are able to obey the Third Golden Rule of Redisplay. The first thing we
6197 do to help out the cache is to always add the displayed region. This
6198 region had to be generated anyway, so the cache ends up getting the
6199 information basically for free. In those cases where a user is simply
6200 scrolling around viewing a buffer there is a high probability that this is
6201 sufficient to always provide the needed information. The second thing we
6202 can do is be smart about invalidating the cache.
6204 TODO -- Be smart about invalidating the cache. Potential places:
6206 + Insertions at end-of-line which don't cause line-wraps do not alter the
6207 starting positions of any display lines. These types of buffer
6208 modifications should not invalidate the cache. This is actually a large
6209 optimization for redisplay speed as well.
6211 + Buffer modifications frequently only affect the display of lines at and
6212 below where they occur. In these situations we should only invalidate
6213 the part of the cache starting at where the modification occurs.
6215 In case you're wondering, the Second Golden Rule of Redisplay is not
6217 ****************************************************************************/
6219 /* This will get used quite a bit so we don't want to be constantly
6220 allocating and freeing it. */
6221 line_start_cache_dynarr *internal_cache;
6223 /* Makes internal_cache represent the TYPE display structs and only
6224 the TYPE display structs. */
6227 update_internal_cache_list (struct window *w, int type)
6230 display_line_dynarr *dla = window_display_lines (w, type);
6232 Dynarr_reset (internal_cache);
6233 for (line = 0; line < Dynarr_length (dla); line++)
6235 struct display_line *dl = Dynarr_atp (dla, line);
6241 struct line_start_cache lsc;
6243 lsc.start = dl->bufpos;
6244 lsc.end = dl->end_bufpos;
6245 lsc.height = dl->ascent + dl->descent;
6247 Dynarr_add (internal_cache, lsc);
6252 /* Reset the line cache if necessary. This should be run at the
6253 beginning of any function which access the cache. */
6256 validate_line_start_cache (struct window *w)
6258 struct buffer *b = XBUFFER (w->buffer);
6259 struct frame *f = XFRAME (w->frame);
6261 if (!w->line_cache_validation_override)
6263 /* f->extents_changed used to be in here because extent face and
6264 size changes can cause text shifting. However, the extent
6265 covering the region is constantly having its face set and
6266 priority altered by the mouse code. This means that the line
6267 start cache is constanty being invalidated. This is bad
6268 since the mouse code also triggers heavy usage of the cache.
6269 Since it is an unlikely that f->extents being changed
6270 indicates that the cache really needs to be updated and if it
6271 does redisplay will catch it pretty quickly we no longer
6272 invalidate the cache if it is set. This greatly speeds up
6273 dragging out regions with the mouse. */
6274 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
6278 Dynarr_reset (w->line_start_cache);
6283 /* Return the very first buffer position contained in the given
6284 window's cache, or -1 if the cache is empty. Assumes that the
6288 line_start_cache_start (struct window *w)
6290 line_start_cache_dynarr *cache = w->line_start_cache;
6292 if (!Dynarr_length (cache))
6295 return Dynarr_atp (cache, 0)->start;
6298 /* Return the very last buffer position contained in the given
6299 window's cache, or -1 if the cache is empty. Assumes that the
6303 line_start_cache_end (struct window *w)
6305 line_start_cache_dynarr *cache = w->line_start_cache;
6307 if (!Dynarr_length (cache))
6310 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
6313 /* Return the index of the line POINT is contained within in window
6314 W's line start cache. It will enlarge the cache or move the cache
6315 window in order to have POINT be present in the cache. MIN_PAST is
6316 a guarantee of the number of entries in the cache present on either
6317 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
6318 then it will be treated as 0, but the cache window will not be
6319 allowed to shift. Returns -1 if POINT cannot be found in the cache
6323 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
6325 struct buffer *b = XBUFFER (w->buffer);
6326 line_start_cache_dynarr *cache = w->line_start_cache;
6327 unsigned int top, bottom, pos;
6329 validate_line_start_cache (w);
6330 w->line_cache_validation_override++;
6332 /* Let functions pass in negative values, but we still treat -1
6334 /* #### bogosity alert */
6335 if (min_past < 0 && min_past != -1)
6336 min_past = -min_past;
6338 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
6339 || line_start_cache_end (w) < point)
6342 int win_char_height = window_char_height (w, 1);
6344 /* Occasionally we get here with a 0 height
6345 window. find_next_newline_no_quit will abort if we pass it a
6346 count of 0 so handle that case. */
6347 if (!win_char_height)
6348 win_char_height = 1;
6350 if (!Dynarr_length (cache))
6352 Bufpos from = find_next_newline_no_quit (b, point, -1);
6353 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
6355 update_line_start_cache (w, from, to, point, 0);
6357 if (!Dynarr_length (cache))
6359 w->line_cache_validation_override--;
6364 assert (Dynarr_length (cache));
6367 while (line_start_cache_start (w) > point
6368 && (loop < cache_adjustment || min_past == -1))
6372 from = line_start_cache_start (w);
6373 if (from <= BUF_BEGV (b))
6376 from = find_next_newline_no_quit (b, from, -win_char_height);
6377 to = line_start_cache_end (w);
6379 update_line_start_cache (w, from, to, point, 0);
6383 if (line_start_cache_start (w) > point)
6387 from = find_next_newline_no_quit (b, point, -1);
6388 if (from >= BUF_ZV (b))
6390 to = find_next_newline_no_quit (b, from, -win_char_height);
6395 to = find_next_newline_no_quit (b, from, win_char_height);
6397 update_line_start_cache (w, from, to, point, 0);
6401 while (line_start_cache_end (w) < point
6402 && (loop < cache_adjustment || min_past == -1))
6406 to = line_start_cache_end (w);
6407 if (to >= BUF_ZV (b))
6410 from = line_start_cache_end (w);
6411 to = find_next_newline_no_quit (b, from, win_char_height);
6413 update_line_start_cache (w, from, to, point, 0);
6417 if (line_start_cache_end (w) < point)
6421 from = find_next_newline_no_quit (b, point, -1);
6422 if (from >= BUF_ZV (b))
6424 to = find_next_newline_no_quit (b, from, -win_char_height);
6429 to = find_next_newline_no_quit (b, from, win_char_height);
6431 update_line_start_cache (w, from, to, point, 0);
6435 assert (Dynarr_length (cache));
6440 /* This could happen if the buffer is narrowed. */
6441 if (line_start_cache_start (w) > point
6442 || line_start_cache_end (w) < point)
6444 w->line_cache_validation_override--;
6450 top = Dynarr_length (cache) - 1;
6455 unsigned int new_pos;
6458 pos = (bottom + top + 1) >> 1;
6459 start = Dynarr_atp (cache, pos)->start;
6460 end = Dynarr_atp (cache, pos)->end;
6462 if (point >= start && point <= end)
6464 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
6467 find_next_newline_no_quit (b, line_start_cache_start (w),
6469 Bufpos to = line_start_cache_end (w);
6471 update_line_start_cache (w, from, to, point, 0);
6472 goto find_point_loop;
6474 else if ((Dynarr_length (cache) - pos - 1) < min_past
6475 && line_start_cache_end (w) < BUF_ZV (b))
6477 Bufpos from = line_start_cache_end (w);
6478 Bufpos to = find_next_newline_no_quit (b, from,
6483 update_line_start_cache (w, from, to, point, 0);
6484 goto find_point_loop;
6488 w->line_cache_validation_override--;
6492 else if (point > end)
6494 else if (point < start)
6499 new_pos = (bottom + top + 1) >> 1;
6502 w->line_cache_validation_override--;
6508 /* Return a boolean indicating if POINT would be visible in window W
6509 if display of the window was to begin at STARTP. */
6512 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
6514 struct buffer *b = XBUFFER (w->buffer);
6516 int bottom = WINDOW_TEXT_HEIGHT (w);
6519 /* If point is before the intended start it obviously can't be visible. */
6523 /* If point or start are not in the accessible buffer range, then
6525 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
6526 || point < BUF_BEGV (b) || point > BUF_ZV (b))
6529 validate_line_start_cache (w);
6530 w->line_cache_validation_override++;
6532 start_elt = point_in_line_start_cache (w, startp, 0);
6533 if (start_elt == -1)
6535 w->line_cache_validation_override--;
6539 assert (line_start_cache_start (w) <= startp
6540 && line_start_cache_end (w) >= startp);
6546 /* Expand the cache if necessary. */
6547 if (start_elt == Dynarr_length (w->line_start_cache))
6550 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
6552 start_elt = point_in_line_start_cache (w, old_startp,
6553 window_char_height (w, 0));
6555 /* We've already actually processed old_startp, so increment
6559 /* If this happens we didn't add any extra elements. Bummer. */
6560 if (start_elt == Dynarr_length (w->line_start_cache))
6562 w->line_cache_validation_override--;
6567 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
6569 if (pixpos + height > bottom)
6571 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6573 w->line_cache_validation_override--;
6579 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
6581 w->line_cache_validation_override--;
6589 /* For the given window W, if display starts at STARTP, what will be
6590 the buffer position at the beginning or end of the last line
6591 displayed. The end of the last line is also know as the window end
6594 #### With a little work this could probably be reworked as just a
6595 call to start_with_line_at_pixpos. */
6598 start_end_of_last_line (struct window *w, Bufpos startp, int end)
6600 struct buffer *b = XBUFFER (w->buffer);
6601 line_start_cache_dynarr *cache = w->line_start_cache;
6603 int bottom = WINDOW_TEXT_HEIGHT (w);
6607 validate_line_start_cache (w);
6608 w->line_cache_validation_override++;
6610 if (startp < BUF_BEGV (b))
6611 startp = BUF_BEGV (b);
6612 else if (startp > BUF_ZV (b))
6613 startp = BUF_ZV (b);
6616 start_elt = point_in_line_start_cache (w, cur_start, 0);
6617 if (start_elt == -1)
6618 abort (); /* this had better never happen */
6622 int height = Dynarr_atp (cache, start_elt)->height;
6624 cur_start = Dynarr_atp (cache, start_elt)->start;
6626 if (pixpos + height > bottom)
6628 /* Adjust for any possible clip. */
6629 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6634 w->line_cache_validation_override--;
6638 return BUF_BEGV (b);
6642 w->line_cache_validation_override--;
6644 return Dynarr_atp (cache, start_elt)->end;
6646 return Dynarr_atp (cache, start_elt)->start;
6652 if (start_elt == Dynarr_length (cache))
6654 Bufpos from = line_start_cache_end (w);
6655 int win_char_height = window_char_height (w, 0);
6656 Bufpos to = find_next_newline_no_quit (b, from,
6661 /* We've hit the end of the bottom so that's what it is. */
6662 if (from >= BUF_ZV (b))
6664 w->line_cache_validation_override--;
6668 update_line_start_cache (w, from, to, BUF_PT (b), 0);
6670 /* Updating the cache invalidates any current indexes. */
6671 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
6676 /* For the given window W, if display starts at STARTP, what will be
6677 the buffer position at the beginning of the last line displayed. */
6680 start_of_last_line (struct window *w, Bufpos startp)
6682 return start_end_of_last_line (w, startp, 0);
6685 /* For the given window W, if display starts at STARTP, what will be
6686 the buffer position at the end of the last line displayed. This is
6687 also know as the window end position. */
6690 end_of_last_line (struct window *w, Bufpos startp)
6692 return start_end_of_last_line (w, startp, 1);
6695 /* For window W, what does the starting position have to be so that
6696 the line containing POINT will cover pixel position PIXPOS. */
6699 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
6701 struct buffer *b = XBUFFER (w->buffer);
6703 Bufpos cur_pos, prev_pos = point;
6704 int point_line_height;
6705 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
6707 validate_line_start_cache (w);
6708 w->line_cache_validation_override++;
6710 cur_elt = point_in_line_start_cache (w, point, 0);
6711 /* #### See comment in update_line_start_cache about big minibuffers. */
6714 w->line_cache_validation_override--;
6718 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
6722 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6724 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6726 /* Do not take into account the value of vertical_clip here.
6727 That is the responsibility of the calling functions. */
6730 w->line_cache_validation_override--;
6731 if (-pixheight > point_line_height)
6732 /* We can't make the target line cover pixpos, so put it
6733 above pixpos. That way it will at least be visible. */
6743 int win_char_height;
6745 if (cur_pos <= BUF_BEGV (b))
6747 w->line_cache_validation_override--;
6748 return BUF_BEGV (b);
6751 win_char_height = window_char_height (w, 0);
6752 if (!win_char_height)
6753 win_char_height = 1;
6755 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
6756 to = line_start_cache_end (w);
6757 update_line_start_cache (w, from, to, point, 0);
6759 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
6760 assert (cur_elt >= 0);
6766 /* For window W, what does the starting position have to be so that
6767 the line containing point is on display line LINE. If LINE is
6768 positive it is considered to be the number of lines from the top of
6769 the window (0 is the top line). If it is negative the number is
6770 considered to be the number of lines from the bottom (-1 is the
6774 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
6776 validate_line_start_cache (w);
6777 w->line_cache_validation_override++;
6781 int cur_elt = point_in_line_start_cache (w, point, line);
6783 if (cur_elt - line < 0)
6784 cur_elt = 0; /* Hit the top */
6788 w->line_cache_validation_override--;
6789 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
6793 /* The calculated value of pixpos is correct for the bottom line
6794 or what we want when line is -1. Therefore we subtract one
6795 because we have already handled one line. */
6796 int new_line = -line - 1;
6797 int cur_elt = point_in_line_start_cache (w, point, new_line);
6798 int pixpos = WINDOW_TEXT_BOTTOM (w);
6799 Bufpos retval, search_point;
6801 /* If scroll_on_clipped_lines is false, the last "visible" line of
6802 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
6803 If s_o_c_l is true, then we don't want to count a clipped
6804 line, so back up from the bottom by the height of the line
6805 containing point. */
6806 if (scroll_on_clipped_lines)
6807 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6811 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
6813 /* Hit the bottom of the buffer. */
6815 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
6819 XSETWINDOW (window, w);
6820 default_face_height_and_width (window, &defheight, 0);
6822 cur_elt = Dynarr_length (w->line_start_cache) - 1;
6824 pixpos -= (adjustment * defheight);
6825 if (pixpos < WINDOW_TEXT_TOP (w))
6826 pixpos = WINDOW_TEXT_TOP (w);
6829 cur_elt = cur_elt + new_line;
6831 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6833 retval = start_with_line_at_pixpos (w, search_point, pixpos);
6834 w->line_cache_validation_override--;
6839 /* This is used to speed up vertical scrolling by caching the known
6840 buffer starting positions for display lines. This allows the
6841 scrolling routines to avoid costly calls to regenerate_window. If
6842 NO_REGEN is true then it will only add the values in the DESIRED
6843 display structs which are in the given range.
6845 Note also that the FROM/TO values are minimums. It is possible
6846 that this function will actually add information outside of the
6847 lines containing those positions. This can't hurt but it could
6850 #### We currently force the cache to have only 1 contiguous region.
6851 It might help to make the cache a dynarr of caches so that we can
6852 cover more areas. This might, however, turn out to be a lot of
6853 overhead for too little gain. */
6856 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
6857 Bufpos point, int no_regen)
6859 struct buffer *b = XBUFFER (w->buffer);
6860 line_start_cache_dynarr *cache = w->line_start_cache;
6861 Bufpos low_bound, high_bound;
6863 validate_line_start_cache (w);
6864 w->line_cache_validation_override++;
6865 updating_line_start_cache = 1;
6867 if (from < BUF_BEGV (b))
6868 from = BUF_BEGV (b);
6869 if (to > BUF_ZV (b))
6874 updating_line_start_cache = 0;
6875 w->line_cache_validation_override--;
6879 if (Dynarr_length (cache))
6881 low_bound = line_start_cache_start (w);
6882 high_bound = line_start_cache_end (w);
6884 /* Check to see if the desired range is already in the cache. */
6885 if (from >= low_bound && to <= high_bound)
6887 updating_line_start_cache = 0;
6888 w->line_cache_validation_override--;
6892 /* Check to make sure that the desired range is adjacent to the
6893 current cache. If not, invalidate the cache. */
6894 if (to < low_bound || from > high_bound)
6896 Dynarr_reset (cache);
6897 low_bound = high_bound = -1;
6902 low_bound = high_bound = -1;
6905 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
6907 /* This could be integrated into the next two sections, but it is easier
6908 to follow what's going on by having it separate. */
6913 update_internal_cache_list (w, DESIRED_DISP);
6914 if (!Dynarr_length (internal_cache))
6916 updating_line_start_cache = 0;
6917 w->line_cache_validation_override--;
6921 start = Dynarr_atp (internal_cache, 0)->start;
6923 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
6925 /* We aren't allowed to generate additional information to fill in
6926 gaps, so if the DESIRED structs don't overlap the cache, reset the
6928 if (Dynarr_length (cache))
6930 if (end < low_bound || start > high_bound)
6931 Dynarr_reset (cache);
6933 /* #### What should really happen if what we are doing is
6934 extending a line (the last line)? */
6935 if (Dynarr_length (cache) == 1
6936 && Dynarr_length (internal_cache) == 1)
6937 Dynarr_reset (cache);
6940 if (!Dynarr_length (cache))
6942 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
6943 Dynarr_length (internal_cache));
6944 updating_line_start_cache = 0;
6945 w->line_cache_validation_override--;
6949 /* An extra check just in case the calling function didn't pass in
6950 the bounds of the DESIRED structs in the first place. */
6951 if (start >= low_bound && end <= high_bound)
6953 updating_line_start_cache = 0;
6954 w->line_cache_validation_override--;
6958 /* At this point we know that the internal cache partially overlaps
6960 if (start < low_bound)
6962 int ic_elt = Dynarr_length (internal_cache) - 1;
6965 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
6973 Dynarr_reset (cache);
6974 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
6975 Dynarr_length (internal_cache));
6976 updating_line_start_cache = 0;
6977 w->line_cache_validation_override--;
6981 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
6985 if (end > high_bound)
6989 while (ic_elt < Dynarr_length (internal_cache))
6991 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
6997 if (!(ic_elt < Dynarr_length (internal_cache)))
6999 Dynarr_reset (cache);
7000 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7001 Dynarr_length (internal_cache));
7002 updating_line_start_cache = 0;
7003 w->line_cache_validation_override--;
7007 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7008 Dynarr_length (internal_cache) - ic_elt);
7011 updating_line_start_cache = 0;
7012 w->line_cache_validation_override--;
7016 if (!Dynarr_length (cache) || from < low_bound)
7018 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7020 int old_lb = low_bound;
7022 while (startp < old_lb || low_bound == -1)
7027 regenerate_window (w, startp, point, CMOTION_DISP);
7028 update_internal_cache_list (w, CMOTION_DISP);
7030 /* If this assert is triggered then regenerate_window failed
7031 to layout a single line. That is not supposed to be
7032 possible because we impose a minimum height on the buffer
7033 and override vertical clip when we are in here. */
7034 /* #### Ah, but it is because the window may temporarily
7035 exist but not have any lines at all if the minibuffer is
7036 real big. Look into that situation better. */
7037 if (!Dynarr_length (internal_cache))
7039 if (old_lb == -1 && low_bound == -1)
7041 updating_line_start_cache = 0;
7042 w->line_cache_validation_override--;
7046 assert (Dynarr_length (internal_cache));
7048 assert (startp == Dynarr_atp (internal_cache, 0)->start);
7050 ic_elt = Dynarr_length (internal_cache) - 1;
7051 if (low_bound != -1)
7055 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
7061 assert (ic_elt >= 0);
7063 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
7066 * Handle invisible text properly:
7067 * If the last line we're inserting has the same end as the
7068 * line before which it will be added, merge the two lines.
7070 if (Dynarr_length (cache) &&
7071 Dynarr_atp (internal_cache, ic_elt)->end ==
7072 Dynarr_atp (cache, marker)->end)
7074 Dynarr_atp (cache, marker)->start
7075 = Dynarr_atp (internal_cache, ic_elt)->start;
7076 Dynarr_atp (cache, marker)->height
7077 = Dynarr_atp (internal_cache, ic_elt)->height;
7081 if (ic_elt >= 0) /* we still have lines to add.. */
7083 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
7084 ic_elt + 1, marker);
7085 marker += (ic_elt + 1);
7088 if (startp < low_bound || low_bound == -1)
7090 startp = new_startp;
7091 if (startp > BUF_ZV (b))
7093 updating_line_start_cache = 0;
7094 w->line_cache_validation_override--;
7100 assert (Dynarr_length (cache));
7101 assert (from >= low_bound);
7103 /* Readjust the high_bound to account for any changes made while
7104 correcting the low_bound. */
7105 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7107 if (to > high_bound)
7109 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
7113 regenerate_window (w, startp, point, CMOTION_DISP);
7114 update_internal_cache_list (w, CMOTION_DISP);
7116 /* See comment above about regenerate_window failing. */
7117 assert (Dynarr_length (internal_cache));
7119 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7120 Dynarr_length (internal_cache));
7121 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7122 startp = high_bound + 1;
7124 while (to > high_bound);
7127 updating_line_start_cache = 0;
7128 w->line_cache_validation_override--;
7129 assert (to <= high_bound);
7133 /* Given x and y coordinates in characters, relative to a window,
7134 return the pixel location corresponding to those coordinates. The
7135 pixel location returned is the center of the given character
7136 position. The pixel values are generated relative to the window,
7139 The modeline is considered to be part of the window. */
7142 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
7143 int *pix_x, int *pix_y)
7145 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
7146 int num_disp_lines, modeline;
7148 int defheight, defwidth;
7150 XSETWINDOW (window, w);
7151 default_face_height_and_width (window, &defheight, &defwidth);
7153 /* If we get a bogus value indicating somewhere above or to the left of
7154 the window, use the first window line or character position
7161 num_disp_lines = Dynarr_length (dla);
7165 if (Dynarr_atp (dla, 0)->modeline)
7172 /* First check if the y position intersects the display lines. */
7173 if (char_y < num_disp_lines)
7175 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
7176 struct display_block *db = get_display_block_from_line (dl, TEXT);
7178 *pix_y = (dl->ypos - dl->ascent +
7179 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
7181 if (char_x < Dynarr_length (db->runes))
7183 struct rune *rb = Dynarr_atp (db->runes, char_x);
7185 *pix_x = rb->xpos + (rb->width >> 1);
7189 int last_rune = Dynarr_length (db->runes) - 1;
7190 struct rune *rb = Dynarr_atp (db->runes, last_rune);
7192 char_x -= last_rune;
7194 *pix_x = rb->xpos + rb->width;
7195 *pix_x += ((char_x - 1) * defwidth);
7196 *pix_x += (defwidth >> 1);
7201 /* It didn't intersect, so extrapolate. #### For now, we include the
7202 modeline in this since we don't have true character positions in
7205 if (!Dynarr_length (w->face_cachels))
7206 reset_face_cachels (w);
7208 char_y -= num_disp_lines;
7210 if (Dynarr_length (dla))
7212 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
7213 *pix_y = dl->ypos + dl->descent - dl->clip;
7216 *pix_y = WINDOW_TEXT_TOP (w);
7218 *pix_y += (char_y * defheight);
7219 *pix_y += (defheight >> 1);
7221 *pix_x = WINDOW_TEXT_LEFT (w);
7222 /* Don't adjust by one because this is still the unadjusted value. */
7223 *pix_x += (char_x * defwidth);
7224 *pix_x += (defwidth >> 1);
7227 if (*pix_x > w->pixel_left + w->pixel_width)
7228 *pix_x = w->pixel_left + w->pixel_width;
7229 if (*pix_y > w->pixel_top + w->pixel_height)
7230 *pix_y = w->pixel_top + w->pixel_height;
7232 *pix_x -= w->pixel_left;
7233 *pix_y -= w->pixel_top;
7236 /* Given a display line and a position, determine if there is a glyph
7237 there and return information about it if there is. */
7240 get_position_object (struct display_line *dl, Lisp_Object *obj1,
7241 Lisp_Object *obj2, int x_coord, int *low_x_coord,
7244 struct display_block *db;
7247 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
7249 /* We use get_next_display_block to get the actual display block
7250 that would be displayed at x_coord. */
7252 if (block == NO_BLOCK)
7255 db = Dynarr_atp (dl->display_blocks, block);
7257 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
7259 struct rune *rb = Dynarr_atp (db->runes, elt);
7261 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
7263 if (rb->type == RUNE_DGLYPH)
7265 *obj1 = rb->object.dglyph.glyph;
7266 *obj2 = rb->object.dglyph.extent;
7275 *low_x_coord = rb->xpos;
7277 *high_x_coord = rb->xpos + rb->width;
7284 #define UPDATE_CACHE_RETURN \
7286 d->pixel_to_glyph_cache.valid = 1; \
7287 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
7288 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
7289 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
7290 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
7291 d->pixel_to_glyph_cache.frame = f; \
7292 d->pixel_to_glyph_cache.col = *col; \
7293 d->pixel_to_glyph_cache.row = *row; \
7294 d->pixel_to_glyph_cache.obj_x = *obj_x; \
7295 d->pixel_to_glyph_cache.obj_y = *obj_y; \
7296 d->pixel_to_glyph_cache.w = *w; \
7297 d->pixel_to_glyph_cache.bufpos = *bufpos; \
7298 d->pixel_to_glyph_cache.closest = *closest; \
7299 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
7300 d->pixel_to_glyph_cache.obj1 = *obj1; \
7301 d->pixel_to_glyph_cache.obj2 = *obj2; \
7302 d->pixel_to_glyph_cache.retval = position; \
7303 RETURN__ position; \
7306 /* Given x and y coordinates in pixels relative to a frame, return
7307 information about what is located under those coordinates.
7309 The return value will be one of:
7311 OVER_TOOLBAR: over one of the 4 frame toolbars
7312 OVER_MODELINE: over a modeline
7313 OVER_BORDER: over an internal border
7314 OVER_NOTHING: over the text area, but not over text
7315 OVER_OUTSIDE: outside of the frame border
7316 OVER_TEXT: over text in the text area
7322 -- nil if the coordinates are not over a glyph or a toolbar button.
7326 -- an extent, if the coordinates are over a glyph in the text area
7329 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
7330 equivalent coordinates relative to the upper-left corner of the glyph.
7332 If the coordinates are over a character, OBJ_X and OBJ_Y give the
7333 equivalent coordinates relative to the upper-left corner of the character.
7335 Otherwise, OBJ_X and OBJ_Y are undefined.
7339 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
7340 int *col, int *row, int *obj_x, int *obj_y,
7341 struct window **w, Bufpos *bufpos,
7342 Bufpos *closest, Charcount *modeline_closest,
7343 Lisp_Object *obj1, Lisp_Object *obj2)
7346 struct pixel_to_glyph_translation_cache *cache;
7348 int frm_left, frm_right, frm_top, frm_bottom;
7349 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
7350 int position = OVER_NOTHING;
7351 int device_check_failed = 0;
7352 display_line_dynarr *dla;
7354 /* This is a safety valve in case this got called with a frame in
7355 the middle of being deleted. */
7356 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
7358 device_check_failed = 1;
7359 d = NULL, cache = NULL; /* Warning suppression */
7363 d = XDEVICE (f->device);
7364 cache = &d->pixel_to_glyph_cache;
7367 if (!device_check_failed
7369 && cache->frame == f
7370 && cache->low_x_coord <= x_coord
7371 && cache->high_x_coord > x_coord
7372 && cache->low_y_coord <= y_coord
7373 && cache->high_y_coord > y_coord)
7377 *obj_x = cache->obj_x;
7378 *obj_y = cache->obj_y;
7380 *bufpos = cache->bufpos;
7381 *closest = cache->closest;
7382 *modeline_closest = cache->modeline_closest;
7383 *obj1 = cache->obj1;
7384 *obj2 = cache->obj2;
7386 return cache->retval;
7397 *modeline_closest = -1;
7401 low_x_coord = x_coord;
7402 high_x_coord = x_coord + 1;
7403 low_y_coord = y_coord;
7404 high_y_coord = y_coord + 1;
7407 if (device_check_failed)
7408 return OVER_NOTHING;
7410 frm_left = FRAME_LEFT_BORDER_END (f);
7411 frm_right = FRAME_RIGHT_BORDER_START (f);
7412 frm_top = FRAME_TOP_BORDER_END (f);
7413 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
7415 /* Check if the mouse is outside of the text area actually used by
7417 if (y_coord < frm_top)
7419 if (y_coord >= FRAME_TOP_BORDER_START (f))
7421 low_y_coord = FRAME_TOP_BORDER_START (f);
7422 high_y_coord = frm_top;
7423 position = OVER_BORDER;
7425 else if (y_coord >= 0)
7428 high_y_coord = FRAME_TOP_BORDER_START (f);
7429 position = OVER_TOOLBAR;
7433 low_y_coord = y_coord;
7435 position = OVER_OUTSIDE;
7438 else if (y_coord >= frm_bottom)
7440 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
7442 low_y_coord = frm_bottom;
7443 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
7444 position = OVER_BORDER;
7446 else if (y_coord < FRAME_PIXHEIGHT (f))
7448 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
7449 high_y_coord = FRAME_PIXHEIGHT (f);
7450 position = OVER_TOOLBAR;
7454 low_y_coord = FRAME_PIXHEIGHT (f);
7455 high_y_coord = y_coord;
7456 position = OVER_OUTSIDE;
7460 if (position != OVER_TOOLBAR && position != OVER_BORDER)
7462 if (x_coord < frm_left)
7464 if (x_coord >= FRAME_LEFT_BORDER_START (f))
7466 low_x_coord = FRAME_LEFT_BORDER_START (f);
7467 high_x_coord = frm_left;
7468 position = OVER_BORDER;
7470 else if (x_coord >= 0)
7473 high_x_coord = FRAME_LEFT_BORDER_START (f);
7474 position = OVER_TOOLBAR;
7478 low_x_coord = x_coord;
7480 position = OVER_OUTSIDE;
7483 else if (x_coord >= frm_right)
7485 if (x_coord < FRAME_RIGHT_BORDER_END (f))
7487 low_x_coord = frm_right;
7488 high_x_coord = FRAME_RIGHT_BORDER_END (f);
7489 position = OVER_BORDER;
7491 else if (x_coord < FRAME_PIXWIDTH (f))
7493 low_x_coord = FRAME_RIGHT_BORDER_END (f);
7494 high_x_coord = FRAME_PIXWIDTH (f);
7495 position = OVER_TOOLBAR;
7499 low_x_coord = FRAME_PIXWIDTH (f);
7500 high_x_coord = x_coord;
7501 position = OVER_OUTSIDE;
7506 #ifdef HAVE_TOOLBARS
7507 if (position == OVER_TOOLBAR)
7509 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
7512 UPDATE_CACHE_RETURN;
7514 #endif /* HAVE_TOOLBARS */
7516 /* We still have to return the window the pointer is next to and its
7517 relative y position even if it is outside the x boundary. */
7518 if (x_coord < frm_left)
7520 else if (x_coord > frm_right)
7521 x_coord = frm_right;
7523 /* Same in reverse. */
7524 if (y_coord < frm_top)
7526 else if (y_coord > frm_bottom)
7527 y_coord = frm_bottom;
7529 /* Find what window the given coordinates are actually in. */
7530 window = f->root_window;
7531 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
7533 /* If we didn't find a window, we're done. */
7536 UPDATE_CACHE_RETURN;
7538 else if (position != OVER_NOTHING)
7541 *modeline_closest = -1;
7543 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
7546 UPDATE_CACHE_RETURN;
7550 /* Check if the window is a minibuffer but isn't active. */
7551 if (MINI_WINDOW_P (*w) && !minibuf_level)
7553 /* Must reset the window value since some callers will ignore
7554 the return value if it is set. */
7556 UPDATE_CACHE_RETURN;
7559 /* See if the point is over window vertical divider */
7560 if (window_needs_vertical_divider (*w))
7562 int div_x_high = WINDOW_RIGHT (*w);
7563 int div_x_low = div_x_high - window_divider_width (*w);
7564 int div_y_high = WINDOW_BOTTOM (*w);
7565 int div_y_low = WINDOW_TOP (*w);
7567 if (div_x_low < x_coord && x_coord <= div_x_high &&
7568 div_y_low < y_coord && y_coord <= div_y_high)
7570 low_x_coord = div_x_low;
7571 high_x_coord = div_x_high;
7572 low_y_coord = div_y_low;
7573 high_y_coord = div_y_high;
7574 position = OVER_V_DIVIDER;
7575 UPDATE_CACHE_RETURN;
7579 dla = window_display_lines (*w, CURRENT_DISP);
7581 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
7583 int really_over_nothing = 0;
7584 struct display_line *dl = Dynarr_atp (dla, *row);
7586 if ((int) (dl->ypos - dl->ascent) <= y_coord
7587 && y_coord <= (int) (dl->ypos + dl->descent))
7589 int check_margin_glyphs = 0;
7590 struct display_block *db = get_display_block_from_line (dl, TEXT);
7591 struct rune *rb = 0;
7593 if (x_coord < dl->bounds.left_white
7594 || x_coord >= dl->bounds.right_white)
7595 check_margin_glyphs = 1;
7597 low_y_coord = dl->ypos - dl->ascent;
7598 high_y_coord = dl->ypos + dl->descent + 1;
7600 if (position == OVER_BORDER
7601 || position == OVER_OUTSIDE
7602 || check_margin_glyphs)
7604 int x_check, left_bound;
7606 if (check_margin_glyphs)
7609 left_bound = dl->bounds.left_white;
7613 x_check = high_x_coord;
7614 left_bound = frm_left;
7617 if (Dynarr_length (db->runes))
7619 if (x_check <= left_bound)
7622 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
7624 *closest = Dynarr_atp (db->runes, 0)->bufpos;
7630 Dynarr_atp (db->runes,
7631 Dynarr_length (db->runes) - 1)->bufpos;
7634 Dynarr_atp (db->runes,
7635 Dynarr_length (db->runes) - 1)->bufpos;
7639 *modeline_closest += dl->offset;
7641 *closest += dl->offset;
7645 /* #### What should be here. */
7647 *modeline_closest = 0;
7652 if (check_margin_glyphs)
7654 if (x_coord < dl->bounds.left_in
7655 || x_coord >= dl->bounds.right_in)
7657 /* If we are over the outside margins then we
7658 know the loop over the text block isn't going
7659 to accomplish anything. So we go ahead and
7660 set what information we can right here and
7663 *obj_y = y_coord - (dl->ypos - dl->ascent);
7664 get_position_object (dl, obj1, obj2, x_coord,
7665 &low_x_coord, &high_x_coord);
7667 UPDATE_CACHE_RETURN;
7671 UPDATE_CACHE_RETURN;
7674 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
7676 int past_end = (*col == Dynarr_length (db->runes));
7679 rb = Dynarr_atp (db->runes, *col);
7682 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
7687 rb = Dynarr_atp (db->runes, *col);
7690 *bufpos = rb->bufpos + dl->offset;
7691 low_x_coord = rb->xpos;
7692 high_x_coord = rb->xpos + rb->width;
7694 if (rb->type == RUNE_DGLYPH)
7698 /* Find the first character after the glyph. */
7699 while (elt < Dynarr_length (db->runes))
7701 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
7705 (Dynarr_atp (db->runes, elt)->bufpos +
7709 (Dynarr_atp (db->runes, elt)->bufpos +
7717 /* In this case we failed to find a non-glyph
7718 character so we return the last position
7719 displayed on the line. */
7720 if (elt == Dynarr_length (db->runes))
7723 *modeline_closest = dl->end_bufpos + dl->offset;
7725 *closest = dl->end_bufpos + dl->offset;
7726 really_over_nothing = 1;
7732 *modeline_closest = rb->bufpos + dl->offset;
7734 *closest = rb->bufpos + dl->offset;
7739 *row = window_displayed_height (*w);
7741 if (position == OVER_NOTHING)
7742 position = OVER_MODELINE;
7744 if (rb->type == RUNE_DGLYPH)
7746 *obj1 = rb->object.dglyph.glyph;
7747 *obj2 = rb->object.dglyph.extent;
7749 else if (rb->type == RUNE_CHAR)
7760 UPDATE_CACHE_RETURN;
7763 || (rb->type == RUNE_CHAR
7764 && rb->object.chr.ch == '\n'))
7767 /* At this point we may have glyphs in the right
7769 if (check_margin_glyphs)
7770 get_position_object (dl, obj1, obj2, x_coord,
7771 &low_x_coord, &high_x_coord);
7772 UPDATE_CACHE_RETURN;
7777 if (rb->type == RUNE_DGLYPH)
7779 *obj1 = rb->object.dglyph.glyph;
7780 *obj2 = rb->object.dglyph.extent;
7782 else if (rb->type == RUNE_CHAR)
7793 *obj_x = x_coord - rb->xpos;
7794 *obj_y = y_coord - (dl->ypos - dl->ascent);
7796 /* At this point we may have glyphs in the left
7798 if (check_margin_glyphs)
7799 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
7801 if (position == OVER_NOTHING && !really_over_nothing)
7802 position = OVER_TEXT;
7804 UPDATE_CACHE_RETURN;
7811 *row = Dynarr_length (dla) - 1;
7812 if (FRAME_WIN_P (f))
7814 int bot_elt = Dynarr_length (dla) - 1;
7818 struct display_line *dl = Dynarr_atp (dla, bot_elt);
7819 int adj_area = y_coord - (dl->ypos + dl->descent);
7823 XSETWINDOW (lwin, *w);
7824 default_face_height_and_width (lwin, 0, &defheight);
7826 *row += (adj_area / defheight);
7830 /* #### This should be checked out some more to determine what
7831 should really be going on. */
7832 if (!MARKERP ((*w)->start[CURRENT_DISP]))
7835 *closest = end_of_last_line (*w,
7836 marker_position ((*w)->start[CURRENT_DISP]));
7838 UPDATE_CACHE_RETURN;
7840 #undef UPDATE_CACHE_RETURN
7843 /***************************************************************************/
7845 /* Lisp functions */
7847 /***************************************************************************/
7849 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
7850 Ensure that all minibuffers are correctly showing the echo area.
7854 Lisp_Object devcons, concons;
7856 DEVICE_LOOP_NO_BREAK (devcons, concons)
7858 struct device *d = XDEVICE (XCAR (devcons));
7859 Lisp_Object frmcons;
7861 DEVICE_FRAME_LOOP (frmcons, d)
7863 struct frame *f = XFRAME (XCAR (frmcons));
7865 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
7867 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
7869 * If the frame size has changed, there may be random
7870 * chud on the screen left from previous messages
7871 * because redisplay_frame hasn't been called yet.
7872 * Clear the screen to get rid of the potential mess.
7874 if (f->echo_area_garbaged)
7876 DEVMETH (d, clear_frame, (f));
7877 f->echo_area_garbaged = 0;
7879 redisplay_window (window, 0);
7880 call_redisplay_end_triggers (XWINDOW (window), 0);
7884 /* We now call the output_end routine for tty frames. We delay
7885 doing so in order to avoid cursor flicker. So much for 100%
7887 if (DEVICE_TTY_P (d))
7888 DEVMETH (d, output_end, (d));
7895 restore_disable_preemption_value (Lisp_Object value)
7897 disable_preemption = XINT (value);
7901 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
7902 Clear frame FRAME and output again what is supposed to appear on it.
7903 FRAME defaults to the selected frame if omitted.
7904 Normally, redisplay is preempted as normal if input arrives. However,
7905 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7906 input and is guaranteed to proceed to completion.
7908 (frame, no_preempt))
7910 struct frame *f = decode_frame (frame);
7911 int count = specpdl_depth ();
7913 if (!NILP (no_preempt))
7915 record_unwind_protect (restore_disable_preemption_value,
7916 make_int (disable_preemption));
7917 disable_preemption++;
7921 redisplay_frame (f, 1);
7923 return unbind_to (count, Qnil);
7926 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
7927 Ensure that FRAME's contents are correctly displayed.
7928 This differs from `redraw-frame' in that it only redraws what needs to
7929 be updated, as opposed to unconditionally clearing and redrawing
7931 FRAME defaults to the selected frame if omitted.
7932 Normally, redisplay is preempted as normal if input arrives. However,
7933 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7934 input and is guaranteed to proceed to completion.
7936 (frame, no_preempt))
7938 struct frame *f = decode_frame (frame);
7939 int count = specpdl_depth ();
7941 if (!NILP (no_preempt))
7943 record_unwind_protect (restore_disable_preemption_value,
7944 make_int (disable_preemption));
7945 disable_preemption++;
7948 redisplay_frame (f, 1);
7950 return unbind_to (count, Qnil);
7953 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
7954 Clear device DEVICE and output again what is supposed to appear on it.
7955 DEVICE defaults to the selected device if omitted.
7956 Normally, redisplay is preempted as normal if input arrives. However,
7957 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7958 input and is guaranteed to proceed to completion.
7960 (device, no_preempt))
7962 struct device *d = decode_device (device);
7963 Lisp_Object frmcons;
7964 int count = specpdl_depth ();
7966 if (!NILP (no_preempt))
7968 record_unwind_protect (restore_disable_preemption_value,
7969 make_int (disable_preemption));
7970 disable_preemption++;
7973 DEVICE_FRAME_LOOP (frmcons, d)
7975 XFRAME (XCAR (frmcons))->clear = 1;
7977 redisplay_device (d);
7979 return unbind_to (count, Qnil);
7982 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
7983 Ensure that DEVICE's contents are correctly displayed.
7984 This differs from `redraw-device' in that it only redraws what needs to
7985 be updated, as opposed to unconditionally clearing and redrawing
7987 DEVICE defaults to the selected device if omitted.
7988 Normally, redisplay is preempted as normal if input arrives. However,
7989 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7990 input and is guaranteed to proceed to completion.
7992 (device, no_preempt))
7994 struct device *d = decode_device (device);
7995 int count = specpdl_depth ();
7997 if (!NILP (no_preempt))
7999 record_unwind_protect (restore_disable_preemption_value,
8000 make_int (disable_preemption));
8001 disable_preemption++;
8004 redisplay_device (d);
8006 return unbind_to (count, Qnil);
8009 /* Big lie. Big lie. This will force all modelines to be updated
8010 regardless if the all flag is set or not. It remains in existence
8011 solely for backwards compatibility. */
8012 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8013 Force the modeline of the current buffer to be redisplayed.
8014 With optional non-nil ALL, force redisplay of all modelines.
8018 MARK_MODELINE_CHANGED;
8022 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8023 Force an immediate update of the cursor on FRAME.
8024 FRAME defaults to the selected frame if omitted.
8028 redisplay_redraw_cursor (decode_frame (frame), 1);
8033 /***************************************************************************/
8035 /* Lisp-variable change triggers */
8037 /***************************************************************************/
8040 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
8043 /* Nothing to be done? */
8047 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
8048 Lisp_Object in_object, int flags)
8050 /* #### clip_changed should really be renamed something like
8051 global_redisplay_change. */
8057 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8060 if (WINDOWP (locale))
8062 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (locale)));
8063 MARK_FRAME_GLYPHS_CHANGED (f);
8065 else if (FRAMEP (locale))
8067 struct frame *f = XFRAME (locale);
8068 MARK_FRAME_GLYPHS_CHANGED (f);
8070 else if (DEVICEP (locale))
8072 Lisp_Object frmcons;
8073 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
8075 struct frame *f = XFRAME (XCAR (frmcons));
8076 MARK_FRAME_GLYPHS_CHANGED (f);
8079 else if (CONSOLEP (locale))
8081 Lisp_Object frmcons, devcons;
8082 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
8084 struct frame *f = XFRAME (XCAR (frmcons));
8085 MARK_FRAME_GLYPHS_CHANGED (f);
8088 else /* global or buffer */
8090 Lisp_Object frmcons, devcons, concons;
8091 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
8093 struct frame *f = XFRAME (XCAR (frmcons));
8094 MARK_FRAME_GLYPHS_CHANGED (f);
8100 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
8103 if (XFRAME (w->frame)->init_finished)
8104 Fforce_cursor_redisplay (w->frame);
8107 #ifdef MEMORY_USAGE_STATS
8110 /***************************************************************************/
8112 /* memory usage computation */
8114 /***************************************************************************/
8117 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
8119 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8123 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
8124 struct overhead_stats *ovstats)
8131 total = Dynarr_memory_usage (dyn, ovstats);
8132 for (i = 0; i < Dynarr_largest (dyn); i++)
8133 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
8139 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
8140 struct overhead_stats *ovstats)
8142 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8146 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
8147 struct overhead_stats *ovstats)
8154 total = Dynarr_memory_usage (dyn, ovstats);
8155 for (i = 0; i < Dynarr_largest (dyn); i++)
8157 struct display_line *dl = &Dynarr_at (dyn, i);
8158 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
8159 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
8160 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
8167 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
8168 struct overhead_stats *ovstats)
8170 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8173 #endif /* MEMORY_USAGE_STATS */
8176 /***************************************************************************/
8178 /* initialization */
8180 /***************************************************************************/
8183 init_redisplay (void)
8185 disable_preemption = 0;
8186 preemption_count = 0;
8187 max_preempts = INIT_MAX_PREEMPTS;
8191 cmotion_display_lines = Dynarr_new (display_line);
8192 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
8193 formatted_string_emchar_dynarr = Dynarr_new (Emchar);
8194 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
8195 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
8196 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
8197 internal_cache = Dynarr_new (line_start_cache);
8198 xzero (formatted_string_display_line);
8201 /* window system is nil when in -batch mode */
8202 if (!initialized || noninteractive)
8205 /* If the user wants to use a window system, we shouldn't bother
8206 initializing the terminal. This is especially important when the
8207 terminal is so dumb that emacs gives up before and doesn't bother
8208 using the window system.
8210 If the DISPLAY environment variable is set, try to use X, and die
8211 with an error message if that doesn't work. */
8213 #ifdef HAVE_X_WINDOWS
8214 if (!strcmp (display_use, "x"))
8216 /* Some stuff checks this way early. */
8217 Vwindow_system = Qx;
8218 Vinitial_window_system = Qx;
8221 #endif /* HAVE_X_WINDOWS */
8223 #ifdef HAVE_MS_WINDOWS
8224 if (!strcmp (display_use, "mswindows"))
8226 /* Some stuff checks this way early. */
8227 Vwindow_system = Qmswindows;
8228 Vinitial_window_system = Qmswindows;
8231 #endif /* HAVE_MS_WINDOWS */
8234 /* If no window system has been specified, try to use the terminal. */
8237 stderr_out ("XEmacs: standard input is not a tty\n");
8241 /* Look at the TERM variable */
8242 if (!getenv ("TERM"))
8244 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
8248 Vinitial_window_system = Qtty;
8250 #else /* not HAVE_TTY */
8251 /* No DISPLAY specified, and no TTY support. */
8252 stderr_out ("XEmacs: Cannot open display.\n\
8253 Please set the environmental variable DISPLAY to an appropriate value.\n");
8260 syms_of_redisplay (void)
8262 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
8263 #ifndef INHIBIT_REDISPLAY_HOOKS
8264 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
8265 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
8266 #endif /* INHIBIT_REDISPLAY_HOOKS */
8267 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
8268 defsymbol (&Qbar_cursor, "bar-cursor");
8269 defsymbol (&Qwindow_scroll_functions, "window-scroll-functions");
8270 defsymbol (&Qredisplay_end_trigger_functions,
8271 "redisplay-end-trigger-functions");
8273 DEFSUBR (Fredisplay_echo_area);
8274 DEFSUBR (Fredraw_frame);
8275 DEFSUBR (Fredisplay_frame);
8276 DEFSUBR (Fredraw_device);
8277 DEFSUBR (Fredisplay_device);
8278 DEFSUBR (Fredraw_modeline);
8279 DEFSUBR (Fforce_cursor_redisplay);
8283 vars_of_redisplay (void)
8286 staticpro (&last_arrow_position);
8287 staticpro (&last_arrow_string);
8288 last_arrow_position = Qnil;
8289 last_arrow_string = Qnil;
8292 updating_line_start_cache = 0;
8294 /* #### Probably temporary */
8295 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
8296 \(Temporary) Setting this will impact the performance of the internal
8299 cache_adjustment = 2;
8301 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
8302 Minimum pixel height for clipped bottom display line.
8303 A clipped line shorter than this won't be displayed.
8305 redisplay_variable_changed);
8308 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
8309 Minimum visible area for clipped glyphs at right boundary.
8310 Clipped glyphs shorter than this won't be displayed.
8311 Only pixmap glyph instances are currently allowed to be clipped.
8313 redisplay_variable_changed);
8314 horizontal_clip = 5;
8316 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
8317 String displayed by modeline-format's "%m" specification.
8319 Vglobal_mode_string = Qnil;
8321 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
8322 Marker for where to display an arrow on top of the buffer text.
8323 This must be the beginning of a line in order to work.
8324 See also `overlay-arrow-string'.
8325 */ , redisplay_variable_changed);
8326 Voverlay_arrow_position = Qnil;
8328 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
8329 String to display as an arrow. See also `overlay-arrow-position'.
8331 redisplay_variable_changed);
8332 Voverlay_arrow_string = Qnil;
8334 DEFVAR_INT ("scroll-step", &scroll_step /*
8335 *The number of lines to try scrolling a window by when point moves out.
8336 If that fails to bring point back on frame, point is centered instead.
8337 If this is zero, point is always centered after it moves off screen.
8341 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
8342 *Scroll up to this many lines, to bring point back on screen.
8344 scroll_conservatively = 0;
8346 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
8347 &truncate_partial_width_windows /*
8348 *Non-nil means truncate lines in all windows less than full frame wide.
8350 redisplay_variable_changed);
8351 truncate_partial_width_windows = 1;
8353 DEFVAR_BOOL ("visible-bell", &visible_bell /*
8354 *Non-nil means try to flash the frame to represent a bell.
8358 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
8359 *Non-nil means no need to redraw entire frame after suspending.
8360 A non-nil value is useful if the terminal can automatically preserve
8361 Emacs's frame display when you reenter Emacs.
8362 It is up to you to set this variable if your terminal can do that.
8364 no_redraw_on_reenter = 0;
8366 DEFVAR_LISP ("window-system", &Vwindow_system /*
8367 A symbol naming the window-system under which Emacs is running,
8368 such as `x', or nil if emacs is running on an ordinary terminal.
8370 Do not use this variable, except for GNU Emacs compatibility, as it
8371 gives wrong values in a multi-device environment. Use `console-type'
8374 Vwindow_system = Qnil;
8376 /* #### Temporary shit until window-system is eliminated. */
8377 DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /*
8380 Vinitial_window_system = Qnil;
8382 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
8383 Non-nil means put cursor in minibuffer, at end of any message there.
8385 cursor_in_echo_area = 0;
8387 /* #### Shouldn't this be generalized as follows:
8389 if nil, use block cursor.
8390 if a number, use a bar cursor of that width.
8391 Otherwise, use a 1-pixel bar cursor.
8393 #### Or better yet, this variable should be trashed entirely
8394 (use a Lisp-magic variable to maintain compatibility)
8395 and a specifier `cursor-shape' added, which allows a block
8396 cursor, a bar cursor, a flashing block or bar cursor,
8397 maybe a caret cursor, etc. */
8399 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
8400 Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
8404 #ifndef INHIBIT_REDISPLAY_HOOKS
8405 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
8406 Function or functions to run before every redisplay.
8407 Functions on this hook must be careful to avoid signalling errors!
8409 Vpre_redisplay_hook = Qnil;
8411 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
8412 Function or functions to run after every redisplay.
8413 Functions on this hook must be careful to avoid signalling errors!
8415 Vpost_redisplay_hook = Qnil;
8416 #endif /* INHIBIT_REDISPLAY_HOOKS */
8418 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
8419 Bump this to tell the C code to call `display-warning-buffer'
8420 at next redisplay. You should not normally change this; the function
8421 `display-warning' automatically does this at appropriate times.
8423 display_warning_tick = 0;
8425 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
8426 Non-nil means inhibit display of warning messages.
8427 You should *bind* this, not set it. Any pending warning messages
8428 will be displayed when the binding no longer applies.
8430 /* reset to 0 by startup.el after the splash screen has displayed.
8431 This way, the warnings don't obliterate the splash screen. */
8432 inhibit_warning_display = 1;
8434 DEFVAR_LISP ("window-size-change-functions",
8435 &Vwindow_size_change_functions /*
8436 Not currently implemented.
8437 Functions called before redisplay, if window sizes have changed.
8438 The value should be a list of functions that take one argument.
8439 Just before redisplay, for each frame, if any of its windows have changed
8440 size since the last redisplay, or have been split or deleted,
8441 all the functions in the list are called, with the frame as argument.
8443 Vwindow_size_change_functions = Qnil;
8445 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
8446 Not currently implemented.
8447 Functions to call before redisplaying a window with scrolling.
8448 Each function is called with two arguments, the window
8449 and its new display-start position. Note that the value of `window-end'
8450 is not valid when these functions are called.
8452 Vwindow_scroll_functions = Qnil;
8454 DEFVAR_LISP ("redisplay-end-trigger-functions",
8455 &Vredisplay_end_trigger_functions /*
8456 See `set-window-redisplay-end-trigger'.
8458 Vredisplay_end_trigger_functions = Qnil;
8460 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
8461 *Non-nil means column display number starts at 1.
8463 column_number_start_at_one = 0;
8467 specifier_vars_of_redisplay (void)
8469 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
8470 *Width of left margin.
8471 This is a specifier; use `set-specifier' to change it.
8473 Vleft_margin_width = Fmake_specifier (Qnatnum);
8474 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
8475 set_specifier_caching (Vleft_margin_width,
8476 slot_offset (struct window, left_margin_width),
8477 some_window_value_changed,
8478 slot_offset (struct frame, left_margin_width),
8479 margin_width_changed_in_frame);
8481 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
8482 *Width of right margin.
8483 This is a specifier; use `set-specifier' to change it.
8485 Vright_margin_width = Fmake_specifier (Qnatnum);
8486 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
8487 set_specifier_caching (Vright_margin_width,
8488 slot_offset (struct window, right_margin_width),
8489 some_window_value_changed,
8490 slot_offset (struct frame, right_margin_width),
8491 margin_width_changed_in_frame);
8493 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
8494 *Minimum ascent height of lines.
8495 This is a specifier; use `set-specifier' to change it.
8497 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
8498 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
8499 set_specifier_caching (Vminimum_line_ascent,
8500 slot_offset (struct window, minimum_line_ascent),
8501 some_window_value_changed,
8504 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
8505 *Minimum descent height of lines.
8506 This is a specifier; use `set-specifier' to change it.
8508 Vminimum_line_descent = Fmake_specifier (Qnatnum);
8509 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
8510 set_specifier_caching (Vminimum_line_descent,
8511 slot_offset (struct window, minimum_line_descent),
8512 some_window_value_changed,
8515 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
8516 *Non-nil means use the left outside margin as extra whitespace when
8517 displaying 'whitespace or 'inside-margin glyphs.
8518 This is a specifier; use `set-specifier' to change it.
8520 Vuse_left_overflow = Fmake_specifier (Qboolean);
8521 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
8522 set_specifier_caching (Vuse_left_overflow,
8523 slot_offset (struct window, use_left_overflow),
8524 some_window_value_changed,
8527 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
8528 *Non-nil means use the right outside margin as extra whitespace when
8529 displaying 'whitespace or 'inside-margin glyphs.
8530 This is a specifier; use `set-specifier' to change it.
8532 Vuse_right_overflow = Fmake_specifier (Qboolean);
8533 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
8534 set_specifier_caching (Vuse_right_overflow,
8535 slot_offset (struct window, use_right_overflow),
8536 some_window_value_changed,
8539 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
8540 *Non-nil means the text cursor is visible (this is usually the case).
8541 This is a specifier; use `set-specifier' to change it.
8543 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
8544 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
8545 set_specifier_caching (Vtext_cursor_visible_p,
8546 slot_offset (struct window, text_cursor_visible_p),
8547 text_cursor_visible_p_changed,