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_charc_string (struct window *w, int findex,
479 Charc *str, Charcount len)
481 Charset_ID charsets[NUM_LEADING_BYTES];
484 find_charsets_in_charc_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 Charc_dynarr *rtw_charc_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_charc_dynarr)
501 rtw_charc_dynarr = Dynarr_new (Charc);
502 Dynarr_reset (rtw_charc_dynarr);
504 fixup_internal_substring (nonreloc, reloc, offset, &len);
506 nonreloc = XSTRING_DATA (reloc);
507 convert_bufbyte_string_into_charc_dynarr (nonreloc, len, rtw_charc_dynarr);
508 return redisplay_text_width_charc_string
509 (w, findex, Dynarr_atp (rtw_charc_dynarr, 0),
510 Dynarr_length (rtw_charc_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 Charset_ID charsets[NUM_LEADING_BYTES];
520 struct face_cachel cachel;
522 if (!rtw_charc_dynarr)
523 rtw_charc_dynarr = Dynarr_new (Charc);
524 Dynarr_reset (rtw_charc_dynarr);
526 fixup_internal_substring (nonreloc, reloc, offset, &len);
528 nonreloc = XSTRING_DATA (reloc);
529 convert_bufbyte_string_into_charc_dynarr (nonreloc, len, rtw_charc_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_charc_dynarr, 0),
537 Dynarr_length (rtw_charc_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;
833 if (data->bi_start_col_enabled)
835 return add_hscroll_rune (data);
838 if (data->ch == '\n')
840 char_glyph = ASCII_TO_CHARC ('\n');
841 data->font_is_bogus = 0;
842 /* Cheesy end-of-line pseudo-character. */
843 width = data->blank_width;
849 char_glyph = CHAR_TO_CHARC (data->ch);
850 charset = CHARC_CHARSET (char_glyph);
851 if (!EQ (charset, data->last_charset) ||
852 data->findex != data->last_findex)
854 /* OK, we need to do things the hard way. */
855 struct window *w = XWINDOW (data->window);
856 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
857 Lisp_Object font_instance =
858 ensure_face_cachel_contains_charset (cachel, data->window,
860 Lisp_Font_Instance *fi;
862 if (EQ (font_instance, Vthe_null_font_instance))
864 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
865 data->font_is_bogus = 1;
868 data->font_is_bogus = 0;
870 fi = XFONT_INSTANCE (font_instance);
871 if (!fi->proportional_p)
872 /* sweetness and light. */
873 data->last_char_width = fi->width;
875 data->last_char_width = -1;
876 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
877 data->new_descent = max (data->new_descent, (int) fi->descent);
878 data->last_charset = charset;
879 data->last_findex = data->findex;
882 width = data->last_char_width;
885 /* bummer. Proportional fonts. */
886 width = redisplay_text_width_charc_string (XWINDOW (data->window),
892 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
897 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
899 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
908 crb->findex = data->findex;
909 crb->xpos = data->pixpos;
913 if (NILP (data->string))
915 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
919 bytecount_to_charcount (XSTRING_DATA (data->string),
922 else if (data->is_modeline)
923 crb->bufpos = data->modeline_charpos;
925 /* Text but not in buffer */
927 crb->type = RUNE_CHAR;
928 crb->object.cglyph = data->font_is_bogus
929 ? ASCII_TO_CHARC ('~')
933 if (data->cursor_type == CURSOR_ON)
935 if (data->bi_bufpos == data->bi_cursor_bufpos)
937 crb->cursor_type = CURSOR_ON;
938 data->cursor_x = Dynarr_length (data->db->runes);
941 crb->cursor_type = CURSOR_OFF;
943 else if (data->cursor_type == NEXT_CURSOR)
945 crb->cursor_type = CURSOR_ON;
946 data->cursor_x = Dynarr_length (data->db->runes);
947 data->cursor_type = NO_CURSOR;
949 else if (data->cursor_type == IGNORE_CURSOR)
950 crb->cursor_type = IGNORE_CURSOR;
952 crb->cursor_type = CURSOR_OFF;
955 Dynarr_add (data->db->runes, *crb);
957 Dynarr_increment (data->db->runes);
959 data->pixpos += width;
964 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
965 for each character in the string. Propagate any left-over data
966 unless NO_PROP is non-zero. */
968 static prop_block_dynarr *
969 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
970 Bytecount c_length, int no_prop)
972 Bufbyte *pos, *end = c_string + c_length;
973 prop_block_dynarr *prop;
975 /* #### This function is too simplistic. It needs to do the same
976 sort of character interpretation (display-table lookup,
977 ctl-arrow checking), etc. that create_text_block() does.
978 The functionality to do this in that routine needs to be
981 for (pos = c_string; pos < end;)
983 Bufbyte *old_pos = pos;
985 data->ch = charptr_emchar (pos);
987 prop = add_emchar_rune (data);
995 struct prop_block pb;
996 Bytecount len = end - pos;
997 prop = Dynarr_new (prop_block);
999 pb.type = PROP_STRING;
1000 pb.data.p_string.str = xnew_array (Bufbyte, len);
1001 strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
1002 pb.data.p_string.len = len;
1004 Dynarr_add (prop, pb);
1009 assert (pos <= end);
1010 /* #### Duplicate code from add_string_to_fstring_db_runes
1011 should we do more?*/
1012 data->bytepos += pos - old_pos;
1018 /* Add a single rune of the specified width. The area covered by this
1019 rune will be displayed in the foreground color of the associated
1022 static prop_block_dynarr *
1023 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1027 /* If data->start_col is not 0 then this call to add_blank_rune must have
1028 been to add it as a tab. */
1029 if (data->start_col)
1031 /* assert (w != NULL) */
1032 prop_block_dynarr *retval;
1034 /* If we have still not fully scrolled horizontally, subtract
1035 the width of this tab and return. */
1036 if (char_tab_width < data->start_col)
1038 data->start_col -= char_tab_width;
1041 else if (char_tab_width == data->start_col)
1042 data->blank_width = 0;
1045 int spcwid = space_width (w);
1047 if (spcwid >= data->blank_width)
1048 data->blank_width = 0;
1050 data->blank_width -= spcwid;
1053 data->start_col = 0;
1054 retval = add_hscroll_rune (data);
1056 /* Could be caused by the handling of the hscroll rune. */
1057 if (retval != NULL || !data->blank_width)
1061 /* Blank runes are always calculated to fit. */
1062 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1064 rb.findex = data->findex;
1065 rb.xpos = data->pixpos;
1066 rb.width = data->blank_width;
1067 if (data->bi_bufpos)
1069 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1072 /* #### and this is really correct too? */
1075 rb.type = RUNE_BLANK;
1077 if (data->cursor_type == CURSOR_ON)
1079 if (data->bi_bufpos == data->bi_cursor_bufpos)
1081 rb.cursor_type = CURSOR_ON;
1082 data->cursor_x = Dynarr_length (data->db->runes);
1085 rb.cursor_type = CURSOR_OFF;
1087 else if (data->cursor_type == NEXT_CURSOR)
1089 rb.cursor_type = CURSOR_ON;
1090 data->cursor_x = Dynarr_length (data->db->runes);
1091 data->cursor_type = NO_CURSOR;
1094 rb.cursor_type = CURSOR_OFF;
1096 Dynarr_add (data->db->runes, rb);
1097 data->pixpos += data->blank_width;
1102 /* Add runes representing a character in octal. */
1104 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1106 if (add_failed || (add_failed = add_emchar_rune (data))) \
1108 struct prop_block pb; \
1110 prop = Dynarr_new (prop_block); \
1112 pb.type = PROP_CHAR; \
1113 pb.data.p_char.ch = data->ch; \
1114 pb.data.p_char.cursor_type = data->cursor_type; \
1115 Dynarr_add (prop, pb); \
1119 static prop_block_dynarr *
1120 add_octal_runes (pos_data *data)
1122 prop_block_dynarr *prop, *add_failed;
1123 Emchar orig_char = data->ch;
1124 unsigned int orig_cursor_type = data->cursor_type;
1130 if (data->start_col)
1133 if (!data->start_col)
1135 if (data->bi_start_col_enabled)
1137 add_failed = add_hscroll_rune (data);
1141 struct glyph_block gb;
1142 struct window *w = XWINDOW (data->window);
1145 gb.glyph = Voctal_escape_glyph;
1147 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1148 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1152 /* We only propagate information if the glyph was partially
1157 data->cursor_type = IGNORE_CURSOR;
1159 if (data->ch >= 0x100)
1161 /* If the character is an extended Mule character, it could have
1162 up to 19 bits. For the moment, we treat it as a seven-digit
1163 octal number. This is not that pretty, but whatever. */
1164 data->ch = (7 & (orig_char >> 18)) + '0';
1165 ADD_NEXT_OCTAL_RUNE_CHAR;
1167 data->ch = (7 & (orig_char >> 15)) + '0';
1168 ADD_NEXT_OCTAL_RUNE_CHAR;
1170 data->ch = (7 & (orig_char >> 12)) + '0';
1171 ADD_NEXT_OCTAL_RUNE_CHAR;
1173 data->ch = (7 & (orig_char >> 9)) + '0';
1174 ADD_NEXT_OCTAL_RUNE_CHAR;
1177 data->ch = (7 & (orig_char >> 6)) + '0';
1178 ADD_NEXT_OCTAL_RUNE_CHAR;
1180 data->ch = (7 & (orig_char >> 3)) + '0';
1181 ADD_NEXT_OCTAL_RUNE_CHAR;
1183 data->ch = (7 & orig_char) + '0';
1184 ADD_NEXT_OCTAL_RUNE_CHAR;
1186 data->cursor_type = orig_cursor_type;
1190 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1192 /* Add runes representing a control character to a display block. */
1194 static prop_block_dynarr *
1195 add_control_char_runes (pos_data *data, struct buffer *b)
1197 if (!NILP (b->ctl_arrow))
1199 prop_block_dynarr *prop;
1200 Emchar orig_char = data->ch;
1201 unsigned int old_cursor_type = data->cursor_type;
1206 if (data->start_col)
1209 if (!data->start_col)
1211 if (data->bi_start_col_enabled)
1213 prop_block_dynarr *retval;
1215 retval = add_hscroll_rune (data);
1221 struct glyph_block gb;
1222 struct window *w = XWINDOW (data->window);
1225 gb.glyph = Vcontrol_arrow_glyph;
1227 /* We only propagate information if the glyph was partially
1229 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1230 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1235 if (orig_char == 0177)
1238 data->ch = orig_char ^ 0100;
1239 data->cursor_type = IGNORE_CURSOR;
1241 if (add_emchar_rune (data))
1243 struct prop_block pb;
1245 prop = Dynarr_new (prop_block);
1247 pb.type = PROP_CHAR;
1248 pb.data.p_char.ch = data->ch;
1249 pb.data.p_char.cursor_type = data->cursor_type;
1250 Dynarr_add (prop, pb);
1253 data->cursor_type = old_cursor_type;
1258 return add_octal_runes (data);
1262 static prop_block_dynarr *
1263 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
1265 prop_block_dynarr *prop = NULL;
1267 if (STRINGP (entry))
1269 prop = add_bufbyte_string_runes (data,
1270 XSTRING_DATA (entry),
1271 XSTRING_LENGTH (entry),
1274 else if (GLYPHP (entry))
1276 if (data->start_col)
1279 if (!data->start_col && data->bi_start_col_enabled)
1281 prop = add_hscroll_rune (data);
1285 struct glyph_block gb;
1289 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1292 else if (CHAR_OR_CHAR_INTP (entry))
1294 data->ch = XCHAR_OR_CHAR_INT (entry);
1295 prop = add_emchar_rune (data);
1297 else if (CONSP (entry))
1299 if (EQ (XCAR (entry), Qformat)
1300 && CONSP (XCDR (entry))
1301 && STRINGP (XCAR (XCDR (entry))))
1303 Lisp_Object format = XCAR (XCDR (entry));
1304 Bytind len = XSTRING_LENGTH (format);
1305 Bufbyte *src = XSTRING_DATA (format), *end = src + len;
1306 Bufbyte *result = alloca_array (Bufbyte, len);
1307 Bufbyte *dst = result;
1311 Emchar c = charptr_emchar (src);
1313 if (c != '%' || src == end)
1314 dst += set_charptr_emchar (dst, c);
1317 c = charptr_emchar (src);
1322 dst += long_to_string_base ((char *)dst, data->ch, 16);
1325 dst += set_charptr_emchar (dst, '%');
1327 /* #### unimplemented */
1331 prop = add_bufbyte_string_runes (data, result, dst - result, 0);
1335 /* Else blow it off because someone added a bad entry and we don't
1336 have any safe way of signaling an error. */
1340 /* Given a display table entry, call the appropriate functions to
1341 display each element of the entry. */
1343 static prop_block_dynarr *
1344 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1346 prop_block_dynarr *prop = NULL;
1347 if (VECTORP (entry))
1349 Lisp_Vector *de = XVECTOR (entry);
1350 EMACS_INT len = vector_length (de);
1353 for (elt = 0; elt < len; elt++)
1355 if (NILP (vector_data (de)[elt]))
1358 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
1359 /* Else blow it off because someone added a bad entry and we
1360 don't have any safe way of signaling an error. Hey, this
1361 comment sounds familiar. */
1363 /* #### Still need to add any remaining elements to the
1364 propagation information. */
1370 prop = add_disp_table_entry_runes_1 (data, entry);
1374 /* Add runes which were propagated from the previous line. */
1376 static prop_block_dynarr *
1377 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1379 /* #### Remember to handle start_col parameter of data when the rest of
1380 this is finished. */
1381 /* #### Chuck -- I've redone this function a bit. It looked like the
1382 case of not all the propagation blocks being added was not handled
1384 /* #### Chuck -- I also think the double indirection of PROP is kind
1385 of bogus. A cleaner solution is just to check for
1386 Dynarr_length (prop) > 0. */
1387 /* #### This function also doesn't even pay attention to ADD_FAILED!
1388 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1391 prop_block_dynarr *add_failed;
1392 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1393 unsigned int old_cursor_type = data->cursor_type;
1395 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1397 struct prop_block *pb = Dynarr_atp (*prop, elt);
1402 data->ch = pb->data.p_char.ch;
1403 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1404 data->cursor_type = pb->data.p_char.cursor_type;
1405 add_failed = add_emchar_rune (data);
1408 goto oops_no_more_space;
1411 if (pb->data.p_string.str)
1412 xfree (pb->data.p_string.str);
1413 /* #### bogus bogus -- this doesn't do anything!
1414 Should probably call add_bufbyte_string_runes(),
1415 once that function is fixed. */
1417 case PROP_MINIBUF_PROMPT:
1419 face_index old_findex = data->findex;
1420 Bytind bi_old_bufpos = data->bi_bufpos;
1422 data->findex = DEFAULT_INDEX;
1423 data->bi_bufpos = 0;
1424 data->cursor_type = NO_CURSOR;
1426 while (pb->data.p_string.len > 0)
1428 data->ch = charptr_emchar (pb->data.p_string.str);
1429 add_failed = add_emchar_rune (data);
1433 data->findex = old_findex;
1434 data->bi_bufpos = bi_old_bufpos;
1435 goto oops_no_more_space;
1439 /* Complicated equivalent of ptr++, len-- */
1440 Bufbyte *oldpos = pb->data.p_string.str;
1441 INC_CHARPTR (pb->data.p_string.str);
1442 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1446 data->findex = old_findex;
1447 /* ##### FIXME FIXME FIXME -- Upon successful return from
1448 this function, data->bi_bufpos is automatically incremented.
1449 However, we don't want that to happen if we were adding
1450 the minibuffer prompt. */
1452 struct buffer *buf =
1453 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1454 /* #### Chuck fix this shit or I'm gonna scream! */
1455 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1456 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1458 /* #### is this correct? Does anyone know?
1459 Does anyone care? Is this a cheesy hack or what? */
1460 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1466 /* #### I think it's unnecessary and misleading to preserve
1467 the blank_width, as it implies that the value carries
1468 over from one rune to the next, which is wrong. */
1469 int old_width = data->blank_width;
1470 face_index old_findex = data->findex;
1472 data->findex = pb->data.p_blank.findex;
1473 data->blank_width = pb->data.p_blank.width;
1474 data->bi_cursor_bufpos = 0;
1475 data->cursor_type = IGNORE_CURSOR;
1477 if (data->pixpos + data->blank_width > data->max_pixpos)
1478 data->blank_width = data->max_pixpos - data->pixpos;
1480 /* We pass a bogus value of char_tab_width. It shouldn't
1481 matter because unless something is really screwed up
1482 this call won't cause that arg to be used. */
1483 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1485 /* This can happen in the case where we have a tab which
1486 is wider than the window. */
1487 if (data->blank_width != pb->data.p_blank.width)
1489 pb->data.p_blank.width -= data->blank_width;
1490 add_failed = ADD_FAILED;
1493 data->findex = old_findex;
1494 data->blank_width = old_width;
1497 goto oops_no_more_space;
1507 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1508 data->cursor_type = old_cursor_type;
1509 if (elt < Dynarr_length (*prop))
1511 Dynarr_delete_many (*prop, 0, elt);
1516 Dynarr_free (*prop);
1521 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1522 the display block, but add all other types to the appropriate list
1523 of the display line. They will be added later by different
1526 static prop_block_dynarr *
1527 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1528 int allow_cursor, struct glyph_cachel *cachel)
1530 struct window *w = XWINDOW (data->window);
1532 /* If window faces changed, and glyph instance is text, then
1533 glyph sizes might have changed too */
1534 invalidate_glyph_geometry_maybe (gb->glyph, w);
1536 /* This makes sure the glyph is in the cachels.
1538 #### We do this to make sure the glyph is in the glyph cachels,
1539 so that the dirty flag can be reset after redisplay has
1540 finished. We should do this some other way, maybe by iterating
1541 over the window cache of subwindows. */
1542 get_glyph_cachel_index (w, gb->glyph);
1544 /* A nil extent indicates a special glyph (ex. truncator). */
1545 if (NILP (gb->extent)
1546 || (pos_type == BEGIN_GLYPHS &&
1547 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1548 || (pos_type == END_GLYPHS &&
1549 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1550 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS)
1555 int ascent, descent;
1556 Lisp_Object baseline;
1558 Lisp_Object instance;
1562 width = cachel->width;
1564 width = glyph_width (gb->glyph, data->window);
1569 if (data->start_col || data->start_col_xoffset)
1571 prop_block_dynarr *retval;
1572 int glyph_char_width = width / space_width (w);
1574 /* If we still have not fully scrolled horizontally after
1575 taking into account the width of the glyph, subtract its
1576 width and return. */
1577 if (glyph_char_width < data->start_col)
1579 data->start_col -= glyph_char_width;
1582 else if (glyph_char_width == data->start_col)
1586 xoffset = space_width (w) * data->start_col;
1589 /* #### Can this happen? */
1594 data->start_col = 0;
1595 retval = add_hscroll_rune (data);
1597 /* Could be caused by the handling of the hscroll rune. */
1598 if (retval != NULL || !width)
1604 if (data->pixpos + width > data->max_pixpos)
1606 /* If this is the first object we are attempting to add to
1607 the line then we ignore the horizontal_clip threshold.
1608 Otherwise we will loop until the bottom of the window
1609 continually failing to add this glyph because it is wider
1610 than the window. We could alternatively just completely
1611 ignore the glyph and proceed from there but I think that
1612 this is a better solution. */
1613 if (Dynarr_length (data->db->runes)
1614 && data->max_pixpos - data->pixpos < horizontal_clip)
1617 width = data->max_pixpos - data->pixpos;
1622 ascent = cachel->ascent;
1623 descent = cachel->descent;
1627 ascent = glyph_ascent (gb->glyph, data->window);
1628 descent = glyph_descent (gb->glyph, data->window);
1631 baseline = glyph_baseline (gb->glyph, data->window);
1633 if (glyph_contrib_p (gb->glyph, data->window))
1635 /* A pixmap that has not had a baseline explicitly set. Its
1636 contribution will be determined later. */
1637 if (NILP (baseline))
1639 int height = ascent + descent;
1640 data->max_pixmap_height = max (data->max_pixmap_height, height);
1643 /* A string so determine contribution normally. */
1644 else if (EQ (baseline, Qt))
1646 data->new_ascent = max (data->new_ascent, ascent);
1647 data->new_descent = max (data->new_descent, descent);
1650 /* A pixmap with an explicitly set baseline. We determine the
1651 contribution here. */
1652 else if (INTP (baseline))
1654 int height = ascent + descent;
1655 int pix_ascent, pix_descent;
1657 pix_ascent = height * XINT (baseline) / 100;
1658 pix_descent = height - pix_ascent;
1660 data->new_ascent = max (data->new_ascent, pix_ascent);
1661 data->new_descent = max (data->new_descent, pix_descent);
1664 /* Otherwise something is screwed up. */
1669 face = glyph_face (gb->glyph, data->window);
1671 findex = data->findex;
1673 findex = get_builtin_face_cache_index (w, face);
1675 instance = glyph_image_instance (gb->glyph, data->window,
1677 if (TEXT_IMAGE_INSTANCEP (instance))
1679 Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance);
1680 face_index orig_findex = data->findex;
1681 Bytind orig_bufpos = data->bi_bufpos;
1682 Bytind orig_start_col_enabled = data->bi_start_col_enabled;
1684 data->findex = findex;
1685 data->bi_start_col_enabled = 0;
1687 data->bi_bufpos = 0;
1688 add_bufbyte_string_runes (data, XSTRING_DATA (string),
1689 XSTRING_LENGTH (string), 0);
1690 data->findex = orig_findex;
1691 data->bi_bufpos = orig_bufpos;
1692 data->bi_start_col_enabled = orig_start_col_enabled;
1697 rb.xpos = data->pixpos;
1699 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1700 if (data->bi_endpos)
1701 /* #### is this necessary at all? */
1702 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1706 rb.type = RUNE_DGLYPH;
1707 rb.object.dglyph.glyph = gb->glyph;
1708 rb.object.dglyph.extent = gb->extent;
1709 rb.object.dglyph.xoffset = xoffset;
1713 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1716 if (data->cursor_type == CURSOR_ON)
1718 if (data->bi_bufpos == data->bi_cursor_bufpos)
1720 rb.cursor_type = CURSOR_ON;
1721 data->cursor_x = Dynarr_length (data->db->runes);
1724 rb.cursor_type = CURSOR_OFF;
1726 else if (data->cursor_type == NEXT_CURSOR)
1728 rb.cursor_type = CURSOR_ON;
1729 data->cursor_x = Dynarr_length (data->db->runes);
1730 data->cursor_type = NO_CURSOR;
1732 else if (data->cursor_type == IGNORE_CURSOR)
1733 rb.cursor_type = IGNORE_CURSOR;
1734 else if (data->cursor_type == NO_CURSOR)
1735 rb.cursor_type = NO_CURSOR;
1737 rb.cursor_type = CURSOR_OFF;
1740 rb.cursor_type = CURSOR_OFF;
1742 Dynarr_add (data->db->runes, rb);
1743 data->pixpos += width;
1749 if (!NILP (glyph_face (gb->glyph, data->window)))
1751 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1754 gb->findex = data->findex;
1756 if (pos_type == BEGIN_GLYPHS)
1758 if (!data->dl->left_glyphs)
1759 data->dl->left_glyphs = Dynarr_new (glyph_block);
1760 Dynarr_add (data->dl->left_glyphs, *gb);
1763 else if (pos_type == END_GLYPHS)
1765 if (!data->dl->right_glyphs)
1766 data->dl->right_glyphs = Dynarr_new (glyph_block);
1767 Dynarr_add (data->dl->right_glyphs, *gb);
1771 abort (); /* there are no unknown types */
1774 return NULL; /* shut up compiler */
1777 /* Add all glyphs at position POS_TYPE that are contained in the given
1780 static prop_block_dynarr *
1781 add_glyph_runes (pos_data *data, int pos_type)
1783 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1784 why didn't you just modify add_glyph_rune in the first place? */
1786 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1787 ? data->ef->begin_glyphs
1788 : data->ef->end_glyphs);
1789 prop_block_dynarr *prop;
1791 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1793 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1798 /* #### Add some propagation information. */
1803 Dynarr_reset (glyph_arr);
1808 /* Given a position for a buffer in a window, ensure that the given
1809 display line DL accurately represents the text on a line starting
1810 at the given position.
1812 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1813 You must do appropriate conversion. */
1816 create_text_block (struct window *w, struct display_line *dl,
1817 Bytind bi_start_pos, prop_block_dynarr **prop,
1820 struct frame *f = XFRAME (w->frame);
1821 struct buffer *b = XBUFFER (w->buffer);
1822 struct device *d = XDEVICE (f->device);
1826 /* Don't display anything in the minibuffer if this window is not on
1827 a selected frame. We consider all other windows to be active
1828 minibuffers as it simplifies the coding. */
1829 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1830 (f == device_selected_frame (d)) ||
1831 is_surrogate_for_selected_frame (f));
1833 int truncate_win = window_truncation_on (w);
1834 int end_glyph_width;
1836 /* If the buffer's value of selective_display is an integer then
1837 only lines that start with less than selective_display columns of
1838 space will be displayed. If selective_display is t then all text
1839 after a ^M is invisible. */
1840 int selective = (INTP (b->selective_display)
1841 ? XINT (b->selective_display)
1842 : (!NILP (b->selective_display) ? -1 : 0));
1844 /* The variable ctl-arrow allows the user to specify what characters
1845 can actually be displayed and which octal should be used for.
1846 #### This variable should probably have some rethought done to
1849 #### It would also be really nice if you could specify that
1850 the characters come out in hex instead of in octal. Mule
1851 does that by adding a ctl-hexa variable similar to ctl-arrow,
1852 but that's bogus -- we need a more general solution. I
1853 think you need to extend the concept of display tables
1854 into a more general conversion mechanism. Ideally you
1855 could specify a Lisp function that converts characters,
1856 but this violates the Second Golden Rule and besides would
1857 make things way way way way slow.
1859 So instead, we extend the display-table concept, which was
1860 historically limited to 256-byte vectors, to one of the
1863 a) A 256-entry vector, for backward compatibility;
1864 b) char-table, mapping characters to values;
1865 c) range-table, mapping ranges of characters to values;
1866 d) a list of the above.
1868 The (d) option allows you to specify multiple display tables
1869 instead of just one. Each display table can specify conversions
1870 for some characters and leave others unchanged. The way the
1871 character gets displayed is determined by the first display table
1872 with a binding for that character. This way, you could call a
1873 function `enable-hex-display' that adds a hex display-table to
1874 the list of display tables for the current buffer.
1876 #### ...not yet implemented... Also, we extend the concept of
1877 "mapping" to include a printf-like spec. Thus you can make all
1878 extended characters show up as hex with a display table like
1881 #s(range-table data ((256 524288) (format "%x")))
1883 Since more than one display table is possible, you have
1884 great flexibility in mapping ranges of characters. */
1885 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1886 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1887 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1890 Lisp_Object face_dt, window_dt;
1892 /* The text display block for this display line. */
1893 struct display_block *db = get_display_block_from_line (dl, TEXT);
1895 /* The first time through the main loop we need to force the glyph
1896 data to be updated. */
1899 /* Apparently the new extent_fragment_update returns an end position
1900 equal to the position passed in if there are no more runs to be
1902 int no_more_frags = 0;
1904 Lisp_Object synch_minibuffers_value =
1905 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1907 dl->used_prop_data = 0;
1909 dl->line_continuation = 0;
1912 data.ef = extent_fragment_new (w->buffer, f);
1914 /* These values are used by all of the rune addition routines. We add
1915 them to this structure for ease of passing. */
1917 XSETWINDOW (data.window, w);
1922 data.bi_bufpos = bi_start_pos;
1923 data.pixpos = dl->bounds.left_in;
1924 data.last_charset = Qunbound;
1925 data.last_findex = DEFAULT_INDEX;
1926 data.result_str = Qnil;
1928 /* Set the right boundary adjusting it to take into account any end
1929 glyph. Save the width of the end glyph for later use. */
1930 data.max_pixpos = dl->bounds.right_in;
1932 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1934 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1935 data.max_pixpos -= end_glyph_width;
1937 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1939 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1940 data.cursor_type = CURSOR_ON;
1942 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1943 data.cursor_type = NO_CURSOR;
1944 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1945 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1946 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1947 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1949 data.bi_cursor_bufpos = BI_BUF_PT (b);
1950 data.cursor_type = CURSOR_ON;
1952 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1954 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1955 data.cursor_type = CURSOR_ON;
1958 data.cursor_type = NO_CURSOR;
1961 data.start_col = w->hscroll;
1962 data.start_col_xoffset = w->left_xoffset;
1963 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1964 data.hscroll_glyph_width_adjust = 0;
1966 /* We regenerate the line from the very beginning. */
1967 Dynarr_reset (db->runes);
1969 /* Why is this less than or equal and not just less than? If the
1970 starting position is already equal to the maximum we can't add
1971 anything else, right? Wrong. We might still have a newline to
1972 add. A newline can use the room allocated for an end glyph since
1973 if we add it we know we aren't going to be adding any end
1976 /* #### Chuck -- I think this condition should be while (1).
1977 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1978 and the begin-glyph ends exactly at the end of the window, the
1979 end-glyph and text might not be displayed. while (1) ensures
1980 that the loop terminates only when either (a) there is
1981 propagation data or (b) the end-of-line or end-of-buffer is hit.
1983 #### Also I think you need to ensure that the operation
1984 "add begin glyphs; add end glyphs; add text" is atomic and
1985 can't get interrupted in the middle. If you run off the end
1986 of the line during that operation, then you keep accumulating
1987 propagation data until you're done. Otherwise, if the (e.g.)
1988 there's a begin glyph at a particular position and attempting
1989 to display that glyph results in window-end being hit and
1990 propagation data being generated, then the character at that
1991 position won't be displayed.
1993 #### See also the comment after the end of this loop, below.
1995 while (data.pixpos <= data.max_pixpos
1996 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1998 /* #### This check probably should not be necessary. */
1999 if (data.bi_bufpos > BI_BUF_ZV (b))
2001 /* #### urk! More of this lossage! */
2006 /* If selective display was an integer and we aren't working on
2007 a continuation line then find the next line we are actually
2008 supposed to display. */
2010 && (data.bi_bufpos == BI_BUF_BEGV (b)
2011 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
2013 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2016 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2017 if (data.bi_bufpos >= BI_BUF_ZV (b))
2019 data.bi_bufpos = BI_BUF_ZV (b);
2025 /* Check for face changes. */
2026 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
2028 /* Now compute the face and begin/end-glyph information. */
2030 /* Remember that the extent-fragment routines deal in Bytind's. */
2031 extent_fragment_update (w, data.ef, data.bi_bufpos);
2033 get_display_tables (w, data.findex, &face_dt, &window_dt);
2035 if (data.bi_bufpos == data.ef->end)
2040 /* Determine what is next to be displayed. We first handle any
2041 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2042 display then we determine what to do based on the character at the
2043 current buffer position. */
2045 /* If the current position is covered by an invisible extent, do
2046 nothing (except maybe add some ellipses).
2048 #### The behavior of begin and end-glyphs at the edge of an
2049 invisible extent should be investigated further. This is
2050 fairly low priority though. */
2051 if (data.ef->invisible)
2053 /* #### Chuck, perhaps you could look at this code? I don't
2054 really know what I'm doing. */
2057 Dynarr_free (*prop);
2061 /* The extent fragment code only sets this when we should
2062 really display the ellipses. It makes sure the ellipses
2063 don't get displayed more than once in a row. */
2064 if (data.ef->invisible_ellipses)
2066 struct glyph_block gb;
2068 data.ef->invisible_ellipses_already_displayed = 1;
2069 data.ef->invisible_ellipses = 0;
2071 gb.glyph = Vinvisible_text_glyph;
2072 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2073 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2074 /* Perhaps they shouldn't propagate if the very next thing
2075 is to display a newline (for compatibility with
2076 selective-display-ellipses)? Maybe that's too
2082 /* If point is in an invisible region we place it on the
2083 next visible character. */
2084 if (data.cursor_type == CURSOR_ON
2085 && data.bi_bufpos == data.bi_cursor_bufpos)
2087 data.cursor_type = NEXT_CURSOR;
2090 /* #### What if we we're dealing with a display table? */
2094 if (data.bi_bufpos == BI_BUF_ZV (b))
2097 INC_BYTIND (b, data.bi_bufpos);
2100 /* If there is propagation data, then it represents the current
2101 buffer position being displayed. Add them and advance the
2102 position counter. This might also add the minibuffer
2106 dl->used_prop_data = 1;
2107 *prop = add_propagation_runes (prop, &data);
2110 goto done; /* gee, a really narrow window */
2111 else if (data.bi_bufpos == BI_BUF_ZV (b))
2113 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2114 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2115 data.bi_bufpos = BI_BUF_BEGV (b);
2117 INC_BYTIND (b, data.bi_bufpos);
2120 /* If there are end glyphs, add them to the line. These are
2121 the end glyphs for the previous run of text. We add them
2122 here rather than doing them at the end of handling the
2123 previous run so that glyphs at the beginning and end of
2124 a line are handled correctly. */
2125 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2127 *prop = add_glyph_runes (&data, END_GLYPHS);
2132 /* If there are begin glyphs, add them to the line. */
2133 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2135 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2140 /* If at end-of-buffer, we've already processed begin and
2141 end-glyphs at this point and there's no text to process,
2143 else if (data.bi_bufpos == BI_BUF_ZV (b))
2148 Lisp_Object entry = Qnil;
2149 /* Get the character at the current buffer position. */
2150 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2151 if (!NILP (face_dt) || !NILP (window_dt))
2152 entry = display_table_entry (data.ch, face_dt, window_dt);
2154 /* If there is a display table entry for it, hand it off to
2155 add_disp_table_entry_runes and let it worry about it. */
2156 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
2158 *prop = add_disp_table_entry_runes (&data, entry);
2164 /* Check if we have hit a newline character. If so, add a marker
2165 to the line and end this loop. */
2166 else if (data.ch == '\n')
2168 /* We aren't going to be adding an end glyph so give its
2169 space back in order to make sure that the cursor can
2171 data.max_pixpos += end_glyph_width;
2174 && (bi_spaces_at_point
2175 (b, next_bytind (b, data.bi_bufpos))
2178 if (!NILP (b->selective_display_ellipses))
2180 struct glyph_block gb;
2183 gb.glyph = Vinvisible_text_glyph;
2184 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2185 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2189 /* Cheesy, cheesy, cheesy. We mark the end of the
2190 line with a special "character rune" whose width
2191 is the EOL cursor width and whose character is
2192 the non-printing character '\n'. */
2193 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2194 *prop = add_emchar_rune (&data);
2197 /* We need to set data.bi_bufpos to the start of the
2198 next visible region in order to make this line
2199 appear to contain all of the invisible area.
2200 Otherwise, the line cache won't work
2202 INC_BYTIND (b, data.bi_bufpos);
2203 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2206 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2207 if (data.bi_bufpos >= BI_BUF_ZV (b))
2209 data.bi_bufpos = BI_BUF_ZV (b);
2213 if (BI_BUF_FETCH_CHAR
2214 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2215 DEC_BYTIND (b, data.bi_bufpos);
2219 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2220 *prop = add_emchar_rune (&data);
2226 /* If the current character is ^M, and selective display is
2227 enabled, then add the invisible-text-glyph if
2228 selective-display-ellipses is set. In any case, this
2230 else if (data.ch == (('M' & 037)) && selective == -1)
2232 Bytind bi_next_bufpos;
2234 /* Find the buffer position at the end of the line. */
2236 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2237 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2239 DEC_BYTIND (b, bi_next_bufpos);
2241 /* If the cursor is somewhere in the elided text make
2242 sure that the cursor gets drawn appropriately. */
2243 if (data.cursor_type == CURSOR_ON
2244 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2245 data.bi_cursor_bufpos < bi_next_bufpos))
2247 data.cursor_type = NEXT_CURSOR;
2250 /* We won't be adding a truncation or continuation glyph
2251 so give up the room allocated for them. */
2252 data.max_pixpos += end_glyph_width;
2254 if (!NILP (b->selective_display_ellipses))
2256 /* We don't propagate anything from the invisible
2257 text glyph if it fails to fit. This is
2259 struct glyph_block gb;
2262 gb.glyph = Vinvisible_text_glyph;
2263 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2264 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2267 /* Set the buffer position to the end of the line. We
2268 need to do this before potentially adding a newline
2269 so that the cursor flag will get set correctly (if
2271 data.bi_bufpos = bi_next_bufpos;
2273 if (NILP (b->selective_display_ellipses)
2274 || data.bi_cursor_bufpos == bi_next_bufpos)
2276 /* We have to at least add a newline character so
2277 that the cursor shows up properly. */
2279 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2280 data.findex = DEFAULT_INDEX;
2282 data.start_col_xoffset = 0;
2283 data.bi_start_col_enabled = 0;
2285 add_emchar_rune (&data);
2288 /* This had better be a newline but doing it this way
2289 we'll see obvious incorrect results if it isn't. No
2290 need to abort here. */
2291 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2296 /* If the current character is considered to be printable, then
2298 else if (data.ch >= printable_min)
2300 *prop = add_emchar_rune (&data);
2305 /* If the current character is a tab, determine the next tab
2306 starting position and add a blank rune which extends from the
2307 current pixel position to that starting position. */
2308 else if (data.ch == '\t')
2310 int tab_start_pixpos = data.pixpos;
2315 if (data.start_col > 1)
2316 tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
2317 + data.start_col_xoffset;
2320 next_tab_position (w, tab_start_pixpos,
2321 dl->bounds.left_in +
2322 data.hscroll_glyph_width_adjust);
2323 if (next_tab_start > data.max_pixpos)
2325 prop_width = next_tab_start - data.max_pixpos;
2326 next_tab_start = data.max_pixpos;
2328 data.blank_width = next_tab_start - data.pixpos;
2330 (next_tab_start - tab_start_pixpos) / space_width (w);
2332 *prop = add_blank_rune (&data, w, char_tab_width);
2334 /* add_blank_rune is only supposed to be called with
2335 sizes guaranteed to fit in the available space. */
2340 struct prop_block pb;
2341 *prop = Dynarr_new (prop_block);
2343 pb.type = PROP_BLANK;
2344 pb.data.p_blank.width = prop_width;
2345 pb.data.p_blank.findex = data.findex;
2346 Dynarr_add (*prop, pb);
2352 /* If character is a control character, pass it off to
2353 add_control_char_runes.
2355 The is_*() routines have undefined results on
2356 arguments outside of the range [-1, 255]. (This
2357 often bites people who carelessly use `char' instead
2358 of `unsigned char'.)
2360 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2362 *prop = add_control_char_runes (&data, b);
2368 /* If the character is above the ASCII range and we have not
2369 already handled it, then print it as an octal number. */
2370 else if (data.ch >= 0200)
2372 *prop = add_octal_runes (&data);
2378 /* Assume the current character is considered to be printable,
2379 then just add it. */
2382 *prop = add_emchar_rune (&data);
2387 INC_BYTIND (b, data.bi_bufpos);
2393 /* Determine the starting point of the next line if we did not hit the
2394 end of the buffer. */
2395 if (data.bi_bufpos < BI_BUF_ZV (b)
2396 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2398 /* #### This check is not correct. If the line terminated
2399 due to a begin-glyph or end-glyph hitting window-end, then
2400 data.ch will not point to the character at data.bi_bufpos. If
2401 you make the two changes mentioned at the top of this loop,
2402 you should be able to say '(if (*prop))'. That should also
2403 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2406 /* The common case is that the line ended because we hit a newline.
2407 In that case, the next character is just the next buffer
2409 if (data.ch == '\n')
2411 /* If data.start_col_enabled is still true, then the window is
2412 scrolled far enough so that nothing on this line is visible.
2413 We need to stick a truncation glyph at the beginning of the
2414 line in that case unless the line is completely blank. */
2415 if (data.bi_start_col_enabled)
2417 if (data.cursor_type == CURSOR_ON)
2419 if (data.bi_cursor_bufpos >= bi_start_pos
2420 && data.bi_cursor_bufpos <= data.bi_bufpos)
2421 data.bi_cursor_bufpos = data.bi_bufpos;
2423 data.findex = DEFAULT_INDEX;
2425 data.bi_start_col_enabled = 0;
2427 if (data.bi_bufpos != bi_start_pos)
2429 struct glyph_block gb;
2432 gb.glyph = Vhscroll_glyph;
2433 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2434 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2438 /* This duplicates code down below to add a newline to
2439 the end of an otherwise empty line.*/
2441 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2443 add_emchar_rune (&data);
2447 INC_BYTIND (b, data.bi_bufpos);
2450 /* Otherwise we have a buffer line which cannot fit on one display
2454 struct glyph_block gb;
2455 struct glyph_cachel *cachel;
2457 /* If the line is to be truncated then we actually have to look
2458 for the next newline. We also add the end-of-line glyph which
2459 we know will fit because we adjusted the right border before
2460 we starting laying out the line. */
2461 data.max_pixpos += end_glyph_width;
2462 data.findex = DEFAULT_INDEX;
2469 /* Now find the start of the next line. */
2470 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2472 /* If the cursor is past the truncation line then we
2473 make it appear on the truncation glyph. If we've hit
2474 the end of the buffer then we also make the cursor
2475 appear unless eob is immediately preceded by a
2476 newline. In that case the cursor should actually
2477 appear on the next line. */
2478 if (data.cursor_type == CURSOR_ON
2479 && data.bi_cursor_bufpos >= data.bi_bufpos
2480 && (data.bi_cursor_bufpos < bi_pos ||
2481 (bi_pos == BI_BUF_ZV (b)
2482 && (bi_pos == BI_BUF_BEGV (b)
2483 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2485 data.bi_cursor_bufpos = bi_pos;
2487 data.cursor_type = NO_CURSOR;
2489 data.bi_bufpos = bi_pos;
2490 gb.glyph = Vtruncation_glyph;
2491 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2495 /* The cursor can never be on the continuation glyph. */
2496 data.cursor_type = NO_CURSOR;
2498 /* data.bi_bufpos is already at the start of the next line. */
2500 dl->line_continuation = 1;
2501 gb.glyph = Vcontinuation_glyph;
2502 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2505 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
2507 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2508 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2509 /* #### Damn this losing shit. */
2513 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2514 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2516 /* We need to add a marker to the end of the line since there is no
2517 newline character in order for the cursor to get drawn. We label
2518 it as a newline so that it gets handled correctly by the
2519 whitespace routines below. */
2522 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2523 data.findex = DEFAULT_INDEX;
2525 data.start_col_xoffset = 0;
2526 data.bi_start_col_enabled = 0;
2528 data.max_pixpos += data.blank_width;
2529 add_emchar_rune (&data);
2530 data.max_pixpos -= data.blank_width;
2532 /* #### urk! Chuck, this shit is bad news. Going around
2533 manipulating invalid positions is guaranteed to result in
2534 trouble sooner or later. */
2535 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2538 /* Calculate left whitespace boundary. */
2542 /* Whitespace past a newline is considered right whitespace. */
2543 while (elt < Dynarr_length (db->runes))
2545 struct rune *rb = Dynarr_atp (db->runes, elt);
2547 if ((rb->type == RUNE_CHAR && CHARC_ASCII_EQ (rb->object.cglyph, ' '))
2548 || rb->type == RUNE_BLANK)
2550 dl->bounds.left_white += rb->width;
2554 elt = Dynarr_length (db->runes);
2558 /* Calculate right whitespace boundary. */
2560 int elt = Dynarr_length (db->runes) - 1;
2563 while (!done && elt >= 0)
2565 struct rune *rb = Dynarr_atp (db->runes, elt);
2567 if (!(rb->type == RUNE_CHAR && CHARC_IS_SPACE (rb->object.cglyph))
2568 && !rb->type == RUNE_BLANK)
2570 dl->bounds.right_white = rb->xpos + rb->width;
2578 /* The line is blank so everything is considered to be right
2581 dl->bounds.right_white = dl->bounds.left_in;
2584 /* Set the display blocks bounds. */
2585 db->start_pos = dl->bounds.left_in;
2586 if (Dynarr_length (db->runes))
2588 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2590 db->end_pos = rb->xpos + rb->width;
2593 db->end_pos = dl->bounds.right_white;
2595 /* update line height parameters */
2596 if (!data.new_ascent && !data.new_descent)
2598 /* We've got a blank line so initialize these values from the default
2600 default_face_font_info (data.window, &data.new_ascent,
2601 &data.new_descent, 0, 0, 0);
2604 if (data.max_pixmap_height)
2606 int height = data.new_ascent + data.new_descent;
2607 int pix_ascent, pix_descent;
2609 pix_descent = data.max_pixmap_height * data.new_descent / height;
2610 pix_ascent = data.max_pixmap_height - pix_descent;
2612 data.new_ascent = max (data.new_ascent, pix_ascent);
2613 data.new_descent = max (data.new_descent, pix_descent);
2616 dl->ascent = data.new_ascent;
2617 dl->descent = data.new_descent;
2620 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2622 if (dl->ascent < ascent)
2623 dl->ascent = ascent;
2626 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2628 if (dl->descent < descent)
2629 dl->descent = descent;
2632 dl->cursor_elt = data.cursor_x;
2633 /* #### lossage lossage lossage! Fix this shit! */
2634 if (data.bi_bufpos > BI_BUF_ZV (b))
2635 dl->end_bufpos = BUF_ZV (b);
2637 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2639 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2641 /* This doesn't correctly take into account tabs and control
2642 characters but if the window isn't being truncated then this
2643 value isn't going to end up being used anyhow. */
2644 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2646 /* #### handle horizontally scrolled line with text none of which
2647 was actually laid out. */
2649 /* #### handle any remainder of overlay arrow */
2651 if (*prop == ADD_FAILED)
2654 if (truncate_win && *prop)
2656 Dynarr_free (*prop);
2660 extent_fragment_delete (data.ef);
2662 /* #### If we started at EOB, then make sure we return a value past
2663 it so that regenerate_window will exit properly. This is bogus.
2664 The main loop should get fixed so that it isn't necessary to call
2665 this function if we are already at EOB. */
2667 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2668 return data.bi_bufpos + 1; /* Yuck! */
2670 return data.bi_bufpos;
2673 /* Display the overlay arrow at the beginning of the given line. */
2676 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2678 struct frame *f = XFRAME (w->frame);
2679 struct device *d = XDEVICE (f->device);
2682 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2683 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2689 XSETWINDOW (data.window, w);
2690 data.db = get_display_block_from_line (dl, OVERWRITE);
2692 data.pixpos = dl->bounds.left_in;
2693 data.max_pixpos = dl->bounds.right_in;
2694 data.cursor_type = NO_CURSOR;
2696 data.findex = DEFAULT_INDEX;
2697 data.last_charset = Qunbound;
2698 data.last_findex = DEFAULT_INDEX;
2699 data.result_str = Qnil;
2702 Dynarr_reset (data.db->runes);
2704 if (STRINGP (Voverlay_arrow_string))
2706 add_bufbyte_string_runes
2708 XSTRING_DATA (Voverlay_arrow_string),
2709 XSTRING_LENGTH (Voverlay_arrow_string),
2712 else if (GLYPHP (Voverlay_arrow_string))
2714 struct glyph_block gb;
2716 gb.glyph = Voverlay_arrow_string;
2718 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2721 if (data.max_pixmap_height)
2723 int height = data.new_ascent + data.new_descent;
2724 int pix_ascent, pix_descent;
2726 pix_descent = data.max_pixmap_height * data.new_descent / height;
2727 pix_ascent = data.max_pixmap_height - pix_descent;
2729 data.new_ascent = max (data.new_ascent, pix_ascent);
2730 data.new_descent = max (data.new_descent, pix_descent);
2733 dl->ascent = data.new_ascent;
2734 dl->descent = data.new_descent;
2736 data.db->start_pos = dl->bounds.left_in;
2737 data.db->end_pos = data.pixpos;
2739 return data.pixpos - dl->bounds.left_in;
2742 /* Add a type of glyph to a margin display block. */
2745 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2746 int count, enum glyph_layout layout, int side, Lisp_Object window)
2748 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2750 : dl->right_glyphs);
2753 struct window *w = XWINDOW (window);
2754 struct frame *f = XFRAME (w->frame);
2755 struct device *d = XDEVICE (f->device);
2760 data.window = window;
2763 data.pixpos = start;
2764 data.cursor_type = NO_CURSOR;
2766 data.last_charset = Qunbound;
2767 data.last_findex = DEFAULT_INDEX;
2768 data.result_str = Qnil;
2770 data.new_ascent = dl->ascent;
2771 data.new_descent = dl->descent;
2773 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2774 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2777 elt = Dynarr_length (gbd) - 1;
2784 end = Dynarr_length (gbd);
2787 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2789 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2791 if (NILP (gb->extent))
2792 abort (); /* these should have been handled in add_glyph_rune */
2795 ((side == LEFT_GLYPHS &&
2796 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2797 || (side == RIGHT_GLYPHS &&
2798 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2800 data.findex = gb->findex;
2801 data.max_pixpos = data.pixpos + gb->width;
2802 add_glyph_rune (&data, gb, side, 0, NULL);
2807 (reverse ? elt-- : elt++);
2810 if (data.max_pixmap_height)
2812 int height = data.new_ascent + data.new_descent;
2813 int pix_ascent, pix_descent;
2815 pix_descent = data.max_pixmap_height * data.new_descent / height;
2816 pix_ascent = data.max_pixmap_height - pix_descent;
2817 data.new_ascent = max (data.new_ascent, pix_ascent);
2818 data.new_descent = max (data.new_descent, pix_descent);
2821 dl->ascent = data.new_ascent;
2822 dl->descent = data.new_descent;
2827 /* Add a blank to a margin display block. */
2830 add_margin_blank (struct display_line *dl, struct display_block *db,
2831 struct window *w, int xpos, int width, int side)
2835 rb.findex = (side == LEFT_GLYPHS
2836 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2837 : get_builtin_face_cache_index (w, Vright_margin_face));
2842 rb.type = RUNE_BLANK;
2843 rb.cursor_type = CURSOR_OFF;
2845 Dynarr_add (db->runes, rb);
2848 /* Display glyphs in the left outside margin, left inside margin and
2849 left whitespace area. */
2852 create_left_glyph_block (struct window *w, struct display_line *dl,
2857 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2859 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2860 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2861 int left_in_start = dl->bounds.left_in;
2862 int left_in_end = dl->bounds.left_in + overlay_width;
2864 struct display_block *odb, *idb;
2866 XSETWINDOW (window, w);
2868 /* We have to add the glyphs to the line in the order outside,
2869 inside, whitespace. However the precedence dictates that we
2870 determine how many will fit in the reverse order. */
2872 /* Determine how many whitespace glyphs we can display and where
2873 they should start. */
2874 white_in_start = dl->bounds.left_white;
2875 white_out_start = left_in_start;
2876 white_out_cnt = white_in_cnt = 0;
2879 while (elt < Dynarr_length (dl->left_glyphs))
2881 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2883 if (NILP (gb->extent))
2884 abort (); /* these should have been handled in add_glyph_rune */
2886 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2890 width = glyph_width (gb->glyph, window);
2892 if (white_in_start - width >= left_in_end)
2895 white_in_start -= width;
2899 else if (use_overflow
2900 && (white_out_start - width > dl->bounds.left_out))
2903 white_out_start -= width;
2914 /* Determine how many inside margin glyphs we can display and where
2915 they should start. The inside margin glyphs get whatever space
2916 is left after the whitespace glyphs have been displayed. These
2917 are tricky to calculate since if we decide to use the overflow
2918 area we basically have to start over. So for these we build up a
2919 list of just the inside margin glyphs and manipulate it to
2920 determine the needed info. */
2922 glyph_block_dynarr *ib;
2923 int avail_in, avail_out;
2926 int used_in, used_out;
2929 used_in = used_out = 0;
2930 ib = Dynarr_new (glyph_block);
2931 while (elt < Dynarr_length (dl->left_glyphs))
2933 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2935 if (NILP (gb->extent))
2936 abort (); /* these should have been handled in add_glyph_rune */
2938 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2941 gb->width = glyph_width (gb->glyph, window);
2942 used_in += gb->width;
2943 Dynarr_add (ib, *gb);
2953 avail_in = white_in_start - left_in_end;
2961 avail_out = white_out_start - dl->bounds.left_out;
2964 while (!done && marker < Dynarr_length (ib))
2966 int width = Dynarr_atp (ib, marker)->width;
2968 /* If everything now fits in the available inside margin
2969 space, we're done. */
2970 if (used_in <= avail_in)
2974 /* Otherwise see if we have room to move a glyph to the
2976 if (used_out + width <= avail_out)
2989 /* At this point we now know that everything from marker on goes in
2990 the inside margin and everything before it goes in the outside
2991 margin. The stuff going into the outside margin is guaranteed
2992 to fit, but we may have to trim some stuff from the inside. */
2994 in_in_end = left_in_end;
2995 in_out_start = white_out_start;
2996 in_out_cnt = in_in_cnt = 0;
3000 while (elt < Dynarr_length (dl->left_glyphs))
3002 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3004 if (NILP (gb->extent))
3005 abort (); /* these should have been handled in add_glyph_rune */
3007 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3010 int width = glyph_width (gb->glyph, window);
3015 in_out_start -= width;
3020 else if (in_in_end + width < white_in_start)
3035 /* Determine how many outside margin glyphs we can display. They
3036 always start at the left outside margin and can only use the
3037 outside margin space. */
3038 out_end = dl->bounds.left_out;
3042 while (elt < Dynarr_length (dl->left_glyphs))
3044 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3046 if (NILP (gb->extent))
3047 abort (); /* these should have been handled in add_glyph_rune */
3049 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3052 int width = glyph_width (gb->glyph, window);
3054 if (out_end + width <= in_out_start)
3068 /* Now that we know where everything goes, we add the glyphs as
3069 runes to the appropriate display blocks. */
3070 if (out_cnt || in_out_cnt || white_out_cnt)
3072 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3073 odb->start_pos = dl->bounds.left_out;
3074 /* #### We should stop adding a blank to account for the space
3075 between the end of the glyphs and the margin and instead set
3076 this accordingly. */
3077 odb->end_pos = dl->bounds.left_in;
3078 Dynarr_reset (odb->runes);
3083 if (in_in_cnt || white_in_cnt)
3085 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3086 idb->start_pos = dl->bounds.left_in;
3087 /* #### See above comment for odb->end_pos */
3088 idb->end_pos = dl->bounds.left_white;
3089 Dynarr_reset (idb->runes);
3094 /* First add the outside margin glyphs. */
3096 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3097 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3099 end_xpos = dl->bounds.left_out;
3101 /* There may be blank space between the outside margin glyphs and
3102 the inside margin glyphs. If so, add a blank. */
3103 if (in_out_cnt && (in_out_start - end_xpos))
3105 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3109 /* Next add the inside margin glyphs which are actually in the
3113 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3114 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3117 /* If we didn't add any inside margin glyphs to the outside margin,
3118 but are adding whitespace glyphs, then we need to add a blank
3120 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3122 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3126 /* Next add the whitespace margin glyphs which are actually in the
3130 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3131 GL_WHITESPACE, LEFT_GLYPHS, window);
3134 /* We take care of clearing between the end of the glyphs and the
3135 start of the inside margin for lines which have glyphs. */
3136 if (odb && (left_in_start - end_xpos))
3138 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3142 /* Next add the inside margin glyphs which are actually in the
3146 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3147 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3150 end_xpos = left_in_end;
3152 /* Make sure that the area between the end of the inside margin
3153 glyphs and the whitespace glyphs is cleared. */
3154 if (idb && (white_in_start - end_xpos > 0))
3156 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3160 /* Next add the whitespace margin glyphs which are actually in the
3164 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3165 LEFT_GLYPHS, window);
3168 /* Whitespace glyphs always end right next to the text block so
3169 there is nothing we have to make sure is cleared after them. */
3172 /* Display glyphs in the right outside margin, right inside margin and
3173 right whitespace area. */
3176 create_right_glyph_block (struct window *w, struct display_line *dl)
3180 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3182 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3183 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3185 struct display_block *odb, *idb;
3187 XSETWINDOW (window, w);
3189 /* We have to add the glyphs to the line in the order outside,
3190 inside, whitespace. However the precedence dictates that we
3191 determine how many will fit in the reverse order. */
3193 /* Determine how many whitespace glyphs we can display and where
3194 they should start. */
3195 white_in_end = dl->bounds.right_white;
3196 white_out_end = dl->bounds.right_in;
3197 white_out_cnt = white_in_cnt = 0;
3200 while (elt < Dynarr_length (dl->right_glyphs))
3202 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3204 if (NILP (gb->extent))
3205 abort (); /* these should have been handled in add_glyph_rune */
3207 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3209 int width = glyph_width (gb->glyph, window);
3211 if (white_in_end + width <= dl->bounds.right_in)
3214 white_in_end += width;
3218 else if (use_overflow
3219 && (white_out_end + width <= dl->bounds.right_out))
3222 white_out_end += width;
3233 /* Determine how many inside margin glyphs we can display and where
3234 they should start. The inside margin glyphs get whatever space
3235 is left after the whitespace glyphs have been displayed. These
3236 are tricky to calculate since if we decide to use the overflow
3237 area we basically have to start over. So for these we build up a
3238 list of just the inside margin glyphs and manipulate it to
3239 determine the needed info. */
3241 glyph_block_dynarr *ib;
3242 int avail_in, avail_out;
3245 int used_in, used_out;
3248 used_in = used_out = 0;
3249 ib = Dynarr_new (glyph_block);
3250 while (elt < Dynarr_length (dl->right_glyphs))
3252 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3254 if (NILP (gb->extent))
3255 abort (); /* these should have been handled in add_glyph_rune */
3257 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3259 gb->width = glyph_width (gb->glyph, window);
3260 used_in += gb->width;
3261 Dynarr_add (ib, *gb);
3270 avail_in = dl->bounds.right_in - white_in_end;
3275 avail_out = dl->bounds.right_out - white_out_end;
3278 while (!done && marker < Dynarr_length (ib))
3280 int width = Dynarr_atp (ib, marker)->width;
3282 /* If everything now fits in the available inside margin
3283 space, we're done. */
3284 if (used_in <= avail_in)
3288 /* Otherwise see if we have room to move a glyph to the
3290 if (used_out + width <= avail_out)
3303 /* At this point we now know that everything from marker on goes in
3304 the inside margin and everything before it goes in the outside
3305 margin. The stuff going into the outside margin is guaranteed
3306 to fit, but we may have to trim some stuff from the inside. */
3308 in_in_start = dl->bounds.right_in;
3309 in_out_end = dl->bounds.right_in;
3310 in_out_cnt = in_in_cnt = 0;
3314 while (elt < Dynarr_length (dl->right_glyphs))
3316 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3318 if (NILP (gb->extent))
3319 abort (); /* these should have been handled in add_glyph_rune */
3321 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3323 int width = glyph_width (gb->glyph, window);
3328 in_out_end += width;
3333 else if (in_in_start - width >= white_in_end)
3336 in_in_start -= width;
3348 /* Determine how many outside margin glyphs we can display. They
3349 always start at the right outside margin and can only use the
3350 outside margin space. */
3351 out_start = dl->bounds.right_out;
3355 while (elt < Dynarr_length (dl->right_glyphs))
3357 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3359 if (NILP (gb->extent))
3360 abort (); /* these should have been handled in add_glyph_rune */
3362 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3364 int width = glyph_width (gb->glyph, window);
3366 if (out_start - width >= in_out_end)
3380 /* Now that we now where everything goes, we add the glyphs as runes
3381 to the appropriate display blocks. */
3382 if (out_cnt || in_out_cnt || white_out_cnt)
3384 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3385 /* #### See comments before odb->start_pos init in
3386 create_left_glyph_block */
3387 odb->start_pos = dl->bounds.right_in;
3388 odb->end_pos = dl->bounds.right_out;
3389 Dynarr_reset (odb->runes);
3394 if (in_in_cnt || white_in_cnt)
3396 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3397 idb->start_pos = dl->bounds.right_white;
3398 /* #### See comments before odb->start_pos init in
3399 create_left_glyph_block */
3400 idb->end_pos = dl->bounds.right_in;
3401 Dynarr_reset (idb->runes);
3406 /* First add the whitespace margin glyphs which are actually in the
3410 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3411 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3415 end_xpos = dl->bounds.right_white;
3417 /* Make sure that the area between the end of the whitespace glyphs
3418 and the inside margin glyphs is cleared. */
3419 if (in_in_cnt && (in_in_start - end_xpos))
3421 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3425 /* Next add the inside margin glyphs which are actually in the
3429 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3430 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3433 /* If we didn't add any inside margin glyphs then make sure the rest
3434 of the inside margin area gets cleared. */
3435 if (idb && (dl->bounds.right_in - end_xpos))
3437 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3441 /* Next add any whitespace glyphs in the outside margin. */
3444 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3445 GL_WHITESPACE, RIGHT_GLYPHS, window);
3448 end_xpos = dl->bounds.right_in;
3450 /* Next add any inside margin glyphs in the outside margin. */
3453 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3454 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3457 /* There may be space between any whitespace or inside margin glyphs
3458 in the outside margin and the actual outside margin glyphs. */
3459 if (odb && (out_start - end_xpos))
3461 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3465 /* Finally, add the outside margin glyphs. */
3468 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3469 RIGHT_GLYPHS, window);
3474 /***************************************************************************/
3476 /* modeline routines */
3478 /***************************************************************************/
3480 /* This function is also used in frame.c by `generate_title_string' */
3482 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3483 struct window *w, struct display_line *dl,
3484 struct display_block *db, face_index findex,
3485 int min_pixpos, int max_pixpos, int type)
3487 struct frame *f = XFRAME (w->frame);
3488 struct device *d = XDEVICE (f->device);
3492 Charcount offset = 0;
3498 data.findex = findex;
3499 data.pixpos = min_pixpos;
3500 data.max_pixpos = max_pixpos;
3501 data.cursor_type = NO_CURSOR;
3502 data.last_charset = Qunbound;
3503 data.last_findex = DEFAULT_INDEX;
3504 data.result_str = result_str;
3505 data.is_modeline = 1;
3507 XSETWINDOW (data.window, w);
3509 Dynarr_reset (formatted_string_extent_dynarr);
3510 Dynarr_reset (formatted_string_extent_start_dynarr);
3511 Dynarr_reset (formatted_string_extent_end_dynarr);
3513 /* result_str is nil when we're building a frame or icon title. Otherwise,
3514 we're building a modeline, so the offset starts at the modeline
3515 horizontal scrolling amount */
3516 if (! NILP (result_str))
3517 offset = w->modeline_hscroll;
3518 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3519 max_pixpos - min_pixpos, findex, type, &offset,
3522 if (Dynarr_length (db->runes))
3525 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3526 c_pixpos = rb->xpos + rb->width;
3529 c_pixpos = min_pixpos;
3531 /* If we don't reach the right side of the window, add a blank rune
3532 to make up the difference. This usually only occurs if the
3533 modeline face is using a proportional width font or a fixed width
3534 font of a different size from the default face font. */
3536 if (c_pixpos < max_pixpos)
3538 data.pixpos = c_pixpos;
3539 data.blank_width = max_pixpos - data.pixpos;
3541 add_blank_rune (&data, NULL, 0);
3544 /* Now create the result string and frob the extents into it. */
3545 if (!NILP (result_str))
3550 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3552 in_modeline_generation = 1;
3554 detach_all_extents (result_str);
3555 resize_string (XSTRING (result_str), -1,
3556 data.bytepos - XSTRING_LENGTH (result_str));
3558 strdata = XSTRING_DATA (result_str);
3560 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3562 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3564 len += (set_charptr_emchar
3566 CHARC_TO_CHAR (Dynarr_atp (db->runes,
3567 elt)->object.cglyph)));
3571 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3574 Lisp_Object extent = Qnil;
3577 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3578 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3581 child = Fmake_extent (Qnil, Qnil, result_str);
3582 Fputhash (extent, child, buf->modeline_extent_table);
3584 Fset_extent_parent (child, extent);
3585 set_extent_endpoints
3587 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3588 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3592 in_modeline_generation = 0;
3596 /* Ensure that the given display line DL accurately represents the
3597 modeline for the given window. */
3599 generate_modeline (struct window *w, struct display_line *dl, int type)
3601 struct buffer *b = XBUFFER (w->buffer);
3602 struct frame *f = XFRAME (w->frame);
3603 struct device *d = XDEVICE (f->device);
3605 /* Unlike display line and rune pointers, this one can't change underneath
3607 struct display_block *db = get_display_block_from_line (dl, TEXT);
3608 int max_pixpos, min_pixpos, ypos_adj;
3609 Lisp_Object font_inst;
3611 /* This will actually determine incorrect inside boundaries for the
3612 modeline since it ignores the margins. However being aware of this fact
3613 we never use those values anywhere so it doesn't matter. */
3614 dl->bounds = calculate_display_line_boundaries (w, 1);
3616 /* We are generating a modeline. */
3618 dl->cursor_elt = -1;
3620 /* Reset the runes on the modeline. */
3621 Dynarr_reset (db->runes);
3623 if (!WINDOW_HAS_MODELINE_P (w))
3627 /* If there is a horizontal scrollbar, don't add anything. */
3628 if (window_scrollbar_height (w))
3631 dl->ascent = DEVMETH (d, divider_height, ());
3633 /* The modeline is at the bottom of the gutters. */
3634 dl->ypos = WINDOW_BOTTOM (w);
3636 rb.findex = MODELINE_INDEX;
3637 rb.xpos = dl->bounds.left_out;
3638 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3641 rb.type = RUNE_HLINE;
3642 rb.object.hline.thickness = 1;
3643 rb.object.hline.yoffset = 0;
3644 rb.cursor_type = NO_CURSOR;
3646 if (!EQ (Qzero, w->modeline_shadow_thickness)
3649 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3651 dl->ypos -= shadow_thickness;
3652 rb.xpos += shadow_thickness;
3653 rb.width -= 2 * shadow_thickness;
3656 Dynarr_add (db->runes, rb);
3660 /* !!#### not right; needs to compute the max height of
3662 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3664 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3665 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3667 min_pixpos = dl->bounds.left_out;
3668 max_pixpos = dl->bounds.right_out;
3670 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3672 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3674 ypos_adj = shadow_thickness;
3675 min_pixpos += shadow_thickness;
3676 max_pixpos -= shadow_thickness;
3681 generate_formatted_string_db (b->modeline_format,
3682 b->generated_modeline_string, w, dl, db,
3683 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3685 /* The modeline is at the bottom of the gutters. We have to wait to
3686 set this until we've generated the modeline in order to account
3687 for any embedded faces. */
3688 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3692 add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str,
3693 Charcount pos, Charcount min_pos, Charcount max_pos)
3695 /* This function has been Mule-ized. */
3697 const Bufbyte *cur_pos = str;
3698 struct display_block *db = data->db;
3700 data->blank_width = space_width (XWINDOW (data->window));
3701 while (Dynarr_length (db->runes) < pos)
3702 add_blank_rune (data, NULL, 0);
3704 end = (Dynarr_length (db->runes) +
3705 bytecount_to_charcount (str, strlen ((const char *) str)));
3707 end = min (max_pos, end);
3709 while (pos < end && *cur_pos)
3711 const Bufbyte *old_cur_pos = cur_pos;
3714 data->ch = charptr_emchar (cur_pos);
3715 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3716 INC_CHARPTR (cur_pos);
3720 data->modeline_charpos++;
3721 data->bytepos += cur_pos - old_cur_pos;
3725 while (Dynarr_length (db->runes) < min_pos &&
3726 (data->pixpos + data->blank_width <= data->max_pixpos))
3727 add_blank_rune (data, NULL, 0);
3729 return Dynarr_length (db->runes);
3732 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3733 modeline extents. */
3735 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3736 Charcount pos, Charcount min_pos,
3737 Charcount max_pos, Lisp_Object extent)
3739 /* This function has been Mule-ized. */
3741 struct display_block *db = data->db;
3742 struct glyph_block gb;
3744 data->blank_width = space_width (XWINDOW (data->window));
3745 while (Dynarr_length (db->runes) < pos)
3746 add_blank_rune (data, NULL, 0);
3748 end = Dynarr_length (db->runes) + 1;
3750 end = min (max_pos, end);
3754 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3757 while (Dynarr_length (db->runes) < pos &&
3758 (data->pixpos + data->blank_width <= data->max_pixpos))
3759 add_blank_rune (data, NULL, 0);
3761 return Dynarr_length (db->runes);
3764 /* If max_pos is == -1, it is considered to be infinite. The same is
3765 true of max_pixsize. */
3766 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3767 if (Dynarr_length (data->db->runes)) \
3768 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3772 /* Note that this function does "positions" in terms of characters and
3773 not in terms of columns. This is necessary to make the formatting
3774 work correctly when proportional width fonts are used in the
3777 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3778 Charcount min_pos, Charcount max_pos,
3779 Lisp_Object elt, int depth, int max_pixsize,
3780 face_index findex, int type, Charcount *offset,
3781 Lisp_Object cur_ext)
3783 /* This function has been Mule-ized. */
3784 /* #### The other losing things in this function are:
3786 -- C zero-terminated-string lossage.
3787 -- Non-printable characters should be converted into something
3788 appropriate (e.g. ^F) instead of blindly being printed anyway.
3799 /* A string. Add to the display line and check for %-constructs
3802 Bufbyte *this = XSTRING_DATA (elt);
3804 while ((pos < max_pos || max_pos == -1) && *this)
3806 Bufbyte *last = this;
3808 while (*this && *this != '%')
3813 /* No %-construct */
3815 bytecount_to_charcount (last, this - last);
3817 if (size <= *offset)
3821 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
3822 min (pos + size - *offset, max_pos));
3823 const Bufbyte *tmp_last = charptr_n_addr (last, *offset);
3825 pos = add_string_to_fstring_db_runes (data, tmp_last,
3830 else /* *this == '%' */
3832 Charcount spec_width = 0;
3834 this++; /* skip over '%' */
3836 /* We can't allow -ve args due to the "%-" construct.
3837 * Argument specifies minwidth but not maxwidth
3838 * (maxwidth can be specified by
3839 * (<negative-number> . <stuff>) modeline elements)
3841 while (isdigit (*this))
3843 spec_width = spec_width * 10 + (*this - '0');
3850 pos = generate_fstring_runes (w, data, pos, spec_width,
3851 max_pos, Vglobal_mode_string,
3852 depth, max_pixsize, findex,
3853 type, offset, cur_ext);
3855 else if (*this == '-')
3857 Charcount num_to_add;
3859 if (max_pixsize < 0)
3861 else if (max_pos != -1)
3862 num_to_add = max_pos - pos;
3868 SET_CURRENT_MODE_CHARS_PIXSIZE;
3871 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3874 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3878 while (num_to_add--)
3879 pos = add_string_to_fstring_db_runes
3880 (data, (const Bufbyte *) "-", pos, pos, max_pos);
3882 else if (*this != 0)
3884 Emchar ch = charptr_emchar (this);
3888 decode_mode_spec (w, ch, type);
3890 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3891 size = bytecount_to_charcount
3892 /* Skip the null character added by `decode_mode_spec' */
3893 (str, Dynarr_length (mode_spec_bufbyte_string)) - 1;
3895 if (size <= *offset)
3899 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3901 /* #### NOTE: I don't understand why a tmp_max is not
3902 computed and used here as in the plain string case
3904 pos = add_string_to_fstring_db_runes (data, tmp_str,
3911 /* NOT this++. There could be any sort of character at
3912 the current position. */
3916 if (max_pixsize > 0)
3919 SET_CURRENT_MODE_CHARS_PIXSIZE;
3921 if (cur_pixsize >= max_pixsize)
3926 else if (SYMBOLP (elt))
3928 /* A symbol: process the value of the symbol recursively
3929 as if it appeared here directly. */
3930 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3932 if (!UNBOUNDP (tem))
3934 /* If value is a string, output that string literally:
3935 don't check for % within it. */
3938 Bufbyte *str = XSTRING_DATA (tem);
3939 Charcount size = XSTRING_CHAR_LENGTH (tem);
3941 if (size <= *offset)
3945 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3947 /* #### NOTE: I don't understand why a tmp_max is not
3948 computed and used here as in the plain string case
3950 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
3955 /* Give up right away for nil or t. */
3956 else if (!EQ (tem, elt))
3963 else if (GENERIC_SPECIFIERP (elt))
3965 Lisp_Object window, tem;
3966 XSETWINDOW (window, w);
3967 tem = specifier_instance_no_quit (elt, Qunbound, window,
3968 ERROR_ME_NOT, 0, Qzero);
3969 if (!UNBOUNDP (tem))
3975 else if (CONSP (elt))
3977 /* A cons cell: four distinct cases.
3978 * - If first element is a string or a cons, process all the elements
3979 * and effectively concatenate them.
3980 * - If first element is a negative number, truncate displaying cdr to
3981 * at most that many characters. If positive, pad (with spaces)
3982 * to at least that many characters.
3983 * - If first element is another symbol, process the cadr or caddr
3984 * recursively according to whether the symbol's value is non-nil or
3986 * - If first element is an extent, process the cdr recursively
3987 * and handle the extent's face.
3990 Lisp_Object car, tem;
3999 tem = symbol_value_in_buffer (car, w->buffer);
4000 /* elt is now the cdr, and we know it is a cons cell.
4001 Use its car if CAR has a non-nil value. */
4002 if (!UNBOUNDP (tem))
4010 /* Symbol's value is nil (or symbol is unbound)
4011 * Get the cddr of the original list
4012 * and if possible find the caddr and use that.
4017 else if (!CONSP (elt))
4025 else if (INTP (car))
4027 Charcount lim = XINT (car);
4033 /* Negative int means reduce maximum width.
4034 * DO NOT change MIN_PIXPOS here!
4035 * (20 -10 . foo) should truncate foo to 10 col
4036 * and then pad to 20.
4039 max_pos = pos - lim;
4041 max_pos = min (max_pos, pos - lim);
4045 /* Padding specified. Don't let it be more than
4049 if (max_pos != -1 && lim > max_pos)
4051 /* If that's more padding than already wanted, queue it.
4052 * But don't reduce padding already specified even if
4053 * that is beyond the current truncation point.
4060 else if (STRINGP (car) || CONSP (car))
4064 /* LIMIT is to protect against circular lists. */
4065 while (CONSP (elt) && --limit > 0
4066 && (pos < max_pos || max_pos == -1))
4068 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4069 XCAR (elt), depth, max_pixsize,
4070 findex, type, offset, cur_ext);
4074 else if (EXTENTP (car))
4076 struct extent *ext = XEXTENT (car);
4078 if (EXTENT_LIVE_P (ext))
4080 face_index old_findex = data->findex;
4082 Lisp_Object font_inst;
4083 face_index new_findex;
4084 Bytecount start = data->bytepos;
4086 face = extent_face (ext);
4089 /* #### needs to merge faces, sigh */
4090 /* #### needs to handle list of faces */
4091 new_findex = get_builtin_face_cache_index (w, face);
4092 /* !!#### not right; needs to compute the max height of
4094 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
4097 data->dl->ascent = max (data->dl->ascent,
4098 XFONT_INSTANCE (font_inst)->ascent);
4099 data->dl->descent = max (data->dl->descent,
4100 XFONT_INSTANCE (font_inst)->
4104 new_findex = old_findex;
4106 data->findex = new_findex;
4107 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4108 XCDR (elt), depth - 1,
4109 max_pixsize, new_findex, type,
4111 data->findex = old_findex;
4112 Dynarr_add (formatted_string_extent_dynarr, ext);
4113 Dynarr_add (formatted_string_extent_start_dynarr, start);
4114 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4118 else if (GLYPHP (elt))
4120 /* Glyphs are considered as one character with respect to the modeline
4121 horizontal scrolling facility. -- dv */
4125 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos,
4132 char *str = GETTEXT ("*invalid*");
4133 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */
4135 if (size <= *offset)
4139 const Bufbyte *tmp_str =
4140 charptr_n_addr ((const Bufbyte *) str, *offset);
4142 /* #### NOTE: I don't understand why a tmp_max is not computed and
4143 used here as in the plain string case above. -- dv */
4144 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
4153 add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos,
4160 /* Update just the modeline. Assumes the desired display structs. If
4161 they do not have a modeline block, it does nothing. */
4163 regenerate_modeline (struct window *w)
4165 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4167 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4171 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4172 redisplay_update_line (w, 0, 0, 0);
4176 /* Make sure that modeline display line is present in the given
4177 display structs if the window has a modeline and update that
4178 line. Returns true if a modeline was needed. */
4180 ensure_modeline_generated (struct window *w, int type)
4184 /* minibuffer windows don't have modelines */
4185 if (MINI_WINDOW_P (w))
4187 /* windows which haven't had it turned off do */
4188 else if (WINDOW_HAS_MODELINE_P (w))
4190 /* windows which have it turned off don't have a divider if there is
4191 a horizontal scrollbar */
4192 else if (window_scrollbar_height (w))
4194 /* and in this case there is none */
4200 display_line_dynarr *dla;
4202 dla = window_display_lines (w, type);
4204 /* We don't care if there is a display line which is not
4205 currently a modeline because it is definitely going to become
4206 one if we have gotten to this point. */
4207 if (Dynarr_length (dla) == 0)
4209 if (Dynarr_largest (dla) > 0)
4211 struct display_line *mlp = Dynarr_atp (dla, 0);
4212 Dynarr_add (dla, *mlp);
4216 struct display_line modeline;
4218 Dynarr_add (dla, modeline);
4222 /* If we're adding a new place marker go ahead and generate the
4223 modeline so that it is available for use by
4224 window_modeline_height. */
4225 generate_modeline (w, Dynarr_atp (dla, 0), type);
4228 return need_modeline;
4231 /* #### Kludge or not a kludge. I tend towards the former. */
4233 real_current_modeline_height (struct window *w)
4235 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4236 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4238 if (ensure_modeline_generated (w, CMOTION_DISP))
4240 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4242 if (Dynarr_length (dla))
4244 if (Dynarr_atp (dla, 0)->modeline)
4245 return (Dynarr_atp (dla, 0)->ascent +
4246 Dynarr_atp (dla, 0)->descent);
4253 /***************************************************************************/
4255 /* displayable string routines */
4257 /***************************************************************************/
4259 /* Given a position for a string in a window, ensure that the given
4260 display line DL accurately represents the text on a line starting
4261 at the given position.
4263 Yes, this is duplicating the code of create_text_block, but it
4264 looked just too hard to change create_text_block to handle strings
4265 *and* buffers. We already make a distinction between the two
4266 elsewhere in the code so I think unifying them would require a
4267 complete MULE rewrite. Besides, the other distinction is that these
4268 functions cover text that the user *cannot edit* so we can remove
4269 everything to do with cursors, minibuffers etc. Eventually the
4270 modeline routines should be modified to use this code as it copes
4271 with many more types of display situation. */
4274 create_string_text_block (struct window *w, Lisp_Object disp_string,
4275 struct display_line *dl,
4277 prop_block_dynarr **prop,
4278 face_index default_face)
4280 struct frame *f = XFRAME (w->frame);
4281 /* Note that a lot of the buffer controlled stuff has been left in
4282 because you might well want to make use of it (selective display
4283 etc), its just the buffer text that we do not use. However, it
4284 seems to be possible for buffer to be nil sometimes so protect
4285 against this case. */
4286 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
4287 struct device *d = XDEVICE (f->device);
4288 Lisp_String* s = XSTRING (disp_string);
4290 /* we're working with these a lot so precalculate them */
4291 Bytecount slen = XSTRING_LENGTH (disp_string);
4292 Bytecount bi_string_zv = slen;
4293 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4297 int truncate_win = b ? window_truncation_on (w) : 0;
4298 int end_glyph_width = 0;
4300 /* We're going to ditch selective display for static text, it's an
4301 FSF thing and invisible extents are the way to go here.
4302 Implementing it also relies on a number of buffer-specific
4303 functions that we don't have the luxury of being able to use
4306 /* The variable ctl-arrow allows the user to specify what characters
4307 can actually be displayed and which octal should be used for.
4308 #### This variable should probably have some rethought done to
4311 #### It would also be really nice if you could specify that
4312 the characters come out in hex instead of in octal. Mule
4313 does that by adding a ctl-hexa variable similar to ctl-arrow,
4314 but that's bogus -- we need a more general solution. I
4315 think you need to extend the concept of display tables
4316 into a more general conversion mechanism. Ideally you
4317 could specify a Lisp function that converts characters,
4318 but this violates the Second Golden Rule and besides would
4319 make things way way way way slow.
4321 So instead, we extend the display-table concept, which was
4322 historically limited to 256-byte vectors, to one of the
4325 a) A 256-entry vector, for backward compatibility;
4326 b) char-table, mapping characters to values;
4327 c) range-table, mapping ranges of characters to values;
4328 d) a list of the above.
4330 The (d) option allows you to specify multiple display tables
4331 instead of just one. Each display table can specify conversions
4332 for some characters and leave others unchanged. The way the
4333 character gets displayed is determined by the first display table
4334 with a binding for that character. This way, you could call a
4335 function `enable-hex-display' that adds a hex display-table to
4336 the list of display tables for the current buffer.
4338 #### ...not yet implemented... Also, we extend the concept of
4339 "mapping" to include a printf-like spec. Thus you can make all
4340 extended characters show up as hex with a display table like
4343 #s(range-table data ((256 524288) (format "%x")))
4345 Since more than one display table is possible, you have
4346 great flexibility in mapping ranges of characters. */
4347 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4348 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4349 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4350 ? 255 : 160)) : 255;
4352 Lisp_Object face_dt, window_dt;
4354 /* The text display block for this display line. */
4355 struct display_block *db = get_display_block_from_line (dl, TEXT);
4357 /* The first time through the main loop we need to force the glyph
4358 data to be updated. */
4361 /* Apparently the new extent_fragment_update returns an end position
4362 equal to the position passed in if there are no more runs to be
4364 int no_more_frags = 0;
4366 dl->used_prop_data = 0;
4368 dl->line_continuation = 0;
4370 /* set up faces to use for clearing areas, used by
4371 output_display_line */
4372 dl->default_findex = default_face;
4375 dl->left_margin_findex = default_face;
4376 dl->right_margin_findex = default_face;
4380 dl->left_margin_findex =
4381 get_builtin_face_cache_index (w, Vleft_margin_face);
4382 dl->right_margin_findex =
4383 get_builtin_face_cache_index (w, Vright_margin_face);
4387 data.ef = extent_fragment_new (disp_string, f);
4389 /* These values are used by all of the rune addition routines. We add
4390 them to this structure for ease of passing. */
4392 XSETWINDOW (data.window, w);
4396 data.bi_bufpos = bi_start_pos;
4397 data.pixpos = dl->bounds.left_in;
4398 data.last_charset = Qunbound;
4399 data.last_findex = default_face;
4400 data.result_str = Qnil;
4401 data.string = disp_string;
4403 /* Set the right boundary adjusting it to take into account any end
4404 glyph. Save the width of the end glyph for later use. */
4405 data.max_pixpos = dl->bounds.right_in;
4408 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
4410 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
4412 data.max_pixpos -= end_glyph_width;
4414 data.cursor_type = NO_CURSOR;
4418 /* I don't think we want this, string areas should not scroll with
4420 data.start_col = w->hscroll;
4421 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4423 data.bi_start_col_enabled = 0;
4424 data.hscroll_glyph_width_adjust = 0;
4426 /* We regenerate the line from the very beginning. */
4427 Dynarr_reset (db->runes);
4429 /* Why is this less than or equal and not just less than? If the
4430 starting position is already equal to the maximum we can't add
4431 anything else, right? Wrong. We might still have a newline to
4432 add. A newline can use the room allocated for an end glyph since
4433 if we add it we know we aren't going to be adding any end
4436 /* #### Chuck -- I think this condition should be while (1).
4437 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4438 and the begin-glyph ends exactly at the end of the window, the
4439 end-glyph and text might not be displayed. while (1) ensures
4440 that the loop terminates only when either (a) there is
4441 propagation data or (b) the end-of-line or end-of-buffer is hit.
4443 #### Also I think you need to ensure that the operation
4444 "add begin glyphs; add end glyphs; add text" is atomic and
4445 can't get interrupted in the middle. If you run off the end
4446 of the line during that operation, then you keep accumulating
4447 propagation data until you're done. Otherwise, if the (e.g.)
4448 there's a begin glyph at a particular position and attempting
4449 to display that glyph results in window-end being hit and
4450 propagation data being generated, then the character at that
4451 position won't be displayed.
4453 #### See also the comment after the end of this loop, below.
4455 while (data.pixpos <= data.max_pixpos)
4457 /* #### This check probably should not be necessary. */
4458 if (data.bi_bufpos > bi_string_zv)
4460 /* #### urk! More of this lossage! */
4465 /* Check for face changes. */
4466 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
4468 /* Now compute the face and begin/end-glyph information. */
4470 /* Remember that the extent-fragment routines deal in Bytind's. */
4471 extent_fragment_update (w, data.ef, data.bi_bufpos);
4472 /* This is somewhat cheesy but the alternative is to
4473 propagate default_face into extent_fragment_update. */
4474 if (data.findex == DEFAULT_INDEX)
4475 data.findex = default_face;
4477 get_display_tables (w, data.findex, &face_dt, &window_dt);
4479 if (data.bi_bufpos == data.ef->end)
4484 /* Determine what is next to be displayed. We first handle any
4485 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4486 display then we determine what to do based on the character at the
4487 current buffer position. */
4489 /* If the current position is covered by an invisible extent, do
4490 nothing (except maybe add some ellipses).
4492 #### The behavior of begin and end-glyphs at the edge of an
4493 invisible extent should be investigated further. This is
4494 fairly low priority though. */
4495 if (data.ef->invisible)
4497 /* #### Chuck, perhaps you could look at this code? I don't
4498 really know what I'm doing. */
4501 Dynarr_free (*prop);
4505 /* The extent fragment code only sets this when we should
4506 really display the ellipses. It makes sure the ellipses
4507 don't get displayed more than once in a row. */
4508 if (data.ef->invisible_ellipses)
4510 struct glyph_block gb;
4512 data.ef->invisible_ellipses_already_displayed = 1;
4513 data.ef->invisible_ellipses = 0;
4515 gb.glyph = Vinvisible_text_glyph;
4516 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
4517 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
4518 /* Perhaps they shouldn't propagate if the very next thing
4519 is to display a newline (for compatibility with
4520 selective-display-ellipses)? Maybe that's too
4526 /* #### What if we we're dealing with a display table? */
4530 if (data.bi_bufpos == bi_string_zv)
4533 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4536 /* If there is propagation data, then it represents the current
4537 buffer position being displayed. Add them and advance the
4538 position counter. This might also add the minibuffer
4542 dl->used_prop_data = 1;
4543 *prop = add_propagation_runes (prop, &data);
4546 goto done; /* gee, a really narrow window */
4547 else if (data.bi_bufpos == bi_string_zv)
4549 else if (data.bi_bufpos < 0)
4550 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4553 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4556 /* If there are end glyphs, add them to the line. These are
4557 the end glyphs for the previous run of text. We add them
4558 here rather than doing them at the end of handling the
4559 previous run so that glyphs at the beginning and end of
4560 a line are handled correctly. */
4561 else if (Dynarr_length (data.ef->end_glyphs) > 0)
4563 *prop = add_glyph_runes (&data, END_GLYPHS);
4568 /* If there are begin glyphs, add them to the line. */
4569 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
4571 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
4576 /* If at end-of-buffer, we've already processed begin and
4577 end-glyphs at this point and there's no text to process,
4579 else if (data.bi_bufpos == bi_string_zv)
4584 Lisp_Object entry = Qnil;
4585 /* Get the character at the current buffer position. */
4586 data.ch = string_char (s, data.bi_bufpos);
4587 if (!NILP (face_dt) || !NILP (window_dt))
4588 entry = display_table_entry (data.ch, face_dt, window_dt);
4590 /* If there is a display table entry for it, hand it off to
4591 add_disp_table_entry_runes and let it worry about it. */
4592 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
4594 *prop = add_disp_table_entry_runes (&data, entry);
4600 /* Check if we have hit a newline character. If so, add a marker
4601 to the line and end this loop. */
4602 else if (data.ch == '\n')
4604 /* We aren't going to be adding an end glyph so give its
4605 space back in order to make sure that the cursor can
4607 data.max_pixpos += end_glyph_width;
4611 /* If the current character is considered to be printable, then
4613 else if (data.ch >= printable_min)
4615 *prop = add_emchar_rune (&data);
4620 /* If the current character is a tab, determine the next tab
4621 starting position and add a blank rune which extends from the
4622 current pixel position to that starting position. */
4623 else if (data.ch == '\t')
4625 int tab_start_pixpos = data.pixpos;
4630 if (data.start_col > 1)
4631 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
4634 next_tab_position (w, tab_start_pixpos,
4635 dl->bounds.left_in +
4636 data.hscroll_glyph_width_adjust);
4637 if (next_tab_start > data.max_pixpos)
4639 prop_width = next_tab_start - data.max_pixpos;
4640 next_tab_start = data.max_pixpos;
4642 data.blank_width = next_tab_start - data.pixpos;
4644 (next_tab_start - tab_start_pixpos) / space_width (w);
4646 *prop = add_blank_rune (&data, w, char_tab_width);
4648 /* add_blank_rune is only supposed to be called with
4649 sizes guaranteed to fit in the available space. */
4654 struct prop_block pb;
4655 *prop = Dynarr_new (prop_block);
4657 pb.type = PROP_BLANK;
4658 pb.data.p_blank.width = prop_width;
4659 pb.data.p_blank.findex = data.findex;
4660 Dynarr_add (*prop, pb);
4666 /* If character is a control character, pass it off to
4667 add_control_char_runes.
4669 The is_*() routines have undefined results on
4670 arguments outside of the range [-1, 255]. (This
4671 often bites people who carelessly use `char' instead
4672 of `unsigned char'.)
4674 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
4676 *prop = add_control_char_runes (&data, b);
4682 /* If the character is above the ASCII range and we have not
4683 already handled it, then print it as an octal number. */
4684 else if (data.ch >= 0200)
4686 *prop = add_octal_runes (&data);
4692 /* Assume the current character is considered to be printable,
4693 then just add it. */
4696 *prop = add_emchar_rune (&data);
4701 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4707 /* Determine the starting point of the next line if we did not hit the
4708 end of the buffer. */
4709 if (data.bi_bufpos < bi_string_zv)
4711 /* #### This check is not correct. If the line terminated
4712 due to a begin-glyph or end-glyph hitting window-end, then
4713 data.ch will not point to the character at data.bi_bufpos. If
4714 you make the two changes mentioned at the top of this loop,
4715 you should be able to say '(if (*prop))'. That should also
4716 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4719 /* The common case is that the line ended because we hit a newline.
4720 In that case, the next character is just the next buffer
4722 if (data.ch == '\n')
4724 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4727 /* Otherwise we have a buffer line which cannot fit on one display
4731 struct glyph_block gb;
4732 struct glyph_cachel *cachel;
4734 /* If the line is to be truncated then we actually have to look
4735 for the next newline. We also add the end-of-line glyph which
4736 we know will fit because we adjusted the right border before
4737 we starting laying out the line. */
4738 data.max_pixpos += end_glyph_width;
4739 data.findex = default_face;
4746 /* Now find the start of the next line. */
4747 bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
4749 data.cursor_type = NO_CURSOR;
4750 data.bi_bufpos = bi_pos;
4751 gb.glyph = Vtruncation_glyph;
4752 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
4756 /* The cursor can never be on the continuation glyph. */
4757 data.cursor_type = NO_CURSOR;
4759 /* data.bi_bufpos is already at the start of the next line. */
4761 dl->line_continuation = 1;
4762 gb.glyph = Vcontinuation_glyph;
4763 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
4766 if (end_glyph_width)
4767 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
4769 if (truncate_win && data.bi_bufpos == bi_string_zv)
4771 const Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
4773 if (charptr_emchar (endb) != '\n')
4775 /* #### Damn this losing shit. */
4781 else if (data.bi_bufpos == bi_string_zv)
4783 /* create_text_block () adds a bogus \n marker here which screws
4784 up subwindow display. Since we never have a cursor in the
4785 gutter we can safely ignore it. */
4787 /* Calculate left whitespace boundary. */
4791 /* Whitespace past a newline is considered right whitespace. */
4792 while (elt < Dynarr_length (db->runes))
4794 struct rune *rb = Dynarr_atp (db->runes, elt);
4796 if ((rb->type == RUNE_CHAR && CHARC_ASCII_EQ (rb->object.cglyph, ' '))
4797 || rb->type == RUNE_BLANK)
4799 dl->bounds.left_white += rb->width;
4803 elt = Dynarr_length (db->runes);
4807 /* Calculate right whitespace boundary. */
4809 int elt = Dynarr_length (db->runes) - 1;
4812 while (!done && elt >= 0)
4814 struct rune *rb = Dynarr_atp (db->runes, elt);
4816 if (!(rb->type == RUNE_CHAR && CHARC_IS_SPACE (rb->object.cglyph))
4817 && !rb->type == RUNE_BLANK)
4819 dl->bounds.right_white = rb->xpos + rb->width;
4827 /* The line is blank so everything is considered to be right
4830 dl->bounds.right_white = dl->bounds.left_in;
4833 /* Set the display blocks bounds. */
4834 db->start_pos = dl->bounds.left_in;
4835 if (Dynarr_length (db->runes))
4837 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4839 db->end_pos = rb->xpos + rb->width;
4842 db->end_pos = dl->bounds.right_white;
4844 /* update line height parameters */
4845 if (!data.new_ascent && !data.new_descent)
4847 /* We've got a blank line so initialize these values from the default
4849 default_face_font_info (data.window, &data.new_ascent,
4850 &data.new_descent, 0, 0, 0);
4853 if (data.max_pixmap_height)
4855 int height = data.new_ascent + data.new_descent;
4856 int pix_ascent, pix_descent;
4858 pix_descent = data.max_pixmap_height * data.new_descent / height;
4859 pix_ascent = data.max_pixmap_height - pix_descent;
4861 data.new_ascent = max (data.new_ascent, pix_ascent);
4862 data.new_descent = max (data.new_descent, pix_descent);
4865 dl->ascent = data.new_ascent;
4866 dl->descent = data.new_descent;
4869 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
4871 if (dl->ascent < ascent)
4872 dl->ascent = ascent;
4875 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
4877 if (dl->descent < descent)
4878 dl->descent = descent;
4881 dl->cursor_elt = data.cursor_x;
4882 /* #### lossage lossage lossage! Fix this shit! */
4883 if (data.bi_bufpos > bi_string_zv)
4884 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4886 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4888 data.dl->num_chars =
4889 string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
4891 /* This doesn't correctly take into account tabs and control
4892 characters but if the window isn't being truncated then this
4893 value isn't going to end up being used anyhow. */
4894 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4896 /* #### handle horizontally scrolled line with text none of which
4897 was actually laid out. */
4899 /* #### handle any remainder of overlay arrow */
4901 if (*prop == ADD_FAILED)
4904 if (truncate_win && *prop)
4906 Dynarr_free (*prop);
4910 extent_fragment_delete (data.ef);
4912 /* #### If we started at EOB, then make sure we return a value past
4913 it so that regenerate_window will exit properly. This is bogus.
4914 The main loop should get fixed so that it isn't necessary to call
4915 this function if we are already at EOB. */
4917 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4918 return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
4920 return bytecount_to_charcount (string_data (s), data.bi_bufpos);
4923 /* Given a display line and a starting position, ensure that the
4924 contents of the display line accurately represent the visual
4925 representation of the buffer contents starting from the given
4926 position when displayed in the given window. The display line ends
4927 when the contents of the line reach the right boundary of the given
4930 This is very similar to generate_display_line but with the same
4931 limitations as create_string_text_block. I have taken the liberty
4932 of fixing the bytind stuff though.*/
4935 generate_string_display_line (struct window *w, Lisp_Object disp_string,
4936 struct display_line *dl,
4938 prop_block_dynarr **prop,
4939 face_index default_face)
4943 /* you must set bounds before calling this. */
4945 /* Reset what this line is using. */
4946 if (dl->display_blocks)
4947 Dynarr_reset (dl->display_blocks);
4948 if (dl->left_glyphs)
4950 Dynarr_free (dl->left_glyphs);
4951 dl->left_glyphs = 0;
4953 if (dl->right_glyphs)
4955 Dynarr_free (dl->right_glyphs);
4956 dl->right_glyphs = 0;
4959 /* We aren't generating a modeline at the moment. */
4962 /* Create a display block for the text region of the line. */
4963 ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
4964 prop, default_face);
4965 dl->bufpos = start_pos;
4966 if (dl->end_bufpos < dl->bufpos)
4967 dl->end_bufpos = dl->bufpos;
4969 /* If there are left glyphs associated with any character in the
4970 text block, then create a display block to handle them. */
4971 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
4972 create_left_glyph_block (w, dl, 0);
4974 /* If there are right glyphs associated with any character in the
4975 text block, then create a display block to handle them. */
4976 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
4977 create_right_glyph_block (w, dl);
4982 /* This is ripped off from regenerate_window. All we want to do is
4983 loop through elements in the string creating display lines until we
4984 have covered the provided area. Simple really. */
4986 generate_displayable_area (struct window *w, Lisp_Object disp_string,
4987 int xpos, int ypos, int width, int height,
4988 display_line_dynarr* dla,
4990 face_index default_face)
4992 int yend = ypos + height;
4995 prop_block_dynarr *prop = 0;
4996 layout_bounds bounds;
5000 /* if there's nothing to do then do nothing. code after this assumes
5001 there is something to do. */
5002 if (NILP (disp_string))
5005 s_zv = XSTRING_CHAR_LENGTH (disp_string);
5007 bounds.left_out = xpos;
5008 bounds.right_out = xpos + width;
5009 /* The inner boundaries mark where the glyph margins are located. */
5010 bounds.left_in = bounds.left_out + window_left_margin_width (w);
5011 bounds.right_in = bounds.right_out - window_right_margin_width (w);
5012 /* We cannot fully calculate the whitespace boundaries as they
5013 depend on the contents of the line being displayed. */
5014 bounds.left_white = bounds.left_in;
5015 bounds.right_white = bounds.right_in;
5019 struct display_line dl;
5020 struct display_line *dlp;
5024 if (Dynarr_length (dla) < Dynarr_largest (dla))
5026 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5037 dlp->bounds = bounds;
5039 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5040 &prop, default_face);
5041 /* we need to make sure that we continue along the line if there
5042 is more left to display otherwise we just end up redisplaying
5043 the same chunk over and over again. */
5044 if (next_pos == start_pos && next_pos < s_zv)
5047 start_pos = next_pos;
5049 dlp->ypos = ypos + dlp->ascent;
5050 ypos = dlp->ypos + dlp->descent;
5054 int visible_height = dlp->ascent + dlp->descent;
5056 dlp->clip = (ypos - yend);
5057 visible_height -= dlp->clip;
5059 if (visible_height < VERTICAL_CLIP (w, 1))
5062 free_display_line (dlp);
5069 Dynarr_add (dla, *dlp);
5071 /* #### This type of check needs to be done down in the
5072 generate_display_line call. */
5073 if (start_pos >= s_zv)
5082 /***************************************************************************/
5084 /* window-regeneration routines */
5086 /***************************************************************************/
5088 /* For a given window and starting position in the buffer it contains,
5089 ensure that the TYPE display lines accurately represent the
5090 presentation of the window. We pass the buffer instead of getting
5091 it from the window since redisplay_window may have temporarily
5092 changed it to the echo area buffer. */
5095 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
5097 struct frame *f = XFRAME (w->frame);
5098 struct buffer *b = XBUFFER (w->buffer);
5099 int ypos = WINDOW_TEXT_TOP (w);
5100 int yend; /* set farther down */
5101 int yclip = WINDOW_TEXT_TOP_CLIP (w);
5104 prop_block_dynarr *prop;
5105 layout_bounds bounds;
5106 display_line_dynarr *dla;
5109 /* The lines had better exist by this point. */
5110 if (!(dla = window_display_lines (w, type)))
5113 w->max_line_len = 0;
5115 /* Normally these get updated in redisplay_window but it is possible
5116 for this function to get called from some other points where that
5117 update may not have occurred. This acts as a safety check. */
5118 if (!Dynarr_length (w->face_cachels))
5119 reset_face_cachels (w);
5120 if (!Dynarr_length (w->glyph_cachels))
5121 reset_glyph_cachels (w);
5123 Fset_marker (w->start[type], make_int (start_pos), w->buffer);
5124 Fset_marker (w->pointm[type], make_int (point), w->buffer);
5125 w->last_point_x[type] = -1;
5126 w->last_point_y[type] = -1;
5128 /* Make sure a modeline is in the structs if needed. */
5129 need_modeline = ensure_modeline_generated (w, type);
5131 /* Wait until here to set this so that the structs have a modeline
5132 generated in the case where one didn't exist. */
5133 yend = WINDOW_TEXT_BOTTOM (w);
5135 bounds = calculate_display_line_boundaries (w, 0);
5137 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5138 if (MINI_WINDOW_P (w)
5139 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
5140 && !echo_area_active (f)
5141 && start_pos == BUF_BEGV (b))
5143 struct prop_block pb;
5145 prop = Dynarr_new (prop_block);
5147 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5148 pb.type = PROP_MINIBUF_PROMPT;
5149 pb.data.p_string.str = XSTRING_DATA(string);
5150 pb.data.p_string.len = XSTRING_LENGTH(string);
5151 Dynarr_add (prop, pb);
5156 /* When we are computing things for scrolling purposes, make
5157 sure at least one line is always generated */
5158 force = (type == CMOTION_DISP);
5160 /* Make sure this is set always */
5161 /* Note the conversion at end */
5162 w->window_end_pos[type] = start_pos;
5163 while (ypos < yend || force)
5165 struct display_line dl;
5166 struct display_line *dlp;
5169 if (Dynarr_length (dla) < Dynarr_largest (dla))
5171 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5182 dlp->bounds = bounds;
5184 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
5186 if (yclip > dlp->ascent)
5188 /* this should never happen, but if it does just display the
5193 dlp->ypos = (ypos + dlp->ascent) - yclip;
5194 ypos = dlp->ypos + dlp->descent;
5196 /* See if we've been asked to start midway through a line, for
5197 partial display line scrolling. */
5200 dlp->top_clip = yclip;
5208 int visible_height = dlp->ascent + dlp->descent;
5210 dlp->clip = (ypos - yend);
5211 /* Although this seems strange we could have a single very
5212 tall line visible for which we need to account for both
5213 the top clip and the bottom clip. */
5214 visible_height -= (dlp->clip + dlp->top_clip);
5216 if (visible_height < VERTICAL_CLIP (w, 1) && !force)
5219 free_display_line (dlp);
5226 if (dlp->cursor_elt != -1)
5228 /* #### This check is steaming crap. Have to get things
5229 fixed so when create_text_block hits EOB, we're done,
5231 if (w->last_point_x[type] == -1)
5233 w->last_point_x[type] = dlp->cursor_elt;
5234 w->last_point_y[type] = Dynarr_length (dla);
5238 /* #### This means that we've added a cursor at EOB
5239 twice. Yuck oh yuck. */
5240 struct display_block *db =
5241 get_display_block_from_line (dlp, TEXT);
5243 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
5244 dlp->cursor_elt = -1;
5248 if (dlp->num_chars > w->max_line_len)
5249 w->max_line_len = dlp->num_chars;
5251 Dynarr_add (dla, *dlp);
5253 /* #### This isn't right, but it is close enough for now. */
5254 w->window_end_pos[type] = start_pos;
5256 /* #### This type of check needs to be done down in the
5257 generate_display_line call. */
5258 if (start_pos > BUF_ZV (b))
5267 /* #### More not quite right, but close enough. */
5268 /* Ben sez: apparently window_end_pos[] is measured
5269 as the number of characters between the window end and the
5270 end of the buffer? This seems rather weirdo. What's
5271 the justification for this?
5273 JV sez: Because BUF_Z (b) would be a good initial value, however
5274 that can change. This representation allows initalizing with 0.
5276 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
5280 /* We know that this is the right thing to use because we put it
5281 there when we first started working in this function. */
5282 generate_modeline (w, Dynarr_atp (dla, 0), type);
5286 #define REGEN_INC_FIND_START_END \
5288 /* Determine start and end of lines. */ \
5289 if (!Dynarr_length (cdla)) \
5293 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5297 else if (!Dynarr_atp (cdla, 0)->modeline \
5298 && !Dynarr_atp (ddla, 0)->modeline) \
5303 abort (); /* structs differ */ \
5305 dla_end = Dynarr_length (cdla) - 1; \
5308 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5309 + Dynarr_atp (cdla, dla_start)->offset); \
5310 /* If this isn't true, then startp has changed and we need to do a \
5312 if (startp != start_pos) \
5315 /* Point is outside the visible region so give up. */ \
5316 if (pointm < start_pos) \
5321 /* This attempts to incrementally update the display structures. It
5322 returns a boolean indicating success or failure. This function is
5323 very similar to regenerate_window_incrementally and is in fact only
5324 called from that function. However, because of the nature of the
5325 changes it deals with it sometimes makes different assumptions
5326 which can lead to success which are much more difficult to make
5327 when dealing with buffer changes. */
5330 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
5332 Charcount beg_unchanged,
5333 Charcount end_unchanged)
5335 struct buffer *b = XBUFFER (w->buffer);
5336 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5337 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5341 int first_line, last_line;
5343 /* Don't define this in the loop where it is used because we
5344 definitely want its value to survive between passes. */
5345 prop_block_dynarr *prop = NULL;
5347 /* If we don't have any buffer change recorded but the modiff flag has
5348 been incremented, then fail. I'm not sure of the exact circumstances
5349 under which this can happen, but I believe that it is probably a
5350 reasonable happening. */
5351 if (!point_visible (w, pointm, CURRENT_DISP)
5352 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
5355 /* If the cursor is moved we attempt to update it. If we succeed we
5356 go ahead and proceed with the optimization attempt. */
5357 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5358 || pointm != marker_position (w->last_point[CURRENT_DISP]))
5360 struct frame *f = XFRAME (w->frame);
5361 struct device *d = XDEVICE (f->device);
5362 struct frame *sel_f = device_selected_frame (d);
5365 if (w->last_point_x[CURRENT_DISP] != -1
5366 && w->last_point_y[CURRENT_DISP] != -1)
5369 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
5371 /* Always regenerate the modeline in case it is
5372 displaying the current line or column. */
5373 regenerate_modeline (w);
5377 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
5379 if (f->modeline_changed)
5380 regenerate_modeline (w);
5388 if (beg_unchanged == -1 && end_unchanged == -1)
5391 /* assert: There are no buffer modifications or they are all below the
5392 visible region. We assume that regenerate_window_incrementally has
5393 not called us unless this is true. */
5395 REGEN_INC_FIND_START_END;
5397 /* If the changed are starts before the visible area, give up. */
5398 if (beg_unchanged < startp)
5401 /* Find what display line the extent changes first affect. */
5403 while (line <= dla_end)
5405 struct display_line *dl = Dynarr_atp (cdla, line);
5406 Bufpos lstart = dl->bufpos + dl->offset;
5407 Bufpos lend = dl->end_bufpos + dl->offset;
5409 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5415 /* If the changes are below the visible area then if point hasn't
5416 moved return success otherwise fail in order to be safe. */
5419 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5420 && pointm == marker_position (w->last_point[CURRENT_DISP]))
5426 /* At this point we know what line the changes first affect. We now
5427 begin redrawing lines as long as we are still in the affected
5428 region and the line's size and positioning don't change.
5429 Otherwise we fail. If we fail we will have altered the desired
5430 structs which could lead to an assertion failure. However, if we
5431 fail the next thing that is going to happen is a full regen so we
5432 will actually end up being safe. */
5433 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5434 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5435 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5436 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5438 first_line = last_line = line;
5439 while (line <= dla_end)
5441 Bufpos old_start, old_end, new_start;
5442 struct display_line *cdl = Dynarr_atp (cdla, line);
5443 struct display_line *ddl = Dynarr_atp (ddla, line);
5444 struct display_block *db;
5447 assert (cdl->bufpos == ddl->bufpos);
5448 assert (cdl->end_bufpos == ddl->end_bufpos);
5449 assert (cdl->offset == ddl->offset);
5451 db = get_display_block_from_line (ddl, TEXT);
5452 initial_size = Dynarr_length (db->runes);
5453 old_start = ddl->bufpos + ddl->offset;
5454 old_end = ddl->end_bufpos + ddl->offset;
5456 /* If this is the first line being updated and it used
5457 propagation data, fail. Otherwise we'll be okay because
5458 we'll have the necessary propagation data. */
5459 if (line == first_line && ddl->used_prop_data)
5462 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5463 &prop, DESIRED_DISP);
5466 /* #### If there is propagated stuff the fail. We could
5467 probably actually deal with this if the line had propagated
5468 information when originally created by a full
5476 /* If any line position parameters have changed or a
5477 cursor has disappeared or disappeared, fail. */
5478 db = get_display_block_from_line (ddl, TEXT);
5479 if (cdl->ypos != ddl->ypos
5480 || cdl->ascent != ddl->ascent
5481 || cdl->descent != ddl->descent
5482 || cdl->top_clip != ddl->top_clip
5483 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5484 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5485 || old_start != ddl->bufpos
5486 || old_end != ddl->end_bufpos
5487 || initial_size != Dynarr_length (db->runes))
5492 if (ddl->cursor_elt != -1)
5494 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5495 w->last_point_y[DESIRED_DISP] = line;
5500 /* If the extent changes end on the line we just updated then
5501 we're done. Otherwise go on to the next line. */
5502 if (end_unchanged <= ddl->end_bufpos)
5508 redisplay_update_line (w, first_line, last_line, 1);
5512 /* Attempt to update the display data structures based on knowledge of
5513 the changed region in the buffer. Returns a boolean indicating
5514 success or failure. If this function returns a failure then a
5515 regenerate_window _must_ be performed next in order to maintain
5516 invariants located here. */
5519 regenerate_window_incrementally (struct window *w, Bufpos startp,
5522 struct buffer *b = XBUFFER (w->buffer);
5523 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5524 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5525 Charcount beg_unchanged, end_unchanged;
5526 Charcount extent_beg_unchanged, extent_end_unchanged;
5532 /* If this function is called, the current and desired structures
5533 had better be identical. If they are not, then that is a bug. */
5534 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
5536 /* We don't handle minibuffer windows yet. The minibuffer prompt
5538 if (MINI_WINDOW_P (w))
5541 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
5542 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
5544 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
5546 /* If nothing has changed in the buffer, then make sure point is ok
5548 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
5549 return regenerate_window_extents_only_changed (w, startp, pointm,
5550 extent_beg_unchanged,
5551 extent_end_unchanged);
5553 /* We can't deal with deleted newlines. */
5554 if (BUF_NEWLINE_WAS_DELETED (b))
5557 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
5558 end_unchanged = (BUF_END_UNCHANGED (b) == -1
5560 : BUF_Z (b) - BUF_END_UNCHANGED (b));
5562 REGEN_INC_FIND_START_END;
5564 /* If the changed area starts before the visible area, give up. */
5565 if (beg_unchanged < startp)
5568 /* Find what display line the buffer changes first affect. */
5570 while (line <= dla_end)
5572 struct display_line *dl = Dynarr_atp (cdla, line);
5573 Bufpos lstart = dl->bufpos + dl->offset;
5574 Bufpos lend = dl->end_bufpos + dl->offset;
5576 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5582 /* If the changes are below the visible area then if point hasn't
5583 moved return success otherwise fail in order to be safe. */
5585 return regenerate_window_extents_only_changed (w, startp, pointm,
5586 extent_beg_unchanged,
5587 extent_end_unchanged);
5589 /* At this point we know what line the changes first affect. We
5590 now redraw that line. If the changes are contained within it
5591 we are going to succeed and can update just that one line.
5592 Otherwise we fail. If we fail we will have altered the desired
5593 structs which could lead to an assertion failure. However, if
5594 we fail the next thing that is going to happen is a full regen
5595 so we will actually end up being safe. */
5598 prop_block_dynarr *prop = NULL;
5599 struct display_line *cdl = Dynarr_atp (cdla, line);
5600 struct display_line *ddl = Dynarr_atp (ddla, line);
5602 assert (cdl->bufpos == ddl->bufpos);
5603 assert (cdl->end_bufpos == ddl->end_bufpos);
5604 assert (cdl->offset == ddl->offset);
5606 /* If the line continues to next display line, fail. */
5607 if (ddl->line_continuation)
5610 /* If the line was generated using propagation data, fail. */
5611 if (ddl->used_prop_data)
5614 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5615 &prop, DESIRED_DISP);
5618 /* If there is propagated stuff then it is pretty much a
5619 guarantee that more than just the one line is affected. */
5626 /* If the line continues to next display line, fail. */
5627 if (ddl->line_continuation)
5630 /* If any line position parameters have changed or a
5631 cursor has disappeared or disappeared, fail. */
5632 if (cdl->ypos != ddl->ypos
5633 || cdl->ascent != ddl->ascent
5634 || cdl->descent != ddl->descent
5635 || cdl->top_clip != ddl->top_clip
5636 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5637 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
5642 /* If the changed area also ends on this line, then we may be in
5643 business. Update everything and return success. */
5644 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
5646 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5647 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5648 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
5650 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
5653 if (ddl->cursor_elt != -1)
5655 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5656 w->last_point_y[DESIRED_DISP] = line;
5659 redisplay_update_line (w, line, line, 1);
5660 regenerate_modeline (w);
5662 /* #### For now we just flush the cache until this has been
5663 tested. After that is done, this should correct the
5665 Dynarr_reset (w->line_start_cache);
5667 /* Adjust the extent changed boundaries to remove any
5668 overlap with the buffer changes since we've just
5669 successfully updated that area. */
5670 if (extent_beg_unchanged != -1
5671 && extent_beg_unchanged >= beg_unchanged
5672 && extent_beg_unchanged < end_unchanged)
5673 extent_beg_unchanged = end_unchanged;
5675 if (extent_end_unchanged != -1
5676 && extent_end_unchanged >= beg_unchanged
5677 && extent_end_unchanged < end_unchanged)
5678 extent_end_unchanged = beg_unchanged - 1;
5680 if (extent_end_unchanged <= extent_beg_unchanged)
5681 extent_beg_unchanged = extent_end_unchanged = -1;
5683 /* This could lead to odd results if it fails, but since the
5684 buffer changes update succeeded this probably will to.
5685 We already know that the extent changes start at or after
5686 the line because we checked before entering the loop. */
5687 if (extent_beg_unchanged != -1
5688 && extent_end_unchanged != -1
5689 && ((extent_beg_unchanged < ddl->bufpos)
5690 || (extent_end_unchanged > ddl->end_bufpos)))
5691 return regenerate_window_extents_only_changed (w, startp, pointm,
5692 extent_beg_unchanged,
5693 extent_end_unchanged);
5703 /* Given a window and a point, update the given display lines such
5704 that point is displayed in the middle of the window.
5705 Return the window's new start position. */
5708 regenerate_window_point_center (struct window *w, Bufpos point, int type)
5712 /* We need to make sure that the modeline is generated so that the
5713 window height can be calculated correctly. */
5714 ensure_modeline_generated (w, type);
5716 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
5717 regenerate_window (w, startp, point, type);
5718 Fset_marker (w->start[type], make_int (startp), w->buffer);
5723 /* Given a window and a set of display lines, return a boolean
5724 indicating whether the given point is contained within. */
5727 point_visible (struct window *w, Bufpos point, int type)
5729 struct buffer *b = XBUFFER (w->buffer);
5730 display_line_dynarr *dla = window_display_lines (w, type);
5733 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5738 if (Dynarr_length (dla) > first_line)
5741 struct display_line *dl = Dynarr_atp (dla, first_line);
5744 end = BUF_Z (b) - w->window_end_pos[type] - 1;
5746 if (point >= start && point <= end)
5748 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
5750 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
5752 if (point >= (dl->bufpos + dl->offset)
5753 && point <= (dl->end_bufpos + dl->offset))
5768 /* Return pixel position the middle of the window, not including the
5769 modeline and any potential horizontal scrollbar. */
5772 window_half_pixpos (struct window *w)
5774 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
5777 /* Return the display line which is currently in the middle of the
5778 window W for display lines TYPE. */
5781 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5783 display_line_dynarr *dla;
5786 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
5788 if (type == CMOTION_DISP)
5789 regenerate_window (w, start, point, type);
5791 dla = window_display_lines (w, type);
5792 half = window_half_pixpos (w);
5794 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
5796 struct display_line *dl = Dynarr_atp (dla, elt);
5797 int line_bot = dl->ypos + dl->descent;
5799 if (line_bot > half)
5803 /* We may not have a line at the middle if the end of the buffer is
5808 /* Return a value for point that would place it at the beginning of
5809 the line which is in the middle of the window. */
5812 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5814 /* line_at_center will regenerate the display structures, if necessary. */
5815 int line = line_at_center (w, type, start, point);
5818 return BUF_ZV (XBUFFER (w->buffer));
5821 display_line_dynarr *dla = window_display_lines (w, type);
5822 struct display_line *dl = Dynarr_atp (dla, line);
5828 /* For a given window, ensure that the current visual representation
5832 redisplay_window (Lisp_Object window, int skip_selected)
5834 struct window *w = XWINDOW (window);
5835 struct frame *f = XFRAME (w->frame);
5836 struct device *d = XDEVICE (f->device);
5837 Lisp_Object old_buffer = w->buffer;
5838 Lisp_Object the_buffer = w->buffer;
5840 int echo_active = 0;
5845 int selected_in_its_frame;
5846 int selected_globally;
5847 int skip_output = 0;
5848 int truncation_changed;
5849 int inactive_minibuffer =
5850 (MINI_WINDOW_P (w) &&
5851 (f != device_selected_frame (d)) &&
5852 !is_surrogate_for_selected_frame (f));
5854 /* #### In the new world this function actually does a bunch of
5855 optimizations such as buffer-based scrolling, but none of that is
5858 /* If this is a combination window, do its children; that's all.
5859 The selected window is always a leaf so we don't check for
5860 skip_selected here. */
5861 if (!NILP (w->vchild))
5863 redisplay_windows (w->vchild, skip_selected);
5866 if (!NILP (w->hchild))
5868 redisplay_windows (w->hchild, skip_selected);
5872 /* Is this window the selected window on its frame? */
5873 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
5875 selected_in_its_frame &&
5876 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5877 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
5878 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5879 if (skip_selected && selected_in_its_frame)
5882 /* It is possible that the window is not fully initialized yet. */
5883 if (NILP (w->buffer))
5886 if (MINI_WINDOW_P (w) && echo_area_active (f))
5888 w->buffer = the_buffer = Vecho_area_buffer;
5892 b = XBUFFER (w->buffer);
5896 old_pointm = selected_globally
5898 : marker_position (w->pointm[CURRENT_DISP]);
5903 if (selected_globally)
5905 pointm = BUF_PT (b);
5909 pointm = marker_position (w->pointm[CURRENT_DISP]);
5911 if (pointm < BUF_BEGV (b))
5912 pointm = BUF_BEGV (b);
5913 else if (pointm > BUF_ZV (b))
5914 pointm = BUF_ZV (b);
5917 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
5919 /* If the buffer has changed we have to invalidate all of our face
5921 if ((!echo_active && b != window_display_buffer (w))
5922 || !Dynarr_length (w->face_cachels)
5923 || f->faces_changed)
5924 reset_face_cachels (w);
5926 mark_face_cachels_as_not_updated (w);
5928 /* Ditto the glyph cache elements, although we do *not* invalidate
5929 the cache purely because glyphs have changed - this is now
5930 handled by the dirty flag.*/
5931 if ((!echo_active && b != window_display_buffer (w))
5932 || !Dynarr_length (w->glyph_cachels) || f->faces_changed)
5933 reset_glyph_cachels (w);
5935 mark_glyph_cachels_as_not_updated (w);
5937 /* If the marker's buffer is not the window's buffer, then we need
5938 to find a new starting position. */
5939 if (!MINI_WINDOW_P (w)
5940 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5942 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5944 goto regeneration_done;
5949 old_startp = marker_position (w->start[CURRENT_DISP]);
5954 startp = marker_position (w->start[CURRENT_DISP]);
5955 if (startp < BUF_BEGV (b))
5956 startp = BUF_BEGV (b);
5957 else if (startp > BUF_ZV (b))
5958 startp = BUF_ZV (b);
5960 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5962 truncation_changed = (find_window_mirror (w)->truncate_win !=
5963 window_truncation_on (w));
5965 /* If w->force_start is set, then some function set w->start and we
5966 should display from there and change point, if necessary, to
5967 ensure that it is visible. */
5968 if (w->force_start || inactive_minibuffer)
5971 w->last_modified[DESIRED_DISP] = Qzero;
5972 w->last_facechange[DESIRED_DISP] = Qzero;
5974 regenerate_window (w, startp, pointm, DESIRED_DISP);
5976 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5978 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5980 if (selected_globally)
5981 BUF_SET_PT (b, pointm);
5983 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5986 /* #### BUFU amounts of overkill just to get the cursor
5987 location marked properly. FIX ME FIX ME FIX ME */
5988 regenerate_window (w, startp, pointm, DESIRED_DISP);
5991 goto regeneration_done;
5994 /* If nothing has changed since the last redisplay, then we just
5995 need to make sure that point is still visible. */
5996 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5997 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
5999 /* This check is to make sure we restore the minibuffer after a
6000 temporary change to the echo area. */
6001 && !(MINI_WINDOW_P (w) && f->buffers_changed)
6002 && !f->frame_changed
6003 && !truncation_changed
6004 /* check whether start is really at the beginning of a line GE */
6005 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
6008 /* Check if the cursor has actually moved. */
6009 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
6010 && pointm == marker_position (w->last_point[CURRENT_DISP])
6011 && selected_globally
6012 && !w->windows_changed
6014 && !f->extents_changed
6015 && !f->faces_changed
6016 && !f->glyphs_changed
6017 && !f->subwindows_changed
6018 /* && !f->subwindows_state_changed*/
6019 && !f->point_changed
6020 && !f->windows_structure_changed)
6022 /* If not, we're done. */
6023 if (f->modeline_changed)
6024 regenerate_modeline (w);
6027 goto regeneration_done;
6031 /* If the new point is visible in the redisplay structures,
6032 then let the output update routines handle it, otherwise
6033 do things the hard way. */
6034 if (!w->windows_changed
6036 && !f->extents_changed
6037 && !f->faces_changed
6038 && !f->glyphs_changed
6039 && !f->subwindows_changed
6040 /* && !f->subwindows_state_changed*/
6041 && !f->windows_structure_changed)
6043 if (point_visible (w, pointm, CURRENT_DISP)
6044 && w->last_point_x[CURRENT_DISP] != -1
6045 && w->last_point_y[CURRENT_DISP] != -1)
6047 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
6049 /* Always regenerate in case it is displaying
6050 the current line or column. */
6051 regenerate_modeline (w);
6054 goto regeneration_done;
6057 else if (!selected_in_its_frame && !f->point_changed)
6059 if (f->modeline_changed)
6060 regenerate_modeline (w);
6063 goto regeneration_done;
6067 /* If we weren't able to take the shortcut method, then use
6068 the brute force method. */
6069 regenerate_window (w, startp, pointm, DESIRED_DISP);
6071 if (point_visible (w, pointm, DESIRED_DISP))
6072 goto regeneration_done;
6076 /* Check if the starting point is no longer at the beginning of a
6077 line, in which case find a new starting point. We also recenter
6078 if our start position is equal to point-max. Otherwise we'll end
6079 up with a blank window. */
6080 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
6081 && !(startp == BUF_BEGV (b)
6082 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
6083 || (pointm == startp &&
6084 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
6085 startp < marker_position (w->last_start[CURRENT_DISP]))
6086 || (startp == BUF_ZV (b)))
6088 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6090 goto regeneration_done;
6092 /* See if we can update the data structures locally based on
6093 knowledge of what changed in the buffer. */
6094 else if (!w->windows_changed
6096 && !f->faces_changed
6097 && !f->glyphs_changed
6098 && !f->subwindows_changed
6099 /* && !f->subwindows_state_changed*/
6100 && !f->windows_structure_changed
6101 && !f->frame_changed
6102 && !truncation_changed
6104 && regenerate_window_incrementally (w, startp, pointm))
6106 if (f->modeline_changed
6107 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
6108 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
6109 regenerate_modeline (w);
6112 goto regeneration_done;
6114 /* #### This is where a check for structure based scrolling would go. */
6115 /* If all else fails, try just regenerating and see what happens. */
6118 regenerate_window (w, startp, pointm, DESIRED_DISP);
6120 if (point_visible (w, pointm, DESIRED_DISP))
6121 goto regeneration_done;
6124 /* We still haven't gotten the window regenerated with point
6125 visible. Next we try scrolling a little and see if point comes
6126 back onto the screen. */
6127 if (scroll_step > 0)
6129 int scrolled = scroll_conservatively;
6130 for (; scrolled >= 0; scrolled -= scroll_step)
6132 startp = vmotion (w, startp,
6133 (pointm < startp) ? -scroll_step : scroll_step, 0);
6134 regenerate_window (w, startp, pointm, DESIRED_DISP);
6136 if (point_visible (w, pointm, DESIRED_DISP))
6137 goto regeneration_done;
6141 /* We still haven't managed to get the screen drawn with point on
6142 the screen, so just center it and be done with it. */
6143 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6148 /* If the window's frame is changed then reset the current display
6149 lines in order to force a full repaint. */
6150 if (f->frame_changed)
6152 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
6157 /* Must do this before calling redisplay_output_window because it
6158 sets some markers on the window. */
6161 w->buffer = old_buffer;
6162 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
6163 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
6166 /* These also have to be set before calling redisplay_output_window
6167 since it sets the CURRENT_DISP values based on them. */
6168 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
6169 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
6170 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
6171 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
6175 Bufpos start = marker_position (w->start[DESIRED_DISP]);
6176 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
6178 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
6179 /* Don't pollute the cache if not sure if we are correct */
6180 if (w->start_at_line_beg)
6181 update_line_start_cache (w, start, end, pointm, 1);
6182 redisplay_output_window (w);
6184 * If we just displayed the echo area, the line start cache is
6185 * no longer valid, because the minibuffer window is associated
6186 * with the window now.
6189 w->line_cache_last_updated = make_int (-1);
6192 /* #### This should be dependent on face changes and will need to be
6193 somewhere else once tty updates occur on a per-frame basis. */
6194 mark_face_cachels_as_clean (w);
6196 /* The glyph cachels only get dirty if someone changed something.
6197 Since redisplay has now effectively ended we can reset the dirty
6198 flag since everything must be up-to-date. */
6200 mark_glyph_cachels_as_clean (w);
6202 w->windows_changed = 0;
6205 /* Call buffer_reset_changes for all buffers present in any window
6206 currently visible in all frames on all devices. #### There has to
6207 be a better way to do this. */
6210 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
6212 buffer_reset_changes (XBUFFER (w->buffer));
6217 reset_buffer_changes (void)
6219 Lisp_Object frmcons, devcons, concons;
6221 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6223 struct frame *f = XFRAME (XCAR (frmcons));
6225 if (FRAME_REPAINT_P (f))
6226 map_windows (f, reset_buffer_changes_mapfun, 0);
6230 /* Ensure that all windows underneath the given window in the window
6231 hierarchy are correctly displayed. */
6234 redisplay_windows (Lisp_Object window, int skip_selected)
6236 for (; !NILP (window) ; window = XWINDOW (window)->next)
6238 redisplay_window (window, skip_selected);
6243 call_redisplay_end_triggers (struct window *w, void *closure)
6245 Bufpos lrpos = w->last_redisplay_pos;
6246 w->last_redisplay_pos = 0;
6247 if (!NILP (w->buffer)
6248 && !NILP (w->redisplay_end_trigger)
6253 if (MARKERP (w->redisplay_end_trigger)
6254 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
6255 pos = marker_position (w->redisplay_end_trigger);
6256 else if (INTP (w->redisplay_end_trigger))
6257 pos = XINT (w->redisplay_end_trigger);
6260 w->redisplay_end_trigger = Qnil;
6267 XSETWINDOW (window, w);
6268 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
6269 Qredisplay_end_trigger_functions,
6271 w->redisplay_end_trigger);
6272 w->redisplay_end_trigger = Qnil;
6279 /* Ensure that all windows on the given frame are correctly displayed. */
6282 redisplay_frame (struct frame *f, int preemption_check)
6284 struct device *d = XDEVICE (f->device);
6286 if (preemption_check)
6288 /* The preemption check itself takes a lot of time,
6289 so normally don't do it here. We do it if called
6290 from Lisp, though (`redisplay-frame'). */
6293 REDISPLAY_PREEMPTION_CHECK;
6298 if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0))
6302 f->old_buffer_alist = Freplace_list (f->old_buffer_alist,
6304 XSETFRAME (frame, f);
6305 va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame);
6308 /* Before we put a hold on frame size changes, attempt to process
6309 any which are already pending. */
6310 if (f->size_change_pending)
6311 change_frame_size (f, f->new_height, f->new_width, 0);
6313 /* If frame size might need to be changed, due to changed size
6314 of toolbars, scrollbars etc, change it now */
6315 if (f->size_slipped)
6317 adjust_frame_size (f);
6318 assert (!f->size_slipped);
6321 /* The menubar, toolbar, and icon updates must be done before
6322 hold_frame_size_changes is called and we are officially
6323 'in_display'. They may eval lisp code which may call Fsignal.
6324 If in_display is set Fsignal will abort. */
6326 #ifdef HAVE_MENUBARS
6327 /* Update the menubar. It is done first since it could change
6328 the menubar's visibility. This way we avoid having flashing
6329 caused by an Expose event generated by the visibility change
6331 update_frame_menubars (f);
6332 #endif /* HAVE_MENUBARS */
6333 #ifdef HAVE_TOOLBARS
6334 /* Update the toolbars. */
6335 update_frame_toolbars (f);
6336 #endif /* HAVE_TOOLBARS */
6337 /* Gutter update proper has to be done inside display when no frame
6338 size changes can occur, thus we separately update the gutter
6339 geometry here if it needs it. */
6340 update_frame_gutter_geometry (f);
6342 /* If we clear the frame we have to force its contents to be redrawn. */
6344 f->frame_changed = 1;
6346 /* Invalidate the subwindow caches. We use subwindows_changed here
6347 to cause subwindows to get instantiated. This is because
6348 subwindows_state_changed is less strict - dealing with things
6349 like the clicked state of button. We have to do this before
6350 redisplaying the gutters as subwindows get unmapped in the
6352 if (f->frame_changed)
6353 reset_frame_subwindow_instance_cache (f);
6355 if (f->frame_changed || f->subwindows_changed)
6357 /* we have to do this so the gutter gets regenerated. */
6358 reset_gutter_display_lines (f);
6361 hold_frame_size_changes ();
6363 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6364 /* Within this section, we are defenseless and assume that the
6365 following cannot happen:
6367 1) garbage collection
6368 2) Lisp code evaluation
6369 3) frame size changes
6371 We ensure (3) by calling hold_frame_size_changes(), which
6372 will cause any pending frame size changes to get put on hold
6373 till after the end of the critical section. (1) follows
6374 automatically if (2) is met. #### Unfortunately, there are
6375 some places where Lisp code can be called within this section.
6376 We need to remove them.
6378 If Fsignal() is called during this critical section, we
6381 If garbage collection is called during this critical section,
6382 we simply return. #### We should abort instead.
6384 #### If a frame-size change does occur we should probably
6385 actually be preempting redisplay. */
6387 MAYBE_DEVMETH (d, frame_output_begin, (f));
6389 /* We can now update the gutters, safe in the knowledge that our
6390 efforts won't get undone. */
6392 /* This can call lisp, but redisplay is protected by binding
6393 inhibit_quit. More importantly the code involving display lines
6394 *assumes* that GC will not happen and so does not GCPRO
6395 anything. Since we use this code the whole time with the gutters
6396 we cannot allow GC to happen when manipulating the gutters. */
6397 update_frame_gutters (f);
6399 /* Erase the frame before outputting its contents. */
6402 MAYBE_DEVMETH (d, clear_frame, (f));
6405 /* Do the selected window first. */
6406 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
6408 /* Then do the rest. */
6409 redisplay_windows (f->root_window, 1);
6411 MAYBE_DEVMETH (d, frame_output_end, (f));
6413 update_frame_title (f);
6415 CLASS_RESET_CHANGED_FLAGS (f);
6416 f->window_face_cache_reset = 0;
6417 f->echo_area_garbaged = 0;
6420 if (!f->size_change_pending)
6421 f->size_changed = 0;
6423 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6425 /* Allow frame size changes to occur again.
6427 #### what happens if changes to other frames happen? */
6428 unhold_one_frame_size_changes (f);
6430 map_windows (f, call_redisplay_end_triggers, 0);
6434 /* Ensure that all frames on the given device are correctly displayed.
6435 If AUTOMATIC is non-zero, and the device implementation indicates
6436 no automatic redisplay, as printers do, then the device is not
6437 redisplayed. AUTOMATIC is set to zero when called from lisp
6438 functions (redraw-device) and (redisplay-device), and to non-zero
6439 when called from "lazy" redisplay();
6443 redisplay_device (struct device *d, int automatic)
6445 Lisp_Object frame, frmcons;
6447 int size_change_failed = 0;
6451 && (MAYBE_INT_DEVMETH (d, device_implementation_flags, ())
6452 & XDEVIMPF_NO_AUTO_REDISPLAY))
6455 if (DEVICE_STREAM_P (d)) /* nothing to do */
6458 /* It is possible that redisplay has been called before the
6459 device is fully initialized. If so then continue with the
6461 if (NILP (DEVICE_SELECTED_FRAME (d)))
6464 REDISPLAY_PREEMPTION_CHECK;
6468 /* Always do the selected frame first. */
6469 frame = DEVICE_SELECTED_FRAME (d);
6473 if (f->icon_changed || f->windows_changed)
6474 update_frame_icon (f);
6476 if (FRAME_REPAINT_P (f))
6478 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
6480 preempted = redisplay_frame (f, 0);
6486 /* If the frame redisplay did not get preempted, then this flag
6487 should have gotten set to 0. It might be possible for that
6488 not to happen if a size change event were to occur at an odd
6489 time. To make sure we don't miss anything we simply don't
6490 reset the top level flags until the condition ends up being
6491 in the right state. */
6492 if (f->size_changed)
6493 size_change_failed = 1;
6496 DEVICE_FRAME_LOOP (frmcons, d)
6498 f = XFRAME (XCAR (frmcons));
6500 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
6503 if (f->icon_changed || f->windows_changed)
6504 update_frame_icon (f);
6506 if (FRAME_REPAINT_P (f))
6508 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
6510 preempted = redisplay_frame (f, 0);
6516 if (f->size_change_pending)
6517 size_change_failed = 1;
6521 /* If we get here then we redisplayed all of our frames without
6522 getting preempted so mark ourselves as clean. */
6523 CLASS_RESET_CHANGED_FLAGS (d);
6525 if (!size_change_failed)
6526 d->size_changed = 0;
6532 restore_profiling_redisplay_flag (Lisp_Object val)
6534 profiling_redisplay_flag = XINT (val);
6538 /* Ensure that all windows on all frames on all devices are displaying
6539 the current contents of their respective buffers. */
6542 redisplay_without_hooks (void)
6544 Lisp_Object devcons, concons;
6545 int size_change_failed = 0;
6546 int count = specpdl_depth ();
6548 if (profiling_active)
6550 record_unwind_protect (restore_profiling_redisplay_flag,
6551 make_int (profiling_redisplay_flag));
6552 profiling_redisplay_flag = 1;
6555 if (asynch_device_change_pending)
6556 handle_asynch_device_change ();
6558 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6559 !disable_preemption && preemption_count < max_preempts)
6562 DEVICE_LOOP_NO_BREAK (devcons, concons)
6564 struct device *d = XDEVICE (XCAR (devcons));
6567 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d))
6569 preempted = redisplay_device (d, 1);
6574 RESET_CHANGED_SET_FLAGS;
6578 /* See comment in redisplay_device. */
6579 if (d->size_changed)
6580 size_change_failed = 1;
6583 preemption_count = 0;
6585 /* Mark redisplay as accurate */
6586 GLOBAL_RESET_CHANGED_FLAGS;
6587 RESET_CHANGED_SET_FLAGS;
6591 mark_all_faces_as_clean ();
6595 if (!size_change_failed)
6598 reset_buffer_changes ();
6601 unbind_to (count, Qnil);
6607 if (last_display_warning_tick != display_warning_tick &&
6608 !inhibit_warning_display)
6610 /* If an error occurs during this function, oh well.
6611 If we report another warning, we could get stuck in an
6612 infinite loop reporting warnings. */
6613 call0_trapping_errors (0, Qdisplay_warning_buffer);
6614 last_display_warning_tick = display_warning_tick;
6616 /* The run_hook_trapping_errors functions are smart enough not
6617 to do any evalling if the hook function is empty, so there
6618 should not be any significant time loss. All places in the
6619 C code that call redisplay() are prepared to handle GCing,
6620 so we should be OK. */
6621 #ifndef INHIBIT_REDISPLAY_HOOKS
6622 run_hook_trapping_errors ("Error in pre-redisplay-hook",
6623 Qpre_redisplay_hook);
6624 #endif /* INHIBIT_REDISPLAY_HOOKS */
6626 redisplay_without_hooks ();
6628 #ifndef INHIBIT_REDISPLAY_HOOKS
6629 run_hook_trapping_errors ("Error in post-redisplay-hook",
6630 Qpost_redisplay_hook);
6631 #endif /* INHIBIT_REDISPLAY_HOOKS */
6635 static char window_line_number_buf[32];
6637 /* Efficiently determine the window line number, and return a pointer
6638 to its printed representation. Do this regardless of whether
6639 line-number-mode is on. The first line in the buffer is counted as
6640 1. If narrowing is in effect, the lines are counted from the
6641 beginning of the visible portion of the buffer. */
6643 window_line_number (struct window *w, int type)
6645 struct device *d = XDEVICE (XFRAME (w->frame)->device);
6646 struct buffer *b = XBUFFER (w->buffer);
6647 /* Be careful in the order of these tests. The first clause will
6648 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6649 This can occur when the frame title is computed really early */
6651 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6652 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
6653 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6654 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
6656 : marker_position (w->pointm[type]));
6659 line = buffer_line_number (b, pos, 1);
6661 long_to_string (window_line_number_buf, line + 1);
6663 return window_line_number_buf;
6667 /* Given a character representing an object in a modeline
6668 specification, return a string (stored into the global array
6669 `mode_spec_bufbyte_string') with the information that object
6672 This function is largely unchanged from previous versions of the
6675 Warning! This code is also used for frame titles and can be called
6676 very early in the device/frame update process! JV
6680 decode_mode_spec (struct window *w, Emchar spec, int type)
6682 Lisp_Object obj = Qnil;
6683 const char *str = NULL;
6684 struct buffer *b = XBUFFER (w->buffer);
6686 Dynarr_reset (mode_spec_bufbyte_string);
6690 /* print buffer name */
6695 /* print visited file name */
6700 /* print the current column */
6703 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
6705 : marker_position (w->pointm[type]);
6706 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
6709 long_to_string (buf, col);
6711 Dynarr_add_many (mode_spec_bufbyte_string,
6712 (const Bufbyte *) buf, strlen (buf));
6714 goto decode_mode_spec_done;
6716 /* print the file coding system */
6720 Lisp_Object codesys = b->buffer_file_coding_system;
6721 /* Be very careful here not to get an error. */
6722 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
6724 codesys = Ffind_coding_system (codesys);
6725 if (CODING_SYSTEMP (codesys))
6726 obj = XCODING_SYSTEM_MNEMONIC (codesys);
6729 #endif /* FILE_CODING */
6732 /* print the current line number */
6734 str = window_line_number (w, type);
6737 /* print value of mode-name (obsolete) */
6742 /* print hyphen and frame number, if != 1 */
6746 struct frame *f = XFRAME (w->frame);
6747 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
6749 /* Naughty, naughty */
6750 char * writable_str = alloca_array (char, 10);
6751 sprintf (writable_str, "-%d", f->order_count);
6755 #endif /* HAVE_TTY */
6758 /* print Narrow if appropriate */
6760 if (BUF_BEGV (b) > BUF_BEG (b)
6761 || BUF_ZV (b) < BUF_Z (b))
6765 /* print %, * or hyphen, if buffer is read-only, modified or neither */
6767 str = (!NILP (b->read_only)
6769 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6774 /* print * or hyphen -- XEmacs change to allow a buffer to be
6775 read-only but still indicate whether it is modified. */
6777 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6779 : (!NILP (b->read_only)
6784 /* #### defined in 19.29 decode_mode_spec, but not in
6785 modeline-format doc string. */
6786 /* This differs from %* in that it ignores read-only-ness. */
6788 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6793 /* print process status */
6795 obj = Fget_buffer_process (w->buffer);
6797 str = GETTEXT ("no process");
6799 obj = Fsymbol_name (Fprocess_status (obj));
6802 /* Print name of selected frame. */
6804 obj = XFRAME (w->frame)->name;
6807 /* indicate TEXT or BINARY */
6809 /* #### NT does not use this any more. Now what? */
6813 /* print percent of buffer above top of window, or Top, Bot or All */
6816 Bufpos pos = marker_position (w->start[type]);
6818 /* This had better be while the desired lines are being done. */
6819 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
6821 if (pos <= BUF_BEGV (b))
6826 else if (pos <= BUF_BEGV (b))
6830 /* This hard limit is ok since the string it will hold has a
6831 fixed maximum length of 3. But just to be safe... */
6833 Charcount chars = pos - BUF_BEGV (b);
6834 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6836 /* Avoid overflow on big buffers */
6837 int percent = total > LONG_MAX/200 ?
6838 (chars + total/200) / (total / 100) :
6839 (chars * 100 + total/2) / total;
6841 /* We can't normally display a 3-digit number, so get us a
6842 2-digit number that is close. */
6846 sprintf (buf, "%d%%", percent);
6847 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6850 goto decode_mode_spec_done;
6855 /* print percent of buffer above bottom of window, perhaps plus
6856 Top, or print Bottom or All */
6859 Bufpos toppos = marker_position (w->start[type]);
6860 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
6862 /* botpos is only accurate as of the last redisplay, so we can
6863 only treat it as a hint. In particular, after erase-buffer,
6864 botpos may be negative. */
6865 if (botpos < toppos)
6868 if (botpos >= BUF_ZV (b))
6870 if (toppos <= BUF_BEGV (b))
6877 /* This hard limit is ok since the string it will hold has a
6878 fixed maximum length of around 6. But just to be safe... */
6880 Charcount chars = botpos - BUF_BEGV (b);
6881 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6883 /* Avoid overflow on big buffers */
6884 int percent = total > LONG_MAX/200 ?
6885 (chars + total/200) / (total / 100) :
6886 (chars * 100 + total/2) / max (total, 1);
6888 /* We can't normally display a 3-digit number, so get us a
6889 2-digit number that is close. */
6893 if (toppos <= BUF_BEGV (b))
6894 sprintf (buf, "Top%d%%", percent);
6896 sprintf (buf, "%d%%", percent);
6898 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6901 goto decode_mode_spec_done;
6911 /* print one [ for each recursive editing level. */
6916 if (command_loop_level > 5)
6922 for (i = 0; i < command_loop_level; i++)
6923 Dynarr_add (mode_spec_bufbyte_string, '[');
6925 goto decode_mode_spec_done;
6928 /* print one ] for each recursive editing level. */
6933 if (command_loop_level > 5)
6939 for (i = 0; i < command_loop_level; i++)
6940 Dynarr_add (mode_spec_bufbyte_string, ']');
6942 goto decode_mode_spec_done;
6945 /* print infinitely many dashes -- handle at top level now */
6952 Dynarr_add_many (mode_spec_bufbyte_string,
6954 XSTRING_LENGTH (obj));
6956 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6958 decode_mode_spec_done:
6959 Dynarr_add (mode_spec_bufbyte_string, '\0');
6962 /* Given a display line, free all of its data structures. */
6965 free_display_line (struct display_line *dl)
6969 if (dl->display_blocks)
6971 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6973 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6975 Dynarr_free (db->runes);
6978 Dynarr_free (dl->display_blocks);
6979 dl->display_blocks = NULL;
6982 if (dl->left_glyphs)
6984 Dynarr_free (dl->left_glyphs);
6985 dl->left_glyphs = NULL;
6988 if (dl->right_glyphs)
6990 Dynarr_free (dl->right_glyphs);
6991 dl->right_glyphs = NULL;
6996 /* Given an array of display lines, free them and all data structures
6997 contained within them. */
7000 free_display_lines (display_line_dynarr *dla)
7004 for (line = 0; line < Dynarr_largest (dla); line++)
7006 free_display_line (Dynarr_atp (dla, line));
7012 /* Call internal free routine for each set of display lines. */
7015 free_display_structs (struct window_mirror *mir)
7017 if (mir->current_display_lines)
7019 free_display_lines (mir->current_display_lines);
7020 mir->current_display_lines = 0;
7023 if (mir->desired_display_lines)
7025 free_display_lines (mir->desired_display_lines);
7026 mir->desired_display_lines = 0;
7032 mark_glyph_block_dynarr (glyph_block_dynarr *gba)
7036 glyph_block *gb = Dynarr_atp (gba, 0);
7037 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
7039 for (; gb < gb_last; gb++)
7041 if (!NILP (gb->glyph))
7042 mark_object (gb->glyph);
7043 if (!NILP (gb->extent))
7044 mark_object (gb->extent);
7049 /* See the comment in image_instantiate_cache_result as to why marking
7050 the glyph will also mark the image_instance. */
7052 mark_redisplay_structs (display_line_dynarr *dla)
7054 display_line *dl = Dynarr_atp (dla, 0);
7055 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
7057 for (; dl < dl_last; dl++)
7059 display_block_dynarr *dba = dl->display_blocks;
7060 display_block *db = Dynarr_atp (dba, 0);
7061 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
7063 for (; db < db_last; db++)
7065 rune_dynarr *ra = db->runes;
7066 rune *r = Dynarr_atp (ra, 0);
7067 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
7069 for (; r < r_last; r++)
7071 if (r->type == RUNE_DGLYPH)
7073 if (!NILP (r->object.dglyph.glyph))
7074 mark_object (r->object.dglyph.glyph);
7075 if (!NILP (r->object.dglyph.extent))
7076 mark_object (r->object.dglyph.extent);
7081 mark_glyph_block_dynarr (dl->left_glyphs);
7082 mark_glyph_block_dynarr (dl->right_glyphs);
7087 mark_window_mirror (struct window_mirror *mir)
7089 mark_redisplay_structs (mir->current_display_lines);
7090 mark_redisplay_structs (mir->desired_display_lines);
7093 mark_window_mirror (mir->next);
7096 mark_window_mirror (mir->hchild);
7097 else if (mir->vchild)
7098 mark_window_mirror (mir->vchild);
7102 mark_redisplay (void)
7104 Lisp_Object frmcons, devcons, concons;
7106 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
7108 struct frame *f = XFRAME (XCAR (frmcons));
7109 update_frame_window_mirror (f);
7110 mark_window_mirror (f->root_mirror);
7115 /*****************************************************************************
7116 Line Start Cache Description and Rationale
7118 The traditional scrolling code in Emacs breaks in a variable height world.
7119 It depends on the key assumption that the number of lines that can be
7120 displayed at any given time is fixed. This led to a complete separation
7121 of the scrolling code from the redisplay code. In order to fully support
7122 variable height lines, the scrolling code must actually be tightly
7123 integrated with redisplay. Only redisplay can determine how many lines
7124 will be displayed on a screen for any given starting point.
7126 What is ideally wanted is a complete list of the starting buffer position
7127 for every possible display line of a buffer along with the height of that
7128 display line. Maintaining such a full list would be very expensive. We
7129 settle for having it include information for all areas which we happen to
7130 generate anyhow (i.e. the region currently being displayed) and for those
7131 areas we need to work with.
7133 In order to ensure that the cache accurately represents what redisplay
7134 would actually show, it is necessary to invalidate it in many situations.
7135 If the buffer changes, the starting positions may no longer be correct.
7136 If a face or an extent has changed then the line heights may have altered.
7137 These events happen frequently enough that the cache can end up being
7138 constantly disabled. With this potentially constant invalidation when is
7139 the cache ever useful?
7141 Even if the cache is invalidated before every single usage, it is
7142 necessary. Scrolling often requires knowledge about display lines which
7143 are actually above or below the visible region. The cache provides a
7144 convenient light-weight method of storing this information for multiple
7145 display regions. This knowledge is necessary for the scrolling code to
7146 always obey the First Golden Rule of Redisplay.
7148 If the cache already contains all of the information that the scrolling
7149 routines happen to need so that it doesn't have to go generate it, then we
7150 are able to obey the Third Golden Rule of Redisplay. The first thing we
7151 do to help out the cache is to always add the displayed region. This
7152 region had to be generated anyway, so the cache ends up getting the
7153 information basically for free. In those cases where a user is simply
7154 scrolling around viewing a buffer there is a high probability that this is
7155 sufficient to always provide the needed information. The second thing we
7156 can do is be smart about invalidating the cache.
7158 TODO -- Be smart about invalidating the cache. Potential places:
7160 + Insertions at end-of-line which don't cause line-wraps do not alter the
7161 starting positions of any display lines. These types of buffer
7162 modifications should not invalidate the cache. This is actually a large
7163 optimization for redisplay speed as well.
7165 + Buffer modifications frequently only affect the display of lines at and
7166 below where they occur. In these situations we should only invalidate
7167 the part of the cache starting at where the modification occurs.
7169 In case you're wondering, the Second Golden Rule of Redisplay is not
7171 ****************************************************************************/
7173 /* This will get used quite a bit so we don't want to be constantly
7174 allocating and freeing it. */
7175 static line_start_cache_dynarr *internal_cache;
7177 /* Makes internal_cache represent the TYPE display structs and only
7178 the TYPE display structs. */
7181 update_internal_cache_list (struct window *w, int type)
7184 display_line_dynarr *dla = window_display_lines (w, type);
7186 Dynarr_reset (internal_cache);
7187 for (line = 0; line < Dynarr_length (dla); line++)
7189 struct display_line *dl = Dynarr_atp (dla, line);
7195 struct line_start_cache lsc;
7197 lsc.start = dl->bufpos;
7198 lsc.end = dl->end_bufpos;
7199 lsc.height = dl->ascent + dl->descent;
7201 Dynarr_add (internal_cache, lsc);
7206 /* Reset the line cache if necessary. This should be run at the
7207 beginning of any function which access the cache. */
7210 validate_line_start_cache (struct window *w)
7212 struct buffer *b = XBUFFER (w->buffer);
7213 struct frame *f = XFRAME (w->frame);
7215 if (!w->line_cache_validation_override)
7217 /* f->extents_changed used to be in here because extent face and
7218 size changes can cause text shifting. However, the extent
7219 covering the region is constantly having its face set and
7220 priority altered by the mouse code. This means that the line
7221 start cache is constantly being invalidated. This is bad
7222 since the mouse code also triggers heavy usage of the cache.
7223 Since it is an unlikely that f->extents being changed
7224 indicates that the cache really needs to be updated and if it
7225 does redisplay will catch it pretty quickly we no longer
7226 invalidate the cache if it is set. This greatly speeds up
7227 dragging out regions with the mouse. */
7228 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
7232 Dynarr_reset (w->line_start_cache);
7237 /* Return the very first buffer position contained in the given
7238 window's cache, or -1 if the cache is empty. Assumes that the
7242 line_start_cache_start (struct window *w)
7244 line_start_cache_dynarr *cache = w->line_start_cache;
7246 if (!Dynarr_length (cache))
7249 return Dynarr_atp (cache, 0)->start;
7252 /* Return the very last buffer position contained in the given
7253 window's cache, or -1 if the cache is empty. Assumes that the
7257 line_start_cache_end (struct window *w)
7259 line_start_cache_dynarr *cache = w->line_start_cache;
7261 if (!Dynarr_length (cache))
7264 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7267 /* Return the index of the line POINT is contained within in window
7268 W's line start cache. It will enlarge the cache or move the cache
7269 window in order to have POINT be present in the cache. MIN_PAST is
7270 a guarantee of the number of entries in the cache present on either
7271 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7272 then it will be treated as 0, but the cache window will not be
7273 allowed to shift. Returns -1 if POINT cannot be found in the cache
7277 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
7279 struct buffer *b = XBUFFER (w->buffer);
7280 line_start_cache_dynarr *cache = w->line_start_cache;
7281 unsigned int top, bottom, pos;
7283 validate_line_start_cache (w);
7284 w->line_cache_validation_override++;
7286 /* Let functions pass in negative values, but we still treat -1
7288 /* #### bogosity alert */
7289 if (min_past < 0 && min_past != -1)
7290 min_past = -min_past;
7292 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
7293 || line_start_cache_end (w) < point)
7296 int win_char_height = window_char_height (w, 1);
7298 /* Occasionally we get here with a 0 height
7299 window. find_next_newline_no_quit will abort if we pass it a
7300 count of 0 so handle that case. */
7301 if (!win_char_height)
7302 win_char_height = 1;
7304 if (!Dynarr_length (cache))
7306 Bufpos from = find_next_newline_no_quit (b, point, -1);
7307 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
7309 update_line_start_cache (w, from, to, point, 0);
7311 if (!Dynarr_length (cache))
7313 w->line_cache_validation_override--;
7318 assert (Dynarr_length (cache));
7321 while (line_start_cache_start (w) > point
7322 && (loop < cache_adjustment || min_past == -1))
7326 from = line_start_cache_start (w);
7327 if (from <= BUF_BEGV (b))
7330 from = find_next_newline_no_quit (b, from, -win_char_height);
7331 to = line_start_cache_end (w);
7333 update_line_start_cache (w, from, to, point, 0);
7337 if (line_start_cache_start (w) > point)
7341 from = find_next_newline_no_quit (b, point, -1);
7342 if (from >= BUF_ZV (b))
7344 to = find_next_newline_no_quit (b, from, -win_char_height);
7349 to = find_next_newline_no_quit (b, from, win_char_height);
7351 update_line_start_cache (w, from, to, point, 0);
7355 while (line_start_cache_end (w) < point
7356 && (loop < cache_adjustment || min_past == -1))
7360 to = line_start_cache_end (w);
7361 if (to >= BUF_ZV (b))
7364 from = line_start_cache_end (w);
7365 to = find_next_newline_no_quit (b, from, win_char_height);
7367 update_line_start_cache (w, from, to, point, 0);
7371 if (line_start_cache_end (w) < point)
7375 from = find_next_newline_no_quit (b, point, -1);
7376 if (from >= BUF_ZV (b))
7378 to = find_next_newline_no_quit (b, from, -win_char_height);
7383 to = find_next_newline_no_quit (b, from, win_char_height);
7385 update_line_start_cache (w, from, to, point, 0);
7389 assert (Dynarr_length (cache));
7394 /* This could happen if the buffer is narrowed. */
7395 if (line_start_cache_start (w) > point
7396 || line_start_cache_end (w) < point)
7398 w->line_cache_validation_override--;
7404 top = Dynarr_length (cache) - 1;
7409 unsigned int new_pos;
7412 pos = (bottom + top + 1) >> 1;
7413 start = Dynarr_atp (cache, pos)->start;
7414 end = Dynarr_atp (cache, pos)->end;
7416 if (point >= start && point <= end)
7418 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
7421 find_next_newline_no_quit (b, line_start_cache_start (w),
7423 Bufpos to = line_start_cache_end (w);
7425 update_line_start_cache (w, from, to, point, 0);
7426 goto find_point_loop;
7428 else if ((Dynarr_length (cache) - pos - 1) < min_past
7429 && line_start_cache_end (w) < BUF_ZV (b))
7431 Bufpos from = line_start_cache_end (w);
7432 Bufpos to = find_next_newline_no_quit (b, from,
7437 update_line_start_cache (w, from, to, point, 0);
7438 goto find_point_loop;
7442 w->line_cache_validation_override--;
7446 else if (point > end)
7448 else if (point < start)
7453 new_pos = (bottom + top + 1) >> 1;
7456 w->line_cache_validation_override--;
7462 /* Return a boolean indicating if POINT would be visible in window W
7463 if display of the window was to begin at STARTP. */
7466 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
7468 struct buffer *b = XBUFFER (w->buffer);
7469 int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
7470 int bottom = WINDOW_TEXT_HEIGHT (w);
7473 /* If point is before the intended start it obviously can't be visible. */
7477 /* If point or start are not in the accessible buffer range, then
7479 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
7480 || point < BUF_BEGV (b) || point > BUF_ZV (b))
7483 validate_line_start_cache (w);
7484 w->line_cache_validation_override++;
7486 start_elt = point_in_line_start_cache (w, startp, 0);
7487 if (start_elt == -1)
7489 w->line_cache_validation_override--;
7493 assert (line_start_cache_start (w) <= startp
7494 && line_start_cache_end (w) >= startp);
7500 /* Expand the cache if necessary. */
7501 if (start_elt == Dynarr_length (w->line_start_cache))
7504 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
7506 start_elt = point_in_line_start_cache (w, old_startp,
7507 window_char_height (w, 0));
7509 /* We've already actually processed old_startp, so increment
7513 /* If this happens we didn't add any extra elements. Bummer. */
7514 if (start_elt == Dynarr_length (w->line_start_cache))
7516 w->line_cache_validation_override--;
7521 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
7523 if (pixpos + height > bottom)
7525 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7527 w->line_cache_validation_override--;
7533 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
7535 w->line_cache_validation_override--;
7543 /* For the given window W, if display starts at STARTP, what will be
7544 the buffer position at the beginning or end of the last line
7545 displayed. The end of the last line is also know as the window end
7548 WARNING: It is possible that redisplay failed to layout any lines for the
7549 windows. Under normal circumstances this is rare. However it seems that it
7550 does occur in the following situation: A mouse event has come in and we
7551 need to compute its location in a window. That code (in
7552 pixel_to_glyph_translation) already can handle 0 as an error return value.
7554 #### With a little work this could probably be reworked as just a
7555 call to start_with_line_at_pixpos. */
7558 start_end_of_last_line (struct window *w, Bufpos startp, int end,
7561 struct buffer *b = XBUFFER (w->buffer);
7562 line_start_cache_dynarr *cache = w->line_start_cache;
7564 int bottom = WINDOW_TEXT_HEIGHT (w);
7568 validate_line_start_cache (w);
7569 w->line_cache_validation_override++;
7571 if (startp < BUF_BEGV (b))
7572 startp = BUF_BEGV (b);
7573 else if (startp > BUF_ZV (b))
7574 startp = BUF_ZV (b);
7577 start_elt = point_in_line_start_cache (w, cur_start, 0);
7578 if (start_elt == -1)
7579 return may_error ? 0 : startp;
7583 int height = Dynarr_atp (cache, start_elt)->height;
7585 cur_start = Dynarr_atp (cache, start_elt)->start;
7587 if (pixpos + height > bottom)
7589 /* Adjust for any possible clip. */
7590 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7595 w->line_cache_validation_override--;
7599 return BUF_BEGV (b);
7603 w->line_cache_validation_override--;
7605 return Dynarr_atp (cache, start_elt)->end;
7607 return Dynarr_atp (cache, start_elt)->start;
7613 if (start_elt == Dynarr_length (cache))
7615 Bufpos from = line_start_cache_end (w);
7616 int win_char_height = window_char_height (w, 0);
7617 Bufpos to = find_next_newline_no_quit (b, from,
7622 /* We've hit the end of the bottom so that's what it is. */
7623 if (from >= BUF_ZV (b))
7625 w->line_cache_validation_override--;
7629 update_line_start_cache (w, from, to, BUF_PT (b), 0);
7631 /* Updating the cache invalidates any current indexes. */
7632 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
7637 /* For the given window W, if display starts at STARTP, what will be
7638 the buffer position at the beginning of the last line displayed. */
7641 start_of_last_line (struct window *w, Bufpos startp)
7643 return start_end_of_last_line (w, startp, 0 , 0);
7646 /* For the given window W, if display starts at STARTP, what will be
7647 the buffer position at the end of the last line displayed. This is
7648 also know as the window end position. */
7651 end_of_last_line (struct window *w, Bufpos startp)
7653 return start_end_of_last_line (w, startp, 1, 0);
7657 end_of_last_line_may_error (struct window *w, Bufpos startp)
7659 return start_end_of_last_line (w, startp, 1, 1);
7663 /* For window W, what does the starting position have to be so that
7664 the line containing POINT will cover pixel position PIXPOS. */
7667 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
7669 struct buffer *b = XBUFFER (w->buffer);
7671 Bufpos cur_pos, prev_pos = point;
7672 int point_line_height;
7673 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
7675 validate_line_start_cache (w);
7676 w->line_cache_validation_override++;
7678 cur_elt = point_in_line_start_cache (w, point, 0);
7679 /* #### See comment in update_line_start_cache about big minibuffers. */
7682 w->line_cache_validation_override--;
7686 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
7690 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7692 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7694 /* Do not take into account the value of vertical_clip here.
7695 That is the responsibility of the calling functions. */
7698 w->line_cache_validation_override--;
7699 if (-pixheight > point_line_height)
7700 /* We can't make the target line cover pixpos, so put it
7701 above pixpos. That way it will at least be visible. */
7711 int win_char_height;
7713 if (cur_pos <= BUF_BEGV (b))
7715 w->line_cache_validation_override--;
7716 return BUF_BEGV (b);
7719 win_char_height = window_char_height (w, 0);
7720 if (!win_char_height)
7721 win_char_height = 1;
7723 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
7724 to = line_start_cache_end (w);
7725 update_line_start_cache (w, from, to, point, 0);
7727 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
7728 assert (cur_elt >= -1);
7729 /* This used to be cur_elt>=0 under the assumption that if
7730 point is in the top line and not at BUF_BEGV, then
7731 setting the window_start to a newline before the start of
7732 the first line will always cause scrolling.
7734 However in my (jv) opinion this is wrong. That new line
7735 can be hidden in various ways: invisible extents, an
7736 explicit window-start not at a newline character etc.
7737 The existence of those are indeed known to create crashes
7738 on that assert. So we have no option but to continue the
7739 search if we found point at the top of the line_start_cache
7741 cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
7747 /* For window W, what does the starting position have to be so that
7748 the line containing point is on display line LINE. If LINE is
7749 positive it is considered to be the number of lines from the top of
7750 the window (0 is the top line). If it is negative the number is
7751 considered to be the number of lines from the bottom (-1 is the
7755 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
7757 validate_line_start_cache (w);
7758 w->line_cache_validation_override++;
7762 int cur_elt = point_in_line_start_cache (w, point, line);
7764 if (cur_elt - line < 0)
7765 cur_elt = 0; /* Hit the top */
7769 w->line_cache_validation_override--;
7770 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
7774 /* The calculated value of pixpos is correct for the bottom line
7775 or what we want when line is -1. Therefore we subtract one
7776 because we have already handled one line. */
7777 int new_line = -line - 1;
7778 int cur_elt = point_in_line_start_cache (w, point, new_line);
7779 int pixpos = WINDOW_TEXT_BOTTOM (w);
7780 Bufpos retval, search_point;
7782 /* If scroll_on_clipped_lines is false, the last "visible" line of
7783 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7784 If s_o_c_l is true, then we don't want to count a clipped
7785 line, so back up from the bottom by the height of the line
7786 containing point. */
7787 if (scroll_on_clipped_lines)
7788 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7792 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
7794 /* Hit the bottom of the buffer. */
7796 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
7800 XSETWINDOW (window, w);
7801 default_face_height_and_width (window, &defheight, 0);
7803 cur_elt = Dynarr_length (w->line_start_cache) - 1;
7805 pixpos -= (adjustment * defheight);
7806 if (pixpos < WINDOW_TEXT_TOP (w))
7807 pixpos = WINDOW_TEXT_TOP (w);
7810 cur_elt = cur_elt + new_line;
7812 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7814 retval = start_with_line_at_pixpos (w, search_point, pixpos);
7815 w->line_cache_validation_override--;
7820 /* This is used to speed up vertical scrolling by caching the known
7821 buffer starting positions for display lines. This allows the
7822 scrolling routines to avoid costly calls to regenerate_window. If
7823 NO_REGEN is true then it will only add the values in the DESIRED
7824 display structs which are in the given range.
7826 Note also that the FROM/TO values are minimums. It is possible
7827 that this function will actually add information outside of the
7828 lines containing those positions. This can't hurt but it could
7831 #### We currently force the cache to have only 1 contiguous region.
7832 It might help to make the cache a dynarr of caches so that we can
7833 cover more areas. This might, however, turn out to be a lot of
7834 overhead for too little gain. */
7837 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
7838 Bufpos point, int no_regen)
7840 struct buffer *b = XBUFFER (w->buffer);
7841 line_start_cache_dynarr *cache = w->line_start_cache;
7842 Bufpos low_bound, high_bound;
7844 validate_line_start_cache (w);
7845 w->line_cache_validation_override++;
7847 if (from < BUF_BEGV (b))
7848 from = BUF_BEGV (b);
7849 if (to > BUF_ZV (b))
7854 w->line_cache_validation_override--;
7858 if (Dynarr_length (cache))
7860 low_bound = line_start_cache_start (w);
7861 high_bound = line_start_cache_end (w);
7863 /* Check to see if the desired range is already in the cache. */
7864 if (from >= low_bound && to <= high_bound)
7866 w->line_cache_validation_override--;
7870 /* Check to make sure that the desired range is adjacent to the
7871 current cache. If not, invalidate the cache. */
7872 if (to < low_bound || from > high_bound)
7874 Dynarr_reset (cache);
7875 low_bound = high_bound = -1;
7880 low_bound = high_bound = -1;
7883 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
7885 /* This could be integrated into the next two sections, but it is easier
7886 to follow what's going on by having it separate. */
7891 update_internal_cache_list (w, DESIRED_DISP);
7892 if (!Dynarr_length (internal_cache))
7894 w->line_cache_validation_override--;
7898 start = Dynarr_atp (internal_cache, 0)->start;
7900 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
7902 /* We aren't allowed to generate additional information to fill in
7903 gaps, so if the DESIRED structs don't overlap the cache, reset the
7905 if (Dynarr_length (cache))
7907 if (end < low_bound || start > high_bound)
7908 Dynarr_reset (cache);
7910 /* #### What should really happen if what we are doing is
7911 extending a line (the last line)? */
7912 if (Dynarr_length (cache) == 1
7913 && Dynarr_length (internal_cache) == 1)
7914 Dynarr_reset (cache);
7917 if (!Dynarr_length (cache))
7919 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7920 Dynarr_length (internal_cache));
7921 w->line_cache_validation_override--;
7925 /* An extra check just in case the calling function didn't pass in
7926 the bounds of the DESIRED structs in the first place. */
7927 if (start >= low_bound && end <= high_bound)
7929 w->line_cache_validation_override--;
7933 /* At this point we know that the internal cache partially overlaps
7935 if (start < low_bound)
7937 int ic_elt = Dynarr_length (internal_cache) - 1;
7940 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7948 Dynarr_reset (cache);
7949 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7950 Dynarr_length (internal_cache));
7951 w->line_cache_validation_override--;
7955 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7959 if (end > high_bound)
7963 while (ic_elt < Dynarr_length (internal_cache))
7965 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7971 if (!(ic_elt < Dynarr_length (internal_cache)))
7973 Dynarr_reset (cache);
7974 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7975 Dynarr_length (internal_cache));
7976 w->line_cache_validation_override--;
7980 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7981 Dynarr_length (internal_cache) - ic_elt);
7984 w->line_cache_validation_override--;
7988 if (!Dynarr_length (cache) || from < low_bound)
7990 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7992 int old_lb = low_bound;
7994 while (startp < old_lb || low_bound == -1)
7999 regenerate_window (w, startp, point, CMOTION_DISP);
8000 update_internal_cache_list (w, CMOTION_DISP);
8002 /* If this assert is triggered then regenerate_window failed
8003 to layout a single line. This is not possible since we
8004 force at least a single line to be layout for CMOTION_DISP */
8005 assert (Dynarr_length (internal_cache));
8006 assert (startp == Dynarr_atp (internal_cache, 0)->start);
8008 ic_elt = Dynarr_length (internal_cache) - 1;
8009 if (low_bound != -1)
8013 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
8019 assert (ic_elt >= 0);
8021 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
8024 * Handle invisible text properly:
8025 * If the last line we're inserting has the same end as the
8026 * line before which it will be added, merge the two lines.
8028 if (Dynarr_length (cache) &&
8029 Dynarr_atp (internal_cache, ic_elt)->end ==
8030 Dynarr_atp (cache, marker)->end)
8032 Dynarr_atp (cache, marker)->start
8033 = Dynarr_atp (internal_cache, ic_elt)->start;
8034 Dynarr_atp (cache, marker)->height
8035 = Dynarr_atp (internal_cache, ic_elt)->height;
8039 if (ic_elt >= 0) /* we still have lines to add.. */
8041 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
8042 ic_elt + 1, marker);
8043 marker += (ic_elt + 1);
8046 if (startp < low_bound || low_bound == -1)
8048 startp = new_startp;
8049 if (startp > BUF_ZV (b))
8051 w->line_cache_validation_override--;
8057 assert (Dynarr_length (cache));
8058 assert (from >= low_bound);
8060 /* Readjust the high_bound to account for any changes made while
8061 correcting the low_bound. */
8062 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8064 if (to > high_bound)
8066 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
8070 regenerate_window (w, startp, point, CMOTION_DISP);
8071 update_internal_cache_list (w, CMOTION_DISP);
8073 /* See comment above about regenerate_window failing. */
8074 assert (Dynarr_length (internal_cache));
8076 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
8077 Dynarr_length (internal_cache));
8078 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8079 startp = high_bound + 1;
8081 while (to > high_bound);
8084 w->line_cache_validation_override--;
8085 assert (to <= high_bound);
8089 /* Given x and y coordinates in characters, relative to a window,
8090 return the pixel location corresponding to those coordinates. The
8091 pixel location returned is the center of the given character
8092 position. The pixel values are generated relative to the window,
8095 The modeline is considered to be part of the window. */
8098 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
8099 int *pix_x, int *pix_y)
8101 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
8102 int num_disp_lines, modeline;
8104 int defheight, defwidth;
8106 XSETWINDOW (window, w);
8107 default_face_height_and_width (window, &defheight, &defwidth);
8109 /* If we get a bogus value indicating somewhere above or to the left of
8110 the window, use the first window line or character position
8117 num_disp_lines = Dynarr_length (dla);
8121 if (Dynarr_atp (dla, 0)->modeline)
8128 /* First check if the y position intersects the display lines. */
8129 if (char_y < num_disp_lines)
8131 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
8132 struct display_block *db = get_display_block_from_line (dl, TEXT);
8134 *pix_y = (dl->ypos - dl->ascent +
8135 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
8137 if (char_x < Dynarr_length (db->runes))
8139 struct rune *rb = Dynarr_atp (db->runes, char_x);
8141 *pix_x = rb->xpos + (rb->width >> 1);
8145 int last_rune = Dynarr_length (db->runes) - 1;
8146 struct rune *rb = Dynarr_atp (db->runes, last_rune);
8148 char_x -= last_rune;
8150 *pix_x = rb->xpos + rb->width;
8151 *pix_x += ((char_x - 1) * defwidth);
8152 *pix_x += (defwidth >> 1);
8157 /* It didn't intersect, so extrapolate. #### For now, we include the
8158 modeline in this since we don't have true character positions in
8161 if (!Dynarr_length (w->face_cachels))
8162 reset_face_cachels (w);
8164 char_y -= num_disp_lines;
8166 if (Dynarr_length (dla))
8168 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
8169 *pix_y = dl->ypos + dl->descent - dl->clip;
8172 *pix_y = WINDOW_TEXT_TOP (w);
8174 *pix_y += (char_y * defheight);
8175 *pix_y += (defheight >> 1);
8177 *pix_x = WINDOW_TEXT_LEFT (w);
8178 /* Don't adjust by one because this is still the unadjusted value. */
8179 *pix_x += (char_x * defwidth);
8180 *pix_x += (defwidth >> 1);
8183 if (*pix_x > w->pixel_left + w->pixel_width)
8184 *pix_x = w->pixel_left + w->pixel_width;
8185 if (*pix_y > w->pixel_top + w->pixel_height)
8186 *pix_y = w->pixel_top + w->pixel_height;
8188 *pix_x -= w->pixel_left;
8189 *pix_y -= w->pixel_top;
8192 /* Given a display line and a position, determine if there is a glyph
8193 there and return information about it if there is. */
8196 get_position_object (struct display_line *dl, Lisp_Object *obj1,
8197 Lisp_Object *obj2, int x_coord, int *low_x_coord,
8200 struct display_block *db;
8203 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
8205 /* We use get_next_display_block to get the actual display block
8206 that would be displayed at x_coord. */
8208 if (block == NO_BLOCK)
8211 db = Dynarr_atp (dl->display_blocks, block);
8213 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
8215 struct rune *rb = Dynarr_atp (db->runes, elt);
8217 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
8219 if (rb->type == RUNE_DGLYPH)
8221 *obj1 = rb->object.dglyph.glyph;
8222 *obj2 = rb->object.dglyph.extent;
8231 *low_x_coord = rb->xpos;
8233 *high_x_coord = rb->xpos + rb->width;
8240 #define UPDATE_CACHE_RETURN \
8242 d->pixel_to_glyph_cache.valid = 1; \
8243 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8244 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8245 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8246 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8247 d->pixel_to_glyph_cache.frame = f; \
8248 d->pixel_to_glyph_cache.col = *col; \
8249 d->pixel_to_glyph_cache.row = *row; \
8250 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8251 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8252 d->pixel_to_glyph_cache.w = *w; \
8253 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8254 d->pixel_to_glyph_cache.closest = *closest; \
8255 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8256 d->pixel_to_glyph_cache.obj1 = *obj1; \
8257 d->pixel_to_glyph_cache.obj2 = *obj2; \
8258 d->pixel_to_glyph_cache.retval = position; \
8259 RETURN_SANS_WARNINGS position; \
8262 /* Given x and y coordinates in pixels relative to a frame, return
8263 information about what is located under those coordinates.
8265 The return value will be one of:
8267 OVER_TOOLBAR: over one of the 4 frame toolbars
8268 OVER_MODELINE: over a modeline
8269 OVER_BORDER: over an internal border
8270 OVER_NOTHING: over the text area, but not over text
8271 OVER_OUTSIDE: outside of the frame border
8272 OVER_TEXT: over text in the text area
8278 -- nil if the coordinates are not over a glyph or a toolbar button.
8282 -- an extent, if the coordinates are over a glyph in the text area
8285 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8286 equivalent coordinates relative to the upper-left corner of the glyph.
8288 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8289 equivalent coordinates relative to the upper-left corner of the character.
8291 Otherwise, OBJ_X and OBJ_Y are undefined.
8295 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
8296 int *col, int *row, int *obj_x, int *obj_y,
8297 struct window **w, Bufpos *bufpos,
8298 Bufpos *closest, Charcount *modeline_closest,
8299 Lisp_Object *obj1, Lisp_Object *obj2)
8302 struct pixel_to_glyph_translation_cache *cache;
8304 int frm_left, frm_right, frm_top, frm_bottom;
8305 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8306 int position = OVER_NOTHING;
8307 int device_check_failed = 0;
8308 display_line_dynarr *dla;
8310 /* This is a safety valve in case this got called with a frame in
8311 the middle of being deleted. */
8312 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
8314 device_check_failed = 1;
8315 d = NULL, cache = NULL; /* Warning suppression */
8319 d = XDEVICE (f->device);
8320 cache = &d->pixel_to_glyph_cache;
8323 if (!device_check_failed
8325 && cache->frame == f
8326 && cache->low_x_coord <= x_coord
8327 && cache->high_x_coord > x_coord
8328 && cache->low_y_coord <= y_coord
8329 && cache->high_y_coord > y_coord)
8333 *obj_x = cache->obj_x;
8334 *obj_y = cache->obj_y;
8336 *bufpos = cache->bufpos;
8337 *closest = cache->closest;
8338 *modeline_closest = cache->modeline_closest;
8339 *obj1 = cache->obj1;
8340 *obj2 = cache->obj2;
8342 return cache->retval;
8353 *modeline_closest = -1;
8357 low_x_coord = x_coord;
8358 high_x_coord = x_coord + 1;
8359 low_y_coord = y_coord;
8360 high_y_coord = y_coord + 1;
8363 if (device_check_failed)
8364 return OVER_NOTHING;
8366 frm_left = FRAME_LEFT_BORDER_END (f);
8367 frm_right = FRAME_RIGHT_BORDER_START (f);
8368 frm_top = FRAME_TOP_BORDER_END (f);
8369 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
8371 /* Check if the mouse is outside of the text area actually used by
8373 if (y_coord < frm_top)
8375 if (y_coord >= FRAME_TOP_BORDER_START (f))
8377 low_y_coord = FRAME_TOP_BORDER_START (f);
8378 high_y_coord = frm_top;
8379 position = OVER_BORDER;
8381 else if (y_coord >= 0)
8384 high_y_coord = FRAME_TOP_BORDER_START (f);
8385 position = OVER_TOOLBAR;
8389 low_y_coord = y_coord;
8391 position = OVER_OUTSIDE;
8394 else if (y_coord >= frm_bottom)
8396 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
8398 low_y_coord = frm_bottom;
8399 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
8400 position = OVER_BORDER;
8402 else if (y_coord < FRAME_PIXHEIGHT (f))
8404 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
8405 high_y_coord = FRAME_PIXHEIGHT (f);
8406 position = OVER_TOOLBAR;
8410 low_y_coord = FRAME_PIXHEIGHT (f);
8411 high_y_coord = y_coord;
8412 position = OVER_OUTSIDE;
8416 if (position != OVER_TOOLBAR && position != OVER_BORDER)
8418 if (x_coord < frm_left)
8420 if (x_coord >= FRAME_LEFT_BORDER_START (f))
8422 low_x_coord = FRAME_LEFT_BORDER_START (f);
8423 high_x_coord = frm_left;
8424 position = OVER_BORDER;
8426 else if (x_coord >= 0)
8429 high_x_coord = FRAME_LEFT_BORDER_START (f);
8430 position = OVER_TOOLBAR;
8434 low_x_coord = x_coord;
8436 position = OVER_OUTSIDE;
8439 else if (x_coord >= frm_right)
8441 if (x_coord < FRAME_RIGHT_BORDER_END (f))
8443 low_x_coord = frm_right;
8444 high_x_coord = FRAME_RIGHT_BORDER_END (f);
8445 position = OVER_BORDER;
8447 else if (x_coord < FRAME_PIXWIDTH (f))
8449 low_x_coord = FRAME_RIGHT_BORDER_END (f);
8450 high_x_coord = FRAME_PIXWIDTH (f);
8451 position = OVER_TOOLBAR;
8455 low_x_coord = FRAME_PIXWIDTH (f);
8456 high_x_coord = x_coord;
8457 position = OVER_OUTSIDE;
8462 #ifdef HAVE_TOOLBARS
8463 if (position == OVER_TOOLBAR)
8465 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
8468 UPDATE_CACHE_RETURN;
8470 #endif /* HAVE_TOOLBARS */
8472 /* We still have to return the window the pointer is next to and its
8473 relative y position even if it is outside the x boundary. */
8474 if (x_coord < frm_left)
8476 else if (x_coord > frm_right)
8477 x_coord = frm_right;
8479 /* Same in reverse. */
8480 if (y_coord < frm_top)
8482 else if (y_coord > frm_bottom)
8483 y_coord = frm_bottom;
8485 /* Find what window the given coordinates are actually in. */
8486 window = f->root_window;
8487 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
8489 /* If we didn't find a window, we're done. */
8492 UPDATE_CACHE_RETURN;
8494 else if (position != OVER_NOTHING)
8497 *modeline_closest = -1;
8499 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
8502 UPDATE_CACHE_RETURN;
8506 /* Check if the window is a minibuffer but isn't active. */
8507 if (MINI_WINDOW_P (*w) && !minibuf_level)
8509 /* Must reset the window value since some callers will ignore
8510 the return value if it is set. */
8512 UPDATE_CACHE_RETURN;
8515 /* See if the point is over window vertical divider */
8516 if (window_needs_vertical_divider (*w))
8518 int div_x_high = WINDOW_RIGHT (*w);
8519 int div_x_low = div_x_high - window_divider_width (*w);
8520 int div_y_high = WINDOW_BOTTOM (*w);
8521 int div_y_low = WINDOW_TOP (*w);
8523 if (div_x_low < x_coord && x_coord <= div_x_high &&
8524 div_y_low < y_coord && y_coord <= div_y_high)
8526 low_x_coord = div_x_low;
8527 high_x_coord = div_x_high;
8528 low_y_coord = div_y_low;
8529 high_y_coord = div_y_high;
8530 position = OVER_V_DIVIDER;
8531 UPDATE_CACHE_RETURN;
8535 dla = window_display_lines (*w, CURRENT_DISP);
8537 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
8539 int really_over_nothing = 0;
8540 struct display_line *dl = Dynarr_atp (dla, *row);
8542 if ((int) (dl->ypos - dl->ascent) <= y_coord
8543 && y_coord <= (int) (dl->ypos + dl->descent))
8545 int check_margin_glyphs = 0;
8546 struct display_block *db = get_display_block_from_line (dl, TEXT);
8547 struct rune *rb = 0;
8549 if (x_coord < dl->bounds.left_white
8550 || x_coord >= dl->bounds.right_white)
8551 check_margin_glyphs = 1;
8553 low_y_coord = dl->ypos - dl->ascent;
8554 high_y_coord = dl->ypos + dl->descent + 1;
8556 if (position == OVER_BORDER
8557 || position == OVER_OUTSIDE
8558 || check_margin_glyphs)
8560 int x_check, left_bound;
8562 if (check_margin_glyphs)
8565 left_bound = dl->bounds.left_white;
8569 x_check = high_x_coord;
8570 left_bound = frm_left;
8573 if (Dynarr_length (db->runes))
8575 if (x_check <= left_bound)
8578 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
8580 *closest = Dynarr_atp (db->runes, 0)->bufpos;
8586 Dynarr_atp (db->runes,
8587 Dynarr_length (db->runes) - 1)->bufpos;
8590 Dynarr_atp (db->runes,
8591 Dynarr_length (db->runes) - 1)->bufpos;
8595 *modeline_closest += dl->offset;
8597 *closest += dl->offset;
8601 /* #### What should be here. */
8603 *modeline_closest = 0;
8608 if (check_margin_glyphs)
8610 if (x_coord < dl->bounds.left_in
8611 || x_coord >= dl->bounds.right_in)
8613 /* If we are over the outside margins then we
8614 know the loop over the text block isn't going
8615 to accomplish anything. So we go ahead and
8616 set what information we can right here and
8619 *obj_y = y_coord - (dl->ypos - dl->ascent);
8620 get_position_object (dl, obj1, obj2, x_coord,
8621 &low_x_coord, &high_x_coord);
8623 UPDATE_CACHE_RETURN;
8627 UPDATE_CACHE_RETURN;
8630 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
8632 int past_end = (*col == Dynarr_length (db->runes));
8635 rb = Dynarr_atp (db->runes, *col);
8638 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
8643 rb = Dynarr_atp (db->runes, *col);
8646 *bufpos = rb->bufpos + dl->offset;
8647 low_x_coord = rb->xpos;
8648 high_x_coord = rb->xpos + rb->width;
8650 if (rb->type == RUNE_DGLYPH)
8654 /* Find the first character after the glyph. */
8655 while (elt < Dynarr_length (db->runes))
8657 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
8661 (Dynarr_atp (db->runes, elt)->bufpos +
8665 (Dynarr_atp (db->runes, elt)->bufpos +
8673 /* In this case we failed to find a non-glyph
8674 character so we return the last position
8675 displayed on the line. */
8676 if (elt == Dynarr_length (db->runes))
8679 *modeline_closest = dl->end_bufpos + dl->offset;
8681 *closest = dl->end_bufpos + dl->offset;
8682 really_over_nothing = 1;
8688 *modeline_closest = rb->bufpos + dl->offset;
8690 *closest = rb->bufpos + dl->offset;
8695 *row = window_displayed_height (*w);
8697 if (position == OVER_NOTHING)
8698 position = OVER_MODELINE;
8700 if (rb->type == RUNE_DGLYPH)
8702 *obj1 = rb->object.dglyph.glyph;
8703 *obj2 = rb->object.dglyph.extent;
8705 else if (rb->type == RUNE_CHAR)
8716 UPDATE_CACHE_RETURN;
8719 || (rb->type == RUNE_CHAR
8720 && CHARC_ASCII_EQ (rb->object.cglyph, '\n')))
8723 /* At this point we may have glyphs in the right
8725 if (check_margin_glyphs)
8726 get_position_object (dl, obj1, obj2, x_coord,
8727 &low_x_coord, &high_x_coord);
8728 UPDATE_CACHE_RETURN;
8733 if (rb->type == RUNE_DGLYPH)
8735 *obj1 = rb->object.dglyph.glyph;
8736 *obj2 = rb->object.dglyph.extent;
8738 else if (rb->type == RUNE_CHAR)
8749 *obj_x = x_coord - rb->xpos;
8750 *obj_y = y_coord - (dl->ypos - dl->ascent);
8752 /* At this point we may have glyphs in the left
8754 if (check_margin_glyphs)
8755 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
8757 if (position == OVER_NOTHING && !really_over_nothing)
8758 position = OVER_TEXT;
8760 UPDATE_CACHE_RETURN;
8767 *row = Dynarr_length (dla) - 1;
8768 if (FRAME_WIN_P (f))
8770 int bot_elt = Dynarr_length (dla) - 1;
8774 struct display_line *dl = Dynarr_atp (dla, bot_elt);
8775 int adj_area = y_coord - (dl->ypos + dl->descent);
8779 XSETWINDOW (lwin, *w);
8780 default_face_height_and_width (lwin, 0, &defheight);
8782 *row += (adj_area / defheight);
8786 /* #### This should be checked out some more to determine what
8787 should really be going on. */
8788 if (!MARKERP ((*w)->start[CURRENT_DISP]))
8791 *closest = end_of_last_line_may_error (*w,
8792 marker_position ((*w)->start[CURRENT_DISP]));
8794 UPDATE_CACHE_RETURN;
8796 #undef UPDATE_CACHE_RETURN
8799 /***************************************************************************/
8801 /* Lisp functions */
8803 /***************************************************************************/
8805 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8806 Ensure that all minibuffers are correctly showing the echo area.
8810 Lisp_Object devcons, concons;
8812 DEVICE_LOOP_NO_BREAK (devcons, concons)
8814 struct device *d = XDEVICE (XCAR (devcons));
8815 Lisp_Object frmcons;
8817 DEVICE_FRAME_LOOP (frmcons, d)
8819 struct frame *f = XFRAME (XCAR (frmcons));
8821 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
8823 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
8825 MAYBE_DEVMETH (d, frame_output_begin, (f));
8828 * If the frame size has changed, there may be random
8829 * chud on the screen left from previous messages
8830 * because redisplay_frame hasn't been called yet.
8831 * Clear the screen to get rid of the potential mess.
8833 if (f->echo_area_garbaged)
8835 MAYBE_DEVMETH (d, clear_frame, (f));
8836 f->echo_area_garbaged = 0;
8838 redisplay_window (window, 0);
8839 MAYBE_DEVMETH (d, frame_output_end, (f));
8841 call_redisplay_end_triggers (XWINDOW (window), 0);
8850 restore_disable_preemption_value (Lisp_Object value)
8852 disable_preemption = XINT (value);
8856 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8857 Clear frame FRAME and output again what is supposed to appear on it.
8858 FRAME defaults to the selected frame if omitted.
8859 Normally, redisplay is preempted as normal if input arrives. However,
8860 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8861 input and is guaranteed to proceed to completion.
8863 (frame, no_preempt))
8865 struct frame *f = decode_frame (frame);
8866 int count = specpdl_depth ();
8868 if (!NILP (no_preempt))
8870 record_unwind_protect (restore_disable_preemption_value,
8871 make_int (disable_preemption));
8872 disable_preemption++;
8876 redisplay_frame (f, 1);
8878 /* See the comment in Fredisplay_frame. */
8879 RESET_CHANGED_SET_FLAGS;
8881 return unbind_to (count, Qnil);
8884 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8885 Ensure that FRAME's contents are correctly displayed.
8886 This differs from `redraw-frame' in that it only redraws what needs to
8887 be updated, as opposed to unconditionally clearing and redrawing
8889 FRAME defaults to the selected frame if omitted.
8890 Normally, redisplay is preempted as normal if input arrives. However,
8891 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8892 input and is guaranteed to proceed to completion.
8894 (frame, no_preempt))
8896 struct frame *f = decode_frame (frame);
8897 int count = specpdl_depth ();
8899 if (!NILP (no_preempt))
8901 record_unwind_protect (restore_disable_preemption_value,
8902 make_int (disable_preemption));
8903 disable_preemption++;
8906 redisplay_frame (f, 1);
8908 /* If we don't reset the global redisplay flags here, subsequent
8909 changes to the display will not get registered by redisplay
8910 because it thinks it already has registered changes. If you
8911 really knew what you were doing you could confuse redisplay by
8912 calling Fredisplay_frame while updating another frame. We assume
8913 that if you know what you are doing you will not be that
8915 RESET_CHANGED_SET_FLAGS;
8917 return unbind_to (count, Qnil);
8920 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
8921 Clear device DEVICE and output again what is supposed to appear on it.
8922 DEVICE defaults to the selected device if omitted.
8923 Normally, redisplay is preempted as normal if input arrives. However,
8924 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8925 input and is guaranteed to proceed to completion.
8927 (device, no_preempt))
8929 struct device *d = decode_device (device);
8930 Lisp_Object frmcons;
8931 int count = specpdl_depth ();
8933 if (!NILP (no_preempt))
8935 record_unwind_protect (restore_disable_preemption_value,
8936 make_int (disable_preemption));
8937 disable_preemption++;
8940 DEVICE_FRAME_LOOP (frmcons, d)
8942 XFRAME (XCAR (frmcons))->clear = 1;
8944 redisplay_device (d, 0);
8946 /* See the comment in Fredisplay_frame. */
8947 RESET_CHANGED_SET_FLAGS;
8949 return unbind_to (count, Qnil);
8952 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8953 Ensure that DEVICE's contents are correctly displayed.
8954 This differs from `redraw-device' in that it only redraws what needs to
8955 be updated, as opposed to unconditionally clearing and redrawing
8957 DEVICE defaults to the selected device if omitted.
8958 Normally, redisplay is preempted as normal if input arrives. However,
8959 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8960 input and is guaranteed to proceed to completion.
8962 (device, no_preempt))
8964 struct device *d = decode_device (device);
8965 int count = specpdl_depth ();
8967 if (!NILP (no_preempt))
8969 record_unwind_protect (restore_disable_preemption_value,
8970 make_int (disable_preemption));
8971 disable_preemption++;
8974 redisplay_device (d, 0);
8976 /* See the comment in Fredisplay_frame. */
8977 RESET_CHANGED_SET_FLAGS;
8979 return unbind_to (count, Qnil);
8982 /* Big lie. Big lie. This will force all modelines to be updated
8983 regardless if the all flag is set or not. It remains in existence
8984 solely for backwards compatibility. */
8985 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8986 Force the modeline of the current buffer to be redisplayed.
8987 With optional non-nil ALL, force redisplay of all modelines.
8991 MARK_MODELINE_CHANGED;
8995 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8996 Force an immediate update of the cursor on FRAME.
8997 FRAME defaults to the selected frame if omitted.
9001 redisplay_redraw_cursor (decode_frame (frame), 1);
9006 /***************************************************************************/
9008 /* Lisp-variable change triggers */
9010 /***************************************************************************/
9013 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
9016 /* Nothing to be done? */
9020 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
9021 Lisp_Object in_object, int flags)
9023 /* #### clip_changed should really be renamed something like
9024 global_redisplay_change. */
9029 /* This is called if the built-in glyphs have their properties
9032 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
9035 if (WINDOWP (locale))
9037 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
9039 else if (FRAMEP (locale))
9041 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
9043 else if (DEVICEP (locale))
9045 Lisp_Object frmcons;
9046 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
9047 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9049 else if (CONSOLEP (locale))
9051 Lisp_Object frmcons, devcons;
9052 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
9053 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9055 else /* global or buffer */
9057 Lisp_Object frmcons, devcons, concons;
9058 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
9059 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9064 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
9067 if (XFRAME (w->frame)->init_finished)
9068 Fforce_cursor_redisplay (w->frame);
9071 #ifdef MEMORY_USAGE_STATS
9074 /***************************************************************************/
9076 /* memory usage computation */
9078 /***************************************************************************/
9081 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
9083 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9087 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
9088 struct overhead_stats *ovstats)
9095 total = Dynarr_memory_usage (dyn, ovstats);
9096 for (i = 0; i < Dynarr_largest (dyn); i++)
9097 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
9103 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
9104 struct overhead_stats *ovstats)
9106 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9110 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
9111 struct overhead_stats *ovstats)
9118 total = Dynarr_memory_usage (dyn, ovstats);
9119 for (i = 0; i < Dynarr_largest (dyn); i++)
9121 struct display_line *dl = &Dynarr_at (dyn, i);
9122 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
9123 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
9124 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
9131 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
9132 struct overhead_stats *ovstats)
9134 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9137 #endif /* MEMORY_USAGE_STATS */
9140 /***************************************************************************/
9142 /* initialization */
9144 /***************************************************************************/
9147 init_redisplay (void)
9149 disable_preemption = 0;
9150 preemption_count = 0;
9151 max_preempts = INIT_MAX_PREEMPTS;
9157 if (!cmotion_display_lines)
9158 cmotion_display_lines = Dynarr_new (display_line);
9159 if (!mode_spec_bufbyte_string)
9160 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
9161 if (!formatted_string_extent_dynarr)
9162 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
9163 if (!formatted_string_extent_start_dynarr)
9164 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
9165 if (!formatted_string_extent_end_dynarr)
9166 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
9167 if (!internal_cache)
9168 internal_cache = Dynarr_new (line_start_cache);
9171 /* window system is nil when in -batch mode */
9172 if (!initialized || noninteractive)
9175 /* If the user wants to use a window system, we shouldn't bother
9176 initializing the terminal. This is especially important when the
9177 terminal is so dumb that emacs gives up before and doesn't bother
9178 using the window system.
9180 If the DISPLAY environment variable is set, try to use X, and die
9181 with an error message if that doesn't work. */
9183 #ifdef HAVE_X_WINDOWS
9184 if (!strcmp (display_use, "x"))
9186 /* Some stuff checks this way early. */
9187 Vwindow_system = Qx;
9188 Vinitial_window_system = Qx;
9191 #endif /* HAVE_X_WINDOWS */
9194 if (!strcmp (display_use, "gtk"))
9196 Vwindow_system = Qgtk;
9197 Vinitial_window_system = Qgtk;
9202 #ifdef HAVE_MS_WINDOWS
9203 if (!strcmp (display_use, "mswindows"))
9205 /* Some stuff checks this way early. */
9206 Vwindow_system = Qmswindows;
9207 Vinitial_window_system = Qmswindows;
9210 #endif /* HAVE_MS_WINDOWS */
9213 /* If no window system has been specified, try to use the terminal. */
9216 stderr_out ("XEmacs: standard input is not a tty\n");
9220 /* Look at the TERM variable */
9221 if (!getenv ("TERM"))
9223 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
9227 Vinitial_window_system = Qtty;
9229 #else /* not HAVE_TTY */
9230 /* No DISPLAY specified, and no TTY support. */
9231 stderr_out ("XEmacs: Cannot open display.\n\
9232 Please set the environmental variable DISPLAY to an appropriate value.\n");
9239 syms_of_redisplay (void)
9241 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
9242 #ifndef INHIBIT_REDISPLAY_HOOKS
9243 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
9244 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
9245 #endif /* INHIBIT_REDISPLAY_HOOKS */
9246 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
9247 defsymbol (&Qbar_cursor, "bar-cursor");
9248 defsymbol (&Qredisplay_end_trigger_functions,
9249 "redisplay-end-trigger-functions");
9250 defsymbol (&Qtop_bottom, "top-bottom");
9251 defsymbol (&Qbuffer_list_changed_hook, "buffer-list-changed-hook");
9253 DEFSUBR (Fredisplay_echo_area);
9254 DEFSUBR (Fredraw_frame);
9255 DEFSUBR (Fredisplay_frame);
9256 DEFSUBR (Fredraw_device);
9257 DEFSUBR (Fredisplay_device);
9258 DEFSUBR (Fredraw_modeline);
9259 DEFSUBR (Fforce_cursor_redisplay);
9263 vars_of_redisplay (void)
9267 staticpro (&last_arrow_position);
9268 staticpro (&last_arrow_string);
9269 last_arrow_position = Qnil;
9270 last_arrow_string = Qnil;
9273 /* #### Probably temporary */
9274 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
9275 \(Temporary) Setting this will impact the performance of the internal
9278 cache_adjustment = 2;
9280 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
9281 Minimum pixel height for clipped bottom display line.
9282 A clipped line shorter than this won't be displayed.
9284 redisplay_variable_changed);
9287 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
9288 Minimum visible area for clipped glyphs at right boundary.
9289 Clipped glyphs shorter than this won't be displayed.
9290 Only pixmap glyph instances are currently allowed to be clipped.
9292 redisplay_variable_changed);
9293 horizontal_clip = 5;
9295 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
9296 String displayed by modeline-format's "%m" specification.
9298 Vglobal_mode_string = Qnil;
9300 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
9301 Marker for where to display an arrow on top of the buffer text.
9302 This must be the beginning of a line in order to work.
9303 See also `overlay-arrow-string'.
9305 redisplay_variable_changed);
9306 Voverlay_arrow_position = Qnil;
9308 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
9309 String or glyph to display as an arrow. See also `overlay-arrow-position'.
9310 \(Note that despite the name of this variable, it can be set to a glyph as
9313 redisplay_variable_changed);
9314 Voverlay_arrow_string = Qnil;
9316 DEFVAR_INT ("scroll-step", &scroll_step /*
9317 *The number of lines to try scrolling a window by when point moves out.
9318 If that fails to bring point back on frame, point is centered instead.
9319 If this is zero, point is always centered after it moves off screen.
9323 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
9324 *Scroll up to this many lines, to bring point back on screen.
9326 scroll_conservatively = 0;
9328 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
9329 &truncate_partial_width_windows /*
9330 *Non-nil means truncate lines in all windows less than full frame wide.
9332 redisplay_variable_changed);
9333 truncate_partial_width_windows = 1;
9335 DEFVAR_LISP ("visible-bell", &Vvisible_bell /*
9336 *Non-nil substitutes a visual signal for the audible bell.
9338 Default behavior is to flash the whole screen. On some platforms,
9339 special effects are available using the following values:
9341 'display Flash the whole screen (ie, the default behavior).
9342 'top-bottom Flash only the top and bottom lines of the selected frame.
9344 When effects are unavailable on a platform, the visual bell is the
9345 default, whole screen. (Currently only X supports any special effects.)
9347 Vvisible_bell = Qnil;
9349 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
9350 *Non-nil means no need to redraw entire frame after suspending.
9351 A non-nil value is useful if the terminal can automatically preserve
9352 Emacs's frame display when you reenter Emacs.
9353 It is up to you to set this variable if your terminal can do that.
9355 no_redraw_on_reenter = 0;
9357 DEFVAR_LISP ("window-system", &Vwindow_system /*
9358 A symbol naming the window-system under which Emacs is running,
9359 such as `x', or nil if emacs is running on an ordinary terminal.
9361 Do not use this variable, except for GNU Emacs compatibility, as it
9362 gives wrong values in a multi-device environment. Use `console-type'
9365 Vwindow_system = Qnil;
9367 /* #### Temporary shit until window-system is eliminated. */
9368 DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /*
9371 Vinitial_window_system = Qnil;
9373 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
9374 Non-nil means put cursor in minibuffer, at end of any message there.
9376 cursor_in_echo_area = 0;
9378 /* #### Shouldn't this be generalized as follows:
9380 if nil, use block cursor.
9381 if a number, use a bar cursor of that width.
9382 Otherwise, use a 1-pixel bar cursor.
9384 #### Or better yet, this variable should be trashed entirely
9385 (use a Lisp-magic variable to maintain compatibility)
9386 and a specifier `cursor-shape' added, which allows a block
9387 cursor, a bar cursor, a flashing block or bar cursor,
9388 maybe a caret cursor, etc. */
9390 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
9391 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9395 #ifndef INHIBIT_REDISPLAY_HOOKS
9396 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
9397 Function or functions to run before every redisplay.
9399 Vpre_redisplay_hook = Qnil;
9401 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
9402 Function or functions to run after every redisplay.
9404 Vpost_redisplay_hook = Qnil;
9405 #endif /* INHIBIT_REDISPLAY_HOOKS */
9407 DEFVAR_LISP ("buffer-list-changed-hook", &Vbuffer_list_changed_hook /*
9408 Function or functions to call when a frame's buffer list has changed.
9409 This is called during redisplay, before redisplaying each frame.
9410 Functions on this hook are called with one argument, the frame.
9412 Vbuffer_list_changed_hook = Qnil;
9414 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
9415 Bump this to tell the C code to call `display-warning-buffer'
9416 at next redisplay. You should not normally change this; the function
9417 `display-warning' automatically does this at appropriate times.
9419 display_warning_tick = 0;
9421 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
9422 Non-nil means inhibit display of warning messages.
9423 You should *bind* this, not set it. Any pending warning messages
9424 will be displayed when the binding no longer applies.
9426 /* reset to 0 by startup.el after the splash screen has displayed.
9427 This way, the warnings don't obliterate the splash screen. */
9428 inhibit_warning_display = 1;
9430 DEFVAR_LISP ("window-size-change-functions",
9431 &Vwindow_size_change_functions /*
9432 Not currently implemented.
9433 Functions called before redisplay, if window sizes have changed.
9434 The value should be a list of functions that take one argument.
9435 Just before redisplay, for each frame, if any of its windows have changed
9436 size since the last redisplay, or have been split or deleted,
9437 all the functions in the list are called, with the frame as argument.
9439 Vwindow_size_change_functions = Qnil;
9441 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
9442 Not currently implemented.
9443 Functions to call before redisplaying a window with scrolling.
9444 Each function is called with two arguments, the window
9445 and its new display-start position. Note that the value of `window-end'
9446 is not valid when these functions are called.
9448 Vwindow_scroll_functions = Qnil;
9450 DEFVAR_LISP ("redisplay-end-trigger-functions",
9451 &Vredisplay_end_trigger_functions /*
9452 See `set-window-redisplay-end-trigger'.
9454 Vredisplay_end_trigger_functions = Qnil;
9456 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
9457 *Non-nil means column display number starts at 1.
9459 column_number_start_at_one = 0;
9463 specifier_vars_of_redisplay (void)
9465 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
9466 *Width of left margin.
9467 This is a specifier; use `set-specifier' to change it.
9469 Vleft_margin_width = Fmake_specifier (Qnatnum);
9470 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
9471 set_specifier_caching (Vleft_margin_width,
9472 offsetof (struct window, left_margin_width),
9473 some_window_value_changed,
9474 offsetof (struct frame, left_margin_width),
9475 margin_width_changed_in_frame, 0);
9477 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
9478 *Width of right margin.
9479 This is a specifier; use `set-specifier' to change it.
9481 Vright_margin_width = Fmake_specifier (Qnatnum);
9482 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
9483 set_specifier_caching (Vright_margin_width,
9484 offsetof (struct window, right_margin_width),
9485 some_window_value_changed,
9486 offsetof (struct frame, right_margin_width),
9487 margin_width_changed_in_frame, 0);
9489 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
9490 *Minimum ascent height of lines.
9491 This is a specifier; use `set-specifier' to change it.
9493 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
9494 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
9495 set_specifier_caching (Vminimum_line_ascent,
9496 offsetof (struct window, minimum_line_ascent),
9497 some_window_value_changed,
9500 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
9501 *Minimum descent height of lines.
9502 This is a specifier; use `set-specifier' to change it.
9504 Vminimum_line_descent = Fmake_specifier (Qnatnum);
9505 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
9506 set_specifier_caching (Vminimum_line_descent,
9507 offsetof (struct window, minimum_line_descent),
9508 some_window_value_changed,
9511 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
9512 *Non-nil means use the left outside margin as extra whitespace when
9513 displaying 'whitespace or 'inside-margin glyphs.
9514 This is a specifier; use `set-specifier' to change it.
9516 Vuse_left_overflow = Fmake_specifier (Qboolean);
9517 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
9518 set_specifier_caching (Vuse_left_overflow,
9519 offsetof (struct window, use_left_overflow),
9520 some_window_value_changed,
9523 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
9524 *Non-nil means use the right outside margin as extra whitespace when
9525 displaying 'whitespace or 'inside-margin glyphs.
9526 This is a specifier; use `set-specifier' to change it.
9528 Vuse_right_overflow = Fmake_specifier (Qboolean);
9529 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
9530 set_specifier_caching (Vuse_right_overflow,
9531 offsetof (struct window, use_right_overflow),
9532 some_window_value_changed,
9535 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9536 *Non-nil means the text cursor is visible (this is usually the case).
9537 This is a specifier; use `set-specifier' to change it.
9539 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
9540 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
9541 set_specifier_caching (Vtext_cursor_visible_p,
9542 offsetof (struct window, text_cursor_visible_p),
9543 text_cursor_visible_p_changed,