1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Free Software Foundation, Inc.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1995 Sun Microsystems, Inc.
6 Copyright (C) 1996 Chuck Thompson.
8 This file is part of XEmacs.
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 /* Synched up with: Not in FSF. */
27 /* Author: Chuck Thompson */
29 /* Fixed up by Ben Wing for Mule */
31 /* This file has been Mule-ized. */
33 /*****************************************************************************
34 The Golden Rules of Redisplay
36 First: It Is Better To Be Correct Than Fast
37 Second: Thou Shalt Not Run Elisp From Within Redisplay
38 Third: It Is Better To Be Fast Than Not To Be
39 ****************************************************************************/
58 #include "redisplay.h"
61 #include "line-number.h"
63 #include "file-coding.h"
69 #include "console-tty.h"
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 #define VERTICAL_CLIP(w, display) \
89 ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
93 /* The following structures are completely private to redisplay.c so
94 we put them here instead of in a header file, for modularity. */
96 /* NOTE: Bytinds not Bufpos's in this structure. */
98 typedef struct position_redisplay_data_type
100 /* This information is normally filled in by the create_*_block
101 routines and is used by the add_*_rune routines. */
103 /* if we are working with strings rather than buffers we need a
104 handle to the string */
107 struct display_block *db;
108 struct display_line *dl;
109 Emchar ch; /* Character that is to be added. This is
110 used to communicate this information to
111 add_emchar_rune(). */
112 Lisp_Object last_charset; /* The charset of the previous character.
113 Used to optimize some lookups -- we
114 only have to do some things when
115 the charset changes. */
116 face_index last_findex; /* The face index of the previous character.
117 Needed to ensure the validity of the
118 last_charset optimization. */
120 int last_char_width; /* The width of the previous character. */
121 int font_is_bogus; /* If true, it means we couldn't instantiate
122 the font for this charset, so we substitute
123 ~'s from the ASCII charset. */
128 int blank_width; /* Width of the blank that is to be added.
129 This is used to communicate this information
132 This is also used rather cheesily to
133 communicate the width of the eol-cursor-size
134 blank that exists at the end of the line.
135 add_emchar_rune() is called cheesily with
136 the non-printing char '\n', which is stuck
137 in the output routines with its width being
139 Bytind bi_cursor_bufpos;/* This stores the buffer position of the cursor. */
140 unsigned int cursor_type :3;
141 int cursor_x; /* rune block cursor is at */
142 int start_col; /* Number of character columns (each column has
143 a width of the default char width) that still
144 need to be skipped. This is used for horizontal
145 scrolling, where a certain number of columns
146 (those off the left side of the screen) need
147 to be skipped before anything is displayed. */
148 Bytind bi_start_col_enabled;
149 int start_col_xoffset; /* Number of pixels that still need to
150 be skipped. This is used for
151 horizontal scrolling of glyphs, where we want
152 to be able to scroll over part of the glyph. */
154 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
155 glyph differs from space_width (w).
156 0 if no hscroll glyph was used,
157 i.e. the window is not scrolled
158 horizontally. Used in tab
161 /* Information about the face the text should be displayed in and
162 any begin-glyphs and end-glyphs. */
163 struct extent_fragment *ef;
166 /* The height of a pixmap may either be predetermined if the user
167 has set a baseline value, or it may be dependent on whatever the
168 line ascent and descent values end up being, based just on font
169 information. In the first case we can immediately update the
170 values, thus their inclusion here. In the last case we cannot
171 determine the actual contribution to the line height until we
172 have finished laying out all text on the line. Thus we propagate
173 the max height of such pixmaps and do a final calculation after
174 all text has been added to the line. */
177 int max_pixmap_height;
179 Lisp_Object result_str; /* String where we put the result of
180 generating a formatted string in the modeline. */
181 int is_modeline; /* Non-zero if we're generating the modeline. */
182 Charcount modeline_charpos; /* Number of chars used in result_str so far;
183 corresponds to bytepos. */
184 Bytecount bytepos; /* Number of bytes used in result_str so far.
185 We don't actually copy the bytes into result_str
186 until the end because we don't know how big the
187 string is going to be until then. */
198 /* Data that should be propagated to the next line. Either a single
199 Emchar or a string of Bufbyte's.
201 The actual data that is propagated ends up as a Dynarr of these
204 #### It's unclean that both Emchars and Bufbytes are here.
207 typedef struct prop_block prop_block;
217 Bytecount len; /* length of the string. */
223 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
224 unsigned int cursor_type :3;
237 Dynarr_declare (prop_block);
241 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
242 Charcount pos, Charcount min_pos,
243 Charcount max_pos, Lisp_Object elt,
244 int depth, int max_pixsize,
245 face_index findex, int type,
247 Lisp_Object cur_ext);
248 static prop_block_dynarr *add_glyph_rune (pos_data *data,
249 struct glyph_block *gb,
250 int pos_type, int allow_cursor,
251 struct glyph_cachel *cachel);
252 static Bytind create_text_block (struct window *w, struct display_line *dl,
253 Bytind bi_start_pos, prop_block_dynarr **prop,
255 static int create_overlay_glyph_block (struct window *w,
256 struct display_line *dl);
257 static void create_left_glyph_block (struct window *w,
258 struct display_line *dl,
260 static void create_right_glyph_block (struct window *w,
261 struct display_line *dl);
262 static void redisplay_windows (Lisp_Object window, int skip_selected);
263 static void decode_mode_spec (struct window *w, Emchar spec, int type);
264 static void free_display_line (struct display_line *dl);
265 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
266 Bufpos point, int no_regen);
267 static int point_visible (struct window *w, Bufpos point, int type);
269 /* This used to be 10 but 30 seems to give much better performance. */
270 #define INIT_MAX_PREEMPTS 30
271 static int max_preempts;
273 #define REDISPLAY_PREEMPTION_CHECK \
276 (!disable_preemption && \
277 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
278 (!INTERACTIVE || detect_input_pending ()))))
281 * Redisplay global variables.
284 /* We need a third set of display structures for the cursor motion
285 routines. We used to just give each window a third set. However,
286 we always fully regenerate the structures when needed so there
287 isn't any reason we need more than a single set. */
288 display_line_dynarr *cmotion_display_lines;
290 /* We store the extents that we need to generate in a Dynarr and then
291 frob them all on at the end of generating the string. We do it
292 this way rather than adding them as we generate the string because
293 we don't store the text into the resulting string until we're done
294 (to avoid having to resize the string multiple times), and we don't
295 want to go around adding extents to a string when the extents might
296 stretch off the end of the string. */
297 static EXTENT_dynarr *formatted_string_extent_dynarr;
298 static Bytecount_dynarr *formatted_string_extent_start_dynarr;
299 static Bytecount_dynarr *formatted_string_extent_end_dynarr;
302 /* #### probably temporary */
303 Fixnum cache_adjustment;
305 /* This holds a string representing the text corresponding to a single
307 static Bufbyte_dynarr *mode_spec_bufbyte_string;
309 int in_display; /* 1 if in redisplay. */
311 int disable_preemption; /* Used for debugging redisplay and for
314 /* We only allow max_preempts preemptions before we force a redisplay. */
315 static int preemption_count;
317 /* Minimum pixel height of clipped bottom display line. */
318 Fixnum vertical_clip;
320 /* Minimum visible pixel width of clipped glyphs at right margin. */
321 Fixnum horizontal_clip;
323 /* Nonzero means reading single-character input with prompt
324 so put cursor on minibuffer after the prompt. */
325 int cursor_in_echo_area;
326 Lisp_Object Qcursor_in_echo_area;
328 /* Nonzero means truncate lines in all windows less wide than the frame */
329 int truncate_partial_width_windows;
331 /* non-nil if a buffer has changed since the last time redisplay completed */
333 int buffers_changed_set;
335 /* non-nil if hscroll has changed somewhere or a buffer has been
336 narrowed or widened */
338 int clip_changed_set;
340 /* non-nil if any extent has changed since the last time redisplay completed */
342 int extents_changed_set;
344 /* non-nil if any face has changed since the last time redisplay completed */
347 /* Nonzero means some frames have been marked as garbaged */
350 /* non-zero if any of the builtin display glyphs (continuation,
351 hscroll, control-arrow, etc) is in need of updating
354 int glyphs_changed_set;
356 /* non-zero if any subwindow has been deleted. */
357 int subwindows_changed;
358 int subwindows_changed_set;
360 /* non-zero if any displayed subwindow is in need of updating
362 int subwindows_state_changed;
363 int subwindows_state_changed_set;
365 /* This variable is 1 if the icon has to be updated.
366 It is set to 1 when `frame-icon-glyph' changes. */
368 int icon_changed_set;
370 /* This variable is 1 if the menubar widget has to be updated.
371 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
374 int menubar_changed_set;
376 /* true iff we should redraw the modelines on the next redisplay */
377 int modeline_changed;
378 int modeline_changed_set;
380 /* non-nil if point has changed in some buffer since the last time
381 redisplay completed */
383 int point_changed_set;
385 /* non-nil if some frame has changed its size */
388 /* non-nil if some device has signaled that it wants to change size */
389 int asynch_device_change_pending;
391 /* non-nil if any toolbar has changed */
393 int toolbar_changed_set;
395 /* non-nil if any gutter has changed */
397 int gutter_changed_set;
399 /* non-nil if any window has changed since the last time redisplay completed */
402 /* non-nil if any frame's window structure has changed since the last
403 time redisplay completed */
404 int windows_structure_changed;
406 /* If non-nil, use vertical bar cursor. */
407 Lisp_Object Vbar_cursor;
408 Lisp_Object Qbar_cursor;
410 Lisp_Object Vvisible_bell; /* If true and the terminal will support it
411 then the frame will flash instead of
412 beeping when an error occurs */
414 /* Nonzero means no need to redraw the entire frame on resuming
415 a suspended Emacs. This is useful on terminals with multiple pages,
416 where one page is used for Emacs and another for all else. */
417 int no_redraw_on_reenter;
419 Lisp_Object Vwindow_system; /* nil or a symbol naming the window system
420 under which emacs is running
421 ('x is the only current possibility) */
422 Lisp_Object Vinitial_window_system;
424 Lisp_Object Vglobal_mode_string;
426 /* The number of lines scroll a window by when point leaves the window; if
427 it is <=0 then point is centered in the window */
430 /* Scroll up to this many lines, to bring point back on screen. */
431 Fixnum scroll_conservatively;
433 /* Marker for where to display an arrow on top of the buffer text. */
434 Lisp_Object Voverlay_arrow_position;
435 /* String to display for the arrow. */
436 Lisp_Object Voverlay_arrow_string;
438 Lisp_Object Vwindow_size_change_functions;
439 Lisp_Object Vwindow_scroll_functions;
440 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
442 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook;
445 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
447 #ifndef INHIBIT_REDISPLAY_HOOKS
448 /* #### Chuck says: I think this needs more thought.
449 Think about this for 19.14. */
450 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
451 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
452 #endif /* INHIBIT_REDISPLAY_HOOKS */
454 static Fixnum last_display_warning_tick;
455 static Fixnum display_warning_tick;
456 Lisp_Object Qdisplay_warning_buffer;
457 int inhibit_warning_display;
459 Lisp_Object Vleft_margin_width, Vright_margin_width;
460 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
461 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
462 Lisp_Object Vtext_cursor_visible_p;
464 int column_number_start_at_one;
466 Lisp_Object Qtop_bottom;
468 #define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset)
471 /***************************************************************************/
473 /* low-level interfaces onto device routines */
475 /***************************************************************************/
478 redisplay_text_width_emchar_string (struct window *w, int findex,
479 Emchar *str, Charcount len)
481 unsigned char charsets[NUM_LEADING_BYTES];
484 find_charsets_in_emchar_string (charsets, str, len);
485 XSETWINDOW (window, w);
486 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
488 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))),
489 text_width, (XFRAME (WINDOW_FRAME (w)),
490 WINDOW_FACE_CACHEL (w, findex), str, len));
493 static Emchar_dynarr *rtw_emchar_dynarr;
496 redisplay_text_width_string (struct window *w, int findex,
497 Bufbyte *nonreloc, Lisp_Object reloc,
498 Bytecount offset, Bytecount len)
500 if (!rtw_emchar_dynarr)
501 rtw_emchar_dynarr = Dynarr_new (Emchar);
502 Dynarr_reset (rtw_emchar_dynarr);
504 fixup_internal_substring (nonreloc, reloc, offset, &len);
506 nonreloc = XSTRING_DATA (reloc);
507 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
508 return redisplay_text_width_emchar_string
509 (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
510 Dynarr_length (rtw_emchar_dynarr));
514 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face,
515 Bufbyte *nonreloc, Lisp_Object reloc,
516 Bytecount offset, Bytecount len)
518 unsigned char charsets[NUM_LEADING_BYTES];
520 struct face_cachel cachel;
522 if (!rtw_emchar_dynarr)
523 rtw_emchar_dynarr = Dynarr_new (Emchar);
524 Dynarr_reset (rtw_emchar_dynarr);
526 fixup_internal_substring (nonreloc, reloc, offset, &len);
528 nonreloc = XSTRING_DATA (reloc);
529 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
530 find_charsets_in_bufbyte_string (charsets, nonreloc, len);
531 reset_face_cachel (&cachel);
533 XSETFRAME (frame, f);
534 ensure_face_cachel_complete (&cachel, frame, charsets);
535 return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
536 text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
537 Dynarr_length (rtw_emchar_dynarr)));
540 /* Return the display block from DL of the given TYPE. A display line
541 can have only one display block of each possible type. If DL does
542 not have a block of type TYPE, one will be created and added to DL. */
544 struct display_block *
545 get_display_block_from_line (struct display_line *dl, enum display_type type)
548 struct display_block db;
550 /* Check if this display line already has a block of the desired type and
552 if (dl->display_blocks)
554 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++)
556 if (Dynarr_at (dl->display_blocks, elt).type == type)
557 return Dynarr_atp (dl->display_blocks, elt);
560 /* There isn't an active block of the desired type, but there
561 might still be allocated blocks we need to reuse. */
562 if (elt < Dynarr_largest (dl->display_blocks))
564 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
566 /* 'add' the block to the list */
567 Dynarr_increment (dl->display_blocks);
569 /* initialize and return */
576 /* This line doesn't have any display blocks, so initialize the display
578 dl->display_blocks = Dynarr_new (display_block);
581 /* The line doesn't have a block of the desired type so go ahead and create
582 one and add it to the line. */
585 db.runes = Dynarr_new (rune);
586 Dynarr_add (dl->display_blocks, db);
588 /* Return the newly added display block. */
589 elt = Dynarr_length (dl->display_blocks) - 1;
591 return Dynarr_atp (dl->display_blocks, elt);
595 tab_char_width (struct window *w)
597 struct buffer *b = XBUFFER (w->buffer);
598 int char_tab_width = XINT (b->tab_width);
600 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8;
602 return char_tab_width;
606 space_width (struct window *w)
608 /* While tabs are traditional composed of spaces, for variable-width
609 fonts the space character tends to give too narrow a value. So
610 we use 'n' instead. Except that we don't. We use the default
611 character width for the default face. If this is actually
612 defined by the font then it is probably the best thing to
613 actually use. If it isn't, we have assumed it is 'n' and have
614 already calculated its width. Thus we can avoid a call to
615 XTextWidth on X frames by just querying the default width. */
616 return XFONT_INSTANCE
617 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width;
621 tab_pix_width (struct window *w)
623 return space_width (w) * tab_char_width (w);
626 /* Given a pixel position in a window, return the pixel location of
627 the next tabstop. Tabs are calculated from the left window edge in
628 terms of spaces displayed in the default face. Formerly the space
629 width was determined using the currently active face. That method
630 leads to tabstops which do not line up. */
633 next_tab_position (struct window *w, int start_pixpos, int left_pixpos)
635 int n_pos = left_pixpos;
636 int pix_tab_width = tab_pix_width (w);
638 /* Adjust n_pos for any hscrolling which has happened. */
639 if (WINDOW_SCROLLED (w))
640 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset;
642 while (n_pos <= start_pixpos)
643 n_pos += pix_tab_width;
648 /* For the given window, calculate the outside and margin boundaries for a
649 display line. The whitespace boundaries must be calculated by the text
653 calculate_display_line_boundaries (struct window *w, int modeline)
655 layout_bounds bounds;
657 /* Set the outermost boundaries which are the boundaries of the
658 window itself minus the gutters (and minus the scrollbars if this
659 is for the modeline). */
662 bounds.left_out = WINDOW_TEXT_LEFT (w);
663 bounds.right_out = WINDOW_TEXT_RIGHT (w);
667 bounds.left_out = WINDOW_MODELINE_LEFT (w);
668 bounds.right_out = WINDOW_MODELINE_RIGHT (w);
671 /* The inner boundaries mark where the glyph margins are located. */
672 bounds.left_in = bounds.left_out + window_left_margin_width (w);
673 bounds.right_in = bounds.right_out - window_right_margin_width (w);
675 /* We cannot fully calculate the whitespace boundaries as they
676 depend on the contents of the line being displayed. */
677 bounds.left_white = bounds.left_in;
678 bounds.right_white = bounds.right_in;
683 /* Given a display line and a starting position, ensure that the
684 contents of the display line accurately represent the visual
685 representation of the buffer contents starting from the given
686 position when displayed in the given window. The display line ends
687 when the contents of the line reach the right boundary of the given
691 generate_display_line (struct window *w, struct display_line *dl, int bounds,
692 Bufpos start_pos, prop_block_dynarr **prop,
697 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
699 /* If our caller hasn't already set the boundaries, then do so now. */
701 dl->bounds = calculate_display_line_boundaries (w, 0);
703 /* Reset what this line is using. */
704 if (dl->display_blocks)
705 Dynarr_reset (dl->display_blocks);
708 Dynarr_free (dl->left_glyphs);
711 if (dl->right_glyphs)
713 Dynarr_free (dl->right_glyphs);
714 dl->right_glyphs = 0;
717 /* We aren't generating a modeline at the moment. */
720 /* Create a display block for the text region of the line. */
722 /* #### urk urk urk!!! Chuck fix this shit! */
723 Bytind hacked_up_bytind =
724 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
726 if (hacked_up_bytind > BI_BUF_ZV (b))
727 ret_bufpos = BUF_ZV (b) + 1;
729 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
731 dl->bufpos = start_pos;
732 if (dl->end_bufpos < dl->bufpos)
733 dl->end_bufpos = dl->bufpos;
735 if (MARKERP (Voverlay_arrow_position)
736 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
737 && start_pos == marker_position (Voverlay_arrow_position)
738 && (STRINGP (Voverlay_arrow_string)
739 || GLYPHP (Voverlay_arrow_string)))
741 overlay_width = create_overlay_glyph_block (w, dl);
746 /* If there are left glyphs associated with any character in the
747 text block, then create a display block to handle them. */
748 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
749 create_left_glyph_block (w, dl, overlay_width);
751 /* If there are right glyphs associated with any character in the
752 text block, then create a display block to handle them. */
753 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
754 create_right_glyph_block (w, dl);
756 /* In the future additional types of display blocks may be generated
759 w->last_redisplay_pos = ret_bufpos;
764 /* Adds an hscroll glyph to a display block. If this is called, then
765 the block had better be empty.
767 Yes, there are multiple places where this function is called but
768 that is the way it has to be. Each calling function has to deal
769 with bi_start_col_enabled a little differently depending on the
770 object being worked with. */
772 static prop_block_dynarr *
773 add_hscroll_rune (pos_data *data)
775 struct glyph_block gb;
776 prop_block_dynarr *retval;
777 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
778 unsigned int old_cursor_type = data->cursor_type;
779 Bytind bi_old_bufpos = data->bi_bufpos;
781 if (data->cursor_type == CURSOR_ON
782 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
783 && data->bi_cursor_bufpos <= data->bi_bufpos)
785 data->bi_cursor_bufpos = data->bi_start_col_enabled;
789 data->cursor_type = NO_CURSOR;
792 data->bi_endpos = data->bi_bufpos;
793 data->bi_bufpos = data->bi_start_col_enabled;
796 gb.glyph = Vhscroll_glyph;
798 int oldpixpos = data->pixpos;
799 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0,
800 GLYPH_CACHEL (XWINDOW (data->window),
801 HSCROLL_GLYPH_INDEX));
802 data->hscroll_glyph_width_adjust =
803 data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
806 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
807 data->cursor_type = old_cursor_type;
808 data->bi_bufpos = bi_old_bufpos;
810 data->bi_start_col_enabled = 0;
814 /* Adds a character rune to a display block. If there is not enough
815 room to fit the rune on the display block (as determined by the
816 MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
818 static prop_block_dynarr *
819 add_emchar_rune (pos_data *data)
821 struct rune rb, *crb;
832 if (data->bi_start_col_enabled)
834 return add_hscroll_rune (data);
837 if (data->ch == '\n')
839 data->font_is_bogus = 0;
840 /* Cheesy end-of-line pseudo-character. */
841 width = data->blank_width;
845 Lisp_Object charset = CHAR_CHARSET (data->ch);
846 if (!EQ (charset, data->last_charset) ||
847 data->findex != data->last_findex)
849 /* OK, we need to do things the hard way. */
850 struct window *w = XWINDOW (data->window);
851 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
852 Lisp_Object font_instance =
853 ensure_face_cachel_contains_charset (cachel, data->window,
855 Lisp_Font_Instance *fi;
857 if (EQ (font_instance, Vthe_null_font_instance))
859 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
860 data->font_is_bogus = 1;
863 data->font_is_bogus = 0;
865 fi = XFONT_INSTANCE (font_instance);
866 if (!fi->proportional_p)
867 /* sweetness and light. */
868 data->last_char_width = fi->width;
870 data->last_char_width = -1;
871 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
872 data->new_descent = max (data->new_descent, (int) fi->descent);
873 data->last_charset = charset;
874 data->last_findex = data->findex;
877 width = data->last_char_width;
880 /* bummer. Proportional fonts. */
881 width = redisplay_text_width_emchar_string (XWINDOW (data->window),
887 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
892 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
894 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
903 crb->findex = data->findex;
904 crb->xpos = data->pixpos;
908 if (NILP (data->string))
910 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
914 bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
916 else if (data->is_modeline)
917 crb->bufpos = data->modeline_charpos;
919 /* Text but not in buffer */
921 crb->type = RUNE_CHAR;
922 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
925 if (data->cursor_type == CURSOR_ON)
927 if (data->bi_bufpos == data->bi_cursor_bufpos)
929 crb->cursor_type = CURSOR_ON;
930 data->cursor_x = Dynarr_length (data->db->runes);
933 crb->cursor_type = CURSOR_OFF;
935 else if (data->cursor_type == NEXT_CURSOR)
937 crb->cursor_type = CURSOR_ON;
938 data->cursor_x = Dynarr_length (data->db->runes);
939 data->cursor_type = NO_CURSOR;
941 else if (data->cursor_type == IGNORE_CURSOR)
942 crb->cursor_type = IGNORE_CURSOR;
944 crb->cursor_type = CURSOR_OFF;
947 Dynarr_add (data->db->runes, *crb);
949 Dynarr_increment (data->db->runes);
951 data->pixpos += width;
956 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
957 for each character in the string. Propagate any left-over data
958 unless NO_PROP is non-zero. */
960 static prop_block_dynarr *
961 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
962 Bytecount c_length, int no_prop)
964 Bufbyte *pos, *end = c_string + c_length;
965 prop_block_dynarr *prop;
967 /* #### This function is too simplistic. It needs to do the same
968 sort of character interpretation (display-table lookup,
969 ctl-arrow checking), etc. that create_text_block() does.
970 The functionality to do this in that routine needs to be
973 for (pos = c_string; pos < end;)
975 Bufbyte *old_pos = pos;
977 data->ch = charptr_emchar (pos);
979 prop = add_emchar_rune (data);
987 struct prop_block pb;
988 Bytecount len = end - pos;
989 prop = Dynarr_new (prop_block);
991 pb.type = PROP_STRING;
992 pb.data.p_string.str = xnew_array (Bufbyte, len);
993 strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
994 pb.data.p_string.len = len;
996 Dynarr_add (prop, pb);
1001 assert (pos <= end);
1002 /* #### Duplicate code from add_string_to_fstring_db_runes
1003 should we do more?*/
1004 data->bytepos += pos - old_pos;
1010 /* Add a single rune of the specified width. The area covered by this
1011 rune will be displayed in the foreground color of the associated
1014 static prop_block_dynarr *
1015 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1019 /* If data->start_col is not 0 then this call to add_blank_rune must have
1020 been to add it as a tab. */
1021 if (data->start_col)
1023 /* assert (w != NULL) */
1024 prop_block_dynarr *retval;
1026 /* If we have still not fully scrolled horizontally, subtract
1027 the width of this tab and return. */
1028 if (char_tab_width < data->start_col)
1030 data->start_col -= char_tab_width;
1033 else if (char_tab_width == data->start_col)
1034 data->blank_width = 0;
1037 int spcwid = space_width (w);
1039 if (spcwid >= data->blank_width)
1040 data->blank_width = 0;
1042 data->blank_width -= spcwid;
1045 data->start_col = 0;
1046 retval = add_hscroll_rune (data);
1048 /* Could be caused by the handling of the hscroll rune. */
1049 if (retval != NULL || !data->blank_width)
1053 /* Blank runes are always calculated to fit. */
1054 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1056 rb.findex = data->findex;
1057 rb.xpos = data->pixpos;
1058 rb.width = data->blank_width;
1059 if (data->bi_bufpos)
1061 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1064 /* #### and this is really correct too? */
1067 rb.type = RUNE_BLANK;
1069 if (data->cursor_type == CURSOR_ON)
1071 if (data->bi_bufpos == data->bi_cursor_bufpos)
1073 rb.cursor_type = CURSOR_ON;
1074 data->cursor_x = Dynarr_length (data->db->runes);
1077 rb.cursor_type = CURSOR_OFF;
1079 else if (data->cursor_type == NEXT_CURSOR)
1081 rb.cursor_type = CURSOR_ON;
1082 data->cursor_x = Dynarr_length (data->db->runes);
1083 data->cursor_type = NO_CURSOR;
1086 rb.cursor_type = CURSOR_OFF;
1088 Dynarr_add (data->db->runes, rb);
1089 data->pixpos += data->blank_width;
1094 /* Add runes representing a character in octal. */
1096 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1098 if (add_failed || (add_failed = add_emchar_rune (data))) \
1100 struct prop_block pb; \
1102 prop = Dynarr_new (prop_block); \
1104 pb.type = PROP_CHAR; \
1105 pb.data.p_char.ch = data->ch; \
1106 pb.data.p_char.cursor_type = data->cursor_type; \
1107 Dynarr_add (prop, pb); \
1111 static prop_block_dynarr *
1112 add_octal_runes (pos_data *data)
1114 prop_block_dynarr *prop, *add_failed;
1115 Emchar orig_char = data->ch;
1116 unsigned int orig_cursor_type = data->cursor_type;
1122 if (data->start_col)
1125 if (!data->start_col)
1127 if (data->bi_start_col_enabled)
1129 add_failed = add_hscroll_rune (data);
1133 struct glyph_block gb;
1134 struct window *w = XWINDOW (data->window);
1137 gb.glyph = Voctal_escape_glyph;
1139 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1140 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1144 /* We only propagate information if the glyph was partially
1149 data->cursor_type = IGNORE_CURSOR;
1151 if (data->ch >= 0x100)
1153 /* If the character is an extended Mule character, it could have
1154 up to 19 bits. For the moment, we treat it as a seven-digit
1155 octal number. This is not that pretty, but whatever. */
1156 data->ch = (7 & (orig_char >> 18)) + '0';
1157 ADD_NEXT_OCTAL_RUNE_CHAR;
1159 data->ch = (7 & (orig_char >> 15)) + '0';
1160 ADD_NEXT_OCTAL_RUNE_CHAR;
1162 data->ch = (7 & (orig_char >> 12)) + '0';
1163 ADD_NEXT_OCTAL_RUNE_CHAR;
1165 data->ch = (7 & (orig_char >> 9)) + '0';
1166 ADD_NEXT_OCTAL_RUNE_CHAR;
1169 data->ch = (7 & (orig_char >> 6)) + '0';
1170 ADD_NEXT_OCTAL_RUNE_CHAR;
1172 data->ch = (7 & (orig_char >> 3)) + '0';
1173 ADD_NEXT_OCTAL_RUNE_CHAR;
1175 data->ch = (7 & orig_char) + '0';
1176 ADD_NEXT_OCTAL_RUNE_CHAR;
1178 data->cursor_type = orig_cursor_type;
1182 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1184 /* Add runes representing a control character to a display block. */
1186 static prop_block_dynarr *
1187 add_control_char_runes (pos_data *data, struct buffer *b)
1189 if (!NILP (b->ctl_arrow))
1191 prop_block_dynarr *prop;
1192 Emchar orig_char = data->ch;
1193 unsigned int old_cursor_type = data->cursor_type;
1198 if (data->start_col)
1201 if (!data->start_col)
1203 if (data->bi_start_col_enabled)
1205 prop_block_dynarr *retval;
1207 retval = add_hscroll_rune (data);
1213 struct glyph_block gb;
1214 struct window *w = XWINDOW (data->window);
1217 gb.glyph = Vcontrol_arrow_glyph;
1219 /* We only propagate information if the glyph was partially
1221 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1222 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1227 if (orig_char == 0177)
1230 data->ch = orig_char ^ 0100;
1231 data->cursor_type = IGNORE_CURSOR;
1233 if (add_emchar_rune (data))
1235 struct prop_block pb;
1237 prop = Dynarr_new (prop_block);
1239 pb.type = PROP_CHAR;
1240 pb.data.p_char.ch = data->ch;
1241 pb.data.p_char.cursor_type = data->cursor_type;
1242 Dynarr_add (prop, pb);
1245 data->cursor_type = old_cursor_type;
1250 return add_octal_runes (data);
1254 static prop_block_dynarr *
1255 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
1257 prop_block_dynarr *prop = NULL;
1259 if (STRINGP (entry))
1261 prop = add_bufbyte_string_runes (data,
1262 XSTRING_DATA (entry),
1263 XSTRING_LENGTH (entry),
1266 else if (GLYPHP (entry))
1268 if (data->start_col)
1271 if (!data->start_col && data->bi_start_col_enabled)
1273 prop = add_hscroll_rune (data);
1277 struct glyph_block gb;
1281 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1284 else if (CHAR_OR_CHAR_INTP (entry))
1286 data->ch = XCHAR_OR_CHAR_INT (entry);
1287 prop = add_emchar_rune (data);
1289 else if (CONSP (entry))
1291 if (EQ (XCAR (entry), Qformat)
1292 && CONSP (XCDR (entry))
1293 && STRINGP (XCAR (XCDR (entry))))
1295 Lisp_Object format = XCAR (XCDR (entry));
1296 Bytind len = XSTRING_LENGTH (format);
1297 Bufbyte *src = XSTRING_DATA (format), *end = src + len;
1298 Bufbyte *result = alloca_array (Bufbyte, len);
1299 Bufbyte *dst = result;
1303 Emchar c = charptr_emchar (src);
1305 if (c != '%' || src == end)
1306 dst += set_charptr_emchar (dst, c);
1309 c = charptr_emchar (src);
1314 dst += long_to_string_base ((char *)dst, data->ch, 16);
1317 dst += set_charptr_emchar (dst, '%');
1319 /* #### unimplemented */
1323 prop = add_bufbyte_string_runes (data, result, dst - result, 0);
1327 /* Else blow it off because someone added a bad entry and we don't
1328 have any safe way of signaling an error. */
1332 /* Given a display table entry, call the appropriate functions to
1333 display each element of the entry. */
1335 static prop_block_dynarr *
1336 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1338 prop_block_dynarr *prop = NULL;
1339 if (VECTORP (entry))
1341 Lisp_Vector *de = XVECTOR (entry);
1342 EMACS_INT len = vector_length (de);
1345 for (elt = 0; elt < len; elt++)
1347 if (NILP (vector_data (de)[elt]))
1350 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
1351 /* Else blow it off because someone added a bad entry and we
1352 don't have any safe way of signaling an error. Hey, this
1353 comment sounds familiar. */
1355 /* #### Still need to add any remaining elements to the
1356 propagation information. */
1362 prop = add_disp_table_entry_runes_1 (data, entry);
1366 /* Add runes which were propagated from the previous line. */
1368 static prop_block_dynarr *
1369 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1371 /* #### Remember to handle start_col parameter of data when the rest of
1372 this is finished. */
1373 /* #### Chuck -- I've redone this function a bit. It looked like the
1374 case of not all the propagation blocks being added was not handled
1376 /* #### Chuck -- I also think the double indirection of PROP is kind
1377 of bogus. A cleaner solution is just to check for
1378 Dynarr_length (prop) > 0. */
1379 /* #### This function also doesn't even pay attention to ADD_FAILED!
1380 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1383 prop_block_dynarr *add_failed;
1384 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1385 unsigned int old_cursor_type = data->cursor_type;
1387 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1389 struct prop_block *pb = Dynarr_atp (*prop, elt);
1394 data->ch = pb->data.p_char.ch;
1395 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1396 data->cursor_type = pb->data.p_char.cursor_type;
1397 add_failed = add_emchar_rune (data);
1400 goto oops_no_more_space;
1403 if (pb->data.p_string.str)
1404 xfree (pb->data.p_string.str);
1405 /* #### bogus bogus -- this doesn't do anything!
1406 Should probably call add_bufbyte_string_runes(),
1407 once that function is fixed. */
1409 case PROP_MINIBUF_PROMPT:
1411 face_index old_findex = data->findex;
1412 Bytind bi_old_bufpos = data->bi_bufpos;
1414 data->findex = DEFAULT_INDEX;
1415 data->bi_bufpos = 0;
1416 data->cursor_type = NO_CURSOR;
1418 while (pb->data.p_string.len > 0)
1420 data->ch = charptr_emchar (pb->data.p_string.str);
1421 add_failed = add_emchar_rune (data);
1425 data->findex = old_findex;
1426 data->bi_bufpos = bi_old_bufpos;
1427 goto oops_no_more_space;
1431 /* Complicated equivalent of ptr++, len-- */
1432 Bufbyte *oldpos = pb->data.p_string.str;
1433 INC_CHARPTR (pb->data.p_string.str);
1434 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1438 data->findex = old_findex;
1439 /* ##### FIXME FIXME FIXME -- Upon successful return from
1440 this function, data->bi_bufpos is automatically incremented.
1441 However, we don't want that to happen if we were adding
1442 the minibuffer prompt. */
1444 struct buffer *buf =
1445 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1446 /* #### Chuck fix this shit or I'm gonna scream! */
1447 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1448 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1450 /* #### is this correct? Does anyone know?
1451 Does anyone care? Is this a cheesy hack or what? */
1452 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1458 /* #### I think it's unnecessary and misleading to preserve
1459 the blank_width, as it implies that the value carries
1460 over from one rune to the next, which is wrong. */
1461 int old_width = data->blank_width;
1462 face_index old_findex = data->findex;
1464 data->findex = pb->data.p_blank.findex;
1465 data->blank_width = pb->data.p_blank.width;
1466 data->bi_cursor_bufpos = 0;
1467 data->cursor_type = IGNORE_CURSOR;
1469 if (data->pixpos + data->blank_width > data->max_pixpos)
1470 data->blank_width = data->max_pixpos - data->pixpos;
1472 /* We pass a bogus value of char_tab_width. It shouldn't
1473 matter because unless something is really screwed up
1474 this call won't cause that arg to be used. */
1475 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1477 /* This can happen in the case where we have a tab which
1478 is wider than the window. */
1479 if (data->blank_width != pb->data.p_blank.width)
1481 pb->data.p_blank.width -= data->blank_width;
1482 add_failed = ADD_FAILED;
1485 data->findex = old_findex;
1486 data->blank_width = old_width;
1489 goto oops_no_more_space;
1499 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1500 data->cursor_type = old_cursor_type;
1501 if (elt < Dynarr_length (*prop))
1503 Dynarr_delete_many (*prop, 0, elt);
1508 Dynarr_free (*prop);
1513 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1514 the display block, but add all other types to the appropriate list
1515 of the display line. They will be added later by different
1518 static prop_block_dynarr *
1519 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1520 int allow_cursor, struct glyph_cachel *cachel)
1522 struct window *w = XWINDOW (data->window);
1524 /* If window faces changed, and glyph instance is text, then
1525 glyph sizes might have changed too */
1526 invalidate_glyph_geometry_maybe (gb->glyph, w);
1528 /* This makes sure the glyph is in the cachels.
1530 #### We do this to make sure the glyph is in the glyph cachels,
1531 so that the dirty flag can be reset after redisplay has
1532 finished. We should do this some other way, maybe by iterating
1533 over the window cache of subwindows. */
1534 get_glyph_cachel_index (w, gb->glyph);
1536 /* A nil extent indicates a special glyph (ex. truncator). */
1537 if (NILP (gb->extent)
1538 || (pos_type == BEGIN_GLYPHS &&
1539 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1540 || (pos_type == END_GLYPHS &&
1541 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1542 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS)
1547 int ascent, descent;
1548 Lisp_Object baseline;
1550 Lisp_Object instance;
1554 width = cachel->width;
1556 width = glyph_width (gb->glyph, data->window);
1561 if (data->start_col || data->start_col_xoffset)
1563 prop_block_dynarr *retval;
1564 int glyph_char_width = width / space_width (w);
1566 /* If we still have not fully scrolled horizontally after
1567 taking into account the width of the glyph, subtract its
1568 width and return. */
1569 if (glyph_char_width < data->start_col)
1571 data->start_col -= glyph_char_width;
1574 else if (glyph_char_width == data->start_col)
1578 xoffset = space_width (w) * data->start_col;
1581 /* #### Can this happen? */
1586 data->start_col = 0;
1587 retval = add_hscroll_rune (data);
1589 /* Could be caused by the handling of the hscroll rune. */
1590 if (retval != NULL || !width)
1596 if (data->pixpos + width > data->max_pixpos)
1598 /* If this is the first object we are attempting to add to
1599 the line then we ignore the horizontal_clip threshold.
1600 Otherwise we will loop until the bottom of the window
1601 continually failing to add this glyph because it is wider
1602 than the window. We could alternatively just completely
1603 ignore the glyph and proceed from there but I think that
1604 this is a better solution. */
1605 if (Dynarr_length (data->db->runes)
1606 && data->max_pixpos - data->pixpos < horizontal_clip)
1609 width = data->max_pixpos - data->pixpos;
1614 ascent = cachel->ascent;
1615 descent = cachel->descent;
1619 ascent = glyph_ascent (gb->glyph, data->window);
1620 descent = glyph_descent (gb->glyph, data->window);
1623 baseline = glyph_baseline (gb->glyph, data->window);
1625 if (glyph_contrib_p (gb->glyph, data->window))
1627 /* A pixmap that has not had a baseline explicitly set. Its
1628 contribution will be determined later. */
1629 if (NILP (baseline))
1631 int height = ascent + descent;
1632 data->max_pixmap_height = max (data->max_pixmap_height, height);
1635 /* A string so determine contribution normally. */
1636 else if (EQ (baseline, Qt))
1638 data->new_ascent = max (data->new_ascent, ascent);
1639 data->new_descent = max (data->new_descent, descent);
1642 /* A pixmap with an explicitly set baseline. We determine the
1643 contribution here. */
1644 else if (INTP (baseline))
1646 int height = ascent + descent;
1647 int pix_ascent, pix_descent;
1649 pix_ascent = height * XINT (baseline) / 100;
1650 pix_descent = height - pix_ascent;
1652 data->new_ascent = max (data->new_ascent, pix_ascent);
1653 data->new_descent = max (data->new_descent, pix_descent);
1656 /* Otherwise something is screwed up. */
1661 face = glyph_face (gb->glyph, data->window);
1663 findex = data->findex;
1665 findex = get_builtin_face_cache_index (w, face);
1667 instance = glyph_image_instance (gb->glyph, data->window,
1669 if (TEXT_IMAGE_INSTANCEP (instance))
1671 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance);
1672 face_index orig_findex = data->findex;
1673 Bytind orig_bufpos = data->bi_bufpos;
1674 Bytind orig_start_col_enabled = data->bi_start_col_enabled;
1676 data->findex = findex;
1677 data->bi_start_col_enabled = 0;
1679 data->bi_bufpos = 0;
1680 add_bufbyte_string_runes (data, XSTRING_DATA (string),
1681 XSTRING_LENGTH (string), 0);
1682 data->findex = orig_findex;
1683 data->bi_bufpos = orig_bufpos;
1684 data->bi_start_col_enabled = orig_start_col_enabled;
1689 rb.xpos = data->pixpos;
1691 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1692 if (data->bi_endpos)
1693 /* #### is this necessary at all? */
1694 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1698 rb.type = RUNE_DGLYPH;
1699 rb.object.dglyph.glyph = gb->glyph;
1700 rb.object.dglyph.extent = gb->extent;
1701 rb.object.dglyph.xoffset = xoffset;
1705 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1708 if (data->cursor_type == CURSOR_ON)
1710 if (data->bi_bufpos == data->bi_cursor_bufpos)
1712 rb.cursor_type = CURSOR_ON;
1713 data->cursor_x = Dynarr_length (data->db->runes);
1716 rb.cursor_type = CURSOR_OFF;
1718 else if (data->cursor_type == NEXT_CURSOR)
1720 rb.cursor_type = CURSOR_ON;
1721 data->cursor_x = Dynarr_length (data->db->runes);
1722 data->cursor_type = NO_CURSOR;
1724 else if (data->cursor_type == IGNORE_CURSOR)
1725 rb.cursor_type = IGNORE_CURSOR;
1726 else if (data->cursor_type == NO_CURSOR)
1727 rb.cursor_type = NO_CURSOR;
1729 rb.cursor_type = CURSOR_OFF;
1732 rb.cursor_type = CURSOR_OFF;
1734 Dynarr_add (data->db->runes, rb);
1735 data->pixpos += width;
1741 if (!NILP (glyph_face (gb->glyph, data->window)))
1743 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1746 gb->findex = data->findex;
1748 if (pos_type == BEGIN_GLYPHS)
1750 if (!data->dl->left_glyphs)
1751 data->dl->left_glyphs = Dynarr_new (glyph_block);
1752 Dynarr_add (data->dl->left_glyphs, *gb);
1755 else if (pos_type == END_GLYPHS)
1757 if (!data->dl->right_glyphs)
1758 data->dl->right_glyphs = Dynarr_new (glyph_block);
1759 Dynarr_add (data->dl->right_glyphs, *gb);
1763 abort (); /* there are no unknown types */
1766 return NULL; /* shut up compiler */
1769 /* Add all glyphs at position POS_TYPE that are contained in the given
1772 static prop_block_dynarr *
1773 add_glyph_runes (pos_data *data, int pos_type)
1775 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1776 why didn't you just modify add_glyph_rune in the first place? */
1778 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1779 ? data->ef->begin_glyphs
1780 : data->ef->end_glyphs);
1781 prop_block_dynarr *prop;
1783 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1785 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1790 /* #### Add some propagation information. */
1795 Dynarr_reset (glyph_arr);
1800 /* Given a position for a buffer in a window, ensure that the given
1801 display line DL accurately represents the text on a line starting
1802 at the given position.
1804 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1805 You must do appropriate conversion. */
1808 create_text_block (struct window *w, struct display_line *dl,
1809 Bytind bi_start_pos, prop_block_dynarr **prop,
1812 struct frame *f = XFRAME (w->frame);
1813 struct buffer *b = XBUFFER (w->buffer);
1814 struct device *d = XDEVICE (f->device);
1818 /* Don't display anything in the minibuffer if this window is not on
1819 a selected frame. We consider all other windows to be active
1820 minibuffers as it simplifies the coding. */
1821 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1822 (f == device_selected_frame (d)) ||
1823 is_surrogate_for_selected_frame (f));
1825 int truncate_win = window_truncation_on (w);
1826 int end_glyph_width;
1828 /* If the buffer's value of selective_display is an integer then
1829 only lines that start with less than selective_display columns of
1830 space will be displayed. If selective_display is t then all text
1831 after a ^M is invisible. */
1832 int selective = (INTP (b->selective_display)
1833 ? XINT (b->selective_display)
1834 : (!NILP (b->selective_display) ? -1 : 0));
1836 /* The variable ctl-arrow allows the user to specify what characters
1837 can actually be displayed and which octal should be used for.
1838 #### This variable should probably have some rethought done to
1841 #### It would also be really nice if you could specify that
1842 the characters come out in hex instead of in octal. Mule
1843 does that by adding a ctl-hexa variable similar to ctl-arrow,
1844 but that's bogus -- we need a more general solution. I
1845 think you need to extend the concept of display tables
1846 into a more general conversion mechanism. Ideally you
1847 could specify a Lisp function that converts characters,
1848 but this violates the Second Golden Rule and besides would
1849 make things way way way way slow.
1851 So instead, we extend the display-table concept, which was
1852 historically limited to 256-byte vectors, to one of the
1855 a) A 256-entry vector, for backward compatibility;
1856 b) char-table, mapping characters to values;
1857 c) range-table, mapping ranges of characters to values;
1858 d) a list of the above.
1860 The (d) option allows you to specify multiple display tables
1861 instead of just one. Each display table can specify conversions
1862 for some characters and leave others unchanged. The way the
1863 character gets displayed is determined by the first display table
1864 with a binding for that character. This way, you could call a
1865 function `enable-hex-display' that adds a hex display-table to
1866 the list of display tables for the current buffer.
1868 #### ...not yet implemented... Also, we extend the concept of
1869 "mapping" to include a printf-like spec. Thus you can make all
1870 extended characters show up as hex with a display table like
1873 #s(range-table data ((256 524288) (format "%x")))
1875 Since more than one display table is possible, you have
1876 great flexibility in mapping ranges of characters. */
1877 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1878 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1879 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1882 Lisp_Object face_dt, window_dt;
1884 /* The text display block for this display line. */
1885 struct display_block *db = get_display_block_from_line (dl, TEXT);
1887 /* The first time through the main loop we need to force the glyph
1888 data to be updated. */
1891 /* Apparently the new extent_fragment_update returns an end position
1892 equal to the position passed in if there are no more runs to be
1894 int no_more_frags = 0;
1896 Lisp_Object synch_minibuffers_value =
1897 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1899 dl->used_prop_data = 0;
1901 dl->line_continuation = 0;
1904 data.ef = extent_fragment_new (w->buffer, f);
1906 /* These values are used by all of the rune addition routines. We add
1907 them to this structure for ease of passing. */
1909 XSETWINDOW (data.window, w);
1914 data.bi_bufpos = bi_start_pos;
1915 data.pixpos = dl->bounds.left_in;
1916 data.last_charset = Qunbound;
1917 data.last_findex = DEFAULT_INDEX;
1918 data.result_str = Qnil;
1920 /* Set the right boundary adjusting it to take into account any end
1921 glyph. Save the width of the end glyph for later use. */
1922 data.max_pixpos = dl->bounds.right_in;
1924 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1926 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1927 data.max_pixpos -= end_glyph_width;
1929 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1931 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1932 data.cursor_type = CURSOR_ON;
1934 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1935 data.cursor_type = NO_CURSOR;
1936 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1937 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1938 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1939 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1941 data.bi_cursor_bufpos = BI_BUF_PT (b);
1942 data.cursor_type = CURSOR_ON;
1944 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1946 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1947 data.cursor_type = CURSOR_ON;
1950 data.cursor_type = NO_CURSOR;
1953 data.start_col = w->hscroll;
1954 data.start_col_xoffset = w->left_xoffset;
1955 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1956 data.hscroll_glyph_width_adjust = 0;
1958 /* We regenerate the line from the very beginning. */
1959 Dynarr_reset (db->runes);
1961 /* Why is this less than or equal and not just less than? If the
1962 starting position is already equal to the maximum we can't add
1963 anything else, right? Wrong. We might still have a newline to
1964 add. A newline can use the room allocated for an end glyph since
1965 if we add it we know we aren't going to be adding any end
1968 /* #### Chuck -- I think this condition should be while (1).
1969 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1970 and the begin-glyph ends exactly at the end of the window, the
1971 end-glyph and text might not be displayed. while (1) ensures
1972 that the loop terminates only when either (a) there is
1973 propagation data or (b) the end-of-line or end-of-buffer is hit.
1975 #### Also I think you need to ensure that the operation
1976 "add begin glyphs; add end glyphs; add text" is atomic and
1977 can't get interrupted in the middle. If you run off the end
1978 of the line during that operation, then you keep accumulating
1979 propagation data until you're done. Otherwise, if the (e.g.)
1980 there's a begin glyph at a particular position and attempting
1981 to display that glyph results in window-end being hit and
1982 propagation data being generated, then the character at that
1983 position won't be displayed.
1985 #### See also the comment after the end of this loop, below.
1987 while (data.pixpos <= data.max_pixpos
1988 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1990 /* #### This check probably should not be necessary. */
1991 if (data.bi_bufpos > BI_BUF_ZV (b))
1993 /* #### urk! More of this lossage! */
1998 /* If selective display was an integer and we aren't working on
1999 a continuation line then find the next line we are actually
2000 supposed to display. */
2002 && (data.bi_bufpos == BI_BUF_BEGV (b)
2003 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
2005 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2008 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2009 if (data.bi_bufpos >= BI_BUF_ZV (b))
2011 data.bi_bufpos = BI_BUF_ZV (b);
2017 /* Check for face changes. */
2018 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
2020 /* Now compute the face and begin/end-glyph information. */
2022 /* Remember that the extent-fragment routines deal in Bytind's. */
2023 extent_fragment_update (w, data.ef, data.bi_bufpos);
2025 get_display_tables (w, data.findex, &face_dt, &window_dt);
2027 if (data.bi_bufpos == data.ef->end)
2032 /* Determine what is next to be displayed. We first handle any
2033 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2034 display then we determine what to do based on the character at the
2035 current buffer position. */
2037 /* If the current position is covered by an invisible extent, do
2038 nothing (except maybe add some ellipses).
2040 #### The behavior of begin and end-glyphs at the edge of an
2041 invisible extent should be investigated further. This is
2042 fairly low priority though. */
2043 if (data.ef->invisible)
2045 /* #### Chuck, perhaps you could look at this code? I don't
2046 really know what I'm doing. */
2049 Dynarr_free (*prop);
2053 /* The extent fragment code only sets this when we should
2054 really display the ellipses. It makes sure the ellipses
2055 don't get displayed more than once in a row. */
2056 if (data.ef->invisible_ellipses)
2058 struct glyph_block gb;
2060 data.ef->invisible_ellipses_already_displayed = 1;
2061 data.ef->invisible_ellipses = 0;
2063 gb.glyph = Vinvisible_text_glyph;
2064 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2065 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2066 /* Perhaps they shouldn't propagate if the very next thing
2067 is to display a newline (for compatibility with
2068 selective-display-ellipses)? Maybe that's too
2074 /* If point is in an invisible region we place it on the
2075 next visible character. */
2076 if (data.cursor_type == CURSOR_ON
2077 && data.bi_bufpos == data.bi_cursor_bufpos)
2079 data.cursor_type = NEXT_CURSOR;
2082 /* #### What if we we're dealing with a display table? */
2086 if (data.bi_bufpos == BI_BUF_ZV (b))
2089 INC_BYTIND (b, data.bi_bufpos);
2092 /* If there is propagation data, then it represents the current
2093 buffer position being displayed. Add them and advance the
2094 position counter. This might also add the minibuffer
2098 dl->used_prop_data = 1;
2099 *prop = add_propagation_runes (prop, &data);
2102 goto done; /* gee, a really narrow window */
2103 else if (data.bi_bufpos == BI_BUF_ZV (b))
2105 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2106 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2107 data.bi_bufpos = BI_BUF_BEGV (b);
2109 INC_BYTIND (b, data.bi_bufpos);
2112 /* If there are end glyphs, add them to the line. These are
2113 the end glyphs for the previous run of text. We add them
2114 here rather than doing them at the end of handling the
2115 previous run so that glyphs at the beginning and end of
2116 a line are handled correctly. */
2117 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2119 *prop = add_glyph_runes (&data, END_GLYPHS);
2124 /* If there are begin glyphs, add them to the line. */
2125 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2127 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2132 /* If at end-of-buffer, we've already processed begin and
2133 end-glyphs at this point and there's no text to process,
2135 else if (data.bi_bufpos == BI_BUF_ZV (b))
2140 Lisp_Object entry = Qnil;
2141 /* Get the character at the current buffer position. */
2142 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2143 if (!NILP (face_dt) || !NILP (window_dt))
2144 entry = display_table_entry (data.ch, face_dt, window_dt);
2146 /* If there is a display table entry for it, hand it off to
2147 add_disp_table_entry_runes and let it worry about it. */
2148 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
2150 *prop = add_disp_table_entry_runes (&data, entry);
2156 /* Check if we have hit a newline character. If so, add a marker
2157 to the line and end this loop. */
2158 else if (data.ch == '\n')
2160 /* We aren't going to be adding an end glyph so give its
2161 space back in order to make sure that the cursor can
2163 data.max_pixpos += end_glyph_width;
2166 && (bi_spaces_at_point
2167 (b, next_bytind (b, data.bi_bufpos))
2170 if (!NILP (b->selective_display_ellipses))
2172 struct glyph_block gb;
2175 gb.glyph = Vinvisible_text_glyph;
2176 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2177 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2181 /* Cheesy, cheesy, cheesy. We mark the end of the
2182 line with a special "character rune" whose width
2183 is the EOL cursor width and whose character is
2184 the non-printing character '\n'. */
2185 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2186 *prop = add_emchar_rune (&data);
2189 /* We need to set data.bi_bufpos to the start of the
2190 next visible region in order to make this line
2191 appear to contain all of the invisible area.
2192 Otherwise, the line cache won't work
2194 INC_BYTIND (b, data.bi_bufpos);
2195 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2198 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2199 if (data.bi_bufpos >= BI_BUF_ZV (b))
2201 data.bi_bufpos = BI_BUF_ZV (b);
2205 if (BI_BUF_FETCH_CHAR
2206 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2207 DEC_BYTIND (b, data.bi_bufpos);
2211 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2212 *prop = add_emchar_rune (&data);
2218 /* If the current character is ^M, and selective display is
2219 enabled, then add the invisible-text-glyph if
2220 selective-display-ellipses is set. In any case, this
2222 else if (data.ch == (('M' & 037)) && selective == -1)
2224 Bytind bi_next_bufpos;
2226 /* Find the buffer position at the end of the line. */
2228 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2229 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2231 DEC_BYTIND (b, bi_next_bufpos);
2233 /* If the cursor is somewhere in the elided text make
2234 sure that the cursor gets drawn appropriately. */
2235 if (data.cursor_type == CURSOR_ON
2236 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2237 data.bi_cursor_bufpos < bi_next_bufpos))
2239 data.cursor_type = NEXT_CURSOR;
2242 /* We won't be adding a truncation or continuation glyph
2243 so give up the room allocated for them. */
2244 data.max_pixpos += end_glyph_width;
2246 if (!NILP (b->selective_display_ellipses))
2248 /* We don't propagate anything from the invisible
2249 text glyph if it fails to fit. This is
2251 struct glyph_block gb;
2254 gb.glyph = Vinvisible_text_glyph;
2255 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2256 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2259 /* Set the buffer position to the end of the line. We
2260 need to do this before potentially adding a newline
2261 so that the cursor flag will get set correctly (if
2263 data.bi_bufpos = bi_next_bufpos;
2265 if (NILP (b->selective_display_ellipses)
2266 || data.bi_cursor_bufpos == bi_next_bufpos)
2268 /* We have to at least add a newline character so
2269 that the cursor shows up properly. */
2271 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2272 data.findex = DEFAULT_INDEX;
2274 data.start_col_xoffset = 0;
2275 data.bi_start_col_enabled = 0;
2277 add_emchar_rune (&data);
2280 /* This had better be a newline but doing it this way
2281 we'll see obvious incorrect results if it isn't. No
2282 need to abort here. */
2283 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2288 /* If the current character is considered to be printable, then
2290 else if (data.ch >= printable_min)
2292 *prop = add_emchar_rune (&data);
2297 /* If the current character is a tab, determine the next tab
2298 starting position and add a blank rune which extends from the
2299 current pixel position to that starting position. */
2300 else if (data.ch == '\t')
2302 int tab_start_pixpos = data.pixpos;
2307 if (data.start_col > 1)
2308 tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
2309 + data.start_col_xoffset;
2312 next_tab_position (w, tab_start_pixpos,
2313 dl->bounds.left_in +
2314 data.hscroll_glyph_width_adjust);
2315 if (next_tab_start > data.max_pixpos)
2317 prop_width = next_tab_start - data.max_pixpos;
2318 next_tab_start = data.max_pixpos;
2320 data.blank_width = next_tab_start - data.pixpos;
2322 (next_tab_start - tab_start_pixpos) / space_width (w);
2324 *prop = add_blank_rune (&data, w, char_tab_width);
2326 /* add_blank_rune is only supposed to be called with
2327 sizes guaranteed to fit in the available space. */
2332 struct prop_block pb;
2333 *prop = Dynarr_new (prop_block);
2335 pb.type = PROP_BLANK;
2336 pb.data.p_blank.width = prop_width;
2337 pb.data.p_blank.findex = data.findex;
2338 Dynarr_add (*prop, pb);
2344 /* If character is a control character, pass it off to
2345 add_control_char_runes.
2347 The is_*() routines have undefined results on
2348 arguments outside of the range [-1, 255]. (This
2349 often bites people who carelessly use `char' instead
2350 of `unsigned char'.)
2352 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2354 *prop = add_control_char_runes (&data, b);
2360 /* If the character is above the ASCII range and we have not
2361 already handled it, then print it as an octal number. */
2362 else if (data.ch >= 0200)
2364 *prop = add_octal_runes (&data);
2370 /* Assume the current character is considered to be printable,
2371 then just add it. */
2374 *prop = add_emchar_rune (&data);
2379 INC_BYTIND (b, data.bi_bufpos);
2385 /* Determine the starting point of the next line if we did not hit the
2386 end of the buffer. */
2387 if (data.bi_bufpos < BI_BUF_ZV (b)
2388 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2390 /* #### This check is not correct. If the line terminated
2391 due to a begin-glyph or end-glyph hitting window-end, then
2392 data.ch will not point to the character at data.bi_bufpos. If
2393 you make the two changes mentioned at the top of this loop,
2394 you should be able to say '(if (*prop))'. That should also
2395 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2398 /* The common case is that the line ended because we hit a newline.
2399 In that case, the next character is just the next buffer
2401 if (data.ch == '\n')
2403 /* If data.start_col_enabled is still true, then the window is
2404 scrolled far enough so that nothing on this line is visible.
2405 We need to stick a truncation glyph at the beginning of the
2406 line in that case unless the line is completely blank. */
2407 if (data.bi_start_col_enabled)
2409 if (data.cursor_type == CURSOR_ON)
2411 if (data.bi_cursor_bufpos >= bi_start_pos
2412 && data.bi_cursor_bufpos <= data.bi_bufpos)
2413 data.bi_cursor_bufpos = data.bi_bufpos;
2415 data.findex = DEFAULT_INDEX;
2417 data.bi_start_col_enabled = 0;
2419 if (data.bi_bufpos != bi_start_pos)
2421 struct glyph_block gb;
2424 gb.glyph = Vhscroll_glyph;
2425 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2426 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2430 /* This duplicates code down below to add a newline to
2431 the end of an otherwise empty line.*/
2433 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2435 add_emchar_rune (&data);
2439 INC_BYTIND (b, data.bi_bufpos);
2442 /* Otherwise we have a buffer line which cannot fit on one display
2446 struct glyph_block gb;
2447 struct glyph_cachel *cachel;
2449 /* If the line is to be truncated then we actually have to look
2450 for the next newline. We also add the end-of-line glyph which
2451 we know will fit because we adjusted the right border before
2452 we starting laying out the line. */
2453 data.max_pixpos += end_glyph_width;
2454 data.findex = DEFAULT_INDEX;
2461 /* Now find the start of the next line. */
2462 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2464 /* If the cursor is past the truncation line then we
2465 make it appear on the truncation glyph. If we've hit
2466 the end of the buffer then we also make the cursor
2467 appear unless eob is immediately preceded by a
2468 newline. In that case the cursor should actually
2469 appear on the next line. */
2470 if (data.cursor_type == CURSOR_ON
2471 && data.bi_cursor_bufpos >= data.bi_bufpos
2472 && (data.bi_cursor_bufpos < bi_pos ||
2473 (bi_pos == BI_BUF_ZV (b)
2474 && (bi_pos == BI_BUF_BEGV (b)
2475 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2477 data.bi_cursor_bufpos = bi_pos;
2479 data.cursor_type = NO_CURSOR;
2481 data.bi_bufpos = bi_pos;
2482 gb.glyph = Vtruncation_glyph;
2483 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2487 /* The cursor can never be on the continuation glyph. */
2488 data.cursor_type = NO_CURSOR;
2490 /* data.bi_bufpos is already at the start of the next line. */
2492 dl->line_continuation = 1;
2493 gb.glyph = Vcontinuation_glyph;
2494 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2497 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
2499 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2500 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2501 /* #### Damn this losing shit. */
2505 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2506 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2508 /* We need to add a marker to the end of the line since there is no
2509 newline character in order for the cursor to get drawn. We label
2510 it as a newline so that it gets handled correctly by the
2511 whitespace routines below. */
2514 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2515 data.findex = DEFAULT_INDEX;
2517 data.start_col_xoffset = 0;
2518 data.bi_start_col_enabled = 0;
2520 data.max_pixpos += data.blank_width;
2521 add_emchar_rune (&data);
2522 data.max_pixpos -= data.blank_width;
2524 /* #### urk! Chuck, this shit is bad news. Going around
2525 manipulating invalid positions is guaranteed to result in
2526 trouble sooner or later. */
2527 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2530 /* Calculate left whitespace boundary. */
2534 /* Whitespace past a newline is considered right whitespace. */
2535 while (elt < Dynarr_length (db->runes))
2537 struct rune *rb = Dynarr_atp (db->runes, elt);
2539 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2540 || rb->type == RUNE_BLANK)
2542 dl->bounds.left_white += rb->width;
2546 elt = Dynarr_length (db->runes);
2550 /* Calculate right whitespace boundary. */
2552 int elt = Dynarr_length (db->runes) - 1;
2555 while (!done && elt >= 0)
2557 struct rune *rb = Dynarr_atp (db->runes, elt);
2559 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2560 && isspace (rb->object.chr.ch))
2561 && !rb->type == RUNE_BLANK)
2563 dl->bounds.right_white = rb->xpos + rb->width;
2571 /* The line is blank so everything is considered to be right
2574 dl->bounds.right_white = dl->bounds.left_in;
2577 /* Set the display blocks bounds. */
2578 db->start_pos = dl->bounds.left_in;
2579 if (Dynarr_length (db->runes))
2581 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2583 db->end_pos = rb->xpos + rb->width;
2586 db->end_pos = dl->bounds.right_white;
2588 /* update line height parameters */
2589 if (!data.new_ascent && !data.new_descent)
2591 /* We've got a blank line so initialize these values from the default
2593 default_face_font_info (data.window, &data.new_ascent,
2594 &data.new_descent, 0, 0, 0);
2597 if (data.max_pixmap_height)
2599 int height = data.new_ascent + data.new_descent;
2600 int pix_ascent, pix_descent;
2602 pix_descent = data.max_pixmap_height * data.new_descent / height;
2603 pix_ascent = data.max_pixmap_height - pix_descent;
2605 data.new_ascent = max (data.new_ascent, pix_ascent);
2606 data.new_descent = max (data.new_descent, pix_descent);
2609 dl->ascent = data.new_ascent;
2610 dl->descent = data.new_descent;
2613 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2615 if (dl->ascent < ascent)
2616 dl->ascent = ascent;
2619 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2621 if (dl->descent < descent)
2622 dl->descent = descent;
2625 dl->cursor_elt = data.cursor_x;
2626 /* #### lossage lossage lossage! Fix this shit! */
2627 if (data.bi_bufpos > BI_BUF_ZV (b))
2628 dl->end_bufpos = BUF_ZV (b);
2630 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2632 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2634 /* This doesn't correctly take into account tabs and control
2635 characters but if the window isn't being truncated then this
2636 value isn't going to end up being used anyhow. */
2637 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2639 /* #### handle horizontally scrolled line with text none of which
2640 was actually laid out. */
2642 /* #### handle any remainder of overlay arrow */
2644 if (*prop == ADD_FAILED)
2647 if (truncate_win && *prop)
2649 Dynarr_free (*prop);
2653 extent_fragment_delete (data.ef);
2655 /* #### If we started at EOB, then make sure we return a value past
2656 it so that regenerate_window will exit properly. This is bogus.
2657 The main loop should get fixed so that it isn't necessary to call
2658 this function if we are already at EOB. */
2660 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2661 return data.bi_bufpos + 1; /* Yuck! */
2663 return data.bi_bufpos;
2666 /* Display the overlay arrow at the beginning of the given line. */
2669 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2671 struct frame *f = XFRAME (w->frame);
2672 struct device *d = XDEVICE (f->device);
2675 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2676 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2682 XSETWINDOW (data.window, w);
2683 data.db = get_display_block_from_line (dl, OVERWRITE);
2685 data.pixpos = dl->bounds.left_in;
2686 data.max_pixpos = dl->bounds.right_in;
2687 data.cursor_type = NO_CURSOR;
2689 data.findex = DEFAULT_INDEX;
2690 data.last_charset = Qunbound;
2691 data.last_findex = DEFAULT_INDEX;
2692 data.result_str = Qnil;
2695 Dynarr_reset (data.db->runes);
2697 if (STRINGP (Voverlay_arrow_string))
2699 add_bufbyte_string_runes
2701 XSTRING_DATA (Voverlay_arrow_string),
2702 XSTRING_LENGTH (Voverlay_arrow_string),
2705 else if (GLYPHP (Voverlay_arrow_string))
2707 struct glyph_block gb;
2709 gb.glyph = Voverlay_arrow_string;
2711 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2714 if (data.max_pixmap_height)
2716 int height = data.new_ascent + data.new_descent;
2717 int pix_ascent, pix_descent;
2719 pix_descent = data.max_pixmap_height * data.new_descent / height;
2720 pix_ascent = data.max_pixmap_height - pix_descent;
2722 data.new_ascent = max (data.new_ascent, pix_ascent);
2723 data.new_descent = max (data.new_descent, pix_descent);
2726 dl->ascent = data.new_ascent;
2727 dl->descent = data.new_descent;
2729 data.db->start_pos = dl->bounds.left_in;
2730 data.db->end_pos = data.pixpos;
2732 return data.pixpos - dl->bounds.left_in;
2735 /* Add a type of glyph to a margin display block. */
2738 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2739 int count, enum glyph_layout layout, int side, Lisp_Object window)
2741 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2743 : dl->right_glyphs);
2746 struct window *w = XWINDOW (window);
2747 struct frame *f = XFRAME (w->frame);
2748 struct device *d = XDEVICE (f->device);
2753 data.window = window;
2756 data.pixpos = start;
2757 data.cursor_type = NO_CURSOR;
2759 data.last_charset = Qunbound;
2760 data.last_findex = DEFAULT_INDEX;
2761 data.result_str = Qnil;
2763 data.new_ascent = dl->ascent;
2764 data.new_descent = dl->descent;
2766 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2767 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2770 elt = Dynarr_length (gbd) - 1;
2777 end = Dynarr_length (gbd);
2780 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2782 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2784 if (NILP (gb->extent))
2785 abort (); /* these should have been handled in add_glyph_rune */
2788 ((side == LEFT_GLYPHS &&
2789 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2790 || (side == RIGHT_GLYPHS &&
2791 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2793 data.findex = gb->findex;
2794 data.max_pixpos = data.pixpos + gb->width;
2795 add_glyph_rune (&data, gb, side, 0, NULL);
2800 (reverse ? elt-- : elt++);
2803 if (data.max_pixmap_height)
2805 int height = data.new_ascent + data.new_descent;
2806 int pix_ascent, pix_descent;
2808 pix_descent = data.max_pixmap_height * data.new_descent / height;
2809 pix_ascent = data.max_pixmap_height - pix_descent;
2810 data.new_ascent = max (data.new_ascent, pix_ascent);
2811 data.new_descent = max (data.new_descent, pix_descent);
2814 dl->ascent = data.new_ascent;
2815 dl->descent = data.new_descent;
2820 /* Add a blank to a margin display block. */
2823 add_margin_blank (struct display_line *dl, struct display_block *db,
2824 struct window *w, int xpos, int width, int side)
2828 rb.findex = (side == LEFT_GLYPHS
2829 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2830 : get_builtin_face_cache_index (w, Vright_margin_face));
2835 rb.type = RUNE_BLANK;
2836 rb.cursor_type = CURSOR_OFF;
2838 Dynarr_add (db->runes, rb);
2841 /* Display glyphs in the left outside margin, left inside margin and
2842 left whitespace area. */
2845 create_left_glyph_block (struct window *w, struct display_line *dl,
2850 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2852 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2853 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2854 int left_in_start = dl->bounds.left_in;
2855 int left_in_end = dl->bounds.left_in + overlay_width;
2857 struct display_block *odb, *idb;
2859 XSETWINDOW (window, w);
2861 /* We have to add the glyphs to the line in the order outside,
2862 inside, whitespace. However the precedence dictates that we
2863 determine how many will fit in the reverse order. */
2865 /* Determine how many whitespace glyphs we can display and where
2866 they should start. */
2867 white_in_start = dl->bounds.left_white;
2868 white_out_start = left_in_start;
2869 white_out_cnt = white_in_cnt = 0;
2872 while (elt < Dynarr_length (dl->left_glyphs))
2874 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2876 if (NILP (gb->extent))
2877 abort (); /* these should have been handled in add_glyph_rune */
2879 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2883 width = glyph_width (gb->glyph, window);
2885 if (white_in_start - width >= left_in_end)
2888 white_in_start -= width;
2892 else if (use_overflow
2893 && (white_out_start - width > dl->bounds.left_out))
2896 white_out_start -= width;
2907 /* Determine how many inside margin glyphs we can display and where
2908 they should start. The inside margin glyphs get whatever space
2909 is left after the whitespace glyphs have been displayed. These
2910 are tricky to calculate since if we decide to use the overflow
2911 area we basically have to start over. So for these we build up a
2912 list of just the inside margin glyphs and manipulate it to
2913 determine the needed info. */
2915 glyph_block_dynarr *ib;
2916 int avail_in, avail_out;
2919 int used_in, used_out;
2922 used_in = used_out = 0;
2923 ib = Dynarr_new (glyph_block);
2924 while (elt < Dynarr_length (dl->left_glyphs))
2926 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2928 if (NILP (gb->extent))
2929 abort (); /* these should have been handled in add_glyph_rune */
2931 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2934 gb->width = glyph_width (gb->glyph, window);
2935 used_in += gb->width;
2936 Dynarr_add (ib, *gb);
2946 avail_in = white_in_start - left_in_end;
2954 avail_out = white_out_start - dl->bounds.left_out;
2957 while (!done && marker < Dynarr_length (ib))
2959 int width = Dynarr_atp (ib, marker)->width;
2961 /* If everything now fits in the available inside margin
2962 space, we're done. */
2963 if (used_in <= avail_in)
2967 /* Otherwise see if we have room to move a glyph to the
2969 if (used_out + width <= avail_out)
2982 /* At this point we now know that everything from marker on goes in
2983 the inside margin and everything before it goes in the outside
2984 margin. The stuff going into the outside margin is guaranteed
2985 to fit, but we may have to trim some stuff from the inside. */
2987 in_in_end = left_in_end;
2988 in_out_start = white_out_start;
2989 in_out_cnt = in_in_cnt = 0;
2993 while (elt < Dynarr_length (dl->left_glyphs))
2995 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2997 if (NILP (gb->extent))
2998 abort (); /* these should have been handled in add_glyph_rune */
3000 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3003 int width = glyph_width (gb->glyph, window);
3008 in_out_start -= width;
3013 else if (in_in_end + width < white_in_start)
3028 /* Determine how many outside margin glyphs we can display. They
3029 always start at the left outside margin and can only use the
3030 outside margin space. */
3031 out_end = dl->bounds.left_out;
3035 while (elt < Dynarr_length (dl->left_glyphs))
3037 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3039 if (NILP (gb->extent))
3040 abort (); /* these should have been handled in add_glyph_rune */
3042 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3045 int width = glyph_width (gb->glyph, window);
3047 if (out_end + width <= in_out_start)
3061 /* Now that we know where everything goes, we add the glyphs as
3062 runes to the appropriate display blocks. */
3063 if (out_cnt || in_out_cnt || white_out_cnt)
3065 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3066 odb->start_pos = dl->bounds.left_out;
3067 /* #### We should stop adding a blank to account for the space
3068 between the end of the glyphs and the margin and instead set
3069 this accordingly. */
3070 odb->end_pos = dl->bounds.left_in;
3071 Dynarr_reset (odb->runes);
3076 if (in_in_cnt || white_in_cnt)
3078 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3079 idb->start_pos = dl->bounds.left_in;
3080 /* #### See above comment for odb->end_pos */
3081 idb->end_pos = dl->bounds.left_white;
3082 Dynarr_reset (idb->runes);
3087 /* First add the outside margin glyphs. */
3089 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3090 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3092 end_xpos = dl->bounds.left_out;
3094 /* There may be blank space between the outside margin glyphs and
3095 the inside margin glyphs. If so, add a blank. */
3096 if (in_out_cnt && (in_out_start - end_xpos))
3098 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3102 /* Next add the inside margin glyphs which are actually in the
3106 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3107 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3110 /* If we didn't add any inside margin glyphs to the outside margin,
3111 but are adding whitespace glyphs, then we need to add a blank
3113 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3115 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3119 /* Next add the whitespace margin glyphs which are actually in the
3123 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3124 GL_WHITESPACE, LEFT_GLYPHS, window);
3127 /* We take care of clearing between the end of the glyphs and the
3128 start of the inside margin for lines which have glyphs. */
3129 if (odb && (left_in_start - end_xpos))
3131 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3135 /* Next add the inside margin glyphs which are actually in the
3139 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3140 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3143 end_xpos = left_in_end;
3145 /* Make sure that the area between the end of the inside margin
3146 glyphs and the whitespace glyphs is cleared. */
3147 if (idb && (white_in_start - end_xpos > 0))
3149 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3153 /* Next add the whitespace margin glyphs which are actually in the
3157 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3158 LEFT_GLYPHS, window);
3161 /* Whitespace glyphs always end right next to the text block so
3162 there is nothing we have to make sure is cleared after them. */
3165 /* Display glyphs in the right outside margin, right inside margin and
3166 right whitespace area. */
3169 create_right_glyph_block (struct window *w, struct display_line *dl)
3173 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3175 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3176 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3178 struct display_block *odb, *idb;
3180 XSETWINDOW (window, w);
3182 /* We have to add the glyphs to the line in the order outside,
3183 inside, whitespace. However the precedence dictates that we
3184 determine how many will fit in the reverse order. */
3186 /* Determine how many whitespace glyphs we can display and where
3187 they should start. */
3188 white_in_end = dl->bounds.right_white;
3189 white_out_end = dl->bounds.right_in;
3190 white_out_cnt = white_in_cnt = 0;
3193 while (elt < Dynarr_length (dl->right_glyphs))
3195 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3197 if (NILP (gb->extent))
3198 abort (); /* these should have been handled in add_glyph_rune */
3200 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3202 int width = glyph_width (gb->glyph, window);
3204 if (white_in_end + width <= dl->bounds.right_in)
3207 white_in_end += width;
3211 else if (use_overflow
3212 && (white_out_end + width <= dl->bounds.right_out))
3215 white_out_end += width;
3226 /* Determine how many inside margin glyphs we can display and where
3227 they should start. The inside margin glyphs get whatever space
3228 is left after the whitespace glyphs have been displayed. These
3229 are tricky to calculate since if we decide to use the overflow
3230 area we basically have to start over. So for these we build up a
3231 list of just the inside margin glyphs and manipulate it to
3232 determine the needed info. */
3234 glyph_block_dynarr *ib;
3235 int avail_in, avail_out;
3238 int used_in, used_out;
3241 used_in = used_out = 0;
3242 ib = Dynarr_new (glyph_block);
3243 while (elt < Dynarr_length (dl->right_glyphs))
3245 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3247 if (NILP (gb->extent))
3248 abort (); /* these should have been handled in add_glyph_rune */
3250 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3252 gb->width = glyph_width (gb->glyph, window);
3253 used_in += gb->width;
3254 Dynarr_add (ib, *gb);
3263 avail_in = dl->bounds.right_in - white_in_end;
3268 avail_out = dl->bounds.right_out - white_out_end;
3271 while (!done && marker < Dynarr_length (ib))
3273 int width = Dynarr_atp (ib, marker)->width;
3275 /* If everything now fits in the available inside margin
3276 space, we're done. */
3277 if (used_in <= avail_in)
3281 /* Otherwise see if we have room to move a glyph to the
3283 if (used_out + width <= avail_out)
3296 /* At this point we now know that everything from marker on goes in
3297 the inside margin and everything before it goes in the outside
3298 margin. The stuff going into the outside margin is guaranteed
3299 to fit, but we may have to trim some stuff from the inside. */
3301 in_in_start = dl->bounds.right_in;
3302 in_out_end = dl->bounds.right_in;
3303 in_out_cnt = in_in_cnt = 0;
3307 while (elt < Dynarr_length (dl->right_glyphs))
3309 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3311 if (NILP (gb->extent))
3312 abort (); /* these should have been handled in add_glyph_rune */
3314 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3316 int width = glyph_width (gb->glyph, window);
3321 in_out_end += width;
3326 else if (in_in_start - width >= white_in_end)
3329 in_in_start -= width;
3341 /* Determine how many outside margin glyphs we can display. They
3342 always start at the right outside margin and can only use the
3343 outside margin space. */
3344 out_start = dl->bounds.right_out;
3348 while (elt < Dynarr_length (dl->right_glyphs))
3350 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3352 if (NILP (gb->extent))
3353 abort (); /* these should have been handled in add_glyph_rune */
3355 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3357 int width = glyph_width (gb->glyph, window);
3359 if (out_start - width >= in_out_end)
3373 /* Now that we now where everything goes, we add the glyphs as runes
3374 to the appropriate display blocks. */
3375 if (out_cnt || in_out_cnt || white_out_cnt)
3377 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3378 /* #### See comments before odb->start_pos init in
3379 create_left_glyph_block */
3380 odb->start_pos = dl->bounds.right_in;
3381 odb->end_pos = dl->bounds.right_out;
3382 Dynarr_reset (odb->runes);
3387 if (in_in_cnt || white_in_cnt)
3389 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3390 idb->start_pos = dl->bounds.right_white;
3391 /* #### See comments before odb->start_pos init in
3392 create_left_glyph_block */
3393 idb->end_pos = dl->bounds.right_in;
3394 Dynarr_reset (idb->runes);
3399 /* First add the whitespace margin glyphs which are actually in the
3403 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3404 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3408 end_xpos = dl->bounds.right_white;
3410 /* Make sure that the area between the end of the whitespace glyphs
3411 and the inside margin glyphs is cleared. */
3412 if (in_in_cnt && (in_in_start - end_xpos))
3414 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3418 /* Next add the inside margin glyphs which are actually in the
3422 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3423 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3426 /* If we didn't add any inside margin glyphs then make sure the rest
3427 of the inside margin area gets cleared. */
3428 if (idb && (dl->bounds.right_in - end_xpos))
3430 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3434 /* Next add any whitespace glyphs in the outside margin. */
3437 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3438 GL_WHITESPACE, RIGHT_GLYPHS, window);
3441 end_xpos = dl->bounds.right_in;
3443 /* Next add any inside margin glyphs in the outside margin. */
3446 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3447 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3450 /* There may be space between any whitespace or inside margin glyphs
3451 in the outside margin and the actual outside margin glyphs. */
3452 if (odb && (out_start - end_xpos))
3454 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3458 /* Finally, add the outside margin glyphs. */
3461 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3462 RIGHT_GLYPHS, window);
3467 /***************************************************************************/
3469 /* modeline routines */
3471 /***************************************************************************/
3473 /* This function is also used in frame.c by `generate_title_string' */
3475 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3476 struct window *w, struct display_line *dl,
3477 struct display_block *db, face_index findex,
3478 int min_pixpos, int max_pixpos, int type)
3480 struct frame *f = XFRAME (w->frame);
3481 struct device *d = XDEVICE (f->device);
3485 Charcount offset = 0;
3491 data.findex = findex;
3492 data.pixpos = min_pixpos;
3493 data.max_pixpos = max_pixpos;
3494 data.cursor_type = NO_CURSOR;
3495 data.last_charset = Qunbound;
3496 data.last_findex = DEFAULT_INDEX;
3497 data.result_str = result_str;
3498 data.is_modeline = 1;
3500 XSETWINDOW (data.window, w);
3502 Dynarr_reset (formatted_string_extent_dynarr);
3503 Dynarr_reset (formatted_string_extent_start_dynarr);
3504 Dynarr_reset (formatted_string_extent_end_dynarr);
3506 /* result_str is nil when we're building a frame or icon title. Otherwise,
3507 we're building a modeline, so the offset starts at the modeline
3508 horizontal scrolling amount */
3509 if (! NILP (result_str))
3510 offset = w->modeline_hscroll;
3511 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3512 max_pixpos - min_pixpos, findex, type, &offset,
3515 if (Dynarr_length (db->runes))
3518 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3519 c_pixpos = rb->xpos + rb->width;
3522 c_pixpos = min_pixpos;
3524 /* If we don't reach the right side of the window, add a blank rune
3525 to make up the difference. This usually only occurs if the
3526 modeline face is using a proportional width font or a fixed width
3527 font of a different size from the default face font. */
3529 if (c_pixpos < max_pixpos)
3531 data.pixpos = c_pixpos;
3532 data.blank_width = max_pixpos - data.pixpos;
3534 add_blank_rune (&data, NULL, 0);
3537 /* Now create the result string and frob the extents into it. */
3538 if (!NILP (result_str))
3543 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3545 in_modeline_generation = 1;
3547 detach_all_extents (result_str);
3548 resize_string (XSTRING (result_str), -1,
3549 data.bytepos - XSTRING_LENGTH (result_str));
3551 strdata = XSTRING_DATA (result_str);
3553 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3555 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3557 len += (set_charptr_emchar
3558 (strdata + len, Dynarr_atp (db->runes,
3559 elt)->object.chr.ch));
3563 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3566 Lisp_Object extent = Qnil;
3569 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3570 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3573 child = Fmake_extent (Qnil, Qnil, result_str);
3574 Fputhash (extent, child, buf->modeline_extent_table);
3576 Fset_extent_parent (child, extent);
3577 set_extent_endpoints
3579 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3580 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3584 in_modeline_generation = 0;
3588 /* Ensure that the given display line DL accurately represents the
3589 modeline for the given window. */
3591 generate_modeline (struct window *w, struct display_line *dl, int type)
3593 struct buffer *b = XBUFFER (w->buffer);
3594 struct frame *f = XFRAME (w->frame);
3595 struct device *d = XDEVICE (f->device);
3597 /* Unlike display line and rune pointers, this one can't change underneath
3599 struct display_block *db = get_display_block_from_line (dl, TEXT);
3600 int max_pixpos, min_pixpos, ypos_adj;
3601 Lisp_Object font_inst;
3603 /* This will actually determine incorrect inside boundaries for the
3604 modeline since it ignores the margins. However being aware of this fact
3605 we never use those values anywhere so it doesn't matter. */
3606 dl->bounds = calculate_display_line_boundaries (w, 1);
3608 /* We are generating a modeline. */
3610 dl->cursor_elt = -1;
3612 /* Reset the runes on the modeline. */
3613 Dynarr_reset (db->runes);
3615 if (!WINDOW_HAS_MODELINE_P (w))
3619 /* If there is a horizontal scrollbar, don't add anything. */
3620 if (window_scrollbar_height (w))
3623 dl->ascent = DEVMETH (d, divider_height, ());
3625 /* The modeline is at the bottom of the gutters. */
3626 dl->ypos = WINDOW_BOTTOM (w);
3628 rb.findex = MODELINE_INDEX;
3629 rb.xpos = dl->bounds.left_out;
3630 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3633 rb.type = RUNE_HLINE;
3634 rb.object.hline.thickness = 1;
3635 rb.object.hline.yoffset = 0;
3636 rb.cursor_type = NO_CURSOR;
3638 if (!EQ (Qzero, w->modeline_shadow_thickness)
3641 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3643 dl->ypos -= shadow_thickness;
3644 rb.xpos += shadow_thickness;
3645 rb.width -= 2 * shadow_thickness;
3648 Dynarr_add (db->runes, rb);
3652 /* !!#### not right; needs to compute the max height of
3654 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3656 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3657 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3659 min_pixpos = dl->bounds.left_out;
3660 max_pixpos = dl->bounds.right_out;
3662 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3664 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3666 ypos_adj = shadow_thickness;
3667 min_pixpos += shadow_thickness;
3668 max_pixpos -= shadow_thickness;
3673 generate_formatted_string_db (b->modeline_format,
3674 b->generated_modeline_string, w, dl, db,
3675 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3677 /* The modeline is at the bottom of the gutters. We have to wait to
3678 set this until we've generated the modeline in order to account
3679 for any embedded faces. */
3680 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3684 add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str,
3685 Charcount pos, Charcount min_pos, Charcount max_pos)
3687 /* This function has been Mule-ized. */
3689 const Bufbyte *cur_pos = str;
3690 struct display_block *db = data->db;
3692 data->blank_width = space_width (XWINDOW (data->window));
3693 while (Dynarr_length (db->runes) < pos)
3694 add_blank_rune (data, NULL, 0);
3696 end = (Dynarr_length (db->runes) +
3697 bytecount_to_charcount (str, strlen ((const char *) str)));
3699 end = min (max_pos, end);
3701 while (pos < end && *cur_pos)
3703 const Bufbyte *old_cur_pos = cur_pos;
3706 data->ch = charptr_emchar (cur_pos);
3707 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3708 INC_CHARPTR (cur_pos);
3712 data->modeline_charpos++;
3713 data->bytepos += cur_pos - old_cur_pos;
3717 while (Dynarr_length (db->runes) < min_pos &&
3718 (data->pixpos + data->blank_width <= data->max_pixpos))
3719 add_blank_rune (data, NULL, 0);
3721 return Dynarr_length (db->runes);
3724 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3725 modeline extents. */
3727 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3728 Charcount pos, Charcount min_pos,
3729 Charcount max_pos, Lisp_Object extent)
3731 /* This function has been Mule-ized. */
3733 struct display_block *db = data->db;
3734 struct glyph_block gb;
3736 data->blank_width = space_width (XWINDOW (data->window));
3737 while (Dynarr_length (db->runes) < pos)
3738 add_blank_rune (data, NULL, 0);
3740 end = Dynarr_length (db->runes) + 1;
3742 end = min (max_pos, end);
3746 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3749 while (Dynarr_length (db->runes) < pos &&
3750 (data->pixpos + data->blank_width <= data->max_pixpos))
3751 add_blank_rune (data, NULL, 0);
3753 return Dynarr_length (db->runes);
3756 /* If max_pos is == -1, it is considered to be infinite. The same is
3757 true of max_pixsize. */
3758 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3759 if (Dynarr_length (data->db->runes)) \
3760 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3764 /* Note that this function does "positions" in terms of characters and
3765 not in terms of columns. This is necessary to make the formatting
3766 work correctly when proportional width fonts are used in the
3769 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3770 Charcount min_pos, Charcount max_pos,
3771 Lisp_Object elt, int depth, int max_pixsize,
3772 face_index findex, int type, Charcount *offset,
3773 Lisp_Object cur_ext)
3775 /* This function has been Mule-ized. */
3776 /* #### The other losing things in this function are:
3778 -- C zero-terminated-string lossage.
3779 -- Non-printable characters should be converted into something
3780 appropriate (e.g. ^F) instead of blindly being printed anyway.
3791 /* A string. Add to the display line and check for %-constructs
3794 Bufbyte *this = XSTRING_DATA (elt);
3796 while ((pos < max_pos || max_pos == -1) && *this)
3798 Bufbyte *last = this;
3800 while (*this && *this != '%')
3805 /* No %-construct */
3807 bytecount_to_charcount (last, this - last);
3809 if (size <= *offset)
3813 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
3814 min (pos + size - *offset, max_pos));
3815 const Bufbyte *tmp_last = charptr_n_addr (last, *offset);
3817 pos = add_string_to_fstring_db_runes (data, tmp_last,
3822 else /* *this == '%' */
3824 Charcount spec_width = 0;
3826 this++; /* skip over '%' */
3828 /* We can't allow -ve args due to the "%-" construct.
3829 * Argument specifies minwidth but not maxwidth
3830 * (maxwidth can be specified by
3831 * (<negative-number> . <stuff>) modeline elements)
3833 while (isdigit (*this))
3835 spec_width = spec_width * 10 + (*this - '0');
3842 pos = generate_fstring_runes (w, data, pos, spec_width,
3843 max_pos, Vglobal_mode_string,
3844 depth, max_pixsize, findex,
3845 type, offset, cur_ext);
3847 else if (*this == '-')
3849 Charcount num_to_add;
3851 if (max_pixsize < 0)
3853 else if (max_pos != -1)
3854 num_to_add = max_pos - pos;
3860 SET_CURRENT_MODE_CHARS_PIXSIZE;
3863 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3866 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3870 while (num_to_add--)
3871 pos = add_string_to_fstring_db_runes
3872 (data, (const Bufbyte *) "-", pos, pos, max_pos);
3874 else if (*this != 0)
3876 Emchar ch = charptr_emchar (this);
3880 decode_mode_spec (w, ch, type);
3882 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3883 size = bytecount_to_charcount
3884 /* Skip the null character added by `decode_mode_spec' */
3885 (str, Dynarr_length (mode_spec_bufbyte_string)) - 1;
3887 if (size <= *offset)
3891 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3893 /* #### NOTE: I don't understand why a tmp_max is not
3894 computed and used here as in the plain string case
3896 pos = add_string_to_fstring_db_runes (data, tmp_str,
3903 /* NOT this++. There could be any sort of character at
3904 the current position. */
3908 if (max_pixsize > 0)
3911 SET_CURRENT_MODE_CHARS_PIXSIZE;
3913 if (cur_pixsize >= max_pixsize)
3918 else if (SYMBOLP (elt))
3920 /* A symbol: process the value of the symbol recursively
3921 as if it appeared here directly. */
3922 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3924 if (!UNBOUNDP (tem))
3926 /* If value is a string, output that string literally:
3927 don't check for % within it. */
3930 Bufbyte *str = XSTRING_DATA (tem);
3931 Charcount size = XSTRING_CHAR_LENGTH (tem);
3933 if (size <= *offset)
3937 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3939 /* #### NOTE: I don't understand why a tmp_max is not
3940 computed and used here as in the plain string case
3942 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
3947 /* Give up right away for nil or t. */
3948 else if (!EQ (tem, elt))
3955 else if (GENERIC_SPECIFIERP (elt))
3957 Lisp_Object window, tem;
3958 XSETWINDOW (window, w);
3959 tem = specifier_instance_no_quit (elt, Qunbound, window,
3960 ERROR_ME_NOT, 0, Qzero);
3961 if (!UNBOUNDP (tem))
3967 else if (CONSP (elt))
3969 /* A cons cell: four distinct cases.
3970 * - If first element is a string or a cons, process all the elements
3971 * and effectively concatenate them.
3972 * - If first element is a negative number, truncate displaying cdr to
3973 * at most that many characters. If positive, pad (with spaces)
3974 * to at least that many characters.
3975 * - If first element is another symbol, process the cadr or caddr
3976 * recursively according to whether the symbol's value is non-nil or
3978 * - If first element is an extent, process the cdr recursively
3979 * and handle the extent's face.
3982 Lisp_Object car, tem;
3991 tem = symbol_value_in_buffer (car, w->buffer);
3992 /* elt is now the cdr, and we know it is a cons cell.
3993 Use its car if CAR has a non-nil value. */
3994 if (!UNBOUNDP (tem))
4002 /* Symbol's value is nil (or symbol is unbound)
4003 * Get the cddr of the original list
4004 * and if possible find the caddr and use that.
4009 else if (!CONSP (elt))
4017 else if (INTP (car))
4019 Charcount lim = XINT (car);
4025 /* Negative int means reduce maximum width.
4026 * DO NOT change MIN_PIXPOS here!
4027 * (20 -10 . foo) should truncate foo to 10 col
4028 * and then pad to 20.
4031 max_pos = pos - lim;
4033 max_pos = min (max_pos, pos - lim);
4037 /* Padding specified. Don't let it be more than
4041 if (max_pos != -1 && lim > max_pos)
4043 /* If that's more padding than already wanted, queue it.
4044 * But don't reduce padding already specified even if
4045 * that is beyond the current truncation point.
4052 else if (STRINGP (car) || CONSP (car))
4056 /* LIMIT is to protect against circular lists. */
4057 while (CONSP (elt) && --limit > 0
4058 && (pos < max_pos || max_pos == -1))
4060 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4061 XCAR (elt), depth, max_pixsize,
4062 findex, type, offset, cur_ext);
4066 else if (EXTENTP (car))
4068 struct extent *ext = XEXTENT (car);
4070 if (EXTENT_LIVE_P (ext))
4072 face_index old_findex = data->findex;
4074 Lisp_Object font_inst;
4075 face_index new_findex;
4076 Bytecount start = data->bytepos;
4078 face = extent_face (ext);
4081 /* #### needs to merge faces, sigh */
4082 /* #### needs to handle list of faces */
4083 new_findex = get_builtin_face_cache_index (w, face);
4084 /* !!#### not right; needs to compute the max height of
4086 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
4089 data->dl->ascent = max (data->dl->ascent,
4090 XFONT_INSTANCE (font_inst)->ascent);
4091 data->dl->descent = max (data->dl->descent,
4092 XFONT_INSTANCE (font_inst)->
4096 new_findex = old_findex;
4098 data->findex = new_findex;
4099 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4100 XCDR (elt), depth - 1,
4101 max_pixsize, new_findex, type,
4103 data->findex = old_findex;
4104 Dynarr_add (formatted_string_extent_dynarr, ext);
4105 Dynarr_add (formatted_string_extent_start_dynarr, start);
4106 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4110 else if (GLYPHP (elt))
4112 /* Glyphs are considered as one character with respect to the modeline
4113 horizontal scrolling facility. -- dv */
4117 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos,
4124 char *str = GETTEXT ("*invalid*");
4125 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */
4127 if (size <= *offset)
4131 const Bufbyte *tmp_str =
4132 charptr_n_addr ((const Bufbyte *) str, *offset);
4134 /* #### NOTE: I don't understand why a tmp_max is not computed and
4135 used here as in the plain string case above. -- dv */
4136 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
4145 add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos,
4152 /* Update just the modeline. Assumes the desired display structs. If
4153 they do not have a modeline block, it does nothing. */
4155 regenerate_modeline (struct window *w)
4157 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4159 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4163 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4164 redisplay_update_line (w, 0, 0, 0);
4168 /* Make sure that modeline display line is present in the given
4169 display structs if the window has a modeline and update that
4170 line. Returns true if a modeline was needed. */
4172 ensure_modeline_generated (struct window *w, int type)
4176 /* minibuffer windows don't have modelines */
4177 if (MINI_WINDOW_P (w))
4179 /* windows which haven't had it turned off do */
4180 else if (WINDOW_HAS_MODELINE_P (w))
4182 /* windows which have it turned off don't have a divider if there is
4183 a horizontal scrollbar */
4184 else if (window_scrollbar_height (w))
4186 /* and in this case there is none */
4192 display_line_dynarr *dla;
4194 dla = window_display_lines (w, type);
4196 /* We don't care if there is a display line which is not
4197 currently a modeline because it is definitely going to become
4198 one if we have gotten to this point. */
4199 if (Dynarr_length (dla) == 0)
4201 if (Dynarr_largest (dla) > 0)
4203 struct display_line *mlp = Dynarr_atp (dla, 0);
4204 Dynarr_add (dla, *mlp);
4208 struct display_line modeline;
4210 Dynarr_add (dla, modeline);
4214 /* If we're adding a new place marker go ahead and generate the
4215 modeline so that it is available for use by
4216 window_modeline_height. */
4217 generate_modeline (w, Dynarr_atp (dla, 0), type);
4220 return need_modeline;
4223 /* #### Kludge or not a kludge. I tend towards the former. */
4225 real_current_modeline_height (struct window *w)
4227 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4228 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4230 if (ensure_modeline_generated (w, CMOTION_DISP))
4232 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4234 if (Dynarr_length (dla))
4236 if (Dynarr_atp (dla, 0)->modeline)
4237 return (Dynarr_atp (dla, 0)->ascent +
4238 Dynarr_atp (dla, 0)->descent);
4245 /***************************************************************************/
4247 /* displayable string routines */
4249 /***************************************************************************/
4251 /* Given a position for a string in a window, ensure that the given
4252 display line DL accurately represents the text on a line starting
4253 at the given position.
4255 Yes, this is duplicating the code of create_text_block, but it
4256 looked just too hard to change create_text_block to handle strings
4257 *and* buffers. We already make a distinction between the two
4258 elsewhere in the code so I think unifying them would require a
4259 complete MULE rewrite. Besides, the other distinction is that these
4260 functions cover text that the user *cannot edit* so we can remove
4261 everything to do with cursors, minibuffers etc. Eventually the
4262 modeline routines should be modified to use this code as it copes
4263 with many more types of display situation. */
4266 create_string_text_block (struct window *w, Lisp_Object disp_string,
4267 struct display_line *dl,
4269 prop_block_dynarr **prop,
4270 face_index default_face)
4272 struct frame *f = XFRAME (w->frame);
4273 /* Note that a lot of the buffer controlled stuff has been left in
4274 because you might well want to make use of it (selective display
4275 etc), its just the buffer text that we do not use. However, it
4276 seems to be possible for buffer to be nil sometimes so protect
4277 against this case. */
4278 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
4279 struct device *d = XDEVICE (f->device);
4280 Lisp_String* s = XSTRING (disp_string);
4282 /* we're working with these a lot so precalculate them */
4283 Bytecount slen = XSTRING_LENGTH (disp_string);
4284 Bytecount bi_string_zv = slen;
4285 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4289 int truncate_win = b ? window_truncation_on (w) : 0;
4290 int end_glyph_width = 0;
4292 /* We're going to ditch selective display for static text, it's an
4293 FSF thing and invisible extents are the way to go here.
4294 Implementing it also relies on a number of buffer-specific
4295 functions that we don't have the luxury of being able to use
4298 /* The variable ctl-arrow allows the user to specify what characters
4299 can actually be displayed and which octal should be used for.
4300 #### This variable should probably have some rethought done to
4303 #### It would also be really nice if you could specify that
4304 the characters come out in hex instead of in octal. Mule
4305 does that by adding a ctl-hexa variable similar to ctl-arrow,
4306 but that's bogus -- we need a more general solution. I
4307 think you need to extend the concept of display tables
4308 into a more general conversion mechanism. Ideally you
4309 could specify a Lisp function that converts characters,
4310 but this violates the Second Golden Rule and besides would
4311 make things way way way way slow.
4313 So instead, we extend the display-table concept, which was
4314 historically limited to 256-byte vectors, to one of the
4317 a) A 256-entry vector, for backward compatibility;
4318 b) char-table, mapping characters to values;
4319 c) range-table, mapping ranges of characters to values;
4320 d) a list of the above.
4322 The (d) option allows you to specify multiple display tables
4323 instead of just one. Each display table can specify conversions
4324 for some characters and leave others unchanged. The way the
4325 character gets displayed is determined by the first display table
4326 with a binding for that character. This way, you could call a
4327 function `enable-hex-display' that adds a hex display-table to
4328 the list of display tables for the current buffer.
4330 #### ...not yet implemented... Also, we extend the concept of
4331 "mapping" to include a printf-like spec. Thus you can make all
4332 extended characters show up as hex with a display table like
4335 #s(range-table data ((256 524288) (format "%x")))
4337 Since more than one display table is possible, you have
4338 great flexibility in mapping ranges of characters. */
4339 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4340 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4341 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4342 ? 255 : 160)) : 255;
4344 Lisp_Object face_dt, window_dt;
4346 /* The text display block for this display line. */
4347 struct display_block *db = get_display_block_from_line (dl, TEXT);
4349 /* The first time through the main loop we need to force the glyph
4350 data to be updated. */
4353 /* Apparently the new extent_fragment_update returns an end position
4354 equal to the position passed in if there are no more runs to be
4356 int no_more_frags = 0;
4358 dl->used_prop_data = 0;
4360 dl->line_continuation = 0;
4362 /* set up faces to use for clearing areas, used by
4363 output_display_line */
4364 dl->default_findex = default_face;
4367 dl->left_margin_findex = default_face;
4368 dl->right_margin_findex = default_face;
4372 dl->left_margin_findex =
4373 get_builtin_face_cache_index (w, Vleft_margin_face);
4374 dl->right_margin_findex =
4375 get_builtin_face_cache_index (w, Vright_margin_face);
4379 data.ef = extent_fragment_new (disp_string, f);
4381 /* These values are used by all of the rune addition routines. We add
4382 them to this structure for ease of passing. */
4384 XSETWINDOW (data.window, w);
4388 data.bi_bufpos = bi_start_pos;
4389 data.pixpos = dl->bounds.left_in;
4390 data.last_charset = Qunbound;
4391 data.last_findex = default_face;
4392 data.result_str = Qnil;
4393 data.string = disp_string;
4395 /* Set the right boundary adjusting it to take into account any end
4396 glyph. Save the width of the end glyph for later use. */
4397 data.max_pixpos = dl->bounds.right_in;
4400 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
4402 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
4404 data.max_pixpos -= end_glyph_width;
4406 data.cursor_type = NO_CURSOR;
4410 /* I don't think we want this, string areas should not scroll with
4412 data.start_col = w->hscroll;
4413 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4415 data.bi_start_col_enabled = 0;
4416 data.hscroll_glyph_width_adjust = 0;
4418 /* We regenerate the line from the very beginning. */
4419 Dynarr_reset (db->runes);
4421 /* Why is this less than or equal and not just less than? If the
4422 starting position is already equal to the maximum we can't add
4423 anything else, right? Wrong. We might still have a newline to
4424 add. A newline can use the room allocated for an end glyph since
4425 if we add it we know we aren't going to be adding any end
4428 /* #### Chuck -- I think this condition should be while (1).
4429 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4430 and the begin-glyph ends exactly at the end of the window, the
4431 end-glyph and text might not be displayed. while (1) ensures
4432 that the loop terminates only when either (a) there is
4433 propagation data or (b) the end-of-line or end-of-buffer is hit.
4435 #### Also I think you need to ensure that the operation
4436 "add begin glyphs; add end glyphs; add text" is atomic and
4437 can't get interrupted in the middle. If you run off the end
4438 of the line during that operation, then you keep accumulating
4439 propagation data until you're done. Otherwise, if the (e.g.)
4440 there's a begin glyph at a particular position and attempting
4441 to display that glyph results in window-end being hit and
4442 propagation data being generated, then the character at that
4443 position won't be displayed.
4445 #### See also the comment after the end of this loop, below.
4447 while (data.pixpos <= data.max_pixpos)
4449 /* #### This check probably should not be necessary. */
4450 if (data.bi_bufpos > bi_string_zv)
4452 /* #### urk! More of this lossage! */
4457 /* Check for face changes. */
4458 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
4460 /* Now compute the face and begin/end-glyph information. */
4462 /* Remember that the extent-fragment routines deal in Bytind's. */
4463 extent_fragment_update (w, data.ef, data.bi_bufpos);
4464 /* This is somewhat cheesy but the alternative is to
4465 propagate default_face into extent_fragment_update. */
4466 if (data.findex == DEFAULT_INDEX)
4467 data.findex = default_face;
4469 get_display_tables (w, data.findex, &face_dt, &window_dt);
4471 if (data.bi_bufpos == data.ef->end)
4476 /* Determine what is next to be displayed. We first handle any
4477 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4478 display then we determine what to do based on the character at the
4479 current buffer position. */
4481 /* If the current position is covered by an invisible extent, do
4482 nothing (except maybe add some ellipses).
4484 #### The behavior of begin and end-glyphs at the edge of an
4485 invisible extent should be investigated further. This is
4486 fairly low priority though. */
4487 if (data.ef->invisible)
4489 /* #### Chuck, perhaps you could look at this code? I don't
4490 really know what I'm doing. */
4493 Dynarr_free (*prop);
4497 /* The extent fragment code only sets this when we should
4498 really display the ellipses. It makes sure the ellipses
4499 don't get displayed more than once in a row. */
4500 if (data.ef->invisible_ellipses)
4502 struct glyph_block gb;
4504 data.ef->invisible_ellipses_already_displayed = 1;
4505 data.ef->invisible_ellipses = 0;
4507 gb.glyph = Vinvisible_text_glyph;
4508 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
4509 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
4510 /* Perhaps they shouldn't propagate if the very next thing
4511 is to display a newline (for compatibility with
4512 selective-display-ellipses)? Maybe that's too
4518 /* #### What if we're dealing with a display table? */
4522 if (data.bi_bufpos == bi_string_zv)
4525 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4528 /* If there is propagation data, then it represents the current
4529 buffer position being displayed. Add them and advance the
4530 position counter. This might also add the minibuffer
4534 dl->used_prop_data = 1;
4535 *prop = add_propagation_runes (prop, &data);
4538 goto done; /* gee, a really narrow window */
4539 else if (data.bi_bufpos == bi_string_zv)
4541 else if (data.bi_bufpos < 0)
4542 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4545 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4548 /* If there are end glyphs, add them to the line. These are
4549 the end glyphs for the previous run of text. We add them
4550 here rather than doing them at the end of handling the
4551 previous run so that glyphs at the beginning and end of
4552 a line are handled correctly. */
4553 else if (Dynarr_length (data.ef->end_glyphs) > 0)
4555 *prop = add_glyph_runes (&data, END_GLYPHS);
4560 /* If there are begin glyphs, add them to the line. */
4561 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
4563 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
4568 /* If at end-of-buffer, we've already processed begin and
4569 end-glyphs at this point and there's no text to process,
4571 else if (data.bi_bufpos == bi_string_zv)
4576 Lisp_Object entry = Qnil;
4577 /* Get the character at the current buffer position. */
4578 data.ch = string_char (s, data.bi_bufpos);
4579 if (!NILP (face_dt) || !NILP (window_dt))
4580 entry = display_table_entry (data.ch, face_dt, window_dt);
4582 /* If there is a display table entry for it, hand it off to
4583 add_disp_table_entry_runes and let it worry about it. */
4584 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
4586 *prop = add_disp_table_entry_runes (&data, entry);
4592 /* Check if we have hit a newline character. If so, add a marker
4593 to the line and end this loop. */
4594 else if (data.ch == '\n')
4596 /* We aren't going to be adding an end glyph so give its
4597 space back in order to make sure that the cursor can
4599 data.max_pixpos += end_glyph_width;
4603 /* If the current character is considered to be printable, then
4605 else if (data.ch >= printable_min)
4607 *prop = add_emchar_rune (&data);
4612 /* If the current character is a tab, determine the next tab
4613 starting position and add a blank rune which extends from the
4614 current pixel position to that starting position. */
4615 else if (data.ch == '\t')
4617 int tab_start_pixpos = data.pixpos;
4622 if (data.start_col > 1)
4623 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
4626 next_tab_position (w, tab_start_pixpos,
4627 dl->bounds.left_in +
4628 data.hscroll_glyph_width_adjust);
4629 if (next_tab_start > data.max_pixpos)
4631 prop_width = next_tab_start - data.max_pixpos;
4632 next_tab_start = data.max_pixpos;
4634 data.blank_width = next_tab_start - data.pixpos;
4636 (next_tab_start - tab_start_pixpos) / space_width (w);
4638 *prop = add_blank_rune (&data, w, char_tab_width);
4640 /* add_blank_rune is only supposed to be called with
4641 sizes guaranteed to fit in the available space. */
4646 struct prop_block pb;
4647 *prop = Dynarr_new (prop_block);
4649 pb.type = PROP_BLANK;
4650 pb.data.p_blank.width = prop_width;
4651 pb.data.p_blank.findex = data.findex;
4652 Dynarr_add (*prop, pb);
4658 /* If character is a control character, pass it off to
4659 add_control_char_runes.
4661 The is_*() routines have undefined results on
4662 arguments outside of the range [-1, 255]. (This
4663 often bites people who carelessly use `char' instead
4664 of `unsigned char'.)
4666 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
4668 *prop = add_control_char_runes (&data, b);
4674 /* If the character is above the ASCII range and we have not
4675 already handled it, then print it as an octal number. */
4676 else if (data.ch >= 0200)
4678 *prop = add_octal_runes (&data);
4684 /* Assume the current character is considered to be printable,
4685 then just add it. */
4688 *prop = add_emchar_rune (&data);
4693 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4699 /* Determine the starting point of the next line if we did not hit the
4700 end of the buffer. */
4701 if (data.bi_bufpos < bi_string_zv)
4703 /* #### This check is not correct. If the line terminated
4704 due to a begin-glyph or end-glyph hitting window-end, then
4705 data.ch will not point to the character at data.bi_bufpos. If
4706 you make the two changes mentioned at the top of this loop,
4707 you should be able to say '(if (*prop))'. That should also
4708 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4711 /* The common case is that the line ended because we hit a newline.
4712 In that case, the next character is just the next buffer
4714 if (data.ch == '\n')
4716 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4719 /* Otherwise we have a buffer line which cannot fit on one display
4723 struct glyph_block gb;
4724 struct glyph_cachel *cachel;
4726 /* If the line is to be truncated then we actually have to look
4727 for the next newline. We also add the end-of-line glyph which
4728 we know will fit because we adjusted the right border before
4729 we starting laying out the line. */
4730 data.max_pixpos += end_glyph_width;
4731 data.findex = default_face;
4738 /* Now find the start of the next line. */
4739 bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
4741 data.cursor_type = NO_CURSOR;
4742 data.bi_bufpos = bi_pos;
4743 gb.glyph = Vtruncation_glyph;
4744 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
4748 /* The cursor can never be on the continuation glyph. */
4749 data.cursor_type = NO_CURSOR;
4751 /* data.bi_bufpos is already at the start of the next line. */
4753 dl->line_continuation = 1;
4754 gb.glyph = Vcontinuation_glyph;
4755 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
4758 if (end_glyph_width)
4759 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
4761 if (truncate_win && data.bi_bufpos == bi_string_zv)
4763 const Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
4765 if (charptr_emchar (endb) != '\n')
4767 /* #### Damn this losing shit. */
4773 else if (data.bi_bufpos == bi_string_zv)
4775 /* create_text_block () adds a bogus \n marker here which screws
4776 up subwindow display. Since we never have a cursor in the
4777 gutter we can safely ignore it. */
4779 /* Calculate left whitespace boundary. */
4783 /* Whitespace past a newline is considered right whitespace. */
4784 while (elt < Dynarr_length (db->runes))
4786 struct rune *rb = Dynarr_atp (db->runes, elt);
4788 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4789 || rb->type == RUNE_BLANK)
4791 dl->bounds.left_white += rb->width;
4795 elt = Dynarr_length (db->runes);
4799 /* Calculate right whitespace boundary. */
4801 int elt = Dynarr_length (db->runes) - 1;
4804 while (!done && elt >= 0)
4806 struct rune *rb = Dynarr_atp (db->runes, elt);
4808 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4809 && isspace (rb->object.chr.ch))
4810 && !rb->type == RUNE_BLANK)
4812 dl->bounds.right_white = rb->xpos + rb->width;
4820 /* The line is blank so everything is considered to be right
4823 dl->bounds.right_white = dl->bounds.left_in;
4826 /* Set the display blocks bounds. */
4827 db->start_pos = dl->bounds.left_in;
4828 if (Dynarr_length (db->runes))
4830 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4832 db->end_pos = rb->xpos + rb->width;
4835 db->end_pos = dl->bounds.right_white;
4837 /* update line height parameters */
4838 if (!data.new_ascent && !data.new_descent)
4840 /* We've got a blank line so initialize these values from the default
4842 default_face_font_info (data.window, &data.new_ascent,
4843 &data.new_descent, 0, 0, 0);
4846 if (data.max_pixmap_height)
4848 int height = data.new_ascent + data.new_descent;
4849 int pix_ascent, pix_descent;
4851 pix_descent = data.max_pixmap_height * data.new_descent / height;
4852 pix_ascent = data.max_pixmap_height - pix_descent;
4854 data.new_ascent = max (data.new_ascent, pix_ascent);
4855 data.new_descent = max (data.new_descent, pix_descent);
4858 dl->ascent = data.new_ascent;
4859 dl->descent = data.new_descent;
4862 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
4864 if (dl->ascent < ascent)
4865 dl->ascent = ascent;
4868 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
4870 if (dl->descent < descent)
4871 dl->descent = descent;
4874 dl->cursor_elt = data.cursor_x;
4875 /* #### lossage lossage lossage! Fix this shit! */
4876 if (data.bi_bufpos > bi_string_zv)
4877 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4879 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4881 data.dl->num_chars =
4882 string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
4884 /* This doesn't correctly take into account tabs and control
4885 characters but if the window isn't being truncated then this
4886 value isn't going to end up being used anyhow. */
4887 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4889 /* #### handle horizontally scrolled line with text none of which
4890 was actually laid out. */
4892 /* #### handle any remainder of overlay arrow */
4894 if (*prop == ADD_FAILED)
4897 if (truncate_win && *prop)
4899 Dynarr_free (*prop);
4903 extent_fragment_delete (data.ef);
4905 /* #### If we started at EOB, then make sure we return a value past
4906 it so that regenerate_window will exit properly. This is bogus.
4907 The main loop should get fixed so that it isn't necessary to call
4908 this function if we are already at EOB. */
4910 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4911 return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
4913 return bytecount_to_charcount (string_data (s), data.bi_bufpos);
4916 /* Given a display line and a starting position, ensure that the
4917 contents of the display line accurately represent the visual
4918 representation of the buffer contents starting from the given
4919 position when displayed in the given window. The display line ends
4920 when the contents of the line reach the right boundary of the given
4923 This is very similar to generate_display_line but with the same
4924 limitations as create_string_text_block. I have taken the liberty
4925 of fixing the bytind stuff though.*/
4928 generate_string_display_line (struct window *w, Lisp_Object disp_string,
4929 struct display_line *dl,
4931 prop_block_dynarr **prop,
4932 face_index default_face)
4936 /* you must set bounds before calling this. */
4938 /* Reset what this line is using. */
4939 if (dl->display_blocks)
4940 Dynarr_reset (dl->display_blocks);
4941 if (dl->left_glyphs)
4943 Dynarr_free (dl->left_glyphs);
4944 dl->left_glyphs = 0;
4946 if (dl->right_glyphs)
4948 Dynarr_free (dl->right_glyphs);
4949 dl->right_glyphs = 0;
4952 /* We aren't generating a modeline at the moment. */
4955 /* Create a display block for the text region of the line. */
4956 ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
4957 prop, default_face);
4958 dl->bufpos = start_pos;
4959 if (dl->end_bufpos < dl->bufpos)
4960 dl->end_bufpos = dl->bufpos;
4962 /* If there are left glyphs associated with any character in the
4963 text block, then create a display block to handle them. */
4964 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
4965 create_left_glyph_block (w, dl, 0);
4967 /* If there are right glyphs associated with any character in the
4968 text block, then create a display block to handle them. */
4969 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
4970 create_right_glyph_block (w, dl);
4975 /* This is ripped off from regenerate_window. All we want to do is
4976 loop through elements in the string creating display lines until we
4977 have covered the provided area. Simple really. */
4979 generate_displayable_area (struct window *w, Lisp_Object disp_string,
4980 int xpos, int ypos, int width, int height,
4981 display_line_dynarr* dla,
4983 face_index default_face)
4985 int yend = ypos + height;
4988 prop_block_dynarr *prop = 0;
4989 layout_bounds bounds;
4993 /* if there's nothing to do then do nothing. code after this assumes
4994 there is something to do. */
4995 if (NILP (disp_string))
4998 s_zv = XSTRING_CHAR_LENGTH (disp_string);
5000 bounds.left_out = xpos;
5001 bounds.right_out = xpos + width;
5002 /* The inner boundaries mark where the glyph margins are located. */
5003 bounds.left_in = bounds.left_out + window_left_margin_width (w);
5004 bounds.right_in = bounds.right_out - window_right_margin_width (w);
5005 /* We cannot fully calculate the whitespace boundaries as they
5006 depend on the contents of the line being displayed. */
5007 bounds.left_white = bounds.left_in;
5008 bounds.right_white = bounds.right_in;
5012 struct display_line dl;
5013 struct display_line *dlp;
5017 if (Dynarr_length (dla) < Dynarr_largest (dla))
5019 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5030 dlp->bounds = bounds;
5032 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5033 &prop, default_face);
5034 /* we need to make sure that we continue along the line if there
5035 is more left to display otherwise we just end up redisplaying
5036 the same chunk over and over again. */
5037 if (next_pos == start_pos && next_pos < s_zv)
5040 start_pos = next_pos;
5042 dlp->ypos = ypos + dlp->ascent;
5043 ypos = dlp->ypos + dlp->descent;
5047 int visible_height = dlp->ascent + dlp->descent;
5049 dlp->clip = (ypos - yend);
5050 visible_height -= dlp->clip;
5052 if (visible_height < VERTICAL_CLIP (w, 1))
5055 free_display_line (dlp);
5062 Dynarr_add (dla, *dlp);
5064 /* #### This type of check needs to be done down in the
5065 generate_display_line call. */
5066 if (start_pos >= s_zv)
5075 /***************************************************************************/
5077 /* window-regeneration routines */
5079 /***************************************************************************/
5081 /* For a given window and starting position in the buffer it contains,
5082 ensure that the TYPE display lines accurately represent the
5083 presentation of the window. We pass the buffer instead of getting
5084 it from the window since redisplay_window may have temporarily
5085 changed it to the echo area buffer. */
5088 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
5090 struct frame *f = XFRAME (w->frame);
5091 struct buffer *b = XBUFFER (w->buffer);
5092 int ypos = WINDOW_TEXT_TOP (w);
5093 int yend; /* set farther down */
5094 int yclip = WINDOW_TEXT_TOP_CLIP (w);
5097 prop_block_dynarr *prop;
5098 layout_bounds bounds;
5099 display_line_dynarr *dla;
5102 /* The lines had better exist by this point. */
5103 if (!(dla = window_display_lines (w, type)))
5106 w->max_line_len = 0;
5108 /* Normally these get updated in redisplay_window but it is possible
5109 for this function to get called from some other points where that
5110 update may not have occurred. This acts as a safety check. */
5111 if (!Dynarr_length (w->face_cachels))
5112 reset_face_cachels (w);
5113 if (!Dynarr_length (w->glyph_cachels))
5114 reset_glyph_cachels (w);
5116 Fset_marker (w->start[type], make_int (start_pos), w->buffer);
5117 Fset_marker (w->pointm[type], make_int (point), w->buffer);
5118 w->last_point_x[type] = -1;
5119 w->last_point_y[type] = -1;
5121 /* Make sure a modeline is in the structs if needed. */
5122 need_modeline = ensure_modeline_generated (w, type);
5124 /* Wait until here to set this so that the structs have a modeline
5125 generated in the case where one didn't exist. */
5126 yend = WINDOW_TEXT_BOTTOM (w);
5128 bounds = calculate_display_line_boundaries (w, 0);
5130 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5131 if (MINI_WINDOW_P (w)
5132 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
5133 && !echo_area_active (f)
5134 && start_pos == BUF_BEGV (b))
5136 struct prop_block pb;
5138 prop = Dynarr_new (prop_block);
5140 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5141 pb.type = PROP_MINIBUF_PROMPT;
5142 pb.data.p_string.str = XSTRING_DATA(string);
5143 pb.data.p_string.len = XSTRING_LENGTH(string);
5144 Dynarr_add (prop, pb);
5149 /* When we are computing things for scrolling purposes, make
5150 sure at least one line is always generated */
5151 force = (type == CMOTION_DISP);
5153 /* Make sure this is set always */
5154 /* Note the conversion at end */
5155 w->window_end_pos[type] = start_pos;
5156 while (ypos < yend || force)
5158 struct display_line dl;
5159 struct display_line *dlp;
5162 if (Dynarr_length (dla) < Dynarr_largest (dla))
5164 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5175 dlp->bounds = bounds;
5177 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
5179 if (yclip > dlp->ascent)
5181 /* this should never happen, but if it does just display the
5186 dlp->ypos = (ypos + dlp->ascent) - yclip;
5187 ypos = dlp->ypos + dlp->descent;
5189 /* See if we've been asked to start midway through a line, for
5190 partial display line scrolling. */
5193 dlp->top_clip = yclip;
5201 int visible_height = dlp->ascent + dlp->descent;
5203 dlp->clip = (ypos - yend);
5204 /* Although this seems strange we could have a single very
5205 tall line visible for which we need to account for both
5206 the top clip and the bottom clip. */
5207 visible_height -= (dlp->clip + dlp->top_clip);
5209 if (visible_height < VERTICAL_CLIP (w, 1) && !force)
5212 free_display_line (dlp);
5219 if (dlp->cursor_elt != -1)
5221 /* #### This check is steaming crap. Have to get things
5222 fixed so when create_text_block hits EOB, we're done,
5224 if (w->last_point_x[type] == -1)
5226 w->last_point_x[type] = dlp->cursor_elt;
5227 w->last_point_y[type] = Dynarr_length (dla);
5231 /* #### This means that we've added a cursor at EOB
5232 twice. Yuck oh yuck. */
5233 struct display_block *db =
5234 get_display_block_from_line (dlp, TEXT);
5236 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
5237 dlp->cursor_elt = -1;
5241 if (dlp->num_chars > w->max_line_len)
5242 w->max_line_len = dlp->num_chars;
5244 Dynarr_add (dla, *dlp);
5246 /* #### This isn't right, but it is close enough for now. */
5247 w->window_end_pos[type] = start_pos;
5249 /* #### This type of check needs to be done down in the
5250 generate_display_line call. */
5251 if (start_pos > BUF_ZV (b))
5260 /* #### More not quite right, but close enough. */
5261 /* Ben sez: apparently window_end_pos[] is measured
5262 as the number of characters between the window end and the
5263 end of the buffer? This seems rather weirdo. What's
5264 the justification for this?
5266 JV sez: Because BUF_Z (b) would be a good initial value, however
5267 that can change. This representation allows initalizing with 0.
5269 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
5273 /* We know that this is the right thing to use because we put it
5274 there when we first started working in this function. */
5275 generate_modeline (w, Dynarr_atp (dla, 0), type);
5279 #define REGEN_INC_FIND_START_END \
5281 /* Determine start and end of lines. */ \
5282 if (!Dynarr_length (cdla)) \
5286 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5290 else if (!Dynarr_atp (cdla, 0)->modeline \
5291 && !Dynarr_atp (ddla, 0)->modeline) \
5296 abort (); /* structs differ */ \
5298 dla_end = Dynarr_length (cdla) - 1; \
5301 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5302 + Dynarr_atp (cdla, dla_start)->offset); \
5303 /* If this isn't true, then startp has changed and we need to do a \
5305 if (startp != start_pos) \
5308 /* Point is outside the visible region so give up. */ \
5309 if (pointm < start_pos) \
5314 /* This attempts to incrementally update the display structures. It
5315 returns a boolean indicating success or failure. This function is
5316 very similar to regenerate_window_incrementally and is in fact only
5317 called from that function. However, because of the nature of the
5318 changes it deals with it sometimes makes different assumptions
5319 which can lead to success which are much more difficult to make
5320 when dealing with buffer changes. */
5323 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
5325 Charcount beg_unchanged,
5326 Charcount end_unchanged)
5328 struct buffer *b = XBUFFER (w->buffer);
5329 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5330 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5334 int first_line, last_line;
5336 /* Don't define this in the loop where it is used because we
5337 definitely want its value to survive between passes. */
5338 prop_block_dynarr *prop = NULL;
5340 /* If we don't have any buffer change recorded but the modiff flag has
5341 been incremented, then fail. I'm not sure of the exact circumstances
5342 under which this can happen, but I believe that it is probably a
5343 reasonable happening. */
5344 if (!point_visible (w, pointm, CURRENT_DISP)
5345 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
5348 /* If the cursor is moved we attempt to update it. If we succeed we
5349 go ahead and proceed with the optimization attempt. */
5350 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5351 || pointm != marker_position (w->last_point[CURRENT_DISP]))
5353 struct frame *f = XFRAME (w->frame);
5354 struct device *d = XDEVICE (f->device);
5355 struct frame *sel_f = device_selected_frame (d);
5358 if (w->last_point_x[CURRENT_DISP] != -1
5359 && w->last_point_y[CURRENT_DISP] != -1)
5362 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
5364 /* Always regenerate the modeline in case it is
5365 displaying the current line or column. */
5366 regenerate_modeline (w);
5370 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
5372 if (f->modeline_changed)
5373 regenerate_modeline (w);
5381 if (beg_unchanged == -1 && end_unchanged == -1)
5384 /* assert: There are no buffer modifications or they are all below the
5385 visible region. We assume that regenerate_window_incrementally has
5386 not called us unless this is true. */
5388 REGEN_INC_FIND_START_END;
5390 /* If the changed are starts before the visible area, give up. */
5391 if (beg_unchanged < startp)
5394 /* Find what display line the extent changes first affect. */
5396 while (line <= dla_end)
5398 struct display_line *dl = Dynarr_atp (cdla, line);
5399 Bufpos lstart = dl->bufpos + dl->offset;
5400 Bufpos lend = dl->end_bufpos + dl->offset;
5402 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5408 /* If the changes are below the visible area then if point hasn't
5409 moved return success otherwise fail in order to be safe. */
5412 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5413 && pointm == marker_position (w->last_point[CURRENT_DISP]))
5419 /* At this point we know what line the changes first affect. We now
5420 begin redrawing lines as long as we are still in the affected
5421 region and the line's size and positioning don't change.
5422 Otherwise we fail. If we fail we will have altered the desired
5423 structs which could lead to an assertion failure. However, if we
5424 fail the next thing that is going to happen is a full regen so we
5425 will actually end up being safe. */
5426 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5427 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5428 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5429 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5431 first_line = last_line = line;
5432 while (line <= dla_end)
5434 Bufpos old_start, old_end, new_start;
5435 struct display_line *cdl = Dynarr_atp (cdla, line);
5436 struct display_line *ddl = Dynarr_atp (ddla, line);
5437 struct display_block *db;
5440 assert (cdl->bufpos == ddl->bufpos);
5441 assert (cdl->end_bufpos == ddl->end_bufpos);
5442 assert (cdl->offset == ddl->offset);
5444 db = get_display_block_from_line (ddl, TEXT);
5445 initial_size = Dynarr_length (db->runes);
5446 old_start = ddl->bufpos + ddl->offset;
5447 old_end = ddl->end_bufpos + ddl->offset;
5449 /* If this is the first line being updated and it used
5450 propagation data, fail. Otherwise we'll be okay because
5451 we'll have the necessary propagation data. */
5452 if (line == first_line && ddl->used_prop_data)
5455 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5456 &prop, DESIRED_DISP);
5459 /* #### If there is propagated stuff the fail. We could
5460 probably actually deal with this if the line had propagated
5461 information when originally created by a full
5469 /* If any line position parameters have changed or a
5470 cursor has disappeared or disappeared, fail. */
5471 db = get_display_block_from_line (ddl, TEXT);
5472 if (cdl->ypos != ddl->ypos
5473 || cdl->ascent != ddl->ascent
5474 || cdl->descent != ddl->descent
5475 || cdl->top_clip != ddl->top_clip
5476 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5477 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5478 || old_start != ddl->bufpos
5479 || old_end != ddl->end_bufpos
5480 || initial_size != Dynarr_length (db->runes))
5485 if (ddl->cursor_elt != -1)
5487 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5488 w->last_point_y[DESIRED_DISP] = line;
5493 /* If the extent changes end on the line we just updated then
5494 we're done. Otherwise go on to the next line. */
5495 if (end_unchanged <= ddl->end_bufpos)
5501 redisplay_update_line (w, first_line, last_line, 1);
5505 /* Attempt to update the display data structures based on knowledge of
5506 the changed region in the buffer. Returns a boolean indicating
5507 success or failure. If this function returns a failure then a
5508 regenerate_window _must_ be performed next in order to maintain
5509 invariants located here. */
5512 regenerate_window_incrementally (struct window *w, Bufpos startp,
5515 struct buffer *b = XBUFFER (w->buffer);
5516 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5517 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5518 Charcount beg_unchanged, end_unchanged;
5519 Charcount extent_beg_unchanged, extent_end_unchanged;
5525 /* If this function is called, the current and desired structures
5526 had better be identical. If they are not, then that is a bug. */
5527 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
5529 /* We don't handle minibuffer windows yet. The minibuffer prompt
5531 if (MINI_WINDOW_P (w))
5534 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
5535 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
5537 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
5539 /* If nothing has changed in the buffer, then make sure point is ok
5541 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
5542 return regenerate_window_extents_only_changed (w, startp, pointm,
5543 extent_beg_unchanged,
5544 extent_end_unchanged);
5546 /* We can't deal with deleted newlines. */
5547 if (BUF_NEWLINE_WAS_DELETED (b))
5550 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
5551 end_unchanged = (BUF_END_UNCHANGED (b) == -1
5553 : BUF_Z (b) - BUF_END_UNCHANGED (b));
5555 REGEN_INC_FIND_START_END;
5557 /* If the changed area starts before the visible area, give up. */
5558 if (beg_unchanged < startp)
5561 /* Find what display line the buffer changes first affect. */
5563 while (line <= dla_end)
5565 struct display_line *dl = Dynarr_atp (cdla, line);
5566 Bufpos lstart = dl->bufpos + dl->offset;
5567 Bufpos lend = dl->end_bufpos + dl->offset;
5569 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5575 /* If the changes are below the visible area then if point hasn't
5576 moved return success otherwise fail in order to be safe. */
5578 return regenerate_window_extents_only_changed (w, startp, pointm,
5579 extent_beg_unchanged,
5580 extent_end_unchanged);
5582 /* At this point we know what line the changes first affect. We
5583 now redraw that line. If the changes are contained within it
5584 we are going to succeed and can update just that one line.
5585 Otherwise we fail. If we fail we will have altered the desired
5586 structs which could lead to an assertion failure. However, if
5587 we fail the next thing that is going to happen is a full regen
5588 so we will actually end up being safe. */
5591 prop_block_dynarr *prop = NULL;
5592 struct display_line *cdl = Dynarr_atp (cdla, line);
5593 struct display_line *ddl = Dynarr_atp (ddla, line);
5595 assert (cdl->bufpos == ddl->bufpos);
5596 assert (cdl->end_bufpos == ddl->end_bufpos);
5597 assert (cdl->offset == ddl->offset);
5599 /* If the line continues to next display line, fail. */
5600 if (ddl->line_continuation)
5603 /* If the line was generated using propagation data, fail. */
5604 if (ddl->used_prop_data)
5607 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5608 &prop, DESIRED_DISP);
5611 /* If there is propagated stuff then it is pretty much a
5612 guarantee that more than just the one line is affected. */
5619 /* If the line continues to next display line, fail. */
5620 if (ddl->line_continuation)
5623 /* If any line position parameters have changed or a
5624 cursor has disappeared or disappeared, fail. */
5625 if (cdl->ypos != ddl->ypos
5626 || cdl->ascent != ddl->ascent
5627 || cdl->descent != ddl->descent
5628 || cdl->top_clip != ddl->top_clip
5629 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5630 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
5635 /* If the changed area also ends on this line, then we may be in
5636 business. Update everything and return success. */
5637 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
5639 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5640 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5641 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
5643 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
5646 if (ddl->cursor_elt != -1)
5648 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5649 w->last_point_y[DESIRED_DISP] = line;
5652 redisplay_update_line (w, line, line, 1);
5653 regenerate_modeline (w);
5655 /* #### For now we just flush the cache until this has been
5656 tested. After that is done, this should correct the
5658 Dynarr_reset (w->line_start_cache);
5660 /* Adjust the extent changed boundaries to remove any
5661 overlap with the buffer changes since we've just
5662 successfully updated that area. */
5663 if (extent_beg_unchanged != -1
5664 && extent_beg_unchanged >= beg_unchanged
5665 && extent_beg_unchanged < end_unchanged)
5666 extent_beg_unchanged = end_unchanged;
5668 if (extent_end_unchanged != -1
5669 && extent_end_unchanged >= beg_unchanged
5670 && extent_end_unchanged < end_unchanged)
5671 extent_end_unchanged = beg_unchanged - 1;
5673 if (extent_end_unchanged <= extent_beg_unchanged)
5674 extent_beg_unchanged = extent_end_unchanged = -1;
5676 /* This could lead to odd results if it fails, but since the
5677 buffer changes update succeeded this probably will to.
5678 We already know that the extent changes start at or after
5679 the line because we checked before entering the loop. */
5680 if (extent_beg_unchanged != -1
5681 && extent_end_unchanged != -1
5682 && ((extent_beg_unchanged < ddl->bufpos)
5683 || (extent_end_unchanged > ddl->end_bufpos)))
5684 return regenerate_window_extents_only_changed (w, startp, pointm,
5685 extent_beg_unchanged,
5686 extent_end_unchanged);
5696 /* Given a window and a point, update the given display lines such
5697 that point is displayed in the middle of the window.
5698 Return the window's new start position. */
5701 regenerate_window_point_center (struct window *w, Bufpos point, int type)
5705 /* We need to make sure that the modeline is generated so that the
5706 window height can be calculated correctly. */
5707 ensure_modeline_generated (w, type);
5709 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
5710 regenerate_window (w, startp, point, type);
5711 Fset_marker (w->start[type], make_int (startp), w->buffer);
5716 /* Given a window and a set of display lines, return a boolean
5717 indicating whether the given point is contained within. */
5720 point_visible (struct window *w, Bufpos point, int type)
5722 struct buffer *b = XBUFFER (w->buffer);
5723 display_line_dynarr *dla = window_display_lines (w, type);
5726 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5731 if (Dynarr_length (dla) > first_line)
5734 struct display_line *dl = Dynarr_atp (dla, first_line);
5737 end = BUF_Z (b) - w->window_end_pos[type] - 1;
5739 if (point >= start && point <= end)
5741 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
5743 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
5745 if (point >= (dl->bufpos + dl->offset)
5746 && point <= (dl->end_bufpos + dl->offset))
5761 /* Return pixel position the middle of the window, not including the
5762 modeline and any potential horizontal scrollbar. */
5765 window_half_pixpos (struct window *w)
5767 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
5770 /* Return the display line which is currently in the middle of the
5771 window W for display lines TYPE. */
5774 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5776 display_line_dynarr *dla;
5779 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
5781 if (type == CMOTION_DISP)
5782 regenerate_window (w, start, point, type);
5784 dla = window_display_lines (w, type);
5785 half = window_half_pixpos (w);
5787 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
5789 struct display_line *dl = Dynarr_atp (dla, elt);
5790 int line_bot = dl->ypos + dl->descent;
5792 if (line_bot > half)
5796 /* We may not have a line at the middle if the end of the buffer is
5801 /* Return a value for point that would place it at the beginning of
5802 the line which is in the middle of the window. */
5805 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5807 /* line_at_center will regenerate the display structures, if necessary. */
5808 int line = line_at_center (w, type, start, point);
5811 return BUF_ZV (XBUFFER (w->buffer));
5814 display_line_dynarr *dla = window_display_lines (w, type);
5815 struct display_line *dl = Dynarr_atp (dla, line);
5821 /* For a given window, ensure that the current visual representation
5825 redisplay_window (Lisp_Object window, int skip_selected)
5827 struct window *w = XWINDOW (window);
5828 struct frame *f = XFRAME (w->frame);
5829 struct device *d = XDEVICE (f->device);
5830 Lisp_Object old_buffer = w->buffer;
5831 Lisp_Object the_buffer = w->buffer;
5833 int echo_active = 0;
5838 int selected_in_its_frame;
5839 int selected_globally;
5840 int skip_output = 0;
5841 int truncation_changed;
5842 int inactive_minibuffer =
5843 (MINI_WINDOW_P (w) &&
5844 (f != device_selected_frame (d)) &&
5845 !is_surrogate_for_selected_frame (f));
5847 /* #### In the new world this function actually does a bunch of
5848 optimizations such as buffer-based scrolling, but none of that is
5851 /* If this is a combination window, do its children; that's all.
5852 The selected window is always a leaf so we don't check for
5853 skip_selected here. */
5854 if (!NILP (w->vchild))
5856 redisplay_windows (w->vchild, skip_selected);
5859 if (!NILP (w->hchild))
5861 redisplay_windows (w->hchild, skip_selected);
5865 /* Is this window the selected window on its frame? */
5866 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
5868 selected_in_its_frame &&
5869 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5870 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
5871 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5872 if (skip_selected && selected_in_its_frame)
5875 /* It is possible that the window is not fully initialized yet. */
5876 if (NILP (w->buffer))
5879 if (MINI_WINDOW_P (w) && echo_area_active (f))
5881 w->buffer = the_buffer = Vecho_area_buffer;
5885 b = XBUFFER (w->buffer);
5889 old_pointm = selected_globally
5891 : marker_position (w->pointm[CURRENT_DISP]);
5896 if (selected_globally)
5898 pointm = BUF_PT (b);
5902 pointm = marker_position (w->pointm[CURRENT_DISP]);
5904 if (pointm < BUF_BEGV (b))
5905 pointm = BUF_BEGV (b);
5906 else if (pointm > BUF_ZV (b))
5907 pointm = BUF_ZV (b);
5910 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
5912 /* If the buffer has changed we have to invalidate all of our face
5914 if ((!echo_active && b != window_display_buffer (w))
5915 || !Dynarr_length (w->face_cachels)
5916 || f->faces_changed)
5917 reset_face_cachels (w);
5919 mark_face_cachels_as_not_updated (w);
5921 /* Ditto the glyph cache elements, although we do *not* invalidate
5922 the cache purely because glyphs have changed - this is now
5923 handled by the dirty flag.*/
5924 if ((!echo_active && b != window_display_buffer (w))
5925 || !Dynarr_length (w->glyph_cachels) || f->faces_changed)
5926 reset_glyph_cachels (w);
5928 mark_glyph_cachels_as_not_updated (w);
5930 /* If the marker's buffer is not the window's buffer, then we need
5931 to find a new starting position. */
5932 if (!MINI_WINDOW_P (w)
5933 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5935 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5937 goto regeneration_done;
5942 old_startp = marker_position (w->start[CURRENT_DISP]);
5947 startp = marker_position (w->start[CURRENT_DISP]);
5948 if (startp < BUF_BEGV (b))
5949 startp = BUF_BEGV (b);
5950 else if (startp > BUF_ZV (b))
5951 startp = BUF_ZV (b);
5953 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5955 truncation_changed = (find_window_mirror (w)->truncate_win !=
5956 window_truncation_on (w));
5958 /* If w->force_start is set, then some function set w->start and we
5959 should display from there and change point, if necessary, to
5960 ensure that it is visible. */
5961 if (w->force_start || inactive_minibuffer)
5964 w->last_modified[DESIRED_DISP] = Qzero;
5965 w->last_facechange[DESIRED_DISP] = Qzero;
5967 regenerate_window (w, startp, pointm, DESIRED_DISP);
5969 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5971 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5973 if (selected_globally)
5974 BUF_SET_PT (b, pointm);
5976 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5979 /* #### BUFU amounts of overkill just to get the cursor
5980 location marked properly. FIX ME FIX ME FIX ME */
5981 regenerate_window (w, startp, pointm, DESIRED_DISP);
5984 goto regeneration_done;
5987 /* If nothing has changed since the last redisplay, then we just
5988 need to make sure that point is still visible. */
5989 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5990 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
5992 /* This check is to make sure we restore the minibuffer after a
5993 temporary change to the echo area. */
5994 && !(MINI_WINDOW_P (w) && f->buffers_changed)
5995 && !f->frame_changed
5996 && !truncation_changed
5997 /* check whether start is really at the beginning of a line GE */
5998 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
6001 /* Check if the cursor has actually moved. */
6002 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
6003 && pointm == marker_position (w->last_point[CURRENT_DISP])
6004 && selected_globally
6005 && !w->windows_changed
6007 && !f->extents_changed
6008 && !f->faces_changed
6009 && !f->glyphs_changed
6010 && !f->subwindows_changed
6011 /* && !f->subwindows_state_changed*/
6012 && !f->point_changed
6013 && !f->windows_structure_changed)
6015 /* If not, we're done. */
6016 if (f->modeline_changed)
6017 regenerate_modeline (w);
6020 goto regeneration_done;
6024 /* If the new point is visible in the redisplay structures,
6025 then let the output update routines handle it, otherwise
6026 do things the hard way. */
6027 if (!w->windows_changed
6029 && !f->extents_changed
6030 && !f->faces_changed
6031 && !f->glyphs_changed
6032 && !f->subwindows_changed
6033 /* && !f->subwindows_state_changed*/
6034 && !f->windows_structure_changed)
6036 if (point_visible (w, pointm, CURRENT_DISP)
6037 && w->last_point_x[CURRENT_DISP] != -1
6038 && w->last_point_y[CURRENT_DISP] != -1)
6040 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
6042 /* Always regenerate in case it is displaying
6043 the current line or column. */
6044 regenerate_modeline (w);
6047 goto regeneration_done;
6050 else if (!selected_in_its_frame && !f->point_changed)
6052 if (f->modeline_changed)
6053 regenerate_modeline (w);
6056 goto regeneration_done;
6060 /* If we weren't able to take the shortcut method, then use
6061 the brute force method. */
6062 regenerate_window (w, startp, pointm, DESIRED_DISP);
6064 if (point_visible (w, pointm, DESIRED_DISP))
6065 goto regeneration_done;
6069 /* Check if the starting point is no longer at the beginning of a
6070 line, in which case find a new starting point. We also recenter
6071 if our start position is equal to point-max. Otherwise we'll end
6072 up with a blank window. */
6073 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
6074 && !(startp == BUF_BEGV (b)
6075 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
6076 || (pointm == startp &&
6077 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
6078 startp < marker_position (w->last_start[CURRENT_DISP]))
6079 || (startp == BUF_ZV (b)))
6081 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6083 goto regeneration_done;
6085 /* See if we can update the data structures locally based on
6086 knowledge of what changed in the buffer. */
6087 else if (!w->windows_changed
6089 && !f->faces_changed
6090 && !f->glyphs_changed
6091 && !f->subwindows_changed
6092 /* && !f->subwindows_state_changed*/
6093 && !f->windows_structure_changed
6094 && !f->frame_changed
6095 && !truncation_changed
6097 && regenerate_window_incrementally (w, startp, pointm))
6099 if (f->modeline_changed
6100 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
6101 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
6102 regenerate_modeline (w);
6105 goto regeneration_done;
6107 /* #### This is where a check for structure based scrolling would go. */
6108 /* If all else fails, try just regenerating and see what happens. */
6111 regenerate_window (w, startp, pointm, DESIRED_DISP);
6113 if (point_visible (w, pointm, DESIRED_DISP))
6114 goto regeneration_done;
6117 /* We still haven't gotten the window regenerated with point
6118 visible. Next we try scrolling a little and see if point comes
6119 back onto the screen. */
6120 if (scroll_step > 0)
6122 int scrolled = scroll_conservatively;
6123 for (; scrolled >= 0; scrolled -= scroll_step)
6125 startp = vmotion (w, startp,
6126 (pointm < startp) ? -scroll_step : scroll_step, 0);
6127 regenerate_window (w, startp, pointm, DESIRED_DISP);
6129 if (point_visible (w, pointm, DESIRED_DISP))
6130 goto regeneration_done;
6134 /* We still haven't managed to get the screen drawn with point on
6135 the screen, so just center it and be done with it. */
6136 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6141 /* If the window's frame is changed then reset the current display
6142 lines in order to force a full repaint. */
6143 if (f->frame_changed)
6145 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
6150 /* Must do this before calling redisplay_output_window because it
6151 sets some markers on the window. */
6154 w->buffer = old_buffer;
6155 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
6156 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
6159 /* These also have to be set before calling redisplay_output_window
6160 since it sets the CURRENT_DISP values based on them. */
6161 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
6162 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
6163 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
6164 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
6168 Bufpos start = marker_position (w->start[DESIRED_DISP]);
6169 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
6171 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
6172 /* Don't pollute the cache if not sure if we are correct */
6173 if (w->start_at_line_beg)
6174 update_line_start_cache (w, start, end, pointm, 1);
6175 redisplay_output_window (w);
6177 * If we just displayed the echo area, the line start cache is
6178 * no longer valid, because the minibuffer window is associated
6179 * with the window now.
6182 w->line_cache_last_updated = make_int (-1);
6185 /* #### This should be dependent on face changes and will need to be
6186 somewhere else once tty updates occur on a per-frame basis. */
6187 mark_face_cachels_as_clean (w);
6189 /* The glyph cachels only get dirty if someone changed something.
6190 Since redisplay has now effectively ended we can reset the dirty
6191 flag since everything must be up-to-date. */
6193 mark_glyph_cachels_as_clean (w);
6195 w->windows_changed = 0;
6198 /* Call buffer_reset_changes for all buffers present in any window
6199 currently visible in all frames on all devices. #### There has to
6200 be a better way to do this. */
6203 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
6205 buffer_reset_changes (XBUFFER (w->buffer));
6210 reset_buffer_changes (void)
6212 Lisp_Object frmcons, devcons, concons;
6214 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6216 struct frame *f = XFRAME (XCAR (frmcons));
6218 if (FRAME_REPAINT_P (f))
6219 map_windows (f, reset_buffer_changes_mapfun, 0);
6223 /* Ensure that all windows underneath the given window in the window
6224 hierarchy are correctly displayed. */
6227 redisplay_windows (Lisp_Object window, int skip_selected)
6229 for (; !NILP (window) ; window = XWINDOW (window)->next)
6231 redisplay_window (window, skip_selected);
6236 call_redisplay_end_triggers (struct window *w, void *closure)
6238 Bufpos lrpos = w->last_redisplay_pos;
6239 w->last_redisplay_pos = 0;
6240 if (!NILP (w->buffer)
6241 && !NILP (w->redisplay_end_trigger)
6246 if (MARKERP (w->redisplay_end_trigger)
6247 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
6248 pos = marker_position (w->redisplay_end_trigger);
6249 else if (INTP (w->redisplay_end_trigger))
6250 pos = XINT (w->redisplay_end_trigger);
6253 w->redisplay_end_trigger = Qnil;
6260 XSETWINDOW (window, w);
6261 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
6262 Qredisplay_end_trigger_functions,
6264 w->redisplay_end_trigger);
6265 w->redisplay_end_trigger = Qnil;
6272 /* Ensure that all windows on the given frame are correctly displayed. */
6275 redisplay_frame (struct frame *f, int preemption_check)
6277 struct device *d = XDEVICE (f->device);
6279 if (preemption_check
6280 && !DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY))
6282 /* The preemption check itself takes a lot of time,
6283 so normally don't do it here. We do it if called
6284 from Lisp, though (`redisplay-frame'). */
6287 REDISPLAY_PREEMPTION_CHECK;
6292 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0))
6296 f->old_buffer_alist = Freplace_list (f->old_buffer_alist,
6298 XSETFRAME (frame, f);
6299 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame);
6302 /* Before we put a hold on frame size changes, attempt to process
6303 any which are already pending. */
6304 if (f->size_change_pending)
6305 change_frame_size (f, f->new_height, f->new_width, 0);
6307 /* If frame size might need to be changed, due to changed size
6308 of toolbars, scrollbars etc, change it now */
6309 if (f->size_slipped)
6311 adjust_frame_size (f);
6312 assert (!f->size_slipped);
6315 /* The menubar, toolbar, and icon updates must be done before
6316 hold_frame_size_changes is called and we are officially
6317 'in_display'. They may eval lisp code which may call Fsignal.
6318 If in_display is set Fsignal will abort. */
6320 #ifdef HAVE_MENUBARS
6321 /* Update the menubar. It is done first since it could change
6322 the menubar's visibility. This way we avoid having flashing
6323 caused by an Expose event generated by the visibility change
6325 update_frame_menubars (f);
6326 #endif /* HAVE_MENUBARS */
6327 #ifdef HAVE_TOOLBARS
6328 /* Update the toolbars. */
6329 update_frame_toolbars (f);
6330 #endif /* HAVE_TOOLBARS */
6331 /* Gutter update proper has to be done inside display when no frame
6332 size changes can occur, thus we separately update the gutter
6333 geometry here if it needs it. */
6334 update_frame_gutter_geometry (f);
6336 /* If we clear the frame we have to force its contents to be redrawn. */
6338 f->frame_changed = 1;
6340 /* Invalidate the subwindow caches. We use subwindows_changed here
6341 to cause subwindows to get instantiated. This is because
6342 subwindows_state_changed is less strict - dealing with things
6343 like the clicked state of button. We have to do this before
6344 redisplaying the gutters as subwindows get unmapped in the
6346 if (f->frame_changed)
6347 reset_frame_subwindow_instance_cache (f);
6349 if (f->frame_changed || f->subwindows_changed)
6351 /* we have to do this so the gutter gets regenerated. */
6352 reset_gutter_display_lines (f);
6355 hold_frame_size_changes ();
6357 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6358 /* Within this section, we are defenseless and assume that the
6359 following cannot happen:
6361 1) garbage collection
6362 2) Lisp code evaluation
6363 3) frame size changes
6365 We ensure (3) by calling hold_frame_size_changes(), which
6366 will cause any pending frame size changes to get put on hold
6367 till after the end of the critical section. (1) follows
6368 automatically if (2) is met. #### Unfortunately, there are
6369 some places where Lisp code can be called within this section.
6370 We need to remove them.
6372 If Fsignal() is called during this critical section, we
6375 If garbage collection is called during this critical section,
6376 we simply return. #### We should abort instead.
6378 #### If a frame-size change does occur we should probably
6379 actually be preempting redisplay. */
6381 MAYBE_DEVMETH (d, frame_output_begin, (f));
6383 /* We can now update the gutters, safe in the knowledge that our
6384 efforts won't get undone. */
6386 /* This can call lisp, but redisplay is protected by binding
6387 inhibit_quit. More importantly the code involving display lines
6388 *assumes* that GC will not happen and so does not GCPRO
6389 anything. Since we use this code the whole time with the gutters
6390 we cannot allow GC to happen when manipulating the gutters. */
6391 update_frame_gutters (f);
6393 /* Erase the frame before outputting its contents. */
6396 MAYBE_DEVMETH (d, clear_frame, (f));
6399 /* Do the selected window first. */
6400 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
6402 /* Then do the rest. */
6403 redisplay_windows (f->root_window, 1);
6405 MAYBE_DEVMETH (d, frame_output_end, (f));
6407 update_frame_title (f);
6409 CLASS_RESET_CHANGED_FLAGS (f);
6410 f->window_face_cache_reset = 0;
6411 f->echo_area_garbaged = 0;
6414 if (!f->size_change_pending)
6415 f->size_changed = 0;
6417 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6419 /* Allow frame size changes to occur again.
6421 #### what happens if changes to other frames happen? */
6422 unhold_one_frame_size_changes (f);
6424 map_windows (f, call_redisplay_end_triggers, 0);
6428 /* Ensure that all frames on the given device are correctly displayed.
6429 If AUTOMATIC is non-zero, and the device implementation indicates
6430 no automatic redisplay, as printers do, then the device is not
6431 redisplayed. AUTOMATIC is set to zero when called from lisp
6432 functions (redraw-device) and (redisplay-device), and to non-zero
6433 when called from "lazy" redisplay();
6437 redisplay_device (struct device *d, int automatic)
6439 Lisp_Object frame, frmcons;
6440 int size_change_failed = 0;
6443 if (automatic && DEVICE_IMPL_FLAG (d, XDEVIMPF_NO_AUTO_REDISPLAY))
6446 if (DEVICE_STREAM_P (d)) /* nothing to do */
6449 /* It is possible that redisplay has been called before the
6450 device is fully initialized, or that the console implementation
6451 allows frameless devices. If so then continue with the next
6453 if (NILP (DEVICE_SELECTED_FRAME (d)))
6456 if (!DEVICE_IMPL_FLAG (d, XDEVIMPF_DONT_PREEMPT_REDISPLAY))
6459 REDISPLAY_PREEMPTION_CHECK;
6464 /* Always do the selected frame first. */
6465 frame = DEVICE_SELECTED_FRAME (d);
6469 if (f->icon_changed || f->windows_changed)
6470 update_frame_icon (f);
6472 if (FRAME_REPAINT_P (f))
6474 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
6476 int preempted = redisplay_frame (f, 0);
6481 /* If the frame redisplay did not get preempted, then this flag
6482 should have gotten set to 0. It might be possible for that
6483 not to happen if a size change event were to occur at an odd
6484 time. To make sure we don't miss anything we simply don't
6485 reset the top level flags until the condition ends up being
6486 in the right state. */
6487 if (f->size_changed)
6488 size_change_failed = 1;
6491 DEVICE_FRAME_LOOP (frmcons, d)
6493 f = XFRAME (XCAR (frmcons));
6495 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
6498 if (f->icon_changed || f->windows_changed)
6499 update_frame_icon (f);
6501 if (FRAME_REPAINT_P (f))
6503 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
6505 int preempted = redisplay_frame (f, 0);
6510 if (f->size_change_pending)
6511 size_change_failed = 1;
6515 /* If we get here then we redisplayed all of our frames without
6516 getting preempted so mark ourselves as clean. */
6517 CLASS_RESET_CHANGED_FLAGS (d);
6519 if (!size_change_failed)
6520 d->size_changed = 0;
6526 restore_profiling_redisplay_flag (Lisp_Object val)
6528 profiling_redisplay_flag = XINT (val);
6532 /* Ensure that all windows on all frames on all devices are displaying
6533 the current contents of their respective buffers. */
6536 redisplay_without_hooks (void)
6538 Lisp_Object devcons, concons;
6539 int size_change_failed = 0;
6540 int count = specpdl_depth ();
6542 if (profiling_active)
6544 record_unwind_protect (restore_profiling_redisplay_flag,
6545 make_int (profiling_redisplay_flag));
6546 profiling_redisplay_flag = 1;
6549 if (asynch_device_change_pending)
6550 handle_asynch_device_change ();
6552 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6553 !disable_preemption && preemption_count < max_preempts)
6556 DEVICE_LOOP_NO_BREAK (devcons, concons)
6558 struct device *d = XDEVICE (XCAR (devcons));
6561 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d))
6563 preempted = redisplay_device (d, 1);
6568 RESET_CHANGED_SET_FLAGS;
6572 /* See comment in redisplay_device. */
6573 if (d->size_changed)
6574 size_change_failed = 1;
6577 preemption_count = 0;
6579 /* Mark redisplay as accurate */
6580 GLOBAL_RESET_CHANGED_FLAGS;
6581 RESET_CHANGED_SET_FLAGS;
6585 mark_all_faces_as_clean ();
6589 if (!size_change_failed)
6592 reset_buffer_changes ();
6595 unbind_to (count, Qnil);
6601 if (last_display_warning_tick != display_warning_tick &&
6602 !inhibit_warning_display)
6604 /* If an error occurs during this function, oh well.
6605 If we report another warning, we could get stuck in an
6606 infinite loop reporting warnings. */
6607 call0_trapping_errors (0, Qdisplay_warning_buffer);
6608 last_display_warning_tick = display_warning_tick;
6610 /* The run_hook_trapping_errors functions are smart enough not
6611 to do any evalling if the hook function is empty, so there
6612 should not be any significant time loss. All places in the
6613 C code that call redisplay() are prepared to handle GCing,
6614 so we should be OK. */
6615 #ifndef INHIBIT_REDISPLAY_HOOKS
6616 run_hook_trapping_errors ("Error in pre-redisplay-hook",
6617 Qpre_redisplay_hook);
6618 #endif /* INHIBIT_REDISPLAY_HOOKS */
6620 redisplay_without_hooks ();
6622 #ifndef INHIBIT_REDISPLAY_HOOKS
6623 run_hook_trapping_errors ("Error in post-redisplay-hook",
6624 Qpost_redisplay_hook);
6625 #endif /* INHIBIT_REDISPLAY_HOOKS */
6629 static char window_line_number_buf[32];
6631 /* Efficiently determine the window line number, and return a pointer
6632 to its printed representation. Do this regardless of whether
6633 line-number-mode is on. The first line in the buffer is counted as
6634 1. If narrowing is in effect, the lines are counted from the
6635 beginning of the visible portion of the buffer. */
6637 window_line_number (struct window *w, int type)
6639 struct device *d = XDEVICE (XFRAME (w->frame)->device);
6640 struct buffer *b = XBUFFER (w->buffer);
6641 /* Be careful in the order of these tests. The first clause will
6642 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6643 This can occur when the frame title is computed really early */
6645 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6646 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
6647 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6648 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
6650 : marker_position (w->pointm[type]));
6653 line = buffer_line_number (b, pos, 1);
6655 long_to_string (window_line_number_buf, line + 1);
6657 return window_line_number_buf;
6661 /* Given a character representing an object in a modeline
6662 specification, return a string (stored into the global array
6663 `mode_spec_bufbyte_string') with the information that object
6666 This function is largely unchanged from previous versions of the
6669 Warning! This code is also used for frame titles and can be called
6670 very early in the device/frame update process! JV
6674 decode_mode_spec (struct window *w, Emchar spec, int type)
6676 Lisp_Object obj = Qnil;
6677 const char *str = NULL;
6678 struct buffer *b = XBUFFER (w->buffer);
6680 Dynarr_reset (mode_spec_bufbyte_string);
6684 /* print buffer name */
6689 /* print visited file name */
6694 /* print the current column */
6697 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
6699 : marker_position (w->pointm[type]);
6700 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
6703 long_to_string (buf, col);
6705 Dynarr_add_many (mode_spec_bufbyte_string,
6706 (const Bufbyte *) buf, strlen (buf));
6708 goto decode_mode_spec_done;
6710 /* print the file coding system */
6714 Lisp_Object codesys = b->buffer_file_coding_system;
6715 /* Be very careful here not to get an error. */
6716 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
6718 codesys = Ffind_coding_system (codesys);
6719 if (CODING_SYSTEMP (codesys))
6720 obj = XCODING_SYSTEM_MNEMONIC (codesys);
6723 #endif /* FILE_CODING */
6726 /* print the current line number */
6728 str = window_line_number (w, type);
6731 /* print value of mode-name (obsolete) */
6736 /* print hyphen and frame number, if != 1 */
6740 struct frame *f = XFRAME (w->frame);
6741 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
6743 /* Naughty, naughty */
6744 char * writable_str = alloca_array (char, 10);
6745 sprintf (writable_str, "-%d", f->order_count);
6749 #endif /* HAVE_TTY */
6752 /* print Narrow if appropriate */
6754 if (BUF_BEGV (b) > BUF_BEG (b)
6755 || BUF_ZV (b) < BUF_Z (b))
6759 /* print %, * or hyphen, if buffer is read-only, modified or neither */
6761 str = (!NILP (b->read_only)
6763 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6768 /* print * or hyphen -- XEmacs change to allow a buffer to be
6769 read-only but still indicate whether it is modified. */
6771 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6773 : (!NILP (b->read_only)
6778 /* #### defined in 19.29 decode_mode_spec, but not in
6779 modeline-format doc string. */
6780 /* This differs from %* in that it ignores read-only-ness. */
6782 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6787 /* print process status */
6789 obj = Fget_buffer_process (w->buffer);
6791 str = GETTEXT ("no process");
6793 obj = Fsymbol_name (Fprocess_status (obj));
6796 /* Print name of selected frame. */
6798 obj = XFRAME (w->frame)->name;
6801 /* indicate TEXT or BINARY */
6803 /* #### NT does not use this any more. Now what? */
6807 /* print percent of buffer above top of window, or Top, Bot or All */
6810 Bufpos pos = marker_position (w->start[type]);
6812 /* This had better be while the desired lines are being done. */
6813 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
6815 if (pos <= BUF_BEGV (b))
6820 else if (pos <= BUF_BEGV (b))
6824 /* This hard limit is ok since the string it will hold has a
6825 fixed maximum length of 3. But just to be safe... */
6827 Charcount chars = pos - BUF_BEGV (b);
6828 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6830 /* Avoid overflow on big buffers */
6831 int percent = total > LONG_MAX/200 ?
6832 (chars + total/200) / (total / 100) :
6833 (chars * 100 + total/2) / total;
6835 /* We can't normally display a 3-digit number, so get us a
6836 2-digit number that is close. */
6840 sprintf (buf, "%d%%", percent);
6841 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6844 goto decode_mode_spec_done;
6849 /* print percent of buffer above bottom of window, perhaps plus
6850 Top, or print Bottom or All */
6853 Bufpos toppos = marker_position (w->start[type]);
6854 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
6856 /* botpos is only accurate as of the last redisplay, so we can
6857 only treat it as a hint. In particular, after erase-buffer,
6858 botpos may be negative. */
6859 if (botpos < toppos)
6862 if (botpos >= BUF_ZV (b))
6864 if (toppos <= BUF_BEGV (b))
6871 /* This hard limit is ok since the string it will hold has a
6872 fixed maximum length of around 6. But just to be safe... */
6874 Charcount chars = botpos - BUF_BEGV (b);
6875 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6877 /* Avoid overflow on big buffers */
6878 int percent = total > LONG_MAX/200 ?
6879 (chars + total/200) / (total / 100) :
6880 (chars * 100 + total/2) / max (total, 1);
6882 /* We can't normally display a 3-digit number, so get us a
6883 2-digit number that is close. */
6887 if (toppos <= BUF_BEGV (b))
6888 sprintf (buf, "Top%d%%", percent);
6890 sprintf (buf, "%d%%", percent);
6892 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6895 goto decode_mode_spec_done;
6905 /* print one [ for each recursive editing level. */
6910 if (command_loop_level > 5)
6916 for (i = 0; i < command_loop_level; i++)
6917 Dynarr_add (mode_spec_bufbyte_string, '[');
6919 goto decode_mode_spec_done;
6922 /* print one ] for each recursive editing level. */
6927 if (command_loop_level > 5)
6933 for (i = 0; i < command_loop_level; i++)
6934 Dynarr_add (mode_spec_bufbyte_string, ']');
6936 goto decode_mode_spec_done;
6939 /* print infinitely many dashes -- handle at top level now */
6946 Dynarr_add_many (mode_spec_bufbyte_string,
6948 XSTRING_LENGTH (obj));
6950 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6952 decode_mode_spec_done:
6953 Dynarr_add (mode_spec_bufbyte_string, '\0');
6956 /* Given a display line, free all of its data structures. */
6959 free_display_line (struct display_line *dl)
6963 if (dl->display_blocks)
6965 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6967 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6969 Dynarr_free (db->runes);
6972 Dynarr_free (dl->display_blocks);
6973 dl->display_blocks = NULL;
6976 if (dl->left_glyphs)
6978 Dynarr_free (dl->left_glyphs);
6979 dl->left_glyphs = NULL;
6982 if (dl->right_glyphs)
6984 Dynarr_free (dl->right_glyphs);
6985 dl->right_glyphs = NULL;
6990 /* Given an array of display lines, free them and all data structures
6991 contained within them. */
6994 free_display_lines (display_line_dynarr *dla)
6998 for (line = 0; line < Dynarr_largest (dla); line++)
7000 free_display_line (Dynarr_atp (dla, line));
7006 /* Call internal free routine for each set of display lines. */
7009 free_display_structs (struct window_mirror *mir)
7011 if (mir->current_display_lines)
7013 free_display_lines (mir->current_display_lines);
7014 mir->current_display_lines = 0;
7017 if (mir->desired_display_lines)
7019 free_display_lines (mir->desired_display_lines);
7020 mir->desired_display_lines = 0;
7026 mark_glyph_block_dynarr (glyph_block_dynarr *gba)
7030 glyph_block *gb = Dynarr_atp (gba, 0);
7031 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
7033 for (; gb < gb_last; gb++)
7035 if (!NILP (gb->glyph))
7036 mark_object (gb->glyph);
7037 if (!NILP (gb->extent))
7038 mark_object (gb->extent);
7043 /* See the comment in image_instantiate_cache_result as to why marking
7044 the glyph will also mark the image_instance. */
7046 mark_redisplay_structs (display_line_dynarr *dla)
7048 display_line *dl = Dynarr_atp (dla, 0);
7049 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
7051 for (; dl < dl_last; dl++)
7053 display_block_dynarr *dba = dl->display_blocks;
7054 display_block *db = Dynarr_atp (dba, 0);
7055 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
7057 for (; db < db_last; db++)
7059 rune_dynarr *ra = db->runes;
7060 rune *r = Dynarr_atp (ra, 0);
7061 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
7063 for (; r < r_last; r++)
7065 if (r->type == RUNE_DGLYPH)
7067 if (!NILP (r->object.dglyph.glyph))
7068 mark_object (r->object.dglyph.glyph);
7069 if (!NILP (r->object.dglyph.extent))
7070 mark_object (r->object.dglyph.extent);
7075 mark_glyph_block_dynarr (dl->left_glyphs);
7076 mark_glyph_block_dynarr (dl->right_glyphs);
7081 mark_window_mirror (struct window_mirror *mir)
7083 mark_redisplay_structs (mir->current_display_lines);
7084 mark_redisplay_structs (mir->desired_display_lines);
7087 mark_window_mirror (mir->next);
7090 mark_window_mirror (mir->hchild);
7091 else if (mir->vchild)
7092 mark_window_mirror (mir->vchild);
7096 mark_redisplay (void)
7098 Lisp_Object frmcons, devcons, concons;
7100 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
7102 struct frame *f = XFRAME (XCAR (frmcons));
7103 /* #### urk! this does tons o' crap, such as creating lots of
7104 structs, doing window system actions, etc. we DO NOT want to
7105 be doing this -- marking should never change any state.
7106 i think we can just delete this. --ben */
7107 update_frame_window_mirror (f);
7108 mark_window_mirror (f->root_mirror);
7113 /*****************************************************************************
7114 Line Start Cache Description and Rationale
7116 The traditional scrolling code in Emacs breaks in a variable height world.
7117 It depends on the key assumption that the number of lines that can be
7118 displayed at any given time is fixed. This led to a complete separation
7119 of the scrolling code from the redisplay code. In order to fully support
7120 variable height lines, the scrolling code must actually be tightly
7121 integrated with redisplay. Only redisplay can determine how many lines
7122 will be displayed on a screen for any given starting point.
7124 What is ideally wanted is a complete list of the starting buffer position
7125 for every possible display line of a buffer along with the height of that
7126 display line. Maintaining such a full list would be very expensive. We
7127 settle for having it include information for all areas which we happen to
7128 generate anyhow (i.e. the region currently being displayed) and for those
7129 areas we need to work with.
7131 In order to ensure that the cache accurately represents what redisplay
7132 would actually show, it is necessary to invalidate it in many situations.
7133 If the buffer changes, the starting positions may no longer be correct.
7134 If a face or an extent has changed then the line heights may have altered.
7135 These events happen frequently enough that the cache can end up being
7136 constantly disabled. With this potentially constant invalidation when is
7137 the cache ever useful?
7139 Even if the cache is invalidated before every single usage, it is
7140 necessary. Scrolling often requires knowledge about display lines which
7141 are actually above or below the visible region. The cache provides a
7142 convenient light-weight method of storing this information for multiple
7143 display regions. This knowledge is necessary for the scrolling code to
7144 always obey the First Golden Rule of Redisplay.
7146 If the cache already contains all of the information that the scrolling
7147 routines happen to need so that it doesn't have to go generate it, then we
7148 are able to obey the Third Golden Rule of Redisplay. The first thing we
7149 do to help out the cache is to always add the displayed region. This
7150 region had to be generated anyway, so the cache ends up getting the
7151 information basically for free. In those cases where a user is simply
7152 scrolling around viewing a buffer there is a high probability that this is
7153 sufficient to always provide the needed information. The second thing we
7154 can do is be smart about invalidating the cache.
7156 TODO -- Be smart about invalidating the cache. Potential places:
7158 + Insertions at end-of-line which don't cause line-wraps do not alter the
7159 starting positions of any display lines. These types of buffer
7160 modifications should not invalidate the cache. This is actually a large
7161 optimization for redisplay speed as well.
7163 + Buffer modifications frequently only affect the display of lines at and
7164 below where they occur. In these situations we should only invalidate
7165 the part of the cache starting at where the modification occurs.
7167 In case you're wondering, the Second Golden Rule of Redisplay is not
7169 ****************************************************************************/
7171 /* This will get used quite a bit so we don't want to be constantly
7172 allocating and freeing it. */
7173 static line_start_cache_dynarr *internal_cache;
7175 /* Makes internal_cache represent the TYPE display structs and only
7176 the TYPE display structs. */
7179 update_internal_cache_list (struct window *w, int type)
7182 display_line_dynarr *dla = window_display_lines (w, type);
7184 Dynarr_reset (internal_cache);
7185 for (line = 0; line < Dynarr_length (dla); line++)
7187 struct display_line *dl = Dynarr_atp (dla, line);
7193 struct line_start_cache lsc;
7195 lsc.start = dl->bufpos;
7196 lsc.end = dl->end_bufpos;
7197 lsc.height = dl->ascent + dl->descent;
7199 Dynarr_add (internal_cache, lsc);
7204 /* Reset the line cache if necessary. This should be run at the
7205 beginning of any function which access the cache. */
7208 validate_line_start_cache (struct window *w)
7210 struct buffer *b = XBUFFER (w->buffer);
7211 struct frame *f = XFRAME (w->frame);
7213 if (!w->line_cache_validation_override)
7215 /* f->extents_changed used to be in here because extent face and
7216 size changes can cause text shifting. However, the extent
7217 covering the region is constantly having its face set and
7218 priority altered by the mouse code. This means that the line
7219 start cache is constantly being invalidated. This is bad
7220 since the mouse code also triggers heavy usage of the cache.
7221 Since it is an unlikely that f->extents being changed
7222 indicates that the cache really needs to be updated and if it
7223 does redisplay will catch it pretty quickly we no longer
7224 invalidate the cache if it is set. This greatly speeds up
7225 dragging out regions with the mouse. */
7226 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
7230 Dynarr_reset (w->line_start_cache);
7235 /* Return the very first buffer position contained in the given
7236 window's cache, or -1 if the cache is empty. Assumes that the
7240 line_start_cache_start (struct window *w)
7242 line_start_cache_dynarr *cache = w->line_start_cache;
7244 if (!Dynarr_length (cache))
7247 return Dynarr_atp (cache, 0)->start;
7250 /* Return the very last buffer position contained in the given
7251 window's cache, or -1 if the cache is empty. Assumes that the
7255 line_start_cache_end (struct window *w)
7257 line_start_cache_dynarr *cache = w->line_start_cache;
7259 if (!Dynarr_length (cache))
7262 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7265 /* Return the index of the line POINT is contained within in window
7266 W's line start cache. It will enlarge the cache or move the cache
7267 window in order to have POINT be present in the cache. MIN_PAST is
7268 a guarantee of the number of entries in the cache present on either
7269 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7270 then it will be treated as 0, but the cache window will not be
7271 allowed to shift. Returns -1 if POINT cannot be found in the cache
7275 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
7277 struct buffer *b = XBUFFER (w->buffer);
7278 line_start_cache_dynarr *cache = w->line_start_cache;
7279 unsigned int top, bottom, pos;
7281 validate_line_start_cache (w);
7282 w->line_cache_validation_override++;
7284 /* Let functions pass in negative values, but we still treat -1
7286 /* #### bogosity alert */
7287 if (min_past < 0 && min_past != -1)
7288 min_past = -min_past;
7290 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
7291 || line_start_cache_end (w) < point)
7294 int win_char_height = window_char_height (w, 1);
7296 /* Occasionally we get here with a 0 height
7297 window. find_next_newline_no_quit will abort if we pass it a
7298 count of 0 so handle that case. */
7299 if (!win_char_height)
7300 win_char_height = 1;
7302 if (!Dynarr_length (cache))
7304 Bufpos from = find_next_newline_no_quit (b, point, -1);
7305 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
7307 update_line_start_cache (w, from, to, point, 0);
7309 if (!Dynarr_length (cache))
7311 w->line_cache_validation_override--;
7316 assert (Dynarr_length (cache));
7319 while (line_start_cache_start (w) > point
7320 && (loop < cache_adjustment || min_past == -1))
7324 from = line_start_cache_start (w);
7325 if (from <= BUF_BEGV (b))
7328 from = find_next_newline_no_quit (b, from, -win_char_height);
7329 to = line_start_cache_end (w);
7331 update_line_start_cache (w, from, to, point, 0);
7335 if (line_start_cache_start (w) > point)
7339 from = find_next_newline_no_quit (b, point, -1);
7340 if (from >= BUF_ZV (b))
7342 to = find_next_newline_no_quit (b, from, -win_char_height);
7347 to = find_next_newline_no_quit (b, from, win_char_height);
7349 update_line_start_cache (w, from, to, point, 0);
7353 while (line_start_cache_end (w) < point
7354 && (loop < cache_adjustment || min_past == -1))
7358 to = line_start_cache_end (w);
7359 if (to >= BUF_ZV (b))
7362 from = line_start_cache_end (w);
7363 to = find_next_newline_no_quit (b, from, win_char_height);
7365 update_line_start_cache (w, from, to, point, 0);
7369 if (line_start_cache_end (w) < point)
7373 from = find_next_newline_no_quit (b, point, -1);
7374 if (from >= BUF_ZV (b))
7376 to = find_next_newline_no_quit (b, from, -win_char_height);
7381 to = find_next_newline_no_quit (b, from, win_char_height);
7383 update_line_start_cache (w, from, to, point, 0);
7387 assert (Dynarr_length (cache));
7392 /* This could happen if the buffer is narrowed. */
7393 if (line_start_cache_start (w) > point
7394 || line_start_cache_end (w) < point)
7396 w->line_cache_validation_override--;
7402 top = Dynarr_length (cache) - 1;
7407 unsigned int new_pos;
7410 pos = (bottom + top + 1) >> 1;
7411 start = Dynarr_atp (cache, pos)->start;
7412 end = Dynarr_atp (cache, pos)->end;
7414 if (point >= start && point <= end)
7416 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
7419 find_next_newline_no_quit (b, line_start_cache_start (w),
7421 Bufpos to = line_start_cache_end (w);
7423 update_line_start_cache (w, from, to, point, 0);
7424 goto find_point_loop;
7426 else if ((Dynarr_length (cache) - pos - 1) < min_past
7427 && line_start_cache_end (w) < BUF_ZV (b))
7429 Bufpos from = line_start_cache_end (w);
7430 Bufpos to = find_next_newline_no_quit (b, from,
7435 update_line_start_cache (w, from, to, point, 0);
7436 goto find_point_loop;
7440 w->line_cache_validation_override--;
7444 else if (point > end)
7446 else if (point < start)
7451 new_pos = (bottom + top + 1) >> 1;
7454 w->line_cache_validation_override--;
7460 /* Return a boolean indicating if POINT would be visible in window W
7461 if display of the window was to begin at STARTP. */
7464 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
7466 struct buffer *b = XBUFFER (w->buffer);
7467 int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
7468 int bottom = WINDOW_TEXT_HEIGHT (w);
7471 /* If point is before the intended start it obviously can't be visible. */
7475 /* If point or start are not in the accessible buffer range, then
7477 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
7478 || point < BUF_BEGV (b) || point > BUF_ZV (b))
7481 validate_line_start_cache (w);
7482 w->line_cache_validation_override++;
7484 start_elt = point_in_line_start_cache (w, startp, 0);
7485 if (start_elt == -1)
7487 w->line_cache_validation_override--;
7491 assert (line_start_cache_start (w) <= startp
7492 && line_start_cache_end (w) >= startp);
7498 /* Expand the cache if necessary. */
7499 if (start_elt == Dynarr_length (w->line_start_cache))
7502 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
7504 start_elt = point_in_line_start_cache (w, old_startp,
7505 window_char_height (w, 0));
7507 /* We've already actually processed old_startp, so increment
7511 /* If this happens we didn't add any extra elements. Bummer. */
7512 if (start_elt == Dynarr_length (w->line_start_cache))
7514 w->line_cache_validation_override--;
7519 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
7521 if (pixpos + height > bottom)
7523 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7525 w->line_cache_validation_override--;
7531 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
7533 w->line_cache_validation_override--;
7541 /* For the given window W, if display starts at STARTP, what will be
7542 the buffer position at the beginning or end of the last line
7543 displayed. The end of the last line is also know as the window end
7546 WARNING: It is possible that redisplay failed to layout any lines for the
7547 windows. Under normal circumstances this is rare. However it seems that it
7548 does occur in the following situation: A mouse event has come in and we
7549 need to compute its location in a window. That code (in
7550 pixel_to_glyph_translation) already can handle 0 as an error return value.
7552 #### With a little work this could probably be reworked as just a
7553 call to start_with_line_at_pixpos. */
7556 start_end_of_last_line (struct window *w, Bufpos startp, int end,
7559 struct buffer *b = XBUFFER (w->buffer);
7560 line_start_cache_dynarr *cache = w->line_start_cache;
7562 int bottom = WINDOW_TEXT_HEIGHT (w);
7566 validate_line_start_cache (w);
7567 w->line_cache_validation_override++;
7569 if (startp < BUF_BEGV (b))
7570 startp = BUF_BEGV (b);
7571 else if (startp > BUF_ZV (b))
7572 startp = BUF_ZV (b);
7575 start_elt = point_in_line_start_cache (w, cur_start, 0);
7576 if (start_elt == -1)
7577 return may_error ? 0 : startp;
7581 int height = Dynarr_atp (cache, start_elt)->height;
7583 cur_start = Dynarr_atp (cache, start_elt)->start;
7585 if (pixpos + height > bottom)
7587 /* Adjust for any possible clip. */
7588 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7593 w->line_cache_validation_override--;
7597 return BUF_BEGV (b);
7601 w->line_cache_validation_override--;
7603 return Dynarr_atp (cache, start_elt)->end;
7605 return Dynarr_atp (cache, start_elt)->start;
7611 if (start_elt == Dynarr_length (cache))
7613 Bufpos from = line_start_cache_end (w);
7614 int win_char_height = window_char_height (w, 0);
7615 Bufpos to = find_next_newline_no_quit (b, from,
7620 /* We've hit the end of the bottom so that's what it is. */
7621 if (from >= BUF_ZV (b))
7623 w->line_cache_validation_override--;
7627 update_line_start_cache (w, from, to, BUF_PT (b), 0);
7629 /* Updating the cache invalidates any current indexes. */
7630 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
7635 /* For the given window W, if display starts at STARTP, what will be
7636 the buffer position at the beginning of the last line displayed. */
7639 start_of_last_line (struct window *w, Bufpos startp)
7641 return start_end_of_last_line (w, startp, 0 , 0);
7644 /* For the given window W, if display starts at STARTP, what will be
7645 the buffer position at the end of the last line displayed. This is
7646 also know as the window end position. */
7649 end_of_last_line (struct window *w, Bufpos startp)
7651 return start_end_of_last_line (w, startp, 1, 0);
7655 end_of_last_line_may_error (struct window *w, Bufpos startp)
7657 return start_end_of_last_line (w, startp, 1, 1);
7661 /* For window W, what does the starting position have to be so that
7662 the line containing POINT will cover pixel position PIXPOS. */
7665 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
7667 struct buffer *b = XBUFFER (w->buffer);
7669 Bufpos cur_pos, prev_pos = point;
7670 int point_line_height;
7671 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
7673 validate_line_start_cache (w);
7674 w->line_cache_validation_override++;
7676 cur_elt = point_in_line_start_cache (w, point, 0);
7677 /* #### See comment in update_line_start_cache about big minibuffers. */
7680 w->line_cache_validation_override--;
7684 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
7688 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7690 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7692 /* Do not take into account the value of vertical_clip here.
7693 That is the responsibility of the calling functions. */
7696 w->line_cache_validation_override--;
7697 if (-pixheight > point_line_height)
7698 /* We can't make the target line cover pixpos, so put it
7699 above pixpos. That way it will at least be visible. */
7709 int win_char_height;
7711 if (cur_pos <= BUF_BEGV (b))
7713 w->line_cache_validation_override--;
7714 return BUF_BEGV (b);
7717 win_char_height = window_char_height (w, 0);
7718 if (!win_char_height)
7719 win_char_height = 1;
7721 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
7722 to = line_start_cache_end (w);
7723 update_line_start_cache (w, from, to, point, 0);
7725 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
7726 assert (cur_elt >= -1);
7727 /* This used to be cur_elt>=0 under the assumption that if
7728 point is in the top line and not at BUF_BEGV, then
7729 setting the window_start to a newline before the start of
7730 the first line will always cause scrolling.
7732 However in my (jv) opinion this is wrong. That new line
7733 can be hidden in various ways: invisible extents, an
7734 explicit window-start not at a newline character etc.
7735 The existence of those are indeed known to create crashes
7736 on that assert. So we have no option but to continue the
7737 search if we found point at the top of the line_start_cache
7739 cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
7745 /* For window W, what does the starting position have to be so that
7746 the line containing point is on display line LINE. If LINE is
7747 positive it is considered to be the number of lines from the top of
7748 the window (0 is the top line). If it is negative the number is
7749 considered to be the number of lines from the bottom (-1 is the
7753 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
7755 validate_line_start_cache (w);
7756 w->line_cache_validation_override++;
7760 int cur_elt = point_in_line_start_cache (w, point, line);
7762 if (cur_elt - line < 0)
7763 cur_elt = 0; /* Hit the top */
7767 w->line_cache_validation_override--;
7768 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
7772 /* The calculated value of pixpos is correct for the bottom line
7773 or what we want when line is -1. Therefore we subtract one
7774 because we have already handled one line. */
7775 int new_line = -line - 1;
7776 int cur_elt = point_in_line_start_cache (w, point, new_line);
7777 int pixpos = WINDOW_TEXT_BOTTOM (w);
7778 Bufpos retval, search_point;
7780 /* If scroll_on_clipped_lines is false, the last "visible" line of
7781 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7782 If s_o_c_l is true, then we don't want to count a clipped
7783 line, so back up from the bottom by the height of the line
7784 containing point. */
7785 if (scroll_on_clipped_lines)
7786 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7790 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
7792 /* Hit the bottom of the buffer. */
7794 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
7798 XSETWINDOW (window, w);
7799 default_face_height_and_width (window, &defheight, 0);
7801 cur_elt = Dynarr_length (w->line_start_cache) - 1;
7803 pixpos -= (adjustment * defheight);
7804 if (pixpos < WINDOW_TEXT_TOP (w))
7805 pixpos = WINDOW_TEXT_TOP (w);
7808 cur_elt = cur_elt + new_line;
7810 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7812 retval = start_with_line_at_pixpos (w, search_point, pixpos);
7813 w->line_cache_validation_override--;
7818 /* This is used to speed up vertical scrolling by caching the known
7819 buffer starting positions for display lines. This allows the
7820 scrolling routines to avoid costly calls to regenerate_window. If
7821 NO_REGEN is true then it will only add the values in the DESIRED
7822 display structs which are in the given range.
7824 Note also that the FROM/TO values are minimums. It is possible
7825 that this function will actually add information outside of the
7826 lines containing those positions. This can't hurt but it could
7829 #### We currently force the cache to have only 1 contiguous region.
7830 It might help to make the cache a dynarr of caches so that we can
7831 cover more areas. This might, however, turn out to be a lot of
7832 overhead for too little gain. */
7835 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
7836 Bufpos point, int no_regen)
7838 struct buffer *b = XBUFFER (w->buffer);
7839 line_start_cache_dynarr *cache = w->line_start_cache;
7840 Bufpos low_bound, high_bound;
7842 validate_line_start_cache (w);
7843 w->line_cache_validation_override++;
7845 if (from < BUF_BEGV (b))
7846 from = BUF_BEGV (b);
7847 if (to > BUF_ZV (b))
7852 w->line_cache_validation_override--;
7856 if (Dynarr_length (cache))
7858 low_bound = line_start_cache_start (w);
7859 high_bound = line_start_cache_end (w);
7861 /* Check to see if the desired range is already in the cache. */
7862 if (from >= low_bound && to <= high_bound)
7864 w->line_cache_validation_override--;
7868 /* Check to make sure that the desired range is adjacent to the
7869 current cache. If not, invalidate the cache. */
7870 if (to < low_bound || from > high_bound)
7872 Dynarr_reset (cache);
7873 low_bound = high_bound = -1;
7878 low_bound = high_bound = -1;
7881 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
7883 /* This could be integrated into the next two sections, but it is easier
7884 to follow what's going on by having it separate. */
7889 update_internal_cache_list (w, DESIRED_DISP);
7890 if (!Dynarr_length (internal_cache))
7892 w->line_cache_validation_override--;
7896 start = Dynarr_atp (internal_cache, 0)->start;
7898 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
7900 /* We aren't allowed to generate additional information to fill in
7901 gaps, so if the DESIRED structs don't overlap the cache, reset the
7903 if (Dynarr_length (cache))
7905 if (end < low_bound || start > high_bound)
7906 Dynarr_reset (cache);
7908 /* #### What should really happen if what we are doing is
7909 extending a line (the last line)? */
7910 if (Dynarr_length (cache) == 1
7911 && Dynarr_length (internal_cache) == 1)
7912 Dynarr_reset (cache);
7915 if (!Dynarr_length (cache))
7917 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7918 Dynarr_length (internal_cache));
7919 w->line_cache_validation_override--;
7923 /* An extra check just in case the calling function didn't pass in
7924 the bounds of the DESIRED structs in the first place. */
7925 if (start >= low_bound && end <= high_bound)
7927 w->line_cache_validation_override--;
7931 /* At this point we know that the internal cache partially overlaps
7933 if (start < low_bound)
7935 int ic_elt = Dynarr_length (internal_cache) - 1;
7938 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7946 Dynarr_reset (cache);
7947 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7948 Dynarr_length (internal_cache));
7949 w->line_cache_validation_override--;
7953 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7957 if (end > high_bound)
7961 while (ic_elt < Dynarr_length (internal_cache))
7963 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7969 if (!(ic_elt < Dynarr_length (internal_cache)))
7971 Dynarr_reset (cache);
7972 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7973 Dynarr_length (internal_cache));
7974 w->line_cache_validation_override--;
7978 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7979 Dynarr_length (internal_cache) - ic_elt);
7982 w->line_cache_validation_override--;
7986 if (!Dynarr_length (cache) || from < low_bound)
7988 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7990 int old_lb = low_bound;
7992 while (startp < old_lb || low_bound == -1)
7997 regenerate_window (w, startp, point, CMOTION_DISP);
7998 update_internal_cache_list (w, CMOTION_DISP);
8000 /* If this assert is triggered then regenerate_window failed
8001 to layout a single line. This is not possible since we
8002 force at least a single line to be layout for CMOTION_DISP */
8003 assert (Dynarr_length (internal_cache));
8004 assert (startp == Dynarr_atp (internal_cache, 0)->start);
8006 ic_elt = Dynarr_length (internal_cache) - 1;
8007 if (low_bound != -1)
8011 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
8017 assert (ic_elt >= 0);
8019 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
8022 * Handle invisible text properly:
8023 * If the last line we're inserting has the same end as the
8024 * line before which it will be added, merge the two lines.
8026 if (Dynarr_length (cache) &&
8027 Dynarr_atp (internal_cache, ic_elt)->end ==
8028 Dynarr_atp (cache, marker)->end)
8030 Dynarr_atp (cache, marker)->start
8031 = Dynarr_atp (internal_cache, ic_elt)->start;
8032 Dynarr_atp (cache, marker)->height
8033 = Dynarr_atp (internal_cache, ic_elt)->height;
8037 if (ic_elt >= 0) /* we still have lines to add.. */
8039 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
8040 ic_elt + 1, marker);
8041 marker += (ic_elt + 1);
8044 if (startp < low_bound || low_bound == -1)
8046 startp = new_startp;
8047 if (startp > BUF_ZV (b))
8049 w->line_cache_validation_override--;
8055 assert (Dynarr_length (cache));
8056 assert (from >= low_bound);
8058 /* Readjust the high_bound to account for any changes made while
8059 correcting the low_bound. */
8060 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8062 if (to > high_bound)
8064 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
8068 regenerate_window (w, startp, point, CMOTION_DISP);
8069 update_internal_cache_list (w, CMOTION_DISP);
8071 /* See comment above about regenerate_window failing. */
8072 assert (Dynarr_length (internal_cache));
8074 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
8075 Dynarr_length (internal_cache));
8076 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8077 startp = high_bound + 1;
8079 while (to > high_bound);
8082 w->line_cache_validation_override--;
8083 assert (to <= high_bound);
8087 /* Given x and y coordinates in characters, relative to a window,
8088 return the pixel location corresponding to those coordinates. The
8089 pixel location returned is the center of the given character
8090 position. The pixel values are generated relative to the window,
8093 The modeline is considered to be part of the window. */
8096 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
8097 int *pix_x, int *pix_y)
8099 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
8100 int num_disp_lines, modeline;
8102 int defheight, defwidth;
8104 XSETWINDOW (window, w);
8105 default_face_height_and_width (window, &defheight, &defwidth);
8107 /* If we get a bogus value indicating somewhere above or to the left of
8108 the window, use the first window line or character position
8115 num_disp_lines = Dynarr_length (dla);
8119 if (Dynarr_atp (dla, 0)->modeline)
8126 /* First check if the y position intersects the display lines. */
8127 if (char_y < num_disp_lines)
8129 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
8130 struct display_block *db = get_display_block_from_line (dl, TEXT);
8132 *pix_y = (dl->ypos - dl->ascent +
8133 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
8135 if (char_x < Dynarr_length (db->runes))
8137 struct rune *rb = Dynarr_atp (db->runes, char_x);
8139 *pix_x = rb->xpos + (rb->width >> 1);
8143 int last_rune = Dynarr_length (db->runes) - 1;
8144 struct rune *rb = Dynarr_atp (db->runes, last_rune);
8146 char_x -= last_rune;
8148 *pix_x = rb->xpos + rb->width;
8149 *pix_x += ((char_x - 1) * defwidth);
8150 *pix_x += (defwidth >> 1);
8155 /* It didn't intersect, so extrapolate. #### For now, we include the
8156 modeline in this since we don't have true character positions in
8159 if (!Dynarr_length (w->face_cachels))
8160 reset_face_cachels (w);
8162 char_y -= num_disp_lines;
8164 if (Dynarr_length (dla))
8166 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
8167 *pix_y = dl->ypos + dl->descent - dl->clip;
8170 *pix_y = WINDOW_TEXT_TOP (w);
8172 *pix_y += (char_y * defheight);
8173 *pix_y += (defheight >> 1);
8175 *pix_x = WINDOW_TEXT_LEFT (w);
8176 /* Don't adjust by one because this is still the unadjusted value. */
8177 *pix_x += (char_x * defwidth);
8178 *pix_x += (defwidth >> 1);
8181 if (*pix_x > w->pixel_left + w->pixel_width)
8182 *pix_x = w->pixel_left + w->pixel_width;
8183 if (*pix_y > w->pixel_top + w->pixel_height)
8184 *pix_y = w->pixel_top + w->pixel_height;
8186 *pix_x -= w->pixel_left;
8187 *pix_y -= w->pixel_top;
8190 /* Given a display line and a position, determine if there is a glyph
8191 there and return information about it if there is. */
8194 get_position_object (struct display_line *dl, Lisp_Object *obj1,
8195 Lisp_Object *obj2, int x_coord, int *low_x_coord,
8198 struct display_block *db;
8201 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
8203 /* We use get_next_display_block to get the actual display block
8204 that would be displayed at x_coord. */
8206 if (block == NO_BLOCK)
8209 db = Dynarr_atp (dl->display_blocks, block);
8211 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
8213 struct rune *rb = Dynarr_atp (db->runes, elt);
8215 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
8217 if (rb->type == RUNE_DGLYPH)
8219 *obj1 = rb->object.dglyph.glyph;
8220 *obj2 = rb->object.dglyph.extent;
8229 *low_x_coord = rb->xpos;
8231 *high_x_coord = rb->xpos + rb->width;
8238 #define UPDATE_CACHE_RETURN \
8240 d->pixel_to_glyph_cache.valid = 1; \
8241 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8242 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8243 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8244 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8245 d->pixel_to_glyph_cache.frame = f; \
8246 d->pixel_to_glyph_cache.col = *col; \
8247 d->pixel_to_glyph_cache.row = *row; \
8248 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8249 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8250 d->pixel_to_glyph_cache.w = *w; \
8251 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8252 d->pixel_to_glyph_cache.closest = *closest; \
8253 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8254 d->pixel_to_glyph_cache.obj1 = *obj1; \
8255 d->pixel_to_glyph_cache.obj2 = *obj2; \
8256 d->pixel_to_glyph_cache.retval = position; \
8257 RETURN_SANS_WARNINGS position; \
8260 /* Given x and y coordinates in pixels relative to a frame, return
8261 information about what is located under those coordinates.
8263 The return value will be one of:
8265 OVER_TOOLBAR: over one of the 4 frame toolbars
8266 OVER_MODELINE: over a modeline
8267 OVER_BORDER: over an internal border
8268 OVER_NOTHING: over the text area, but not over text
8269 OVER_OUTSIDE: outside of the frame border
8270 OVER_TEXT: over text in the text area
8276 -- nil if the coordinates are not over a glyph or a toolbar button.
8280 -- an extent, if the coordinates are over a glyph in the text area
8283 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8284 equivalent coordinates relative to the upper-left corner of the glyph.
8286 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8287 equivalent coordinates relative to the upper-left corner of the character.
8289 Otherwise, OBJ_X and OBJ_Y are undefined.
8293 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
8294 int *col, int *row, int *obj_x, int *obj_y,
8295 struct window **w, Bufpos *bufpos,
8296 Bufpos *closest, Charcount *modeline_closest,
8297 Lisp_Object *obj1, Lisp_Object *obj2)
8300 struct pixel_to_glyph_translation_cache *cache;
8302 int frm_left, frm_right, frm_top, frm_bottom;
8303 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8304 int position = OVER_NOTHING;
8305 int device_check_failed = 0;
8306 display_line_dynarr *dla;
8308 /* This is a safety valve in case this got called with a frame in
8309 the middle of being deleted. */
8310 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
8312 device_check_failed = 1;
8313 d = NULL, cache = NULL; /* Warning suppression */
8317 d = XDEVICE (f->device);
8318 cache = &d->pixel_to_glyph_cache;
8321 if (!device_check_failed
8323 && cache->frame == f
8324 && cache->low_x_coord <= x_coord
8325 && cache->high_x_coord > x_coord
8326 && cache->low_y_coord <= y_coord
8327 && cache->high_y_coord > y_coord)
8331 *obj_x = cache->obj_x;
8332 *obj_y = cache->obj_y;
8334 *bufpos = cache->bufpos;
8335 *closest = cache->closest;
8336 *modeline_closest = cache->modeline_closest;
8337 *obj1 = cache->obj1;
8338 *obj2 = cache->obj2;
8340 return cache->retval;
8351 *modeline_closest = -1;
8355 low_x_coord = x_coord;
8356 high_x_coord = x_coord + 1;
8357 low_y_coord = y_coord;
8358 high_y_coord = y_coord + 1;
8361 if (device_check_failed)
8362 return OVER_NOTHING;
8364 frm_left = FRAME_LEFT_BORDER_END (f);
8365 frm_right = FRAME_RIGHT_BORDER_START (f);
8366 frm_top = FRAME_TOP_BORDER_END (f);
8367 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
8369 /* Check if the mouse is outside of the text area actually used by
8371 if (y_coord < frm_top)
8373 if (y_coord >= FRAME_TOP_BORDER_START (f))
8375 low_y_coord = FRAME_TOP_BORDER_START (f);
8376 high_y_coord = frm_top;
8377 position = OVER_BORDER;
8379 else if (y_coord >= 0)
8382 high_y_coord = FRAME_TOP_BORDER_START (f);
8383 position = OVER_TOOLBAR;
8387 low_y_coord = y_coord;
8389 position = OVER_OUTSIDE;
8392 else if (y_coord >= frm_bottom)
8394 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
8396 low_y_coord = frm_bottom;
8397 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
8398 position = OVER_BORDER;
8400 else if (y_coord < FRAME_PIXHEIGHT (f))
8402 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
8403 high_y_coord = FRAME_PIXHEIGHT (f);
8404 position = OVER_TOOLBAR;
8408 low_y_coord = FRAME_PIXHEIGHT (f);
8409 high_y_coord = y_coord;
8410 position = OVER_OUTSIDE;
8414 if (position != OVER_TOOLBAR && position != OVER_BORDER)
8416 if (x_coord < frm_left)
8418 if (x_coord >= FRAME_LEFT_BORDER_START (f))
8420 low_x_coord = FRAME_LEFT_BORDER_START (f);
8421 high_x_coord = frm_left;
8422 position = OVER_BORDER;
8424 else if (x_coord >= 0)
8427 high_x_coord = FRAME_LEFT_BORDER_START (f);
8428 position = OVER_TOOLBAR;
8432 low_x_coord = x_coord;
8434 position = OVER_OUTSIDE;
8437 else if (x_coord >= frm_right)
8439 if (x_coord < FRAME_RIGHT_BORDER_END (f))
8441 low_x_coord = frm_right;
8442 high_x_coord = FRAME_RIGHT_BORDER_END (f);
8443 position = OVER_BORDER;
8445 else if (x_coord < FRAME_PIXWIDTH (f))
8447 low_x_coord = FRAME_RIGHT_BORDER_END (f);
8448 high_x_coord = FRAME_PIXWIDTH (f);
8449 position = OVER_TOOLBAR;
8453 low_x_coord = FRAME_PIXWIDTH (f);
8454 high_x_coord = x_coord;
8455 position = OVER_OUTSIDE;
8460 #ifdef HAVE_TOOLBARS
8461 if (position == OVER_TOOLBAR)
8463 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
8466 UPDATE_CACHE_RETURN;
8468 #endif /* HAVE_TOOLBARS */
8470 /* We still have to return the window the pointer is next to and its
8471 relative y position even if it is outside the x boundary. */
8472 if (x_coord < frm_left)
8474 else if (x_coord > frm_right)
8475 x_coord = frm_right;
8477 /* Same in reverse. */
8478 if (y_coord < frm_top)
8480 else if (y_coord > frm_bottom)
8481 y_coord = frm_bottom;
8483 /* Find what window the given coordinates are actually in. */
8484 window = f->root_window;
8485 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
8487 /* If we didn't find a window, we're done. */
8490 UPDATE_CACHE_RETURN;
8492 else if (position != OVER_NOTHING)
8495 *modeline_closest = -1;
8497 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
8500 UPDATE_CACHE_RETURN;
8504 /* Check if the window is a minibuffer but isn't active. */
8505 if (MINI_WINDOW_P (*w) && !minibuf_level)
8507 /* Must reset the window value since some callers will ignore
8508 the return value if it is set. */
8510 UPDATE_CACHE_RETURN;
8513 /* See if the point is over window vertical divider */
8514 if (window_needs_vertical_divider (*w))
8516 int div_x_high = WINDOW_RIGHT (*w);
8517 int div_x_low = div_x_high - window_divider_width (*w);
8518 int div_y_high = WINDOW_BOTTOM (*w);
8519 int div_y_low = WINDOW_TOP (*w);
8521 if (div_x_low < x_coord && x_coord <= div_x_high &&
8522 div_y_low < y_coord && y_coord <= div_y_high)
8524 low_x_coord = div_x_low;
8525 high_x_coord = div_x_high;
8526 low_y_coord = div_y_low;
8527 high_y_coord = div_y_high;
8528 position = OVER_V_DIVIDER;
8529 UPDATE_CACHE_RETURN;
8533 dla = window_display_lines (*w, CURRENT_DISP);
8535 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
8537 int really_over_nothing = 0;
8538 struct display_line *dl = Dynarr_atp (dla, *row);
8540 if ((int) (dl->ypos - dl->ascent) <= y_coord
8541 && y_coord <= (int) (dl->ypos + dl->descent))
8543 int check_margin_glyphs = 0;
8544 struct display_block *db = get_display_block_from_line (dl, TEXT);
8545 struct rune *rb = 0;
8547 if (x_coord < dl->bounds.left_white
8548 || x_coord >= dl->bounds.right_white)
8549 check_margin_glyphs = 1;
8551 low_y_coord = dl->ypos - dl->ascent;
8552 high_y_coord = dl->ypos + dl->descent + 1;
8554 if (position == OVER_BORDER
8555 || position == OVER_OUTSIDE
8556 || check_margin_glyphs)
8558 int x_check, left_bound;
8560 if (check_margin_glyphs)
8563 left_bound = dl->bounds.left_white;
8567 x_check = high_x_coord;
8568 left_bound = frm_left;
8571 if (Dynarr_length (db->runes))
8573 if (x_check <= left_bound)
8576 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
8578 *closest = Dynarr_atp (db->runes, 0)->bufpos;
8584 Dynarr_atp (db->runes,
8585 Dynarr_length (db->runes) - 1)->bufpos;
8588 Dynarr_atp (db->runes,
8589 Dynarr_length (db->runes) - 1)->bufpos;
8593 *modeline_closest += dl->offset;
8595 *closest += dl->offset;
8599 /* #### What should be here. */
8601 *modeline_closest = 0;
8606 if (check_margin_glyphs)
8608 if (x_coord < dl->bounds.left_in
8609 || x_coord >= dl->bounds.right_in)
8611 /* If we are over the outside margins then we
8612 know the loop over the text block isn't going
8613 to accomplish anything. So we go ahead and
8614 set what information we can right here and
8617 *obj_y = y_coord - (dl->ypos - dl->ascent);
8618 get_position_object (dl, obj1, obj2, x_coord,
8619 &low_x_coord, &high_x_coord);
8621 UPDATE_CACHE_RETURN;
8625 UPDATE_CACHE_RETURN;
8628 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
8630 int past_end = (*col == Dynarr_length (db->runes));
8633 rb = Dynarr_atp (db->runes, *col);
8636 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
8641 rb = Dynarr_atp (db->runes, *col);
8644 *bufpos = rb->bufpos + dl->offset;
8645 low_x_coord = rb->xpos;
8646 high_x_coord = rb->xpos + rb->width;
8648 if (rb->type == RUNE_DGLYPH)
8652 /* Find the first character after the glyph. */
8653 while (elt < Dynarr_length (db->runes))
8655 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
8659 (Dynarr_atp (db->runes, elt)->bufpos +
8663 (Dynarr_atp (db->runes, elt)->bufpos +
8671 /* In this case we failed to find a non-glyph
8672 character so we return the last position
8673 displayed on the line. */
8674 if (elt == Dynarr_length (db->runes))
8677 *modeline_closest = dl->end_bufpos + dl->offset;
8679 *closest = dl->end_bufpos + dl->offset;
8680 really_over_nothing = 1;
8686 *modeline_closest = rb->bufpos + dl->offset;
8688 *closest = rb->bufpos + dl->offset;
8693 *row = window_displayed_height (*w);
8695 if (position == OVER_NOTHING)
8696 position = OVER_MODELINE;
8698 if (rb->type == RUNE_DGLYPH)
8700 *obj1 = rb->object.dglyph.glyph;
8701 *obj2 = rb->object.dglyph.extent;
8703 else if (rb->type == RUNE_CHAR)
8714 UPDATE_CACHE_RETURN;
8717 || (rb->type == RUNE_CHAR
8718 && rb->object.chr.ch == '\n'))
8721 /* At this point we may have glyphs in the right
8723 if (check_margin_glyphs)
8724 get_position_object (dl, obj1, obj2, x_coord,
8725 &low_x_coord, &high_x_coord);
8726 UPDATE_CACHE_RETURN;
8731 if (rb->type == RUNE_DGLYPH)
8733 *obj1 = rb->object.dglyph.glyph;
8734 *obj2 = rb->object.dglyph.extent;
8736 else if (rb->type == RUNE_CHAR)
8747 *obj_x = x_coord - rb->xpos;
8748 *obj_y = y_coord - (dl->ypos - dl->ascent);
8750 /* At this point we may have glyphs in the left
8752 if (check_margin_glyphs)
8753 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
8755 if (position == OVER_NOTHING && !really_over_nothing)
8756 position = OVER_TEXT;
8758 UPDATE_CACHE_RETURN;
8765 *row = Dynarr_length (dla) - 1;
8766 if (FRAME_WIN_P (f))
8768 int bot_elt = Dynarr_length (dla) - 1;
8772 struct display_line *dl = Dynarr_atp (dla, bot_elt);
8773 int adj_area = y_coord - (dl->ypos + dl->descent);
8777 XSETWINDOW (lwin, *w);
8778 default_face_height_and_width (lwin, 0, &defheight);
8780 *row += (adj_area / defheight);
8784 /* #### This should be checked out some more to determine what
8785 should really be going on. */
8786 if (!MARKERP ((*w)->start[CURRENT_DISP]))
8789 *closest = end_of_last_line_may_error (*w,
8790 marker_position ((*w)->start[CURRENT_DISP]));
8792 UPDATE_CACHE_RETURN;
8794 #undef UPDATE_CACHE_RETURN
8797 /***************************************************************************/
8799 /* Lisp functions */
8801 /***************************************************************************/
8803 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8804 Ensure that all minibuffers are correctly showing the echo area.
8808 Lisp_Object devcons, concons;
8810 DEVICE_LOOP_NO_BREAK (devcons, concons)
8812 struct device *d = XDEVICE (XCAR (devcons));
8813 Lisp_Object frmcons;
8815 DEVICE_FRAME_LOOP (frmcons, d)
8817 struct frame *f = XFRAME (XCAR (frmcons));
8819 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
8821 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
8823 MAYBE_DEVMETH (d, frame_output_begin, (f));
8826 * If the frame size has changed, there may be random
8827 * chud on the screen left from previous messages
8828 * because redisplay_frame hasn't been called yet.
8829 * Clear the screen to get rid of the potential mess.
8831 if (f->echo_area_garbaged)
8833 MAYBE_DEVMETH (d, clear_frame, (f));
8834 f->echo_area_garbaged = 0;
8836 redisplay_window (window, 0);
8837 MAYBE_DEVMETH (d, frame_output_end, (f));
8839 call_redisplay_end_triggers (XWINDOW (window), 0);
8848 restore_disable_preemption_value (Lisp_Object value)
8850 disable_preemption = XINT (value);
8854 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8855 Clear frame FRAME and output again what is supposed to appear on it.
8856 FRAME defaults to the selected frame if omitted.
8857 Normally, redisplay is preempted as normal if input arrives. However,
8858 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8859 input and is guaranteed to proceed to completion.
8861 (frame, no_preempt))
8863 struct frame *f = decode_frame (frame);
8864 int count = specpdl_depth ();
8866 if (!NILP (no_preempt))
8868 record_unwind_protect (restore_disable_preemption_value,
8869 make_int (disable_preemption));
8870 disable_preemption++;
8874 redisplay_frame (f, 1);
8876 /* See the comment in Fredisplay_frame. */
8877 RESET_CHANGED_SET_FLAGS;
8879 return unbind_to (count, Qnil);
8882 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8883 Ensure that FRAME's contents are correctly displayed.
8884 This differs from `redraw-frame' in that it only redraws what needs to
8885 be updated, as opposed to unconditionally clearing and redrawing
8887 FRAME defaults to the selected frame if omitted.
8888 Normally, redisplay is preempted as normal if input arrives. However,
8889 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8890 input and is guaranteed to proceed to completion.
8892 (frame, no_preempt))
8894 struct frame *f = decode_frame (frame);
8895 int count = specpdl_depth ();
8897 if (!NILP (no_preempt))
8899 record_unwind_protect (restore_disable_preemption_value,
8900 make_int (disable_preemption));
8901 disable_preemption++;
8904 redisplay_frame (f, 1);
8906 /* If we don't reset the global redisplay flags here, subsequent
8907 changes to the display will not get registered by redisplay
8908 because it thinks it already has registered changes. If you
8909 really knew what you were doing you could confuse redisplay by
8910 calling Fredisplay_frame while updating another frame. We assume
8911 that if you know what you are doing you will not be that
8913 RESET_CHANGED_SET_FLAGS;
8915 return unbind_to (count, Qnil);
8918 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
8919 Clear device DEVICE and output again what is supposed to appear on it.
8920 DEVICE defaults to the selected device if omitted.
8921 Normally, redisplay is preempted as normal if input arrives. However,
8922 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8923 input and is guaranteed to proceed to completion.
8925 (device, no_preempt))
8927 struct device *d = decode_device (device);
8928 Lisp_Object frmcons;
8929 int count = specpdl_depth ();
8931 if (!NILP (no_preempt))
8933 record_unwind_protect (restore_disable_preemption_value,
8934 make_int (disable_preemption));
8935 disable_preemption++;
8938 DEVICE_FRAME_LOOP (frmcons, d)
8940 XFRAME (XCAR (frmcons))->clear = 1;
8942 redisplay_device (d, 0);
8944 /* See the comment in Fredisplay_frame. */
8945 RESET_CHANGED_SET_FLAGS;
8947 return unbind_to (count, Qnil);
8950 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8951 Ensure that DEVICE's contents are correctly displayed.
8952 This differs from `redraw-device' in that it only redraws what needs to
8953 be updated, as opposed to unconditionally clearing and redrawing
8955 DEVICE defaults to the selected device if omitted.
8956 Normally, redisplay is preempted as normal if input arrives. However,
8957 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8958 input and is guaranteed to proceed to completion.
8960 (device, no_preempt))
8962 struct device *d = decode_device (device);
8963 int count = specpdl_depth ();
8965 if (!NILP (no_preempt))
8967 record_unwind_protect (restore_disable_preemption_value,
8968 make_int (disable_preemption));
8969 disable_preemption++;
8972 redisplay_device (d, 0);
8974 /* See the comment in Fredisplay_frame. */
8975 RESET_CHANGED_SET_FLAGS;
8977 return unbind_to (count, Qnil);
8980 /* Big lie. Big lie. This will force all modelines to be updated
8981 regardless if the all flag is set or not. It remains in existence
8982 solely for backwards compatibility. */
8983 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8984 Force the modeline of the current buffer to be redisplayed.
8985 With optional non-nil ALL, force redisplay of all modelines.
8989 MARK_MODELINE_CHANGED;
8993 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8994 Force an immediate update of the cursor on FRAME.
8995 FRAME defaults to the selected frame if omitted.
8999 redisplay_redraw_cursor (decode_frame (frame), 1);
9004 /***************************************************************************/
9006 /* Lisp-variable change triggers */
9008 /***************************************************************************/
9011 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
9014 /* Nothing to be done? */
9018 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
9019 Lisp_Object in_object, int flags)
9021 /* #### clip_changed should really be renamed something like
9022 global_redisplay_change. */
9027 /* This is called if the built-in glyphs have their properties
9030 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
9033 if (WINDOWP (locale))
9035 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
9037 else if (FRAMEP (locale))
9039 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
9041 else if (DEVICEP (locale))
9043 Lisp_Object frmcons;
9044 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
9045 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9047 else if (CONSOLEP (locale))
9049 Lisp_Object frmcons, devcons;
9050 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
9051 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9053 else /* global or buffer */
9055 Lisp_Object frmcons, devcons, concons;
9056 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
9057 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9062 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
9065 if (XFRAME (w->frame)->init_finished)
9066 Fforce_cursor_redisplay (w->frame);
9069 #ifdef MEMORY_USAGE_STATS
9072 /***************************************************************************/
9074 /* memory usage computation */
9076 /***************************************************************************/
9079 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
9081 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9085 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
9086 struct overhead_stats *ovstats)
9093 total = Dynarr_memory_usage (dyn, ovstats);
9094 for (i = 0; i < Dynarr_largest (dyn); i++)
9095 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
9101 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
9102 struct overhead_stats *ovstats)
9104 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9108 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
9109 struct overhead_stats *ovstats)
9116 total = Dynarr_memory_usage (dyn, ovstats);
9117 for (i = 0; i < Dynarr_largest (dyn); i++)
9119 struct display_line *dl = &Dynarr_at (dyn, i);
9120 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
9121 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
9122 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
9129 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
9130 struct overhead_stats *ovstats)
9132 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9135 #endif /* MEMORY_USAGE_STATS */
9138 /***************************************************************************/
9140 /* initialization */
9142 /***************************************************************************/
9145 init_redisplay (void)
9147 disable_preemption = 0;
9148 preemption_count = 0;
9149 max_preempts = INIT_MAX_PREEMPTS;
9155 if (!cmotion_display_lines)
9156 cmotion_display_lines = Dynarr_new (display_line);
9157 if (!mode_spec_bufbyte_string)
9158 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
9159 if (!formatted_string_extent_dynarr)
9160 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
9161 if (!formatted_string_extent_start_dynarr)
9162 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
9163 if (!formatted_string_extent_end_dynarr)
9164 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
9165 if (!internal_cache)
9166 internal_cache = Dynarr_new (line_start_cache);
9169 /* window system is nil when in -batch mode */
9170 if (!initialized || noninteractive)
9173 /* If the user wants to use a window system, we shouldn't bother
9174 initializing the terminal. This is especially important when the
9175 terminal is so dumb that emacs gives up before and doesn't bother
9176 using the window system.
9178 If the DISPLAY environment variable is set, try to use X, and die
9179 with an error message if that doesn't work. */
9181 #ifdef HAVE_X_WINDOWS
9182 if (!strcmp (display_use, "x"))
9184 /* Some stuff checks this way early. */
9185 Vwindow_system = Qx;
9186 Vinitial_window_system = Qx;
9189 #endif /* HAVE_X_WINDOWS */
9192 if (!strcmp (display_use, "gtk"))
9194 Vwindow_system = Qgtk;
9195 Vinitial_window_system = Qgtk;
9200 #ifdef HAVE_MS_WINDOWS
9201 if (!strcmp (display_use, "mswindows"))
9203 /* Some stuff checks this way early. */
9204 Vwindow_system = Qmswindows;
9205 Vinitial_window_system = Qmswindows;
9208 #endif /* HAVE_MS_WINDOWS */
9211 /* If no window system has been specified, try to use the terminal. */
9214 stderr_out ("XEmacs: standard input is not a tty\n");
9218 /* Look at the TERM variable */
9219 if (!getenv ("TERM"))
9221 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
9225 Vinitial_window_system = Qtty;
9227 #else /* not HAVE_TTY */
9228 /* No DISPLAY specified, and no TTY support. */
9229 stderr_out ("XEmacs: Cannot open display.\n\
9230 Please set the environmental variable DISPLAY to an appropriate value.\n");
9237 syms_of_redisplay (void)
9239 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
9240 #ifndef INHIBIT_REDISPLAY_HOOKS
9241 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
9242 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
9243 #endif /* INHIBIT_REDISPLAY_HOOKS */
9244 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
9245 defsymbol (&Qbar_cursor, "bar-cursor");
9246 defsymbol (&Qredisplay_end_trigger_functions,
9247 "redisplay-end-trigger-functions");
9248 defsymbol (&Qtop_bottom, "top-bottom");
9249 defsymbol (&Qbuffer_list_changed_hook, "buffer-list-changed-hook");
9251 DEFSUBR (Fredisplay_echo_area);
9252 DEFSUBR (Fredraw_frame);
9253 DEFSUBR (Fredisplay_frame);
9254 DEFSUBR (Fredraw_device);
9255 DEFSUBR (Fredisplay_device);
9256 DEFSUBR (Fredraw_modeline);
9257 DEFSUBR (Fforce_cursor_redisplay);
9261 vars_of_redisplay (void)
9265 staticpro (&last_arrow_position);
9266 staticpro (&last_arrow_string);
9267 last_arrow_position = Qnil;
9268 last_arrow_string = Qnil;
9271 /* #### Probably temporary */
9272 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
9273 \(Temporary) Setting this will impact the performance of the internal
9276 cache_adjustment = 2;
9278 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
9279 Minimum pixel height for clipped bottom display line.
9280 A clipped line shorter than this won't be displayed.
9282 redisplay_variable_changed);
9285 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
9286 Minimum visible area for clipped glyphs at right boundary.
9287 Clipped glyphs shorter than this won't be displayed.
9288 Only pixmap glyph instances are currently allowed to be clipped.
9290 redisplay_variable_changed);
9291 horizontal_clip = 5;
9293 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
9294 String displayed by modeline-format's "%m" specification.
9296 Vglobal_mode_string = Qnil;
9298 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
9299 Marker for where to display an arrow on top of the buffer text.
9300 This must be the beginning of a line in order to work.
9301 See also `overlay-arrow-string'.
9303 redisplay_variable_changed);
9304 Voverlay_arrow_position = Qnil;
9306 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
9307 String or glyph to display as an arrow. See also `overlay-arrow-position'.
9308 \(Note that despite the name of this variable, it can be set to a glyph as
9311 redisplay_variable_changed);
9312 Voverlay_arrow_string = Qnil;
9314 DEFVAR_INT ("scroll-step", &scroll_step /*
9315 *The number of lines to try scrolling a window by when point moves out.
9316 If that fails to bring point back on frame, point is centered instead.
9317 If this is zero, point is always centered after it moves off screen.
9321 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
9322 *Scroll up to this many lines, to bring point back on screen.
9324 scroll_conservatively = 0;
9326 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
9327 &truncate_partial_width_windows /*
9328 *Non-nil means truncate lines in all windows less than full frame wide.
9330 redisplay_variable_changed);
9331 truncate_partial_width_windows = 1;
9333 DEFVAR_LISP ("visible-bell", &Vvisible_bell /*
9334 *Non-nil substitutes a visual signal for the audible bell.
9336 Default behavior is to flash the whole screen. On some platforms,
9337 special effects are available using the following values:
9339 'display Flash the whole screen (ie, the default behavior).
9340 'top-bottom Flash only the top and bottom lines of the selected frame.
9342 When effects are unavailable on a platform, the visual bell is the
9343 default, whole screen. (Currently only X supports any special effects.)
9345 Vvisible_bell = Qnil;
9347 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
9348 *Non-nil means no need to redraw entire frame after suspending.
9349 A non-nil value is useful if the terminal can automatically preserve
9350 Emacs's frame display when you reenter Emacs.
9351 It is up to you to set this variable if your terminal can do that.
9353 no_redraw_on_reenter = 0;
9355 DEFVAR_LISP ("window-system", &Vwindow_system /*
9356 A symbol naming the window-system under which Emacs is running,
9357 such as `x', or nil if emacs is running on an ordinary terminal.
9359 Do not use this variable, except for GNU Emacs compatibility, as it
9360 gives wrong values in a multi-device environment. Use `console-type'
9363 Vwindow_system = Qnil;
9365 /* #### Temporary shit until window-system is eliminated. */
9366 DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /*
9369 Vinitial_window_system = Qnil;
9371 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
9372 Non-nil means put cursor in minibuffer, at end of any message there.
9374 cursor_in_echo_area = 0;
9376 /* #### Shouldn't this be generalized as follows:
9378 if nil, use block cursor.
9379 if a number, use a bar cursor of that width.
9380 Otherwise, use a 1-pixel bar cursor.
9382 #### Or better yet, this variable should be trashed entirely
9383 (use a Lisp-magic variable to maintain compatibility)
9384 and a specifier `cursor-shape' added, which allows a block
9385 cursor, a bar cursor, a flashing block or bar cursor,
9386 maybe a caret cursor, etc. */
9388 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
9389 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9393 #ifndef INHIBIT_REDISPLAY_HOOKS
9394 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
9395 Function or functions to run before every redisplay.
9397 Vpre_redisplay_hook = Qnil;
9399 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
9400 Function or functions to run after every redisplay.
9402 Vpost_redisplay_hook = Qnil;
9403 #endif /* INHIBIT_REDISPLAY_HOOKS */
9405 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /*
9406 Function or functions to call when a frame's buffer list has changed.
9407 This is called during redisplay, before redisplaying each frame.
9408 Functions on this hook are called with one argument, the frame.
9410 Vbuffer_list_changed_hook = Qnil;
9412 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
9413 Bump this to tell the C code to call `display-warning-buffer'
9414 at next redisplay. You should not normally change this; the function
9415 `display-warning' automatically does this at appropriate times.
9417 display_warning_tick = 0;
9419 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
9420 Non-nil means inhibit display of warning messages.
9421 You should *bind* this, not set it. Any pending warning messages
9422 will be displayed when the binding no longer applies.
9424 /* reset to 0 by startup.el after the splash screen has displayed.
9425 This way, the warnings don't obliterate the splash screen. */
9426 inhibit_warning_display = 1;
9428 DEFVAR_LISP ("window-size-change-functions",
9429 &Vwindow_size_change_functions /*
9430 Not currently implemented.
9431 Functions called before redisplay, if window sizes have changed.
9432 The value should be a list of functions that take one argument.
9433 Just before redisplay, for each frame, if any of its windows have changed
9434 size since the last redisplay, or have been split or deleted,
9435 all the functions in the list are called, with the frame as argument.
9437 Vwindow_size_change_functions = Qnil;
9439 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
9440 Not currently implemented.
9441 Functions to call before redisplaying a window with scrolling.
9442 Each function is called with two arguments, the window
9443 and its new display-start position. Note that the value of `window-end'
9444 is not valid when these functions are called.
9446 Vwindow_scroll_functions = Qnil;
9448 DEFVAR_LISP ("redisplay-end-trigger-functions",
9449 &Vredisplay_end_trigger_functions /*
9450 See `set-window-redisplay-end-trigger'.
9452 Vredisplay_end_trigger_functions = Qnil;
9454 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
9455 *Non-nil means column display number starts at 1.
9457 column_number_start_at_one = 0;
9461 specifier_vars_of_redisplay (void)
9463 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
9464 *Width of left margin.
9465 This is a specifier; use `set-specifier' to change it.
9467 Vleft_margin_width = Fmake_specifier (Qnatnum);
9468 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
9469 set_specifier_caching (Vleft_margin_width,
9470 offsetof (struct window, left_margin_width),
9471 some_window_value_changed,
9472 offsetof (struct frame, left_margin_width),
9473 margin_width_changed_in_frame, 0);
9475 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
9476 *Width of right margin.
9477 This is a specifier; use `set-specifier' to change it.
9479 Vright_margin_width = Fmake_specifier (Qnatnum);
9480 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
9481 set_specifier_caching (Vright_margin_width,
9482 offsetof (struct window, right_margin_width),
9483 some_window_value_changed,
9484 offsetof (struct frame, right_margin_width),
9485 margin_width_changed_in_frame, 0);
9487 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
9488 *Minimum ascent height of lines.
9489 This is a specifier; use `set-specifier' to change it.
9491 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
9492 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
9493 set_specifier_caching (Vminimum_line_ascent,
9494 offsetof (struct window, minimum_line_ascent),
9495 some_window_value_changed,
9498 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
9499 *Minimum descent height of lines.
9500 This is a specifier; use `set-specifier' to change it.
9502 Vminimum_line_descent = Fmake_specifier (Qnatnum);
9503 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
9504 set_specifier_caching (Vminimum_line_descent,
9505 offsetof (struct window, minimum_line_descent),
9506 some_window_value_changed,
9509 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
9510 *Non-nil means use the left outside margin as extra whitespace when
9511 displaying 'whitespace or 'inside-margin glyphs.
9512 This is a specifier; use `set-specifier' to change it.
9514 Vuse_left_overflow = Fmake_specifier (Qboolean);
9515 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
9516 set_specifier_caching (Vuse_left_overflow,
9517 offsetof (struct window, use_left_overflow),
9518 some_window_value_changed,
9521 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
9522 *Non-nil means use the right outside margin as extra whitespace when
9523 displaying 'whitespace or 'inside-margin glyphs.
9524 This is a specifier; use `set-specifier' to change it.
9526 Vuse_right_overflow = Fmake_specifier (Qboolean);
9527 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
9528 set_specifier_caching (Vuse_right_overflow,
9529 offsetof (struct window, use_right_overflow),
9530 some_window_value_changed,
9533 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9534 *Non-nil means the text cursor is visible (this is usually the case).
9535 This is a specifier; use `set-specifier' to change it.
9537 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
9538 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
9539 set_specifier_caching (Vtext_cursor_visible_p,
9540 offsetof (struct window, text_cursor_visible_p),
9541 text_cursor_visible_p_changed,