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 ****************************************************************************/
59 #include "redisplay.h"
62 #include "line-number.h"
64 #include "file-coding.h"
68 #include "console-tty.h"
70 #include <unistd.h> /* for isatty() */
74 /* Note: We have to be careful throughout this code to properly handle
75 and differentiate between Bufbytes and Emchars.
77 Since strings are generally composed of Bufbytes, I've taken the tack
78 that any contiguous set of Bufbytes is called a "string", while
79 any contiguous set of Emchars is called an "array". */
81 /* Return value to indicate a failure by an add_*_rune routine to add
82 a rune, but no propagation information needs to be returned. */
83 #define ADD_FAILED (prop_block_dynarr *) 1
85 #define BEGIN_GLYPHS 0
88 #define RIGHT_GLYPHS 3
90 /* Set the vertical clip to 0 if we are currently updating the line
91 start cache. Otherwise for buffers of line height 1 it may fail to
92 be able to work properly because regenerate_window will not layout
94 #define VERTICAL_CLIP(w, display) \
95 (updating_line_start_cache \
97 : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
101 /* The following structures are completely private to redisplay.c so
102 we put them here instead of in a header file, for modularity. */
104 /* NOTE: Bytinds not Bufpos's in this structure. */
106 typedef struct position_redisplay_data_type
108 /* This information is normally filled in by the create_*_block
109 routines and is used by the add_*_rune routines. */
111 /* if we are working with strings rather than buffers we need a
112 handle to the string */
115 struct display_block *db;
116 struct display_line *dl;
117 Emchar ch; /* Character that is to be added. This is
118 used to communicate this information to
119 add_emchar_rune(). */
120 Lisp_Object last_charset; /* The charset of the previous character.
121 Used to optimize some lookups -- we
122 only have to do some things when
123 the charset changes. */
124 face_index last_findex; /* The face index of the previous character.
125 Needed to ensure the validity of the
126 last_charset optimization. */
128 int last_char_width; /* The width of the previous character. */
129 int font_is_bogus; /* If true, it means we couldn't instantiate
130 the font for this charset, so we substitute
131 ~'s from the ASCII charset. */
136 int blank_width; /* Width of the blank that is to be added.
137 This is used to communicate this information
140 This is also used rather cheesily to
141 communicate the width of the eol-cursor-size
142 blank that exists at the end of the line.
143 add_emchar_rune() is called cheesily with
144 the non-printing char '\n', which is stuck
145 in the output routines with its width being
147 Bytind bi_cursor_bufpos;/* This stores the buffer position of the cursor. */
148 unsigned int cursor_type :3;
149 int cursor_x; /* rune block cursor is at */
150 int start_col; /* Number of character columns (each column has
151 a width of the default char width) that still
152 need to be skipped. This is used for horizontal
153 scrolling, where a certain number of columns
154 (those off the left side of the screen) need
155 to be skipped before anything is displayed. */
156 Bytind bi_start_col_enabled;
157 int start_col_xoffset; /* Number of pixels that still need to
158 be skipped. This is used for
159 horizontal scrolling of glyphs, where we want
160 to be able to scroll over part of the glyph. */
162 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
163 glyph differs from space_width (w).
164 0 if no hscroll glyph was used,
165 i.e. the window is not scrolled
166 horizontally. Used in tab
169 /* Information about the face the text should be displayed in and
170 any begin-glyphs and end-glyphs. */
171 struct extent_fragment *ef;
174 /* The height of a pixmap may either be predetermined if the user
175 has set a baseline value, or it may be dependent on whatever the
176 line ascent and descent values end up being, based just on font
177 information. In the first case we can immediately update the
178 values, thus their inclusion here. In the last case we cannot
179 determine the actual contribution to the line height until we
180 have finished laying out all text on the line. Thus we propagate
181 the max height of such pixmaps and do a final calculation after
182 all text has been added to the line. */
185 int max_pixmap_height;
187 Lisp_Object result_str; /* String where we put the result of
188 generating a formatted string in the modeline. */
189 int is_modeline; /* Non-zero if we're generating the modeline. */
190 Charcount modeline_charpos; /* Number of chars used in result_str so far;
191 corresponds to bytepos. */
192 Bytecount bytepos; /* Number of bytes used in result_str so far.
193 We don't actually copy the bytes into result_str
194 until the end because we don't know how big the
195 string is going to be until then. */
206 /* Data that should be propagated to the next line. Either a single
207 Emchar or a string of Bufbyte's.
209 The actual data that is propagated ends up as a Dynarr of these
212 #### It's unclean that both Emchars and Bufbytes are here.
215 typedef struct prop_block prop_block;
225 Bytecount len; /* length of the string. */
231 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
232 unsigned int cursor_type :3;
245 Dynarr_declare (prop_block);
249 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
250 Charcount pos, Charcount min_pos,
251 Charcount max_pos, Lisp_Object elt,
252 int depth, int max_pixsize,
253 face_index findex, int type,
255 Lisp_Object cur_ext);
256 static prop_block_dynarr *add_glyph_rune (pos_data *data,
257 struct glyph_block *gb,
258 int pos_type, int allow_cursor,
259 struct glyph_cachel *cachel);
260 static Bytind create_text_block (struct window *w, struct display_line *dl,
261 Bytind bi_start_pos, prop_block_dynarr **prop,
263 static int create_overlay_glyph_block (struct window *w,
264 struct display_line *dl);
265 static void create_left_glyph_block (struct window *w,
266 struct display_line *dl,
268 static void create_right_glyph_block (struct window *w,
269 struct display_line *dl);
270 static void redisplay_windows (Lisp_Object window, int skip_selected);
271 static void decode_mode_spec (struct window *w, Emchar spec, int type);
272 static void free_display_line (struct display_line *dl);
273 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
274 Bufpos point, int no_regen);
275 static int point_visible (struct window *w, Bufpos point, int type);
277 /* This used to be 10 but 30 seems to give much better performance. */
278 #define INIT_MAX_PREEMPTS 30
279 static int max_preempts;
281 #define REDISPLAY_PREEMPTION_CHECK \
284 (!disable_preemption && \
285 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
286 (!INTERACTIVE || detect_input_pending ()))))
289 * Redisplay global variables.
292 /* We need a third set of display structures for the cursor motion
293 routines. We used to just give each window a third set. However,
294 we always fully regenerate the structures when needed so there
295 isn't any reason we need more than a single set. */
296 display_line_dynarr *cmotion_display_lines;
298 /* We store the extents that we need to generate in a Dynarr and then
299 frob them all on at the end of generating the string. We do it
300 this way rather than adding them as we generate the string because
301 we don't store the text into the resulting string until we're done
302 (to avoid having to resize the string multiple times), and we don't
303 want to go around adding extents to a string when the extents might
304 stretch off the end of the string. */
305 static EXTENT_dynarr *formatted_string_extent_dynarr;
306 static Bytecount_dynarr *formatted_string_extent_start_dynarr;
307 static Bytecount_dynarr *formatted_string_extent_end_dynarr;
310 /* #### probably temporary */
311 int cache_adjustment;
313 /* This holds a string representing the text corresponding to a single
315 static Bufbyte_dynarr *mode_spec_bufbyte_string;
317 int in_display; /* 1 if in redisplay. */
319 int disable_preemption; /* Used for debugging redisplay and for
322 /* We only allow max_preempts preemptions before we force a redisplay. */
323 static int preemption_count;
325 /* Minimum pixel height of clipped bottom display line. */
328 /* Minimum visible pixel width of clipped glyphs at right margin. */
331 /* Set if currently inside update_line_start_cache. */
332 static int updating_line_start_cache;
334 /* Nonzero means reading single-character input with prompt
335 so put cursor on minibuffer after the prompt. */
336 int cursor_in_echo_area;
337 Lisp_Object Qcursor_in_echo_area;
339 /* Nonzero means truncate lines in all windows less wide than the frame */
340 int truncate_partial_width_windows;
342 /* non-nil if a buffer has changed since the last time redisplay completed */
344 int buffers_changed_set;
346 /* non-nil if hscroll has changed somewhere or a buffer has been
347 narrowed or widened */
349 int clip_changed_set;
351 /* non-nil if any extent has changed since the last time redisplay completed */
353 int extents_changed_set;
355 /* non-nil if any face has changed since the last time redisplay completed */
358 /* Nonzero means some frames have been marked as garbaged */
361 /* non-zero if any of the builtin display glyphs (continuation,
362 hscroll, control-arrow, etc) is in need of updating
365 int glyphs_changed_set;
367 /* non-zero if any subwindow has been deleted. */
368 int subwindows_changed;
369 int subwindows_changed_set;
371 /* non-zero if any displayed subwindow is in need of updating
373 int subwindows_state_changed;
374 int subwindows_state_changed_set;
376 /* This variable is 1 if the icon has to be updated.
377 It is set to 1 when `frame-icon-glyph' changes. */
379 int icon_changed_set;
381 /* This variable is 1 if the menubar widget has to be updated.
382 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
385 int menubar_changed_set;
387 /* true iff we should redraw the modelines on the next redisplay */
388 int modeline_changed;
389 int modeline_changed_set;
391 /* non-nil if point has changed in some buffer since the last time
392 redisplay completed */
394 int point_changed_set;
396 /* non-nil if some frame has changed its size */
399 /* non-nil if some device has signaled that it wants to change size */
400 int asynch_device_change_pending;
402 /* non-nil if any toolbar has changed */
404 int toolbar_changed_set;
406 /* non-nil if any gutter has changed */
408 int gutter_changed_set;
410 /* non-nil if any window has changed since the last time redisplay completed */
413 /* non-nil if any frame's window structure has changed since the last
414 time redisplay completed */
415 int windows_structure_changed;
417 /* If non-nil, use vertical bar cursor. */
418 Lisp_Object Vbar_cursor;
419 Lisp_Object Qbar_cursor;
421 Lisp_Object Vvisible_bell; /* If true and the terminal will support it
422 then the frame will flash instead of
423 beeping when an error occurs */
425 /* Nonzero means no need to redraw the entire frame on resuming
426 a suspended Emacs. This is useful on terminals with multiple pages,
427 where one page is used for Emacs and another for all else. */
428 int no_redraw_on_reenter;
430 Lisp_Object Vwindow_system; /* nil or a symbol naming the window system
431 under which emacs is running
432 ('x is the only current possibility) */
433 Lisp_Object Vinitial_window_system;
435 Lisp_Object Vglobal_mode_string;
437 /* The number of lines scroll a window by when point leaves the window; if
438 it is <=0 then point is centered in the window */
441 /* Scroll up to this many lines, to bring point back on screen. */
442 int scroll_conservatively;
444 /* Marker for where to display an arrow on top of the buffer text. */
445 Lisp_Object Voverlay_arrow_position;
446 /* String to display for the arrow. */
447 Lisp_Object Voverlay_arrow_string;
449 Lisp_Object Vwindow_size_change_functions;
450 Lisp_Object Vwindow_scroll_functions;
451 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
453 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
455 #ifndef INHIBIT_REDISPLAY_HOOKS
456 /* #### Chuck says: I think this needs more thought.
457 Think about this for 19.14. */
458 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
459 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
460 #endif /* INHIBIT_REDISPLAY_HOOKS */
462 static int last_display_warning_tick, display_warning_tick;
463 Lisp_Object Qdisplay_warning_buffer;
464 int inhibit_warning_display;
466 Lisp_Object Vleft_margin_width, Vright_margin_width;
467 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
468 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
469 Lisp_Object Vtext_cursor_visible_p;
471 int column_number_start_at_one;
473 Lisp_Object Qtop_bottom;
475 #define WINDOW_SCROLLED(w) \
476 (w->hscroll > 0 || w->left_xoffset)
479 /***************************************************************************/
481 /* low-level interfaces onto device routines */
483 /***************************************************************************/
486 redisplay_text_width_emchar_string (struct window *w, int findex,
487 Emchar *str, Charcount len)
489 unsigned char charsets[NUM_LEADING_BYTES];
492 find_charsets_in_emchar_string (charsets, str, len);
493 XSETWINDOW (window, w);
494 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
496 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))),
497 text_width, (XFRAME (WINDOW_FRAME (w)),
498 WINDOW_FACE_CACHEL (w, findex), str, len));
501 static Emchar_dynarr *rtw_emchar_dynarr;
504 redisplay_text_width_string (struct window *w, int findex,
505 Bufbyte *nonreloc, Lisp_Object reloc,
506 Bytecount offset, Bytecount len)
508 if (!rtw_emchar_dynarr)
509 rtw_emchar_dynarr = Dynarr_new (Emchar);
510 Dynarr_reset (rtw_emchar_dynarr);
512 fixup_internal_substring (nonreloc, reloc, offset, &len);
514 nonreloc = XSTRING_DATA (reloc);
515 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
516 return redisplay_text_width_emchar_string
517 (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
518 Dynarr_length (rtw_emchar_dynarr));
522 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face,
523 Bufbyte *nonreloc, Lisp_Object reloc,
524 Bytecount offset, Bytecount len)
526 unsigned char charsets[NUM_LEADING_BYTES];
528 struct face_cachel cachel;
530 if (!rtw_emchar_dynarr)
531 rtw_emchar_dynarr = Dynarr_new (Emchar);
532 Dynarr_reset (rtw_emchar_dynarr);
534 fixup_internal_substring (nonreloc, reloc, offset, &len);
536 nonreloc = XSTRING_DATA (reloc);
537 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
538 find_charsets_in_bufbyte_string (charsets, nonreloc, len);
539 reset_face_cachel (&cachel);
541 XSETFRAME (frame, f);
542 ensure_face_cachel_complete (&cachel, frame, charsets);
543 return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
544 text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
545 Dynarr_length (rtw_emchar_dynarr)));
548 /* Return the display block from DL of the given TYPE. A display line
549 can have only one display block of each possible type. If DL does
550 not have a block of type TYPE, one will be created and added to DL. */
552 struct display_block *
553 get_display_block_from_line (struct display_line *dl, enum display_type type)
556 struct display_block db;
558 /* Check if this display line already has a block of the desired type and
560 if (dl->display_blocks)
562 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++)
564 if (Dynarr_at (dl->display_blocks, elt).type == type)
565 return Dynarr_atp (dl->display_blocks, elt);
568 /* There isn't an active block of the desired type, but there
569 might still be allocated blocks we need to reuse. */
570 if (elt < Dynarr_largest (dl->display_blocks))
572 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
574 /* 'add' the block to the list */
575 Dynarr_increment (dl->display_blocks);
577 /* initialize and return */
584 /* This line doesn't have any display blocks, so initialize the display
586 dl->display_blocks = Dynarr_new (display_block);
589 /* The line doesn't have a block of the desired type so go ahead and create
590 one and add it to the line. */
593 db.runes = Dynarr_new (rune);
594 Dynarr_add (dl->display_blocks, db);
596 /* Return the newly added display block. */
597 elt = Dynarr_length (dl->display_blocks) - 1;
599 return Dynarr_atp (dl->display_blocks, elt);
603 tab_char_width (struct window *w)
605 struct buffer *b = XBUFFER (w->buffer);
606 int char_tab_width = XINT (b->tab_width);
608 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8;
610 return char_tab_width;
614 space_width (struct window *w)
616 /* While tabs are traditional composed of spaces, for variable-width
617 fonts the space character tends to give too narrow a value. So
618 we use 'n' instead. Except that we don't. We use the default
619 character width for the default face. If this is actually
620 defined by the font then it is probably the best thing to
621 actually use. If it isn't, we have assumed it is 'n' and have
622 already calculated its width. Thus we can avoid a call to
623 XTextWidth on X frames by just querying the default width. */
624 return XFONT_INSTANCE
625 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width;
629 tab_pix_width (struct window *w)
631 return space_width (w) * tab_char_width (w);
634 /* Given a pixel position in a window, return the pixel location of
635 the next tabstop. Tabs are calculated from the left window edge in
636 terms of spaces displayed in the default face. Formerly the space
637 width was determined using the currently active face. That method
638 leads to tabstops which do not line up. */
641 next_tab_position (struct window *w, int start_pixpos, int left_pixpos)
643 int n_pos = left_pixpos;
644 int pix_tab_width = tab_pix_width (w);
646 /* Adjust n_pos for any hscrolling which has happened. */
647 if (WINDOW_SCROLLED (w))
648 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset;
650 while (n_pos <= start_pixpos)
651 n_pos += pix_tab_width;
656 /* For the given window, calculate the outside and margin boundaries for a
657 display line. The whitespace boundaries must be calculated by the text
661 calculate_display_line_boundaries (struct window *w, int modeline)
663 layout_bounds bounds;
665 /* Set the outermost boundaries which are the boundaries of the
666 window itself minus the gutters (and minus the scrollbars if this
667 is for the modeline). */
670 bounds.left_out = WINDOW_TEXT_LEFT (w);
671 bounds.right_out = WINDOW_TEXT_RIGHT (w);
675 bounds.left_out = WINDOW_MODELINE_LEFT (w);
676 bounds.right_out = WINDOW_MODELINE_RIGHT (w);
679 /* The inner boundaries mark where the glyph margins are located. */
680 bounds.left_in = bounds.left_out + window_left_margin_width (w);
681 bounds.right_in = bounds.right_out - window_right_margin_width (w);
683 /* We cannot fully calculate the whitespace boundaries as they
684 depend on the contents of the line being displayed. */
685 bounds.left_white = bounds.left_in;
686 bounds.right_white = bounds.right_in;
691 /* Given a display line and a starting position, ensure that the
692 contents of the display line accurately represent the visual
693 representation of the buffer contents starting from the given
694 position when displayed in the given window. The display line ends
695 when the contents of the line reach the right boundary of the given
699 generate_display_line (struct window *w, struct display_line *dl, int bounds,
700 Bufpos start_pos, prop_block_dynarr **prop,
705 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
707 /* If our caller hasn't already set the boundaries, then do so now. */
709 dl->bounds = calculate_display_line_boundaries (w, 0);
711 /* Reset what this line is using. */
712 if (dl->display_blocks)
713 Dynarr_reset (dl->display_blocks);
716 Dynarr_free (dl->left_glyphs);
719 if (dl->right_glyphs)
721 Dynarr_free (dl->right_glyphs);
722 dl->right_glyphs = 0;
725 /* We aren't generating a modeline at the moment. */
728 /* Create a display block for the text region of the line. */
730 /* #### urk urk urk!!! Chuck fix this shit! */
731 Bytind hacked_up_bytind =
732 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
734 if (hacked_up_bytind > BI_BUF_ZV (b))
735 ret_bufpos = BUF_ZV (b) + 1;
737 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
739 dl->bufpos = start_pos;
740 if (dl->end_bufpos < dl->bufpos)
741 dl->end_bufpos = dl->bufpos;
743 if (MARKERP (Voverlay_arrow_position)
744 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
745 && start_pos == marker_position (Voverlay_arrow_position)
746 && (STRINGP (Voverlay_arrow_string)
747 || GLYPHP (Voverlay_arrow_string)))
749 overlay_width = create_overlay_glyph_block (w, dl);
754 /* If there are left glyphs associated with any character in the
755 text block, then create a display block to handle them. */
756 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
757 create_left_glyph_block (w, dl, overlay_width);
759 /* If there are right glyphs associated with any character in the
760 text block, then create a display block to handle them. */
761 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
762 create_right_glyph_block (w, dl);
764 /* In the future additional types of display blocks may be generated
767 w->last_redisplay_pos = ret_bufpos;
772 /* Adds an hscroll glyph to a display block. If this is called, then
773 the block had better be empty.
775 Yes, there are multiple places where this function is called but
776 that is the way it has to be. Each calling function has to deal
777 with bi_start_col_enabled a little differently depending on the
778 object being worked with. */
780 static prop_block_dynarr *
781 add_hscroll_rune (pos_data *data)
783 struct glyph_block gb;
784 prop_block_dynarr *retval;
785 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
786 unsigned int old_cursor_type = data->cursor_type;
787 Bytind bi_old_bufpos = data->bi_bufpos;
789 if (data->cursor_type == CURSOR_ON
790 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
791 && data->bi_cursor_bufpos <= data->bi_bufpos)
793 data->bi_cursor_bufpos = data->bi_start_col_enabled;
797 data->cursor_type = NO_CURSOR;
800 data->bi_endpos = data->bi_bufpos;
801 data->bi_bufpos = data->bi_start_col_enabled;
804 gb.glyph = Vhscroll_glyph;
806 int oldpixpos = data->pixpos;
807 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
808 GLYPH_CACHEL (XWINDOW (data->window),
809 HSCROLL_GLYPH_INDEX));
810 data->hscroll_glyph_width_adjust =
811 data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
814 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
815 data->cursor_type = old_cursor_type;
816 data->bi_bufpos = bi_old_bufpos;
818 data->bi_start_col_enabled = 0;
822 /* Adds a character rune to a display block. If there is not enough
823 room to fit the rune on the display block (as determined by the
824 MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
826 static prop_block_dynarr *
827 add_emchar_rune (pos_data *data)
829 struct rune rb, *crb;
840 if (data->bi_start_col_enabled)
842 return add_hscroll_rune (data);
845 if (data->ch == '\n')
847 data->font_is_bogus = 0;
848 /* Cheesy end-of-line pseudo-character. */
849 width = data->blank_width;
853 Lisp_Object charset = CHAR_CHARSET (data->ch);
854 if (!EQ (charset, data->last_charset) ||
855 data->findex != data->last_findex)
857 /* OK, we need to do things the hard way. */
858 struct window *w = XWINDOW (data->window);
859 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
860 Lisp_Object font_instance =
861 ensure_face_cachel_contains_charset (cachel, data->window,
863 Lisp_Font_Instance *fi;
865 if (EQ (font_instance, Vthe_null_font_instance))
867 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
868 data->font_is_bogus = 1;
871 data->font_is_bogus = 0;
873 fi = XFONT_INSTANCE (font_instance);
874 if (!fi->proportional_p)
875 /* sweetness and light. */
876 data->last_char_width = fi->width;
878 data->last_char_width = -1;
879 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
880 data->new_descent = max (data->new_descent, (int) fi->descent);
881 data->last_charset = charset;
882 data->last_findex = data->findex;
885 width = data->last_char_width;
888 /* bummer. Proportional fonts. */
889 width = redisplay_text_width_emchar_string (XWINDOW (data->window),
895 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
900 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
902 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
911 crb->findex = data->findex;
912 crb->xpos = data->pixpos;
916 if (NILP (data->string))
918 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
922 bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
924 else if (data->is_modeline)
925 crb->bufpos = data->modeline_charpos;
927 /* fuckme if this shouldn't be an abort. */
928 /* abort (); fuckme harder, this abort gets tripped quite often,
929 in propagation and whatnot. #### fixme */
931 crb->type = RUNE_CHAR;
932 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
935 if (data->cursor_type == CURSOR_ON)
937 if (data->bi_bufpos == data->bi_cursor_bufpos)
939 crb->cursor_type = CURSOR_ON;
940 data->cursor_x = Dynarr_length (data->db->runes);
943 crb->cursor_type = CURSOR_OFF;
945 else if (data->cursor_type == NEXT_CURSOR)
947 crb->cursor_type = CURSOR_ON;
948 data->cursor_x = Dynarr_length (data->db->runes);
949 data->cursor_type = NO_CURSOR;
951 else if (data->cursor_type == IGNORE_CURSOR)
952 crb->cursor_type = IGNORE_CURSOR;
954 crb->cursor_type = CURSOR_OFF;
957 Dynarr_add (data->db->runes, *crb);
959 Dynarr_increment (data->db->runes);
961 data->pixpos += width;
966 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
967 for each character in the string. Propagate any left-over data
968 unless NO_PROP is non-zero. */
970 static prop_block_dynarr *
971 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
972 Bytecount c_length, int no_prop)
974 Bufbyte *pos, *end = c_string + c_length;
975 prop_block_dynarr *prop;
977 /* #### This function is too simplistic. It needs to do the same
978 sort of character interpretation (display-table lookup,
979 ctl-arrow checking), etc. that create_text_block() does.
980 The functionality to do this in that routine needs to be
983 for (pos = c_string; pos < end;)
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);
1015 /* Add a single rune of the specified width. The area covered by this
1016 rune will be displayed in the foreground color of the associated
1019 static prop_block_dynarr *
1020 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1024 /* If data->start_col is not 0 then this call to add_blank_rune must have
1025 been to add it as a tab. */
1026 if (data->start_col)
1028 /* assert (w != NULL) */
1029 prop_block_dynarr *retval;
1031 /* If we have still not fully scrolled horizontally, subtract
1032 the width of this tab and return. */
1033 if (char_tab_width < data->start_col)
1035 data->start_col -= char_tab_width;
1038 else if (char_tab_width == data->start_col)
1039 data->blank_width = 0;
1042 int spcwid = space_width (w);
1044 if (spcwid >= data->blank_width)
1045 data->blank_width = 0;
1047 data->blank_width -= spcwid;
1050 data->start_col = 0;
1051 retval = add_hscroll_rune (data);
1053 /* Could be caused by the handling of the hscroll rune. */
1054 if (retval != NULL || !data->blank_width)
1058 /* Blank runes are always calculated to fit. */
1059 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1061 rb.findex = data->findex;
1062 rb.xpos = data->pixpos;
1063 rb.width = data->blank_width;
1064 if (data->bi_bufpos)
1066 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1069 /* #### and this is really correct too? */
1072 rb.type = RUNE_BLANK;
1074 if (data->cursor_type == CURSOR_ON)
1076 if (data->bi_bufpos == data->bi_cursor_bufpos)
1078 rb.cursor_type = CURSOR_ON;
1079 data->cursor_x = Dynarr_length (data->db->runes);
1082 rb.cursor_type = CURSOR_OFF;
1084 else if (data->cursor_type == NEXT_CURSOR)
1086 rb.cursor_type = CURSOR_ON;
1087 data->cursor_x = Dynarr_length (data->db->runes);
1088 data->cursor_type = NO_CURSOR;
1091 rb.cursor_type = CURSOR_OFF;
1093 Dynarr_add (data->db->runes, rb);
1094 data->pixpos += data->blank_width;
1099 /* Add runes representing a character in octal. */
1101 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1103 if (add_failed || (add_failed = add_emchar_rune (data))) \
1105 struct prop_block pb; \
1107 prop = Dynarr_new (prop_block); \
1109 pb.type = PROP_CHAR; \
1110 pb.data.p_char.ch = data->ch; \
1111 pb.data.p_char.cursor_type = data->cursor_type; \
1112 Dynarr_add (prop, pb); \
1116 static prop_block_dynarr *
1117 add_octal_runes (pos_data *data)
1119 prop_block_dynarr *prop, *add_failed;
1120 Emchar orig_char = data->ch;
1121 unsigned int orig_cursor_type = data->cursor_type;
1127 if (data->start_col)
1130 if (!data->start_col)
1132 if (data->bi_start_col_enabled)
1134 add_failed = add_hscroll_rune (data);
1138 struct glyph_block gb;
1139 struct window *w = XWINDOW (data->window);
1142 gb.glyph = Voctal_escape_glyph;
1144 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1145 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1149 /* We only propagate information if the glyph was partially
1154 data->cursor_type = IGNORE_CURSOR;
1156 if (data->ch >= 0x100)
1158 /* If the character is an extended Mule character, it could have
1159 up to 19 bits. For the moment, we treat it as a seven-digit
1160 octal number. This is not that pretty, but whatever. */
1161 data->ch = (7 & (orig_char >> 18)) + '0';
1162 ADD_NEXT_OCTAL_RUNE_CHAR;
1164 data->ch = (7 & (orig_char >> 15)) + '0';
1165 ADD_NEXT_OCTAL_RUNE_CHAR;
1167 data->ch = (7 & (orig_char >> 12)) + '0';
1168 ADD_NEXT_OCTAL_RUNE_CHAR;
1170 data->ch = (7 & (orig_char >> 9)) + '0';
1171 ADD_NEXT_OCTAL_RUNE_CHAR;
1174 data->ch = (7 & (orig_char >> 6)) + '0';
1175 ADD_NEXT_OCTAL_RUNE_CHAR;
1177 data->ch = (7 & (orig_char >> 3)) + '0';
1178 ADD_NEXT_OCTAL_RUNE_CHAR;
1180 data->ch = (7 & orig_char) + '0';
1181 ADD_NEXT_OCTAL_RUNE_CHAR;
1183 data->cursor_type = orig_cursor_type;
1187 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1189 /* Add runes representing a control character to a display block. */
1191 static prop_block_dynarr *
1192 add_control_char_runes (pos_data *data, struct buffer *b)
1194 if (!NILP (b->ctl_arrow))
1196 prop_block_dynarr *prop;
1197 Emchar orig_char = data->ch;
1198 unsigned int old_cursor_type = data->cursor_type;
1203 if (data->start_col)
1206 if (!data->start_col)
1208 if (data->bi_start_col_enabled)
1210 prop_block_dynarr *retval;
1212 retval = add_hscroll_rune (data);
1218 struct glyph_block gb;
1219 struct window *w = XWINDOW (data->window);
1222 gb.glyph = Vcontrol_arrow_glyph;
1224 /* We only propagate information if the glyph was partially
1226 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1227 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1232 if (orig_char == 0177)
1235 data->ch = orig_char ^ 0100;
1236 data->cursor_type = IGNORE_CURSOR;
1238 if (add_emchar_rune (data))
1240 struct prop_block pb;
1242 prop = Dynarr_new (prop_block);
1244 pb.type = PROP_CHAR;
1245 pb.data.p_char.ch = data->ch;
1246 pb.data.p_char.cursor_type = data->cursor_type;
1247 Dynarr_add (prop, pb);
1250 data->cursor_type = old_cursor_type;
1255 return add_octal_runes (data);
1259 static prop_block_dynarr *
1260 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
1262 prop_block_dynarr *prop = NULL;
1264 if (STRINGP (entry))
1266 prop = add_bufbyte_string_runes (data,
1267 XSTRING_DATA (entry),
1268 XSTRING_LENGTH (entry),
1271 else if (GLYPHP (entry))
1273 if (data->start_col)
1276 if (!data->start_col && data->bi_start_col_enabled)
1278 prop = add_hscroll_rune (data);
1282 struct glyph_block gb;
1286 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1289 else if (CHAR_OR_CHAR_INTP (entry))
1291 data->ch = XCHAR_OR_CHAR_INT (entry);
1292 prop = add_emchar_rune (data);
1294 else if (CONSP (entry))
1296 if (EQ (XCAR (entry), Qformat)
1297 && CONSP (XCDR (entry))
1298 && STRINGP (XCAR (XCDR (entry))))
1300 Lisp_Object format = XCAR (XCDR (entry));
1301 Bytind len = XSTRING_LENGTH (format);
1302 Bufbyte *src = XSTRING_DATA (format), *end = src + len;
1303 Bufbyte *result = alloca_array (Bufbyte, len);
1304 Bufbyte *dst = result;
1308 Emchar c = charptr_emchar (src);
1310 if (c != '%' || src == end)
1311 dst += set_charptr_emchar (dst, c);
1314 c = charptr_emchar (src);
1319 dst += long_to_string_base ((char *)dst, data->ch, 16);
1322 dst += set_charptr_emchar (dst, '%');
1327 prop = add_bufbyte_string_runes (data, result, dst - result, 0);
1331 /* Else blow it off because someone added a bad entry and we don't
1332 have any safe way of signaling an error. */
1336 /* Given a display table entry, call the appropriate functions to
1337 display each element of the entry. */
1339 static prop_block_dynarr *
1340 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1342 prop_block_dynarr *prop = NULL;
1343 if (VECTORP (entry))
1345 Lisp_Vector *de = XVECTOR (entry);
1346 EMACS_INT len = vector_length (de);
1349 for (elt = 0; elt < len; elt++)
1351 if (NILP (vector_data (de)[elt]))
1354 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
1355 /* Else blow it off because someone added a bad entry and we
1356 don't have any safe way of signaling an error. Hey, this
1357 comment sounds familiar. */
1359 /* #### Still need to add any remaining elements to the
1360 propagation information. */
1366 prop = add_disp_table_entry_runes_1 (data, entry);
1370 /* Add runes which were propagated from the previous line. */
1372 static prop_block_dynarr *
1373 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1375 /* #### Remember to handle start_col parameter of data when the rest of
1376 this is finished. */
1377 /* #### Chuck -- I've redone this function a bit. It looked like the
1378 case of not all the propagation blocks being added was not handled
1380 /* #### Chuck -- I also think the double indirection of PROP is kind
1381 of bogus. A cleaner solution is just to check for
1382 Dynarr_length (prop) > 0. */
1383 /* #### This function also doesn't even pay attention to ADD_FAILED!
1384 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1387 prop_block_dynarr *add_failed;
1388 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1389 unsigned int old_cursor_type = data->cursor_type;
1391 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1393 struct prop_block *pb = Dynarr_atp (*prop, elt);
1398 data->ch = pb->data.p_char.ch;
1399 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1400 data->cursor_type = pb->data.p_char.cursor_type;
1401 add_failed = add_emchar_rune (data);
1404 goto oops_no_more_space;
1407 if (pb->data.p_string.str)
1408 xfree (pb->data.p_string.str);
1409 /* #### bogus bogus -- this doesn't do anything!
1410 Should probably call add_bufbyte_string_runes(),
1411 once that function is fixed. */
1413 case PROP_MINIBUF_PROMPT:
1415 face_index old_findex = data->findex;
1416 Bytind bi_old_bufpos = data->bi_bufpos;
1418 data->findex = DEFAULT_INDEX;
1419 data->bi_bufpos = 0;
1420 data->cursor_type = NO_CURSOR;
1422 while (pb->data.p_string.len > 0)
1424 data->ch = charptr_emchar (pb->data.p_string.str);
1425 add_failed = add_emchar_rune (data);
1429 data->findex = old_findex;
1430 data->bi_bufpos = bi_old_bufpos;
1431 goto oops_no_more_space;
1435 /* Complicated equivalent of ptr++, len-- */
1436 Bufbyte *oldpos = pb->data.p_string.str;
1437 INC_CHARPTR (pb->data.p_string.str);
1438 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1442 data->findex = old_findex;
1443 /* ##### FIXME FIXME FIXME -- Upon successful return from
1444 this function, data->bi_bufpos is automatically incremented.
1445 However, we don't want that to happen if we were adding
1446 the minibuffer prompt. */
1448 struct buffer *buf =
1449 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1450 /* #### Chuck fix this shit or I'm gonna scream! */
1451 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1452 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1454 /* #### is this correct? Does anyone know?
1455 Does anyone care? Is this a cheesy hack or what? */
1456 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1462 /* #### I think it's unnecessary and misleading to preserve
1463 the blank_width, as it implies that the value carries
1464 over from one rune to the next, which is wrong. */
1465 int old_width = data->blank_width;
1466 face_index old_findex = data->findex;
1468 data->findex = pb->data.p_blank.findex;
1469 data->blank_width = pb->data.p_blank.width;
1470 data->bi_cursor_bufpos = 0;
1471 data->cursor_type = IGNORE_CURSOR;
1473 if (data->pixpos + data->blank_width > data->max_pixpos)
1474 data->blank_width = data->max_pixpos - data->pixpos;
1476 /* We pass a bogus value of char_tab_width. It shouldn't
1477 matter because unless something is really screwed up
1478 this call won't cause that arg to be used. */
1479 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1481 /* This can happen in the case where we have a tab which
1482 is wider than the window. */
1483 if (data->blank_width != pb->data.p_blank.width)
1485 pb->data.p_blank.width -= data->blank_width;
1486 add_failed = ADD_FAILED;
1489 data->findex = old_findex;
1490 data->blank_width = old_width;
1493 goto oops_no_more_space;
1503 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1504 data->cursor_type = old_cursor_type;
1505 if (elt < Dynarr_length (*prop))
1507 Dynarr_delete_many (*prop, 0, elt);
1512 Dynarr_free (*prop);
1517 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1518 the display block, but add all other types to the appropriate list
1519 of the display line. They will be added later by different
1522 static prop_block_dynarr *
1523 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1524 int allow_cursor, struct glyph_cachel *cachel)
1526 struct window *w = XWINDOW (data->window);
1528 /* If window faces changed, and glyph instance is text, then
1529 glyph sizes might have changed too */
1530 invalidate_glyph_geometry_maybe (gb->glyph, w);
1532 /* This makes sure the glyph is in the cachels.
1534 #### We do this to make sure the glyph is in the glyph cachels,
1535 so that the dirty flag can be reset after redisplay has
1536 finished. We should do this some other way, maybe by iterating
1537 over the window cache of subwindows. */
1538 get_glyph_cachel_index (w, gb->glyph);
1540 /* A nil extent indicates a special glyph (ex. truncator). */
1541 if (NILP (gb->extent)
1542 || (pos_type == BEGIN_GLYPHS &&
1543 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1544 || (pos_type == END_GLYPHS &&
1545 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
1550 int ascent, descent;
1551 Lisp_Object baseline;
1555 width = cachel->width;
1557 width = glyph_width (gb->glyph, data->window);
1562 if (data->start_col || data->start_col_xoffset)
1564 prop_block_dynarr *retval;
1565 int glyph_char_width = width / space_width (w);
1567 /* If we still have not fully scrolled horizontally after
1568 taking into account the width of the glyph, subtract its
1569 width and return. */
1570 if (glyph_char_width < data->start_col)
1572 data->start_col -= glyph_char_width;
1575 else if (glyph_char_width == data->start_col)
1579 xoffset = space_width (w) * data->start_col;
1582 /* #### Can this happen? */
1587 data->start_col = 0;
1588 retval = add_hscroll_rune (data);
1590 /* Could be caused by the handling of the hscroll rune. */
1591 if (retval != NULL || !width)
1597 if (data->pixpos + width > data->max_pixpos)
1599 /* If this is the first object we are attempting to add to
1600 the line then we ignore the horizontal_clip threshold.
1601 Otherwise we will loop until the bottom of the window
1602 continually failing to add this glyph because it is wider
1603 than the window. We could alternatively just completely
1604 ignore the glyph and proceed from there but I think that
1605 this is a better solution. */
1606 if (Dynarr_length (data->db->runes)
1607 && data->max_pixpos - data->pixpos < horizontal_clip)
1610 width = data->max_pixpos - data->pixpos;
1615 ascent = cachel->ascent;
1616 descent = cachel->descent;
1620 ascent = glyph_ascent (gb->glyph, data->window);
1621 descent = glyph_descent (gb->glyph, data->window);
1624 baseline = glyph_baseline (gb->glyph, data->window);
1626 if (glyph_contrib_p (gb->glyph, data->window))
1628 /* A pixmap that has not had a baseline explicitly set. Its
1629 contribution will be determined later. */
1630 if (NILP (baseline))
1632 int height = ascent + descent;
1633 data->max_pixmap_height = max (data->max_pixmap_height, height);
1636 /* A string so determine contribution normally. */
1637 else if (EQ (baseline, Qt))
1639 data->new_ascent = max (data->new_ascent, ascent);
1640 data->new_descent = max (data->new_descent, descent);
1643 /* A pixmap with an explicitly set baseline. We determine the
1644 contribution here. */
1645 else if (INTP (baseline))
1647 int height = ascent + descent;
1648 int pix_ascent, pix_descent;
1650 pix_ascent = height * XINT (baseline) / 100;
1651 pix_descent = height - pix_ascent;
1653 data->new_ascent = max (data->new_ascent, pix_ascent);
1654 data->new_descent = max (data->new_descent, pix_descent);
1657 /* Otherwise something is screwed up. */
1662 face = glyph_face (gb->glyph, data->window);
1664 rb.findex = data->findex;
1666 rb.findex = get_builtin_face_cache_index (w, face);
1668 rb.xpos = data->pixpos;
1670 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1671 if (data->bi_endpos)
1672 /* #### is this necessary at all? */
1673 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1677 rb.type = RUNE_DGLYPH;
1678 /* #### Ben sez: this is way bogus if the glyph is a string.
1679 You should not make the output routines have to cope with
1680 this. The string could contain Mule characters, or non-
1681 printable characters, or characters to be passed through
1682 the display table, or non-character objects (when this gets
1683 implemented), etc. Instead, this routine here should parse
1684 the string into a series of runes. */
1685 rb.object.dglyph.glyph = gb->glyph;
1686 rb.object.dglyph.extent = gb->extent;
1687 rb.object.dglyph.xoffset = xoffset;
1691 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1694 if (data->cursor_type == CURSOR_ON)
1696 if (data->bi_bufpos == data->bi_cursor_bufpos)
1698 rb.cursor_type = CURSOR_ON;
1699 data->cursor_x = Dynarr_length (data->db->runes);
1702 rb.cursor_type = CURSOR_OFF;
1704 else if (data->cursor_type == NEXT_CURSOR)
1706 rb.cursor_type = CURSOR_ON;
1707 data->cursor_x = Dynarr_length (data->db->runes);
1708 data->cursor_type = NO_CURSOR;
1710 else if (data->cursor_type == IGNORE_CURSOR)
1711 rb.cursor_type = IGNORE_CURSOR;
1712 else if (data->cursor_type == NO_CURSOR)
1713 rb.cursor_type = NO_CURSOR;
1715 rb.cursor_type = CURSOR_OFF;
1718 rb.cursor_type = CURSOR_OFF;
1720 Dynarr_add (data->db->runes, rb);
1721 data->pixpos += width;
1727 if (!NILP (glyph_face (gb->glyph, data->window)))
1729 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1732 gb->findex = data->findex;
1734 if (pos_type == BEGIN_GLYPHS)
1736 if (!data->dl->left_glyphs)
1737 data->dl->left_glyphs = Dynarr_new (glyph_block);
1738 Dynarr_add (data->dl->left_glyphs, *gb);
1741 else if (pos_type == END_GLYPHS)
1743 if (!data->dl->right_glyphs)
1744 data->dl->right_glyphs = Dynarr_new (glyph_block);
1745 Dynarr_add (data->dl->right_glyphs, *gb);
1749 abort (); /* there are no unknown types */
1752 return NULL; /* shut up compiler */
1755 /* Add all glyphs at position POS_TYPE that are contained in the given
1758 static prop_block_dynarr *
1759 add_glyph_runes (pos_data *data, int pos_type)
1761 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1762 why didn't you just modify add_glyph_rune in the first place? */
1764 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1765 ? data->ef->begin_glyphs
1766 : data->ef->end_glyphs);
1767 prop_block_dynarr *prop;
1769 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1771 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1776 /* #### Add some propagation information. */
1781 Dynarr_reset (glyph_arr);
1786 /* Given a position for a buffer in a window, ensure that the given
1787 display line DL accurately represents the text on a line starting
1788 at the given position.
1790 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1791 You must do appropriate conversion. */
1794 create_text_block (struct window *w, struct display_line *dl,
1795 Bytind bi_start_pos, prop_block_dynarr **prop,
1798 struct frame *f = XFRAME (w->frame);
1799 struct buffer *b = XBUFFER (w->buffer);
1800 struct device *d = XDEVICE (f->device);
1804 /* Don't display anything in the minibuffer if this window is not on
1805 a selected frame. We consider all other windows to be active
1806 minibuffers as it simplifies the coding. */
1807 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1808 (f == device_selected_frame (d)) ||
1809 is_surrogate_for_selected_frame (f));
1811 int truncate_win = window_truncation_on (w);
1812 int end_glyph_width;
1814 /* If the buffer's value of selective_display is an integer then
1815 only lines that start with less than selective_display columns of
1816 space will be displayed. If selective_display is t then all text
1817 after a ^M is invisible. */
1818 int selective = (INTP (b->selective_display)
1819 ? XINT (b->selective_display)
1820 : (!NILP (b->selective_display) ? -1 : 0));
1822 /* The variable ctl-arrow allows the user to specify what characters
1823 can actually be displayed and which octal should be used for.
1824 #### This variable should probably have some rethought done to
1827 #### It would also be really nice if you could specify that
1828 the characters come out in hex instead of in octal. Mule
1829 does that by adding a ctl-hexa variable similar to ctl-arrow,
1830 but that's bogus -- we need a more general solution. I
1831 think you need to extend the concept of display tables
1832 into a more general conversion mechanism. Ideally you
1833 could specify a Lisp function that converts characters,
1834 but this violates the Second Golden Rule and besides would
1835 make things way way way way slow.
1837 So instead, we extend the display-table concept, which was
1838 historically limited to 256-byte vectors, to one of the
1841 a) A 256-entry vector, for backward compatibility;
1842 b) char-table, mapping characters to values;
1843 c) range-table, mapping ranges of characters to values;
1844 d) a list of the above.
1846 The (d) option allows you to specify multiple display tables
1847 instead of just one. Each display table can specify conversions
1848 for some characters and leave others unchanged. The way the
1849 character gets displayed is determined by the first display table
1850 with a binding for that character. This way, you could call a
1851 function `enable-hex-display' that adds a hex display-table to
1852 the list of display tables for the current buffer.
1854 #### ...not yet implemented... Also, we extend the concept of
1855 "mapping" to include a printf-like spec. Thus you can make all
1856 extended characters show up as hex with a display table like
1859 #s(range-table data ((256 524288) (format "%x")))
1861 Since more than one display table is possible, you have
1862 great flexibility in mapping ranges of characters. */
1863 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1864 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1865 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1868 Lisp_Object face_dt, window_dt;
1870 /* The text display block for this display line. */
1871 struct display_block *db = get_display_block_from_line (dl, TEXT);
1873 /* The first time through the main loop we need to force the glyph
1874 data to be updated. */
1877 /* Apparently the new extent_fragment_update returns an end position
1878 equal to the position passed in if there are no more runs to be
1880 int no_more_frags = 0;
1882 Lisp_Object synch_minibuffers_value =
1883 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1885 dl->used_prop_data = 0;
1889 data.ef = extent_fragment_new (w->buffer, f);
1891 /* These values are used by all of the rune addition routines. We add
1892 them to this structure for ease of passing. */
1894 XSETWINDOW (data.window, w);
1899 data.bi_bufpos = bi_start_pos;
1900 data.pixpos = dl->bounds.left_in;
1901 data.last_charset = Qunbound;
1902 data.last_findex = DEFAULT_INDEX;
1903 data.result_str = Qnil;
1905 /* Set the right boundary adjusting it to take into account any end
1906 glyph. Save the width of the end glyph for later use. */
1907 data.max_pixpos = dl->bounds.right_in;
1909 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1911 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1912 data.max_pixpos -= end_glyph_width;
1914 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1916 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1917 data.cursor_type = CURSOR_ON;
1919 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1920 data.cursor_type = NO_CURSOR;
1921 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1922 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1923 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1924 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1926 data.bi_cursor_bufpos = BI_BUF_PT (b);
1927 data.cursor_type = CURSOR_ON;
1929 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1931 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1932 data.cursor_type = CURSOR_ON;
1935 data.cursor_type = NO_CURSOR;
1938 data.start_col = w->hscroll;
1939 data.start_col_xoffset = w->left_xoffset;
1940 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1941 data.hscroll_glyph_width_adjust = 0;
1943 /* We regenerate the line from the very beginning. */
1944 Dynarr_reset (db->runes);
1946 /* Why is this less than or equal and not just less than? If the
1947 starting position is already equal to the maximum we can't add
1948 anything else, right? Wrong. We might still have a newline to
1949 add. A newline can use the room allocated for an end glyph since
1950 if we add it we know we aren't going to be adding any end
1953 /* #### Chuck -- I think this condition should be while (1).
1954 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1955 and the begin-glyph ends exactly at the end of the window, the
1956 end-glyph and text might not be displayed. while (1) ensures
1957 that the loop terminates only when either (a) there is
1958 propagation data or (b) the end-of-line or end-of-buffer is hit.
1960 #### Also I think you need to ensure that the operation
1961 "add begin glyphs; add end glyphs; add text" is atomic and
1962 can't get interrupted in the middle. If you run off the end
1963 of the line during that operation, then you keep accumulating
1964 propagation data until you're done. Otherwise, if the (e.g.)
1965 there's a begin glyph at a particular position and attempting
1966 to display that glyph results in window-end being hit and
1967 propagation data being generated, then the character at that
1968 position won't be displayed.
1970 #### See also the comment after the end of this loop, below.
1972 while (data.pixpos <= data.max_pixpos
1973 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1975 /* #### This check probably should not be necessary. */
1976 if (data.bi_bufpos > BI_BUF_ZV (b))
1978 /* #### urk! More of this lossage! */
1983 /* If selective display was an integer and we aren't working on
1984 a continuation line then find the next line we are actually
1985 supposed to display. */
1987 && (data.bi_bufpos == BI_BUF_BEGV (b)
1988 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
1990 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
1993 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
1994 if (data.bi_bufpos >= BI_BUF_ZV (b))
1996 data.bi_bufpos = BI_BUF_ZV (b);
2002 /* Check for face changes. */
2003 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
2005 /* Now compute the face and begin/end-glyph information. */
2007 /* Remember that the extent-fragment routines deal in Bytind's. */
2008 extent_fragment_update (w, data.ef, data.bi_bufpos);
2010 get_display_tables (w, data.findex, &face_dt, &window_dt);
2012 if (data.bi_bufpos == data.ef->end)
2017 /* Determine what is next to be displayed. We first handle any
2018 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2019 display then we determine what to do based on the character at the
2020 current buffer position. */
2022 /* If the current position is covered by an invisible extent, do
2023 nothing (except maybe add some ellipses).
2025 #### The behavior of begin and end-glyphs at the edge of an
2026 invisible extent should be investigated further. This is
2027 fairly low priority though. */
2028 if (data.ef->invisible)
2030 /* #### Chuck, perhaps you could look at this code? I don't
2031 really know what I'm doing. */
2034 Dynarr_free (*prop);
2038 /* The extent fragment code only sets this when we should
2039 really display the ellipses. It makes sure the ellipses
2040 don't get displayed more than once in a row. */
2041 if (data.ef->invisible_ellipses)
2043 struct glyph_block gb;
2045 data.ef->invisible_ellipses_already_displayed = 1;
2046 data.ef->invisible_ellipses = 0;
2048 gb.glyph = Vinvisible_text_glyph;
2049 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2050 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2051 /* Perhaps they shouldn't propagate if the very next thing
2052 is to display a newline (for compatibility with
2053 selective-display-ellipses)? Maybe that's too
2059 /* If point is in an invisible region we place it on the
2060 next visible character. */
2061 if (data.cursor_type == CURSOR_ON
2062 && data.bi_bufpos == data.bi_cursor_bufpos)
2064 data.cursor_type = NEXT_CURSOR;
2067 /* #### What if we we're dealing with a display table? */
2071 if (data.bi_bufpos == BI_BUF_ZV (b))
2074 INC_BYTIND (b, data.bi_bufpos);
2077 /* If there is propagation data, then it represents the current
2078 buffer position being displayed. Add them and advance the
2079 position counter. This might also add the minibuffer
2083 dl->used_prop_data = 1;
2084 *prop = add_propagation_runes (prop, &data);
2087 goto done; /* gee, a really narrow window */
2088 else if (data.bi_bufpos == BI_BUF_ZV (b))
2090 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2091 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2092 data.bi_bufpos = BI_BUF_BEGV (b);
2094 INC_BYTIND (b, data.bi_bufpos);
2097 /* If there are end glyphs, add them to the line. These are
2098 the end glyphs for the previous run of text. We add them
2099 here rather than doing them at the end of handling the
2100 previous run so that glyphs at the beginning and end of
2101 a line are handled correctly. */
2102 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2104 *prop = add_glyph_runes (&data, END_GLYPHS);
2109 /* If there are begin glyphs, add them to the line. */
2110 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2112 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2117 /* If at end-of-buffer, we've already processed begin and
2118 end-glyphs at this point and there's no text to process,
2120 else if (data.bi_bufpos == BI_BUF_ZV (b))
2125 Lisp_Object entry = Qnil;
2126 /* Get the character at the current buffer position. */
2127 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2128 if (!NILP (face_dt) || !NILP (window_dt))
2129 entry = display_table_entry (data.ch, face_dt, window_dt);
2131 /* If there is a display table entry for it, hand it off to
2132 add_disp_table_entry_runes and let it worry about it. */
2133 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
2135 *prop = add_disp_table_entry_runes (&data, entry);
2141 /* Check if we have hit a newline character. If so, add a marker
2142 to the line and end this loop. */
2143 else if (data.ch == '\n')
2145 /* We aren't going to be adding an end glyph so give its
2146 space back in order to make sure that the cursor can
2148 data.max_pixpos += end_glyph_width;
2151 && (bi_spaces_at_point
2152 (b, next_bytind (b, data.bi_bufpos))
2155 if (!NILP (b->selective_display_ellipses))
2157 struct glyph_block gb;
2160 gb.glyph = Vinvisible_text_glyph;
2161 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2162 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2166 /* Cheesy, cheesy, cheesy. We mark the end of the
2167 line with a special "character rune" whose width
2168 is the EOL cursor width and whose character is
2169 the non-printing character '\n'. */
2170 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2171 *prop = add_emchar_rune (&data);
2174 /* We need to set data.bi_bufpos to the start of the
2175 next visible region in order to make this line
2176 appear to contain all of the invisible area.
2177 Otherwise, the line cache won't work
2179 INC_BYTIND (b, data.bi_bufpos);
2180 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2183 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2184 if (data.bi_bufpos >= BI_BUF_ZV (b))
2186 data.bi_bufpos = BI_BUF_ZV (b);
2190 if (BI_BUF_FETCH_CHAR
2191 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2192 DEC_BYTIND (b, data.bi_bufpos);
2196 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2197 *prop = add_emchar_rune (&data);
2203 /* If the current character is ^M, and selective display is
2204 enabled, then add the invisible-text-glyph if
2205 selective-display-ellipses is set. In any case, this
2207 else if (data.ch == (('M' & 037)) && selective == -1)
2209 Bytind bi_next_bufpos;
2211 /* Find the buffer position at the end of the line. */
2213 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2214 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2216 DEC_BYTIND (b, bi_next_bufpos);
2218 /* If the cursor is somewhere in the elided text make
2219 sure that the cursor gets drawn appropriately. */
2220 if (data.cursor_type == CURSOR_ON
2221 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2222 data.bi_cursor_bufpos < bi_next_bufpos))
2224 data.cursor_type = NEXT_CURSOR;
2227 /* We won't be adding a truncation or continuation glyph
2228 so give up the room allocated for them. */
2229 data.max_pixpos += end_glyph_width;
2231 if (!NILP (b->selective_display_ellipses))
2233 /* We don't propagate anything from the invisible
2234 text glyph if it fails to fit. This is
2236 struct glyph_block gb;
2239 gb.glyph = Vinvisible_text_glyph;
2240 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2241 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2244 /* Set the buffer position to the end of the line. We
2245 need to do this before potentially adding a newline
2246 so that the cursor flag will get set correctly (if
2248 data.bi_bufpos = bi_next_bufpos;
2250 if (NILP (b->selective_display_ellipses)
2251 || data.bi_cursor_bufpos == bi_next_bufpos)
2253 /* We have to at least add a newline character so
2254 that the cursor shows up properly. */
2256 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2257 data.findex = DEFAULT_INDEX;
2259 data.start_col_xoffset = 0;
2260 data.bi_start_col_enabled = 0;
2262 add_emchar_rune (&data);
2265 /* This had better be a newline but doing it this way
2266 we'll see obvious incorrect results if it isn't. No
2267 need to abort here. */
2268 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2273 /* If the current character is considered to be printable, then
2275 else if (data.ch >= printable_min)
2277 *prop = add_emchar_rune (&data);
2282 /* If the current character is a tab, determine the next tab
2283 starting position and add a blank rune which extends from the
2284 current pixel position to that starting position. */
2285 else if (data.ch == '\t')
2287 int tab_start_pixpos = data.pixpos;
2292 if (data.start_col > 1)
2293 tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
2294 + data.start_col_xoffset;
2297 next_tab_position (w, tab_start_pixpos,
2298 dl->bounds.left_in +
2299 data.hscroll_glyph_width_adjust);
2300 if (next_tab_start > data.max_pixpos)
2302 prop_width = next_tab_start - data.max_pixpos;
2303 next_tab_start = data.max_pixpos;
2305 data.blank_width = next_tab_start - data.pixpos;
2307 (next_tab_start - tab_start_pixpos) / space_width (w);
2309 *prop = add_blank_rune (&data, w, char_tab_width);
2311 /* add_blank_rune is only supposed to be called with
2312 sizes guaranteed to fit in the available space. */
2317 struct prop_block pb;
2318 *prop = Dynarr_new (prop_block);
2320 pb.type = PROP_BLANK;
2321 pb.data.p_blank.width = prop_width;
2322 pb.data.p_blank.findex = data.findex;
2323 Dynarr_add (*prop, pb);
2329 /* If character is a control character, pass it off to
2330 add_control_char_runes.
2332 The is_*() routines have undefined results on
2333 arguments outside of the range [-1, 255]. (This
2334 often bites people who carelessly use `char' instead
2335 of `unsigned char'.)
2337 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2339 *prop = add_control_char_runes (&data, b);
2345 /* If the character is above the ASCII range and we have not
2346 already handled it, then print it as an octal number. */
2347 else if (data.ch >= 0200)
2349 *prop = add_octal_runes (&data);
2355 /* Assume the current character is considered to be printable,
2356 then just add it. */
2359 *prop = add_emchar_rune (&data);
2364 INC_BYTIND (b, data.bi_bufpos);
2370 /* Determine the starting point of the next line if we did not hit the
2371 end of the buffer. */
2372 if (data.bi_bufpos < BI_BUF_ZV (b)
2373 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2375 /* #### This check is not correct. If the line terminated
2376 due to a begin-glyph or end-glyph hitting window-end, then
2377 data.ch will not point to the character at data.bi_bufpos. If
2378 you make the two changes mentioned at the top of this loop,
2379 you should be able to say '(if (*prop))'. That should also
2380 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2383 /* The common case is that the line ended because we hit a newline.
2384 In that case, the next character is just the next buffer
2386 if (data.ch == '\n')
2388 /* If data.start_col_enabled is still true, then the window is
2389 scrolled far enough so that nothing on this line is visible.
2390 We need to stick a truncation glyph at the beginning of the
2391 line in that case unless the line is completely blank. */
2392 if (data.bi_start_col_enabled)
2394 if (data.cursor_type == CURSOR_ON)
2396 if (data.bi_cursor_bufpos >= bi_start_pos
2397 && data.bi_cursor_bufpos <= data.bi_bufpos)
2398 data.bi_cursor_bufpos = data.bi_bufpos;
2400 data.findex = DEFAULT_INDEX;
2402 data.bi_start_col_enabled = 0;
2404 if (data.bi_bufpos != bi_start_pos)
2406 struct glyph_block gb;
2409 gb.glyph = Vhscroll_glyph;
2410 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2411 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2415 /* This duplicates code down below to add a newline to
2416 the end of an otherwise empty line.*/
2418 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2420 add_emchar_rune (&data);
2424 INC_BYTIND (b, data.bi_bufpos);
2427 /* Otherwise we have a buffer line which cannot fit on one display
2431 struct glyph_block gb;
2432 struct glyph_cachel *cachel;
2434 /* If the line is to be truncated then we actually have to look
2435 for the next newline. We also add the end-of-line glyph which
2436 we know will fit because we adjusted the right border before
2437 we starting laying out the line. */
2438 data.max_pixpos += end_glyph_width;
2439 data.findex = DEFAULT_INDEX;
2446 /* Now find the start of the next line. */
2447 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2449 /* If the cursor is past the truncation line then we
2450 make it appear on the truncation glyph. If we've hit
2451 the end of the buffer then we also make the cursor
2452 appear unless eob is immediately preceded by a
2453 newline. In that case the cursor should actually
2454 appear on the next line. */
2455 if (data.cursor_type == CURSOR_ON
2456 && data.bi_cursor_bufpos >= data.bi_bufpos
2457 && (data.bi_cursor_bufpos < bi_pos ||
2458 (bi_pos == BI_BUF_ZV (b)
2459 && (bi_pos == BI_BUF_BEGV (b)
2460 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2462 data.bi_cursor_bufpos = bi_pos;
2464 data.cursor_type = NO_CURSOR;
2466 data.bi_bufpos = bi_pos;
2467 gb.glyph = Vtruncation_glyph;
2468 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2472 /* The cursor can never be on the continuation glyph. */
2473 data.cursor_type = NO_CURSOR;
2475 /* data.bi_bufpos is already at the start of the next line. */
2477 gb.glyph = Vcontinuation_glyph;
2478 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2481 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
2483 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2484 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2485 /* #### Damn this losing shit. */
2489 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2490 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2492 /* We need to add a marker to the end of the line since there is no
2493 newline character in order for the cursor to get drawn. We label
2494 it as a newline so that it gets handled correctly by the
2495 whitespace routines below. */
2498 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2499 data.findex = DEFAULT_INDEX;
2501 data.start_col_xoffset = 0;
2502 data.bi_start_col_enabled = 0;
2504 data.max_pixpos += data.blank_width;
2505 add_emchar_rune (&data);
2506 data.max_pixpos -= data.blank_width;
2508 /* #### urk! Chuck, this shit is bad news. Going around
2509 manipulating invalid positions is guaranteed to result in
2510 trouble sooner or later. */
2511 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2514 /* Calculate left whitespace boundary. */
2518 /* Whitespace past a newline is considered right whitespace. */
2519 while (elt < Dynarr_length (db->runes))
2521 struct rune *rb = Dynarr_atp (db->runes, elt);
2523 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2524 || rb->type == RUNE_BLANK)
2526 dl->bounds.left_white += rb->width;
2530 elt = Dynarr_length (db->runes);
2534 /* Calculate right whitespace boundary. */
2536 int elt = Dynarr_length (db->runes) - 1;
2539 while (!done && elt >= 0)
2541 struct rune *rb = Dynarr_atp (db->runes, elt);
2543 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2544 && isspace (rb->object.chr.ch))
2545 && !rb->type == RUNE_BLANK)
2547 dl->bounds.right_white = rb->xpos + rb->width;
2555 /* The line is blank so everything is considered to be right
2558 dl->bounds.right_white = dl->bounds.left_in;
2561 /* Set the display blocks bounds. */
2562 db->start_pos = dl->bounds.left_in;
2563 if (Dynarr_length (db->runes))
2565 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2567 db->end_pos = rb->xpos + rb->width;
2570 db->end_pos = dl->bounds.right_white;
2572 /* update line height parameters */
2573 if (!data.new_ascent && !data.new_descent)
2575 /* We've got a blank line so initialize these values from the default
2577 default_face_font_info (data.window, &data.new_ascent,
2578 &data.new_descent, 0, 0, 0);
2581 if (data.max_pixmap_height)
2583 int height = data.new_ascent + data.new_descent;
2584 int pix_ascent, pix_descent;
2586 pix_descent = data.max_pixmap_height * data.new_descent / height;
2587 pix_ascent = data.max_pixmap_height - pix_descent;
2589 data.new_ascent = max (data.new_ascent, pix_ascent);
2590 data.new_descent = max (data.new_descent, pix_descent);
2593 dl->ascent = data.new_ascent;
2594 dl->descent = data.new_descent;
2597 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2599 if (dl->ascent < ascent)
2600 dl->ascent = ascent;
2603 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2605 if (dl->descent < descent)
2606 dl->descent = descent;
2609 dl->cursor_elt = data.cursor_x;
2610 /* #### lossage lossage lossage! Fix this shit! */
2611 if (data.bi_bufpos > BI_BUF_ZV (b))
2612 dl->end_bufpos = BUF_ZV (b);
2614 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2616 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2618 /* This doesn't correctly take into account tabs and control
2619 characters but if the window isn't being truncated then this
2620 value isn't going to end up being used anyhow. */
2621 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2623 /* #### handle horizontally scrolled line with text none of which
2624 was actually laid out. */
2626 /* #### handle any remainder of overlay arrow */
2628 if (*prop == ADD_FAILED)
2631 if (truncate_win && *prop)
2633 Dynarr_free (*prop);
2637 extent_fragment_delete (data.ef);
2639 /* #### If we started at EOB, then make sure we return a value past
2640 it so that regenerate_window will exit properly. This is bogus.
2641 The main loop should get fixed so that it isn't necessary to call
2642 this function if we are already at EOB. */
2644 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2645 return data.bi_bufpos + 1; /* Yuck! */
2647 return data.bi_bufpos;
2650 /* Display the overlay arrow at the beginning of the given line. */
2653 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2655 struct frame *f = XFRAME (w->frame);
2656 struct device *d = XDEVICE (f->device);
2659 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2660 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2666 XSETWINDOW (data.window, w);
2667 data.db = get_display_block_from_line (dl, OVERWRITE);
2669 data.pixpos = dl->bounds.left_in;
2670 data.max_pixpos = dl->bounds.right_in;
2671 data.cursor_type = NO_CURSOR;
2673 data.findex = DEFAULT_INDEX;
2674 data.last_charset = Qunbound;
2675 data.last_findex = DEFAULT_INDEX;
2676 data.result_str = Qnil;
2679 Dynarr_reset (data.db->runes);
2681 if (STRINGP (Voverlay_arrow_string))
2683 add_bufbyte_string_runes
2685 XSTRING_DATA (Voverlay_arrow_string),
2686 XSTRING_LENGTH (Voverlay_arrow_string),
2689 else if (GLYPHP (Voverlay_arrow_string))
2691 struct glyph_block gb;
2693 gb.glyph = Voverlay_arrow_string;
2695 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2698 if (data.max_pixmap_height)
2700 int height = data.new_ascent + data.new_descent;
2701 int pix_ascent, pix_descent;
2703 pix_descent = data.max_pixmap_height * data.new_descent / height;
2704 pix_ascent = data.max_pixmap_height - pix_descent;
2706 data.new_ascent = max (data.new_ascent, pix_ascent);
2707 data.new_descent = max (data.new_descent, pix_descent);
2710 dl->ascent = data.new_ascent;
2711 dl->descent = data.new_descent;
2713 data.db->start_pos = dl->bounds.left_in;
2714 data.db->end_pos = data.pixpos;
2716 return data.pixpos - dl->bounds.left_in;
2719 /* Add a type of glyph to a margin display block. */
2722 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2723 int count, enum glyph_layout layout, int side, Lisp_Object window)
2725 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2727 : dl->right_glyphs);
2732 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2733 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2736 elt = Dynarr_length (gbd) - 1;
2743 end = Dynarr_length (gbd);
2746 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2748 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2750 if (NILP (gb->extent))
2751 abort (); /* these should have been handled in add_glyph_rune */
2754 ((side == LEFT_GLYPHS &&
2755 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2756 || (side == RIGHT_GLYPHS &&
2757 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2761 rb.width = gb->width;
2762 rb.findex = gb->findex;
2766 rb.type = RUNE_DGLYPH;
2767 rb.object.dglyph.glyph = gb->glyph;
2768 rb.object.dglyph.extent = gb->extent;
2769 rb.object.dglyph.xoffset = 0;
2770 rb.cursor_type = CURSOR_OFF;
2772 Dynarr_add (db->runes, rb);
2777 if (glyph_contrib_p (gb->glyph, window))
2779 unsigned short ascent, descent;
2780 Lisp_Object baseline = glyph_baseline (gb->glyph, window);
2782 ascent = glyph_ascent (gb->glyph, window);
2783 descent = glyph_descent (gb->glyph, window);
2785 /* A pixmap that has not had a baseline explicitly set.
2786 We use the existing ascent / descent ratio of the
2788 if (NILP (baseline))
2790 int gheight = ascent + descent;
2791 int line_height = dl->ascent + dl->descent;
2792 int pix_ascent, pix_descent;
2794 pix_descent = (int) (gheight * dl->descent) / line_height;
2795 pix_ascent = gheight - pix_descent;
2797 dl->ascent = max ((int) dl->ascent, pix_ascent);
2798 dl->descent = max ((int) dl->descent, pix_descent);
2801 /* A string so determine contribution normally. */
2802 else if (EQ (baseline, Qt))
2804 dl->ascent = max (dl->ascent, ascent);
2805 dl->descent = max (dl->descent, descent);
2808 /* A pixmap with an explicitly set baseline. We determine the
2809 contribution here. */
2810 else if (INTP (baseline))
2812 int height = ascent + descent;
2813 int pix_ascent, pix_descent;
2815 pix_ascent = height * XINT (baseline) / 100;
2816 pix_descent = height - pix_ascent;
2818 dl->ascent = max ((int) dl->ascent, pix_ascent);
2819 dl->descent = max ((int) dl->descent, pix_descent);
2822 /* Otherwise something is screwed up. */
2828 (reverse ? elt-- : elt++);
2834 /* Add a blank to a margin display block. */
2837 add_margin_blank (struct display_line *dl, struct display_block *db,
2838 struct window *w, int xpos, int width, int side)
2842 rb.findex = (side == LEFT_GLYPHS
2843 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2844 : get_builtin_face_cache_index (w, Vright_margin_face));
2849 rb.type = RUNE_BLANK;
2850 rb.cursor_type = CURSOR_OFF;
2852 Dynarr_add (db->runes, rb);
2855 /* Display glyphs in the left outside margin, left inside margin and
2856 left whitespace area. */
2859 create_left_glyph_block (struct window *w, struct display_line *dl,
2864 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2866 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2867 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2868 int left_in_start = dl->bounds.left_in;
2869 int left_in_end = dl->bounds.left_in + overlay_width;
2871 struct display_block *odb, *idb;
2873 XSETWINDOW (window, w);
2875 /* We have to add the glyphs to the line in the order outside,
2876 inside, whitespace. However the precedence dictates that we
2877 determine how many will fit in the reverse order. */
2879 /* Determine how many whitespace glyphs we can display and where
2880 they should start. */
2881 white_in_start = dl->bounds.left_white;
2882 white_out_start = left_in_start;
2883 white_out_cnt = white_in_cnt = 0;
2886 while (elt < Dynarr_length (dl->left_glyphs))
2888 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2890 if (NILP (gb->extent))
2891 abort (); /* these should have been handled in add_glyph_rune */
2893 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2897 width = glyph_width (gb->glyph, window);
2899 if (white_in_start - width >= left_in_end)
2902 white_in_start -= width;
2906 else if (use_overflow
2907 && (white_out_start - width > dl->bounds.left_out))
2910 white_out_start -= width;
2921 /* Determine how many inside margin glyphs we can display and where
2922 they should start. The inside margin glyphs get whatever space
2923 is left after the whitespace glyphs have been displayed. These
2924 are tricky to calculate since if we decide to use the overflow
2925 area we basically have to start over. So for these we build up a
2926 list of just the inside margin glyphs and manipulate it to
2927 determine the needed info. */
2929 glyph_block_dynarr *ib;
2930 int avail_in, avail_out;
2933 int used_in, used_out;
2936 used_in = used_out = 0;
2937 ib = Dynarr_new (glyph_block);
2938 while (elt < Dynarr_length (dl->left_glyphs))
2940 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2942 if (NILP (gb->extent))
2943 abort (); /* these should have been handled in add_glyph_rune */
2945 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2948 gb->width = glyph_width (gb->glyph, window);
2949 used_in += gb->width;
2950 Dynarr_add (ib, *gb);
2960 avail_in = white_in_start - left_in_end;
2968 avail_out = white_out_start - dl->bounds.left_out;
2971 while (!done && marker < Dynarr_length (ib))
2973 int width = Dynarr_atp (ib, marker)->width;
2975 /* If everything now fits in the available inside margin
2976 space, we're done. */
2977 if (used_in <= avail_in)
2981 /* Otherwise see if we have room to move a glyph to the
2983 if (used_out + width <= avail_out)
2996 /* At this point we now know that everything from marker on goes in
2997 the inside margin and everything before it goes in the outside
2998 margin. The stuff going into the outside margin is guaranteed
2999 to fit, but we may have to trim some stuff from the inside. */
3001 in_in_end = left_in_end;
3002 in_out_start = white_out_start;
3003 in_out_cnt = in_in_cnt = 0;
3007 while (elt < Dynarr_length (dl->left_glyphs))
3009 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3011 if (NILP (gb->extent))
3012 abort (); /* these should have been handled in add_glyph_rune */
3014 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3017 int width = glyph_width (gb->glyph, window);
3022 in_out_start -= width;
3027 else if (in_in_end + width < white_in_start)
3042 /* Determine how many outside margin glyphs we can display. They
3043 always start at the left outside margin and can only use the
3044 outside margin space. */
3045 out_end = dl->bounds.left_out;
3049 while (elt < Dynarr_length (dl->left_glyphs))
3051 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3053 if (NILP (gb->extent))
3054 abort (); /* these should have been handled in add_glyph_rune */
3056 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3059 int width = glyph_width (gb->glyph, window);
3061 if (out_end + width <= in_out_start)
3075 /* Now that we know where everything goes, we add the glyphs as
3076 runes to the appropriate display blocks. */
3077 if (out_cnt || in_out_cnt || white_out_cnt)
3079 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3080 odb->start_pos = dl->bounds.left_out;
3081 /* #### We should stop adding a blank to account for the space
3082 between the end of the glyphs and the margin and instead set
3083 this accordingly. */
3084 odb->end_pos = dl->bounds.left_in;
3085 Dynarr_reset (odb->runes);
3090 if (in_in_cnt || white_in_cnt)
3092 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3093 idb->start_pos = dl->bounds.left_in;
3094 /* #### See above comment for odb->end_pos */
3095 idb->end_pos = dl->bounds.left_white;
3096 Dynarr_reset (idb->runes);
3101 /* First add the outside margin glyphs. */
3103 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3104 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3106 end_xpos = dl->bounds.left_out;
3108 /* There may be blank space between the outside margin glyphs and
3109 the inside margin glyphs. If so, add a blank. */
3110 if (in_out_cnt && (in_out_start - end_xpos))
3112 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3116 /* Next add the inside margin glyphs which are actually in the
3120 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3121 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3124 /* If we didn't add any inside margin glyphs to the outside margin,
3125 but are adding whitespace glyphs, then we need to add a blank
3127 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3129 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3133 /* Next add the whitespace margin glyphs which are actually in the
3137 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3138 GL_WHITESPACE, LEFT_GLYPHS, window);
3141 /* We take care of clearing between the end of the glyphs and the
3142 start of the inside margin for lines which have glyphs. */
3143 if (odb && (left_in_start - end_xpos))
3145 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3149 /* Next add the inside margin glyphs which are actually in the
3153 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3154 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3157 end_xpos = left_in_end;
3159 /* Make sure that the area between the end of the inside margin
3160 glyphs and the whitespace glyphs is cleared. */
3161 if (idb && (white_in_start - end_xpos > 0))
3163 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3167 /* Next add the whitespace margin glyphs which are actually in the
3171 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3172 LEFT_GLYPHS, window);
3175 /* Whitespace glyphs always end right next to the text block so
3176 there is nothing we have to make sure is cleared after them. */
3179 /* Display glyphs in the right outside margin, right inside margin and
3180 right whitespace area. */
3183 create_right_glyph_block (struct window *w, struct display_line *dl)
3187 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3189 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3190 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3192 struct display_block *odb, *idb;
3194 XSETWINDOW (window, w);
3196 /* We have to add the glyphs to the line in the order outside,
3197 inside, whitespace. However the precedence dictates that we
3198 determine how many will fit in the reverse order. */
3200 /* Determine how many whitespace glyphs we can display and where
3201 they should start. */
3202 white_in_end = dl->bounds.right_white;
3203 white_out_end = dl->bounds.right_in;
3204 white_out_cnt = white_in_cnt = 0;
3207 while (elt < Dynarr_length (dl->right_glyphs))
3209 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3211 if (NILP (gb->extent))
3212 abort (); /* these should have been handled in add_glyph_rune */
3214 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3216 int width = glyph_width (gb->glyph, window);
3218 if (white_in_end + width <= dl->bounds.right_in)
3221 white_in_end += width;
3225 else if (use_overflow
3226 && (white_out_end + width <= dl->bounds.right_out))
3229 white_out_end += width;
3240 /* Determine how many inside margin glyphs we can display and where
3241 they should start. The inside margin glyphs get whatever space
3242 is left after the whitespace glyphs have been displayed. These
3243 are tricky to calculate since if we decide to use the overflow
3244 area we basically have to start over. So for these we build up a
3245 list of just the inside margin glyphs and manipulate it to
3246 determine the needed info. */
3248 glyph_block_dynarr *ib;
3249 int avail_in, avail_out;
3252 int used_in, used_out;
3255 used_in = used_out = 0;
3256 ib = Dynarr_new (glyph_block);
3257 while (elt < Dynarr_length (dl->right_glyphs))
3259 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3261 if (NILP (gb->extent))
3262 abort (); /* these should have been handled in add_glyph_rune */
3264 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3266 gb->width = glyph_width (gb->glyph, window);
3267 used_in += gb->width;
3268 Dynarr_add (ib, *gb);
3277 avail_in = dl->bounds.right_in - white_in_end;
3282 avail_out = dl->bounds.right_out - white_out_end;
3285 while (!done && marker < Dynarr_length (ib))
3287 int width = Dynarr_atp (ib, marker)->width;
3289 /* If everything now fits in the available inside margin
3290 space, we're done. */
3291 if (used_in <= avail_in)
3295 /* Otherwise see if we have room to move a glyph to the
3297 if (used_out + width <= avail_out)
3310 /* At this point we now know that everything from marker on goes in
3311 the inside margin and everything before it goes in the outside
3312 margin. The stuff going into the outside margin is guaranteed
3313 to fit, but we may have to trim some stuff from the inside. */
3315 in_in_start = dl->bounds.right_in;
3316 in_out_end = dl->bounds.right_in;
3317 in_out_cnt = in_in_cnt = 0;
3321 while (elt < Dynarr_length (dl->right_glyphs))
3323 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3325 if (NILP (gb->extent))
3326 abort (); /* these should have been handled in add_glyph_rune */
3328 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3330 int width = glyph_width (gb->glyph, window);
3335 in_out_end += width;
3340 else if (in_in_start - width >= white_in_end)
3343 in_in_start -= width;
3355 /* Determine how many outside margin glyphs we can display. They
3356 always start at the right outside margin and can only use the
3357 outside margin space. */
3358 out_start = dl->bounds.right_out;
3362 while (elt < Dynarr_length (dl->right_glyphs))
3364 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3366 if (NILP (gb->extent))
3367 abort (); /* these should have been handled in add_glyph_rune */
3369 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3371 int width = glyph_width (gb->glyph, window);
3373 if (out_start - width >= in_out_end)
3387 /* Now that we now where everything goes, we add the glyphs as runes
3388 to the appropriate display blocks. */
3389 if (out_cnt || in_out_cnt || white_out_cnt)
3391 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3392 /* #### See comments before odb->start_pos init in
3393 create_left_glyph_block */
3394 odb->start_pos = dl->bounds.right_in;
3395 odb->end_pos = dl->bounds.right_out;
3396 Dynarr_reset (odb->runes);
3401 if (in_in_cnt || white_in_cnt)
3403 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3404 idb->start_pos = dl->bounds.right_white;
3405 /* #### See comments before odb->start_pos init in
3406 create_left_glyph_block */
3407 idb->end_pos = dl->bounds.right_in;
3408 Dynarr_reset (idb->runes);
3413 /* First add the whitespace margin glyphs which are actually in the
3417 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3418 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3422 end_xpos = dl->bounds.right_white;
3424 /* Make sure that the area between the end of the whitespace glyphs
3425 and the inside margin glyphs is cleared. */
3426 if (in_in_cnt && (in_in_start - end_xpos))
3428 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3432 /* Next add the inside margin glyphs which are actually in the
3436 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3437 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3440 /* If we didn't add any inside margin glyphs then make sure the rest
3441 of the inside margin area gets cleared. */
3442 if (idb && (dl->bounds.right_in - end_xpos))
3444 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3448 /* Next add any whitespace glyphs in the outside margin. */
3451 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3452 GL_WHITESPACE, RIGHT_GLYPHS, window);
3455 end_xpos = dl->bounds.right_in;
3457 /* Next add any inside margin glyphs in the outside margin. */
3460 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3461 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3464 /* There may be space between any whitespace or inside margin glyphs
3465 in the outside margin and the actual outside margin glyphs. */
3466 if (odb && (out_start - end_xpos))
3468 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3472 /* Finally, add the outside margin glyphs. */
3475 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3476 RIGHT_GLYPHS, window);
3481 /***************************************************************************/
3483 /* modeline routines */
3485 /***************************************************************************/
3487 /* This function is also used in frame.c by `generate_title_string' */
3489 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3490 struct window *w, struct display_line *dl,
3491 struct display_block *db, face_index findex,
3492 int min_pixpos, int max_pixpos, int type)
3494 struct frame *f = XFRAME (w->frame);
3495 struct device *d = XDEVICE (f->device);
3499 Charcount offset = 0;
3505 data.findex = findex;
3506 data.pixpos = min_pixpos;
3507 data.max_pixpos = max_pixpos;
3508 data.cursor_type = NO_CURSOR;
3509 data.last_charset = Qunbound;
3510 data.last_findex = DEFAULT_INDEX;
3511 data.result_str = result_str;
3512 data.is_modeline = 1;
3514 XSETWINDOW (data.window, w);
3516 Dynarr_reset (formatted_string_extent_dynarr);
3517 Dynarr_reset (formatted_string_extent_start_dynarr);
3518 Dynarr_reset (formatted_string_extent_end_dynarr);
3520 /* result_str is nil when we're building a frame or icon title. Otherwise,
3521 we're building a modeline, so the offset starts at the modeline
3522 horizontal scrolling ammount */
3523 if (! NILP (result_str))
3524 offset = w->modeline_hscroll;
3525 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3526 max_pixpos - min_pixpos, findex, type, &offset,
3529 if (Dynarr_length (db->runes))
3532 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3533 c_pixpos = rb->xpos + rb->width;
3536 c_pixpos = min_pixpos;
3538 /* If we don't reach the right side of the window, add a blank rune
3539 to make up the difference. This usually only occurs if the
3540 modeline face is using a proportional width font or a fixed width
3541 font of a different size from the default face font. */
3543 if (c_pixpos < max_pixpos)
3545 data.pixpos = c_pixpos;
3546 data.blank_width = max_pixpos - data.pixpos;
3548 add_blank_rune (&data, NULL, 0);
3551 /* Now create the result string and frob the extents into it. */
3552 if (!NILP (result_str))
3557 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3559 detach_all_extents (result_str);
3560 resize_string (XSTRING (result_str), -1,
3561 data.bytepos - XSTRING_LENGTH (result_str));
3563 strdata = XSTRING_DATA (result_str);
3565 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3567 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3569 len += (set_charptr_emchar
3570 (strdata + len, Dynarr_atp (db->runes,
3571 elt)->object.chr.ch));
3575 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3578 Lisp_Object extent = Qnil;
3581 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3582 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3585 child = Fmake_extent (Qnil, Qnil, result_str);
3586 Fputhash (extent, child, buf->modeline_extent_table);
3588 Fset_extent_parent (child, extent);
3589 set_extent_endpoints
3591 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3592 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3598 /* Ensure that the given display line DL accurately represents the
3599 modeline for the given window. */
3601 generate_modeline (struct window *w, struct display_line *dl, int type)
3603 struct buffer *b = XBUFFER (w->buffer);
3604 struct frame *f = XFRAME (w->frame);
3605 struct device *d = XDEVICE (f->device);
3607 /* Unlike display line and rune pointers, this one can't change underneath
3609 struct display_block *db = get_display_block_from_line (dl, TEXT);
3610 int max_pixpos, min_pixpos, ypos_adj;
3611 Lisp_Object font_inst;
3613 /* This will actually determine incorrect inside boundaries for the
3614 modeline since it ignores the margins. However being aware of this fact
3615 we never use those values anywhere so it doesn't matter. */
3616 dl->bounds = calculate_display_line_boundaries (w, 1);
3618 /* We are generating a modeline. */
3620 dl->cursor_elt = -1;
3622 /* Reset the runes on the modeline. */
3623 Dynarr_reset (db->runes);
3625 if (!WINDOW_HAS_MODELINE_P (w))
3629 /* If there is a horizontal scrollbar, don't add anything. */
3630 if (window_scrollbar_height (w))
3633 dl->ascent = DEVMETH (d, divider_height, ());
3635 /* The modeline is at the bottom of the gutters. */
3636 dl->ypos = WINDOW_BOTTOM (w);
3638 rb.findex = MODELINE_INDEX;
3639 rb.xpos = dl->bounds.left_out;
3640 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3643 rb.type = RUNE_HLINE;
3644 rb.object.hline.thickness = 1;
3645 rb.object.hline.yoffset = 0;
3646 rb.cursor_type = NO_CURSOR;
3648 if (!EQ (Qzero, w->modeline_shadow_thickness)
3651 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3653 dl->ypos -= shadow_thickness;
3654 rb.xpos += shadow_thickness;
3655 rb.width -= 2 * shadow_thickness;
3658 Dynarr_add (db->runes, rb);
3662 /* !!#### not right; needs to compute the max height of
3664 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3666 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3667 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3669 min_pixpos = dl->bounds.left_out;
3670 max_pixpos = dl->bounds.right_out;
3672 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3674 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3676 ypos_adj = shadow_thickness;
3677 min_pixpos += shadow_thickness;
3678 max_pixpos -= shadow_thickness;
3683 generate_formatted_string_db (b->modeline_format,
3684 b->generated_modeline_string, w, dl, db,
3685 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3687 /* The modeline is at the bottom of the gutters. We have to wait to
3688 set this until we've generated the modeline in order to account
3689 for any embedded faces. */
3690 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3694 add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str,
3695 Charcount pos, Charcount min_pos, Charcount max_pos)
3697 /* This function has been Mule-ized. */
3699 const Bufbyte *cur_pos = str;
3700 struct display_block *db = data->db;
3702 data->blank_width = space_width (XWINDOW (data->window));
3703 while (Dynarr_length (db->runes) < pos)
3704 add_blank_rune (data, NULL, 0);
3706 end = (Dynarr_length (db->runes) +
3707 bytecount_to_charcount (str, strlen ((const char *) str)));
3709 end = min (max_pos, end);
3711 while (pos < end && *cur_pos)
3713 const Bufbyte *old_cur_pos = cur_pos;
3716 data->ch = charptr_emchar (cur_pos);
3717 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3718 INC_CHARPTR (cur_pos);
3722 data->modeline_charpos++;
3723 data->bytepos += cur_pos - old_cur_pos;
3727 while (Dynarr_length (db->runes) < min_pos &&
3728 (data->pixpos + data->blank_width <= data->max_pixpos))
3729 add_blank_rune (data, NULL, 0);
3731 return Dynarr_length (db->runes);
3734 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3735 modeline extents. */
3737 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3738 Charcount pos, Charcount min_pos,
3739 Charcount max_pos, Lisp_Object extent)
3741 /* This function has been Mule-ized. */
3743 struct display_block *db = data->db;
3744 struct glyph_block gb;
3746 data->blank_width = space_width (XWINDOW (data->window));
3747 while (Dynarr_length (db->runes) < pos)
3748 add_blank_rune (data, NULL, 0);
3750 end = Dynarr_length (db->runes) + 1;
3752 end = min (max_pos, end);
3756 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3759 while (Dynarr_length (db->runes) < pos &&
3760 (data->pixpos + data->blank_width <= data->max_pixpos))
3761 add_blank_rune (data, NULL, 0);
3763 return Dynarr_length (db->runes);
3766 /* If max_pos is == -1, it is considered to be infinite. The same is
3767 true of max_pixsize. */
3768 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3769 if (Dynarr_length (data->db->runes)) \
3770 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3774 /* Note that this function does "positions" in terms of characters and
3775 not in terms of columns. This is necessary to make the formatting
3776 work correctly when proportional width fonts are used in the
3779 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3780 Charcount min_pos, Charcount max_pos,
3781 Lisp_Object elt, int depth, int max_pixsize,
3782 face_index findex, int type, Charcount *offset,
3783 Lisp_Object cur_ext)
3785 /* This function has been Mule-ized. */
3786 /* #### The other losing things in this function are:
3788 -- C zero-terminated-string lossage.
3789 -- Non-printable characters should be converted into something
3790 appropriate (e.g. ^F) instead of blindly being printed anyway.
3801 /* A string. Add to the display line and check for %-constructs
3804 Bufbyte *this = XSTRING_DATA (elt);
3806 while ((pos < max_pos || max_pos == -1) && *this)
3808 Bufbyte *last = this;
3810 while (*this && *this != '%')
3815 /* No %-construct */
3817 bytecount_to_charcount (last, this - last);
3819 if (size <= *offset)
3823 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
3824 min (pos + size - *offset, max_pos));
3825 const Bufbyte *tmp_last = charptr_n_addr (last, *offset);
3827 pos = add_string_to_fstring_db_runes (data, tmp_last,
3832 else /* *this == '%' */
3834 Charcount spec_width = 0;
3836 this++; /* skip over '%' */
3838 /* We can't allow -ve args due to the "%-" construct.
3839 * Argument specifies minwidth but not maxwidth
3840 * (maxwidth can be specified by
3841 * (<negative-number> . <stuff>) modeline elements)
3843 while (isdigit (*this))
3845 spec_width = spec_width * 10 + (*this - '0');
3852 pos = generate_fstring_runes (w, data, pos, spec_width,
3853 max_pos, Vglobal_mode_string,
3854 depth, max_pixsize, findex,
3855 type, offset, cur_ext);
3857 else if (*this == '-')
3859 Charcount num_to_add;
3861 if (max_pixsize < 0)
3863 else if (max_pos != -1)
3864 num_to_add = max_pos - pos;
3870 SET_CURRENT_MODE_CHARS_PIXSIZE;
3873 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3876 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3880 while (num_to_add--)
3881 pos = add_string_to_fstring_db_runes
3882 (data, (const Bufbyte *) "-", pos, pos, max_pos);
3884 else if (*this != 0)
3886 Emchar ch = charptr_emchar (this);
3890 decode_mode_spec (w, ch, type);
3892 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3893 size = bytecount_to_charcount
3894 /* Skip the null character added by `decode_mode_spec' */
3895 (str, Dynarr_length (mode_spec_bufbyte_string)) - 1;
3897 if (size <= *offset)
3901 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3903 /* #### NOTE: I don't understand why a tmp_max is not
3904 computed and used here as in the plain string case
3906 pos = add_string_to_fstring_db_runes (data, tmp_str,
3913 /* NOT this++. There could be any sort of character at
3914 the current position. */
3918 if (max_pixsize > 0)
3921 SET_CURRENT_MODE_CHARS_PIXSIZE;
3923 if (cur_pixsize >= max_pixsize)
3928 else if (SYMBOLP (elt))
3930 /* A symbol: process the value of the symbol recursively
3931 as if it appeared here directly. */
3932 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3934 if (!UNBOUNDP (tem))
3936 /* If value is a string, output that string literally:
3937 don't check for % within it. */
3940 Bufbyte *str = XSTRING_DATA (tem);
3941 Charcount size = XSTRING_CHAR_LENGTH (tem);
3943 if (size <= *offset)
3947 const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3949 /* #### NOTE: I don't understand why a tmp_max is not
3950 computed and used here as in the plain string case
3952 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
3957 /* Give up right away for nil or t. */
3958 else if (!EQ (tem, elt))
3965 else if (GENERIC_SPECIFIERP (elt))
3967 Lisp_Object window, tem;
3968 XSETWINDOW (window, w);
3969 tem = specifier_instance_no_quit (elt, Qunbound, window,
3970 ERROR_ME_NOT, 0, Qzero);
3971 if (!UNBOUNDP (tem))
3977 else if (CONSP (elt))
3979 /* A cons cell: four distinct cases.
3980 * - If first element is a string or a cons, process all the elements
3981 * and effectively concatenate them.
3982 * - If first element is a negative number, truncate displaying cdr to
3983 * at most that many characters. If positive, pad (with spaces)
3984 * to at least that many characters.
3985 * - If first element is another symbol, process the cadr or caddr
3986 * recursively according to whether the symbol's value is non-nil or
3988 * - If first element is a face, process the cdr recursively
3989 * without altering the depth.
3992 Lisp_Object car, tem;
4001 tem = symbol_value_in_buffer (car, w->buffer);
4002 /* elt is now the cdr, and we know it is a cons cell.
4003 Use its car if CAR has a non-nil value. */
4004 if (!UNBOUNDP (tem))
4012 /* Symbol's value is nil (or symbol is unbound)
4013 * Get the cddr of the original list
4014 * and if possible find the caddr and use that.
4019 else if (!CONSP (elt))
4027 else if (INTP (car))
4029 Charcount lim = XINT (car);
4035 /* Negative int means reduce maximum width.
4036 * DO NOT change MIN_PIXPOS here!
4037 * (20 -10 . foo) should truncate foo to 10 col
4038 * and then pad to 20.
4041 max_pos = pos - lim;
4043 max_pos = min (max_pos, pos - lim);
4047 /* Padding specified. Don't let it be more than
4051 if (max_pos != -1 && lim > max_pos)
4053 /* If that's more padding than already wanted, queue it.
4054 * But don't reduce padding already specified even if
4055 * that is beyond the current truncation point.
4062 else if (STRINGP (car) || CONSP (car))
4066 /* LIMIT is to protect against circular lists. */
4067 while (CONSP (elt) && --limit > 0
4068 && (pos < max_pos || max_pos == -1))
4070 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4071 XCAR (elt), depth, max_pixsize,
4072 findex, type, offset, cur_ext);
4076 else if (EXTENTP (car))
4078 struct extent *ext = XEXTENT (car);
4080 if (EXTENT_LIVE_P (ext))
4082 face_index old_findex = data->findex;
4084 Lisp_Object font_inst;
4085 face_index new_findex;
4086 Bytecount start = data->bytepos;
4088 face = extent_face (ext);
4091 /* #### needs to merge faces, sigh */
4092 /* #### needs to handle list of faces */
4093 new_findex = get_builtin_face_cache_index (w, face);
4094 /* !!#### not right; needs to compute the max height of
4096 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
4099 data->dl->ascent = max (data->dl->ascent,
4100 XFONT_INSTANCE (font_inst)->ascent);
4101 data->dl->descent = max (data->dl->descent,
4102 XFONT_INSTANCE (font_inst)->
4106 new_findex = old_findex;
4108 data->findex = new_findex;
4109 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4110 XCDR (elt), depth - 1,
4111 max_pixsize, new_findex, type,
4113 data->findex = old_findex;
4114 Dynarr_add (formatted_string_extent_dynarr, ext);
4115 Dynarr_add (formatted_string_extent_start_dynarr, start);
4116 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4120 else if (GLYPHP (elt))
4122 /* Glyphs are considered as one character with respect to the modeline
4123 horizontal scrolling facility. -- dv */
4127 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos,
4134 char *str = GETTEXT ("*invalid*");
4135 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */
4137 if (size <= *offset)
4141 const Bufbyte *tmp_str =
4142 charptr_n_addr ((const Bufbyte *) str, *offset);
4144 /* #### NOTE: I don't understand why a tmp_max is not computed and
4145 used here as in the plain string case above. -- dv */
4146 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
4155 add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos,
4162 /* Update just the modeline. Assumes the desired display structs. If
4163 they do not have a modeline block, it does nothing. */
4165 regenerate_modeline (struct window *w)
4167 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4169 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4173 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4174 redisplay_update_line (w, 0, 0, 0);
4178 /* Make sure that modeline display line is present in the given
4179 display structs if the window has a modeline and update that
4180 line. Returns true if a modeline was needed. */
4182 ensure_modeline_generated (struct window *w, int type)
4186 /* minibuffer windows don't have modelines */
4187 if (MINI_WINDOW_P (w))
4189 /* windows which haven't had it turned off do */
4190 else if (WINDOW_HAS_MODELINE_P (w))
4192 /* windows which have it turned off don't have a divider if there is
4193 a horizontal scrollbar */
4194 else if (window_scrollbar_height (w))
4196 /* and in this case there is none */
4202 display_line_dynarr *dla;
4204 dla = window_display_lines (w, type);
4206 /* We don't care if there is a display line which is not
4207 currently a modeline because it is definitely going to become
4208 one if we have gotten to this point. */
4209 if (Dynarr_length (dla) == 0)
4211 if (Dynarr_largest (dla) > 0)
4213 struct display_line *mlp = Dynarr_atp (dla, 0);
4214 Dynarr_add (dla, *mlp);
4218 struct display_line modeline;
4220 Dynarr_add (dla, modeline);
4224 /* If we're adding a new place marker go ahead and generate the
4225 modeline so that it is available for use by
4226 window_modeline_height. */
4227 generate_modeline (w, Dynarr_atp (dla, 0), type);
4230 return need_modeline;
4233 /* #### Kludge or not a kludge. I tend towards the former. */
4235 real_current_modeline_height (struct window *w)
4237 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4238 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4240 if (ensure_modeline_generated (w, CMOTION_DISP))
4242 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4244 if (Dynarr_length (dla))
4246 if (Dynarr_atp (dla, 0)->modeline)
4247 return (Dynarr_atp (dla, 0)->ascent +
4248 Dynarr_atp (dla, 0)->descent);
4255 /***************************************************************************/
4257 /* displayable string routines */
4259 /***************************************************************************/
4261 /* Given a position for a string in a window, ensure that the given
4262 display line DL accurately represents the text on a line starting
4263 at the given position.
4265 Yes, this is duplicating the code of create_text_block, but it
4266 looked just too hard to change create_text_block to handle strings
4267 *and* buffers. We already make a distinction between the two
4268 elsewhere in the code so I think unifying them would require a
4269 complete MULE rewrite. Besides, the other distinction is that these
4270 functions cover text that the user *cannot edit* so we can remove
4271 everything to do with cursors, minibuffers etc. Eventually the
4272 modeline routines should be modified to use this code as it copes
4273 with many more types of display situation. */
4276 create_string_text_block (struct window *w, Lisp_Object disp_string,
4277 struct display_line *dl,
4279 prop_block_dynarr **prop,
4280 face_index default_face)
4282 struct frame *f = XFRAME (w->frame);
4283 /* Note that a lot of the buffer controlled stuff has been left in
4284 because you might well want to make use of it (selective display
4285 etc), its just the buffer text that we do not use. However, it
4286 seems to be possible for buffer to be nil sometimes so protect
4287 against this case. */
4288 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
4289 struct device *d = XDEVICE (f->device);
4290 Lisp_String* s = XSTRING (disp_string);
4292 /* we're working with these a lot so precalculate them */
4293 Bytecount slen = XSTRING_LENGTH (disp_string);
4294 Bytecount bi_string_zv = slen;
4295 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4299 int truncate_win = b ? window_truncation_on (w) : 0;
4300 int end_glyph_width = 0;
4302 /* we're going to ditch selective display for static text, its an
4303 FSF thing and invisble extents are the way to go
4304 here. Implementing it also relies on a number of buffer-specific
4305 functions that we don't have the luxury of being able to use
4308 /* The variable ctl-arrow allows the user to specify what characters
4309 can actually be displayed and which octal should be used for.
4310 #### This variable should probably have some rethought done to
4313 #### It would also be really nice if you could specify that
4314 the characters come out in hex instead of in octal. Mule
4315 does that by adding a ctl-hexa variable similar to ctl-arrow,
4316 but that's bogus -- we need a more general solution. I
4317 think you need to extend the concept of display tables
4318 into a more general conversion mechanism. Ideally you
4319 could specify a Lisp function that converts characters,
4320 but this violates the Second Golden Rule and besides would
4321 make things way way way way slow.
4323 So instead, we extend the display-table concept, which was
4324 historically limited to 256-byte vectors, to one of the
4327 a) A 256-entry vector, for backward compatibility;
4328 b) char-table, mapping characters to values;
4329 c) range-table, mapping ranges of characters to values;
4330 d) a list of the above.
4332 The (d) option allows you to specify multiple display tables
4333 instead of just one. Each display table can specify conversions
4334 for some characters and leave others unchanged. The way the
4335 character gets displayed is determined by the first display table
4336 with a binding for that character. This way, you could call a
4337 function `enable-hex-display' that adds a hex display-table to
4338 the list of display tables for the current buffer.
4340 #### ...not yet implemented... Also, we extend the concept of
4341 "mapping" to include a printf-like spec. Thus you can make all
4342 extended characters show up as hex with a display table like
4345 #s(range-table data ((256 524288) (format "%x")))
4347 Since more than one display table is possible, you have
4348 great flexibility in mapping ranges of characters. */
4349 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4350 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4351 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4352 ? 255 : 160)) : 255;
4354 Lisp_Object face_dt, window_dt;
4356 /* The text display block for this display line. */
4357 struct display_block *db = get_display_block_from_line (dl, TEXT);
4359 /* The first time through the main loop we need to force the glyph
4360 data to be updated. */
4363 /* Apparently the new extent_fragment_update returns an end position
4364 equal to the position passed in if there are no more runs to be
4366 int no_more_frags = 0;
4368 dl->used_prop_data = 0;
4371 /* set up faces to use for clearing areas, used by
4372 output_display_line */
4373 dl->default_findex = default_face;
4376 dl->left_margin_findex = default_face;
4377 dl->right_margin_findex = default_face;
4381 dl->left_margin_findex =
4382 get_builtin_face_cache_index (w, Vleft_margin_face);
4383 dl->right_margin_findex =
4384 get_builtin_face_cache_index (w, Vright_margin_face);
4388 data.ef = extent_fragment_new (disp_string, f);
4390 /* These values are used by all of the rune addition routines. We add
4391 them to this structure for ease of passing. */
4393 XSETWINDOW (data.window, w);
4397 data.bi_bufpos = bi_start_pos;
4398 data.pixpos = dl->bounds.left_in;
4399 data.last_charset = Qunbound;
4400 data.last_findex = default_face;
4401 data.result_str = Qnil;
4402 data.string = disp_string;
4404 /* Set the right boundary adjusting it to take into account any end
4405 glyph. Save the width of the end glyph for later use. */
4406 data.max_pixpos = dl->bounds.right_in;
4409 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
4411 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
4413 data.max_pixpos -= end_glyph_width;
4415 data.cursor_type = NO_CURSOR;
4419 /* I don't think we want this, string areas should not scroll with
4421 data.start_col = w->hscroll;
4422 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4424 data.bi_start_col_enabled = 0;
4425 data.hscroll_glyph_width_adjust = 0;
4427 /* We regenerate the line from the very beginning. */
4428 Dynarr_reset (db->runes);
4430 /* Why is this less than or equal and not just less than? If the
4431 starting position is already equal to the maximum we can't add
4432 anything else, right? Wrong. We might still have a newline to
4433 add. A newline can use the room allocated for an end glyph since
4434 if we add it we know we aren't going to be adding any end
4437 /* #### Chuck -- I think this condition should be while (1).
4438 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4439 and the begin-glyph ends exactly at the end of the window, the
4440 end-glyph and text might not be displayed. while (1) ensures
4441 that the loop terminates only when either (a) there is
4442 propagation data or (b) the end-of-line or end-of-buffer is hit.
4444 #### Also I think you need to ensure that the operation
4445 "add begin glyphs; add end glyphs; add text" is atomic and
4446 can't get interrupted in the middle. If you run off the end
4447 of the line during that operation, then you keep accumulating
4448 propagation data until you're done. Otherwise, if the (e.g.)
4449 there's a begin glyph at a particular position and attempting
4450 to display that glyph results in window-end being hit and
4451 propagation data being generated, then the character at that
4452 position won't be displayed.
4454 #### See also the comment after the end of this loop, below.
4456 while (data.pixpos <= data.max_pixpos)
4458 /* #### This check probably should not be necessary. */
4459 if (data.bi_bufpos > bi_string_zv)
4461 /* #### urk! More of this lossage! */
4466 /* Check for face changes. */
4467 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
4469 /* Now compute the face and begin/end-glyph information. */
4471 /* Remember that the extent-fragment routines deal in Bytind's. */
4472 extent_fragment_update (w, data.ef, data.bi_bufpos);
4473 /* This is somewhat cheesy but the alternative is to
4474 propagate default_face into extent_fragment_update. */
4475 if (data.findex == DEFAULT_INDEX)
4476 data.findex = default_face;
4478 get_display_tables (w, data.findex, &face_dt, &window_dt);
4480 if (data.bi_bufpos == data.ef->end)
4485 /* Determine what is next to be displayed. We first handle any
4486 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4487 display then we determine what to do based on the character at the
4488 current buffer position. */
4490 /* If the current position is covered by an invisible extent, do
4491 nothing (except maybe add some ellipses).
4493 #### The behavior of begin and end-glyphs at the edge of an
4494 invisible extent should be investigated further. This is
4495 fairly low priority though. */
4496 if (data.ef->invisible)
4498 /* #### Chuck, perhaps you could look at this code? I don't
4499 really know what I'm doing. */
4502 Dynarr_free (*prop);
4506 /* The extent fragment code only sets this when we should
4507 really display the ellipses. It makes sure the ellipses
4508 don't get displayed more than once in a row. */
4509 if (data.ef->invisible_ellipses)
4511 struct glyph_block gb;
4513 data.ef->invisible_ellipses_already_displayed = 1;
4514 data.ef->invisible_ellipses = 0;
4516 gb.glyph = Vinvisible_text_glyph;
4517 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
4518 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
4519 /* Perhaps they shouldn't propagate if the very next thing
4520 is to display a newline (for compatibility with
4521 selective-display-ellipses)? Maybe that's too
4527 /* #### What if we we're dealing with a display table? */
4531 if (data.bi_bufpos == bi_string_zv)
4534 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4537 /* If there is propagation data, then it represents the current
4538 buffer position being displayed. Add them and advance the
4539 position counter. This might also add the minibuffer
4543 dl->used_prop_data = 1;
4544 *prop = add_propagation_runes (prop, &data);
4547 goto done; /* gee, a really narrow window */
4548 else if (data.bi_bufpos == bi_string_zv)
4550 else if (data.bi_bufpos < 0)
4551 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4554 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4557 /* If there are end glyphs, add them to the line. These are
4558 the end glyphs for the previous run of text. We add them
4559 here rather than doing them at the end of handling the
4560 previous run so that glyphs at the beginning and end of
4561 a line are handled correctly. */
4562 else if (Dynarr_length (data.ef->end_glyphs) > 0)
4564 *prop = add_glyph_runes (&data, END_GLYPHS);
4569 /* If there are begin glyphs, add them to the line. */
4570 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
4572 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
4577 /* If at end-of-buffer, we've already processed begin and
4578 end-glyphs at this point and there's no text to process,
4580 else if (data.bi_bufpos == bi_string_zv)
4585 Lisp_Object entry = Qnil;
4586 /* Get the character at the current buffer position. */
4587 data.ch = string_char (s, data.bi_bufpos);
4588 if (!NILP (face_dt) || !NILP (window_dt))
4589 entry = display_table_entry (data.ch, face_dt, window_dt);
4591 /* If there is a display table entry for it, hand it off to
4592 add_disp_table_entry_runes and let it worry about it. */
4593 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
4595 *prop = add_disp_table_entry_runes (&data, entry);
4601 /* Check if we have hit a newline character. If so, add a marker
4602 to the line and end this loop. */
4603 else if (data.ch == '\n')
4605 /* We aren't going to be adding an end glyph so give its
4606 space back in order to make sure that the cursor can
4608 data.max_pixpos += end_glyph_width;
4612 /* If the current character is considered to be printable, then
4614 else if (data.ch >= printable_min)
4616 *prop = add_emchar_rune (&data);
4621 /* If the current character is a tab, determine the next tab
4622 starting position and add a blank rune which extends from the
4623 current pixel position to that starting position. */
4624 else if (data.ch == '\t')
4626 int tab_start_pixpos = data.pixpos;
4631 if (data.start_col > 1)
4632 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
4635 next_tab_position (w, tab_start_pixpos,
4636 dl->bounds.left_in +
4637 data.hscroll_glyph_width_adjust);
4638 if (next_tab_start > data.max_pixpos)
4640 prop_width = next_tab_start - data.max_pixpos;
4641 next_tab_start = data.max_pixpos;
4643 data.blank_width = next_tab_start - data.pixpos;
4645 (next_tab_start - tab_start_pixpos) / space_width (w);
4647 *prop = add_blank_rune (&data, w, char_tab_width);
4649 /* add_blank_rune is only supposed to be called with
4650 sizes guaranteed to fit in the available space. */
4655 struct prop_block pb;
4656 *prop = Dynarr_new (prop_block);
4658 pb.type = PROP_BLANK;
4659 pb.data.p_blank.width = prop_width;
4660 pb.data.p_blank.findex = data.findex;
4661 Dynarr_add (*prop, pb);
4667 /* If character is a control character, pass it off to
4668 add_control_char_runes.
4670 The is_*() routines have undefined results on
4671 arguments outside of the range [-1, 255]. (This
4672 often bites people who carelessly use `char' instead
4673 of `unsigned char'.)
4675 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
4677 *prop = add_control_char_runes (&data, b);
4683 /* If the character is above the ASCII range and we have not
4684 already handled it, then print it as an octal number. */
4685 else if (data.ch >= 0200)
4687 *prop = add_octal_runes (&data);
4693 /* Assume the current character is considered to be printable,
4694 then just add it. */
4697 *prop = add_emchar_rune (&data);
4702 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4708 /* Determine the starting point of the next line if we did not hit the
4709 end of the buffer. */
4710 if (data.bi_bufpos < bi_string_zv)
4712 /* #### This check is not correct. If the line terminated
4713 due to a begin-glyph or end-glyph hitting window-end, then
4714 data.ch will not point to the character at data.bi_bufpos. If
4715 you make the two changes mentioned at the top of this loop,
4716 you should be able to say '(if (*prop))'. That should also
4717 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4720 /* The common case is that the line ended because we hit a newline.
4721 In that case, the next character is just the next buffer
4723 if (data.ch == '\n')
4725 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4728 /* Otherwise we have a buffer line which cannot fit on one display
4732 struct glyph_block gb;
4733 struct glyph_cachel *cachel;
4735 /* If the line is to be truncated then we actually have to look
4736 for the next newline. We also add the end-of-line glyph which
4737 we know will fit because we adjusted the right border before
4738 we starting laying out the line. */
4739 data.max_pixpos += end_glyph_width;
4740 data.findex = default_face;
4747 /* Now find the start of the next line. */
4748 bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
4750 data.cursor_type = NO_CURSOR;
4751 data.bi_bufpos = bi_pos;
4752 gb.glyph = Vtruncation_glyph;
4753 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
4757 /* The cursor can never be on the continuation glyph. */
4758 data.cursor_type = NO_CURSOR;
4760 /* data.bi_bufpos is already at the start of the next line. */
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 && rb->object.chr.ch == ' ')
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 && rb->object.chr.ch < 0x100
4817 && isspace (rb->object.chr.ch))
4818 && !rb->type == RUNE_BLANK)
4820 dl->bounds.right_white = rb->xpos + rb->width;
4828 /* The line is blank so everything is considered to be right
4831 dl->bounds.right_white = dl->bounds.left_in;
4834 /* Set the display blocks bounds. */
4835 db->start_pos = dl->bounds.left_in;
4836 if (Dynarr_length (db->runes))
4838 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4840 db->end_pos = rb->xpos + rb->width;
4843 db->end_pos = dl->bounds.right_white;
4845 /* update line height parameters */
4846 if (!data.new_ascent && !data.new_descent)
4848 /* We've got a blank line so initialize these values from the default
4850 default_face_font_info (data.window, &data.new_ascent,
4851 &data.new_descent, 0, 0, 0);
4854 if (data.max_pixmap_height)
4856 int height = data.new_ascent + data.new_descent;
4857 int pix_ascent, pix_descent;
4859 pix_descent = data.max_pixmap_height * data.new_descent / height;
4860 pix_ascent = data.max_pixmap_height - pix_descent;
4862 data.new_ascent = max (data.new_ascent, pix_ascent);
4863 data.new_descent = max (data.new_descent, pix_descent);
4866 dl->ascent = data.new_ascent;
4867 dl->descent = data.new_descent;
4870 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
4872 if (dl->ascent < ascent)
4873 dl->ascent = ascent;
4876 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
4878 if (dl->descent < descent)
4879 dl->descent = descent;
4882 dl->cursor_elt = data.cursor_x;
4883 /* #### lossage lossage lossage! Fix this shit! */
4884 if (data.bi_bufpos > bi_string_zv)
4885 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4887 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4889 data.dl->num_chars =
4890 string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
4892 /* This doesn't correctly take into account tabs and control
4893 characters but if the window isn't being truncated then this
4894 value isn't going to end up being used anyhow. */
4895 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4897 /* #### handle horizontally scrolled line with text none of which
4898 was actually laid out. */
4900 /* #### handle any remainder of overlay arrow */
4902 if (*prop == ADD_FAILED)
4905 if (truncate_win && *prop)
4907 Dynarr_free (*prop);
4911 extent_fragment_delete (data.ef);
4913 /* #### If we started at EOB, then make sure we return a value past
4914 it so that regenerate_window will exit properly. This is bogus.
4915 The main loop should get fixed so that it isn't necessary to call
4916 this function if we are already at EOB. */
4918 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4919 return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
4921 return bytecount_to_charcount (string_data (s), data.bi_bufpos);
4924 /* Given a display line and a starting position, ensure that the
4925 contents of the display line accurately represent the visual
4926 representation of the buffer contents starting from the given
4927 position when displayed in the given window. The display line ends
4928 when the contents of the line reach the right boundary of the given
4931 This is very similar to generate_display_line but with the same
4932 limitations as create_string_text_block. I have taken the liberty
4933 of fixing the bytind stuff though.*/
4936 generate_string_display_line (struct window *w, Lisp_Object disp_string,
4937 struct display_line *dl,
4939 prop_block_dynarr **prop,
4940 face_index default_face)
4944 /* you must set bounds before calling this. */
4946 /* Reset what this line is using. */
4947 if (dl->display_blocks)
4948 Dynarr_reset (dl->display_blocks);
4949 if (dl->left_glyphs)
4951 Dynarr_free (dl->left_glyphs);
4952 dl->left_glyphs = 0;
4954 if (dl->right_glyphs)
4956 Dynarr_free (dl->right_glyphs);
4957 dl->right_glyphs = 0;
4960 /* We aren't generating a modeline at the moment. */
4963 /* Create a display block for the text region of the line. */
4964 ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
4965 prop, default_face);
4966 dl->bufpos = start_pos;
4967 if (dl->end_bufpos < dl->bufpos)
4968 dl->end_bufpos = dl->bufpos;
4970 /* If there are left glyphs associated with any character in the
4971 text block, then create a display block to handle them. */
4972 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
4973 create_left_glyph_block (w, dl, 0);
4975 /* If there are right glyphs associated with any character in the
4976 text block, then create a display block to handle them. */
4977 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
4978 create_right_glyph_block (w, dl);
4983 /* This is ripped off from regenerate_window. All we want to do is
4984 loop through elements in the string creating display lines until we
4985 have covered the provided area. Simple really. */
4987 generate_displayable_area (struct window *w, Lisp_Object disp_string,
4988 int xpos, int ypos, int width, int height,
4989 display_line_dynarr* dla,
4991 face_index default_face)
4993 int yend = ypos + height;
4996 prop_block_dynarr *prop = 0;
4997 layout_bounds bounds;
5001 /* if there's nothing to do then do nothing. code after this assumes
5002 there is something to do. */
5003 if (NILP (disp_string))
5006 s_zv = XSTRING_CHAR_LENGTH (disp_string);
5008 bounds.left_out = xpos;
5009 bounds.right_out = xpos + width;
5010 /* The inner boundaries mark where the glyph margins are located. */
5011 bounds.left_in = bounds.left_out + window_left_margin_width (w);
5012 bounds.right_in = bounds.right_out - window_right_margin_width (w);
5013 /* We cannot fully calculate the whitespace boundaries as they
5014 depend on the contents of the line being displayed. */
5015 bounds.left_white = bounds.left_in;
5016 bounds.right_white = bounds.right_in;
5020 struct display_line dl;
5021 struct display_line *dlp;
5025 if (Dynarr_length (dla) < Dynarr_largest (dla))
5027 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5038 dlp->bounds = bounds;
5040 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5041 &prop, default_face);
5042 /* we need to make sure that we continue along the line if there
5043 is more left to display otherwise we just end up redisplaying
5044 the same chunk over and over again. */
5045 if (next_pos == start_pos && next_pos < s_zv)
5048 start_pos = next_pos;
5050 dlp->ypos = ypos + dlp->ascent;
5051 ypos = dlp->ypos + dlp->descent;
5055 int visible_height = dlp->ascent + dlp->descent;
5057 dlp->clip = (ypos - yend);
5058 visible_height -= dlp->clip;
5060 if (visible_height < VERTICAL_CLIP (w, 1))
5063 free_display_line (dlp);
5070 Dynarr_add (dla, *dlp);
5072 /* #### This type of check needs to be done down in the
5073 generate_display_line call. */
5074 if (start_pos >= s_zv)
5083 /***************************************************************************/
5085 /* window-regeneration routines */
5087 /***************************************************************************/
5089 /* For a given window and starting position in the buffer it contains,
5090 ensure that the TYPE display lines accurately represent the
5091 presentation of the window. We pass the buffer instead of getting
5092 it from the window since redisplay_window may have temporarily
5093 changed it to the echo area buffer. */
5096 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
5098 struct frame *f = XFRAME (w->frame);
5099 struct buffer *b = XBUFFER (w->buffer);
5100 int ypos = WINDOW_TEXT_TOP (w);
5101 int yend; /* set farther down */
5102 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 /* Make sure this is set always */
5157 /* Note the conversion at end */
5158 w->window_end_pos[type] = start_pos;
5161 struct display_line dl;
5162 struct display_line *dlp;
5165 if (Dynarr_length (dla) < Dynarr_largest (dla))
5167 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5178 dlp->bounds = bounds;
5180 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
5182 if (yclip > dlp->ascent)
5184 /* this should never happen, but if it does just display the
5189 dlp->ypos = (ypos + dlp->ascent) - yclip;
5190 ypos = dlp->ypos + dlp->descent;
5192 /* See if we've been asked to start midway through a line, for
5193 partial display line scrolling. */
5196 dlp->top_clip = yclip;
5204 int visible_height = dlp->ascent + dlp->descent;
5206 dlp->clip = (ypos - yend);
5207 /* Although this seems strange we could have a single very
5208 tall line visible for which we need to account for both
5209 the top clip and the bottom clip. */
5210 visible_height -= (dlp->clip + dlp->top_clip);
5212 if (visible_height < VERTICAL_CLIP (w, 1))
5215 free_display_line (dlp);
5222 if (dlp->cursor_elt != -1)
5224 /* #### This check is steaming crap. Have to get things
5225 fixed so when create_text_block hits EOB, we're done,
5227 if (w->last_point_x[type] == -1)
5229 w->last_point_x[type] = dlp->cursor_elt;
5230 w->last_point_y[type] = Dynarr_length (dla);
5234 /* #### This means that we've added a cursor at EOB
5235 twice. Yuck oh yuck. */
5236 struct display_block *db =
5237 get_display_block_from_line (dlp, TEXT);
5239 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
5240 dlp->cursor_elt = -1;
5244 if (dlp->num_chars > w->max_line_len)
5245 w->max_line_len = dlp->num_chars;
5247 Dynarr_add (dla, *dlp);
5249 /* #### This isn't right, but it is close enough for now. */
5250 w->window_end_pos[type] = start_pos;
5252 /* #### This type of check needs to be done down in the
5253 generate_display_line call. */
5254 if (start_pos > BUF_ZV (b))
5261 /* #### More not quite right, but close enough. */
5262 /* Ben sez: apparently window_end_pos[] is measured
5263 as the number of characters between the window end and the
5264 end of the buffer? This seems rather weirdo. What's
5265 the justification for this?
5267 JV sez: Because BUF_Z (b) would be a good initial value, however
5268 that can change. This representation allows initalizing with 0.
5270 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
5274 /* We know that this is the right thing to use because we put it
5275 there when we first started working in this function. */
5276 generate_modeline (w, Dynarr_atp (dla, 0), type);
5280 #define REGEN_INC_FIND_START_END \
5282 /* Determine start and end of lines. */ \
5283 if (!Dynarr_length (cdla)) \
5287 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5291 else if (!Dynarr_atp (cdla, 0)->modeline \
5292 && !Dynarr_atp (ddla, 0)->modeline) \
5297 abort (); /* structs differ */ \
5299 dla_end = Dynarr_length (cdla) - 1; \
5302 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5303 + Dynarr_atp (cdla, dla_start)->offset); \
5304 /* If this isn't true, then startp has changed and we need to do a \
5306 if (startp != start_pos) \
5309 /* Point is outside the visible region so give up. */ \
5310 if (pointm < start_pos) \
5315 /* This attempts to incrementally update the display structures. It
5316 returns a boolean indicating success or failure. This function is
5317 very similar to regenerate_window_incrementally and is in fact only
5318 called from that function. However, because of the nature of the
5319 changes it deals with it sometimes makes different assumptions
5320 which can lead to success which are much more difficult to make
5321 when dealing with buffer changes. */
5324 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
5326 Charcount beg_unchanged,
5327 Charcount end_unchanged)
5329 struct buffer *b = XBUFFER (w->buffer);
5330 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5331 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5335 int first_line, last_line;
5337 /* Don't define this in the loop where it is used because we
5338 definitely want its value to survive between passes. */
5339 prop_block_dynarr *prop = NULL;
5341 /* If we don't have any buffer change recorded but the modiff flag has
5342 been incremented, then fail. I'm not sure of the exact circumstances
5343 under which this can happen, but I believe that it is probably a
5344 reasonable happening. */
5345 if (!point_visible (w, pointm, CURRENT_DISP)
5346 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
5349 /* If the cursor is moved we attempt to update it. If we succeed we
5350 go ahead and proceed with the optimization attempt. */
5351 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5352 || pointm != marker_position (w->last_point[CURRENT_DISP]))
5354 struct frame *f = XFRAME (w->frame);
5355 struct device *d = XDEVICE (f->device);
5356 struct frame *sel_f = device_selected_frame (d);
5359 if (w->last_point_x[CURRENT_DISP] != -1
5360 && w->last_point_y[CURRENT_DISP] != -1)
5363 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
5365 /* Always regenerate the modeline in case it is
5366 displaying the current line or column. */
5367 regenerate_modeline (w);
5371 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
5373 if (f->modeline_changed)
5374 regenerate_modeline (w);
5382 if (beg_unchanged == -1 && end_unchanged == -1)
5385 /* assert: There are no buffer modifications or they are all below the
5386 visible region. We assume that regenerate_window_incrementally has
5387 not called us unless this is true. */
5389 REGEN_INC_FIND_START_END;
5391 /* If the changed are starts before the visible area, give up. */
5392 if (beg_unchanged < startp)
5395 /* Find what display line the extent changes first affect. */
5397 while (line <= dla_end)
5399 struct display_line *dl = Dynarr_atp (cdla, line);
5400 Bufpos lstart = dl->bufpos + dl->offset;
5401 Bufpos lend = dl->end_bufpos + dl->offset;
5403 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5409 /* If the changes are below the visible area then if point hasn't
5410 moved return success otherwise fail in order to be safe. */
5413 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5414 && pointm == marker_position (w->last_point[CURRENT_DISP]))
5420 /* At this point we know what line the changes first affect. We now
5421 begin redrawing lines as long as we are still in the affected
5422 region and the line's size and positioning don't change.
5423 Otherwise we fail. If we fail we will have altered the desired
5424 structs which could lead to an assertion failure. However, if we
5425 fail the next thing that is going to happen is a full regen so we
5426 will actually end up being safe. */
5427 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5428 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5429 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5430 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5432 first_line = last_line = line;
5433 while (line <= dla_end)
5435 Bufpos old_start, old_end, new_start;
5436 struct display_line *cdl = Dynarr_atp (cdla, line);
5437 struct display_line *ddl = Dynarr_atp (ddla, line);
5438 struct display_block *db;
5441 assert (cdl->bufpos == ddl->bufpos);
5442 assert (cdl->end_bufpos == ddl->end_bufpos);
5443 assert (cdl->offset == ddl->offset);
5445 db = get_display_block_from_line (ddl, TEXT);
5446 initial_size = Dynarr_length (db->runes);
5447 old_start = ddl->bufpos + ddl->offset;
5448 old_end = ddl->end_bufpos + ddl->offset;
5450 /* If this is the first line being updated and it used
5451 propagation data, fail. Otherwise we'll be okay because
5452 we'll have the necessary propagation data. */
5453 if (line == first_line && ddl->used_prop_data)
5456 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5457 &prop, DESIRED_DISP);
5460 /* #### If there is propagated stuff the fail. We could
5461 probably actually deal with this if the line had propagated
5462 information when originally created by a full
5470 /* If any line position parameters have changed or a
5471 cursor has disappeared or disappeared, fail. */
5472 db = get_display_block_from_line (ddl, TEXT);
5473 if (cdl->ypos != ddl->ypos
5474 || cdl->ascent != ddl->ascent
5475 || cdl->descent != ddl->descent
5476 || cdl->top_clip != ddl->top_clip
5477 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5478 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5479 || old_start != ddl->bufpos
5480 || old_end != ddl->end_bufpos
5481 || initial_size != Dynarr_length (db->runes))
5486 if (ddl->cursor_elt != -1)
5488 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5489 w->last_point_y[DESIRED_DISP] = line;
5494 /* If the extent changes end on the line we just updated then
5495 we're done. Otherwise go on to the next line. */
5496 if (end_unchanged <= ddl->end_bufpos)
5502 redisplay_update_line (w, first_line, last_line, 1);
5506 /* Attempt to update the display data structures based on knowledge of
5507 the changed region in the buffer. Returns a boolean indicating
5508 success or failure. If this function returns a failure then a
5509 regenerate_window _must_ be performed next in order to maintain
5510 invariants located here. */
5513 regenerate_window_incrementally (struct window *w, Bufpos startp,
5516 struct buffer *b = XBUFFER (w->buffer);
5517 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5518 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5519 Charcount beg_unchanged, end_unchanged;
5520 Charcount extent_beg_unchanged, extent_end_unchanged;
5526 /* If this function is called, the current and desired structures
5527 had better be identical. If they are not, then that is a bug. */
5528 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
5530 /* We don't handle minibuffer windows yet. The minibuffer prompt
5532 if (MINI_WINDOW_P (w))
5535 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
5536 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
5538 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
5540 /* If nothing has changed in the buffer, then make sure point is ok
5542 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
5543 return regenerate_window_extents_only_changed (w, startp, pointm,
5544 extent_beg_unchanged,
5545 extent_end_unchanged);
5547 /* We can't deal with deleted newlines. */
5548 if (BUF_NEWLINE_WAS_DELETED (b))
5551 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
5552 end_unchanged = (BUF_END_UNCHANGED (b) == -1
5554 : BUF_Z (b) - BUF_END_UNCHANGED (b));
5556 REGEN_INC_FIND_START_END;
5558 /* If the changed area starts before the visible area, give up. */
5559 if (beg_unchanged < startp)
5562 /* Find what display line the buffer changes first affect. */
5564 while (line <= dla_end)
5566 struct display_line *dl = Dynarr_atp (cdla, line);
5567 Bufpos lstart = dl->bufpos + dl->offset;
5568 Bufpos lend = dl->end_bufpos + dl->offset;
5570 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5576 /* If the changes are below the visible area then if point hasn't
5577 moved return success otherwise fail in order to be safe. */
5579 return regenerate_window_extents_only_changed (w, startp, pointm,
5580 extent_beg_unchanged,
5581 extent_end_unchanged);
5583 /* At this point we know what line the changes first affect. We
5584 now redraw that line. If the changes are contained within it
5585 we are going to succeed and can update just that one line.
5586 Otherwise we fail. If we fail we will have altered the desired
5587 structs which could lead to an assertion failure. However, if
5588 we fail the next thing that is going to happen is a full regen
5589 so we will actually end up being safe. */
5592 prop_block_dynarr *prop = NULL;
5593 struct display_line *cdl = Dynarr_atp (cdla, line);
5594 struct display_line *ddl = Dynarr_atp (ddla, line);
5596 assert (cdl->bufpos == ddl->bufpos);
5597 assert (cdl->end_bufpos == ddl->end_bufpos);
5598 assert (cdl->offset == ddl->offset);
5600 /* If the last rune is already a continuation glyph, fail.
5601 #### We should be able to handle this better. */
5603 struct display_block *db = get_display_block_from_line (ddl, TEXT);
5604 if (Dynarr_length (db->runes))
5607 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
5609 if (rb->type == RUNE_DGLYPH
5610 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
5615 /* If the line was generated using propagation data, fail. */
5616 if (ddl->used_prop_data)
5619 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5620 &prop, DESIRED_DISP);
5623 /* If there is propagated stuff then it is pretty much a
5624 guarantee that more than just the one line is affected. */
5631 /* If the last rune is now a continuation glyph, fail. */
5633 struct display_block *db = get_display_block_from_line (ddl, TEXT);
5634 if (Dynarr_length (db->runes))
5637 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
5639 if (rb->type == RUNE_DGLYPH
5640 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
5645 /* If any line position parameters have changed or a
5646 cursor has disappeared or disappeared, fail. */
5647 if (cdl->ypos != ddl->ypos
5648 || cdl->ascent != ddl->ascent
5649 || cdl->descent != ddl->descent
5650 || cdl->top_clip != ddl->top_clip
5651 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5652 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
5657 /* If the changed area also ends on this line, then we may be in
5658 business. Update everything and return success. */
5659 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
5661 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5662 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5663 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
5665 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
5668 if (ddl->cursor_elt != -1)
5670 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5671 w->last_point_y[DESIRED_DISP] = line;
5674 redisplay_update_line (w, line, line, 1);
5675 regenerate_modeline (w);
5677 /* #### For now we just flush the cache until this has been
5678 tested. After that is done, this should correct the
5680 Dynarr_reset (w->line_start_cache);
5682 /* Adjust the extent changed boundaries to remove any
5683 overlap with the buffer changes since we've just
5684 successfully updated that area. */
5685 if (extent_beg_unchanged != -1
5686 && extent_beg_unchanged >= beg_unchanged
5687 && extent_beg_unchanged < end_unchanged)
5688 extent_beg_unchanged = end_unchanged;
5690 if (extent_end_unchanged != -1
5691 && extent_end_unchanged >= beg_unchanged
5692 && extent_end_unchanged < end_unchanged)
5693 extent_end_unchanged = beg_unchanged - 1;
5695 if (extent_end_unchanged <= extent_beg_unchanged)
5696 extent_beg_unchanged = extent_end_unchanged = -1;
5698 /* This could lead to odd results if it fails, but since the
5699 buffer changes update succeeded this probably will to.
5700 We already know that the extent changes start at or after
5701 the line because we checked before entering the loop. */
5702 if (extent_beg_unchanged != -1
5703 && extent_end_unchanged != -1
5704 && ((extent_beg_unchanged < ddl->bufpos)
5705 || (extent_end_unchanged > ddl->end_bufpos)))
5706 return regenerate_window_extents_only_changed (w, startp, pointm,
5707 extent_beg_unchanged,
5708 extent_end_unchanged);
5718 /* Given a window and a point, update the given display lines such
5719 that point is displayed in the middle of the window.
5720 Return the window's new start position. */
5723 regenerate_window_point_center (struct window *w, Bufpos point, int type)
5727 /* We need to make sure that the modeline is generated so that the
5728 window height can be calculated correctly. */
5729 ensure_modeline_generated (w, type);
5731 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
5732 regenerate_window (w, startp, point, type);
5733 Fset_marker (w->start[type], make_int (startp), w->buffer);
5738 /* Given a window and a set of display lines, return a boolean
5739 indicating whether the given point is contained within. */
5742 point_visible (struct window *w, Bufpos point, int type)
5744 struct buffer *b = XBUFFER (w->buffer);
5745 display_line_dynarr *dla = window_display_lines (w, type);
5748 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5753 if (Dynarr_length (dla) > first_line)
5756 struct display_line *dl = Dynarr_atp (dla, first_line);
5759 end = BUF_Z (b) - w->window_end_pos[type] - 1;
5761 if (point >= start && point <= end)
5763 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
5765 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
5767 if (point >= (dl->bufpos + dl->offset)
5768 && point <= (dl->end_bufpos + dl->offset))
5783 /* Return pixel position the middle of the window, not including the
5784 modeline and any potential horizontal scrollbar. */
5787 window_half_pixpos (struct window *w)
5789 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
5792 /* Return the display line which is currently in the middle of the
5793 window W for display lines TYPE. */
5796 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5798 display_line_dynarr *dla;
5801 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
5803 if (type == CMOTION_DISP)
5804 regenerate_window (w, start, point, type);
5806 dla = window_display_lines (w, type);
5807 half = window_half_pixpos (w);
5809 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
5811 struct display_line *dl = Dynarr_atp (dla, elt);
5812 int line_bot = dl->ypos + dl->descent;
5814 if (line_bot > half)
5818 /* We may not have a line at the middle if the end of the buffer is
5823 /* Return a value for point that would place it at the beginning of
5824 the line which is in the middle of the window. */
5827 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5829 /* line_at_center will regenerate the display structures, if necessary. */
5830 int line = line_at_center (w, type, start, point);
5833 return BUF_ZV (XBUFFER (w->buffer));
5836 display_line_dynarr *dla = window_display_lines (w, type);
5837 struct display_line *dl = Dynarr_atp (dla, line);
5843 /* For a given window, ensure that the current visual representation
5847 redisplay_window (Lisp_Object window, int skip_selected)
5849 struct window *w = XWINDOW (window);
5850 struct frame *f = XFRAME (w->frame);
5851 struct device *d = XDEVICE (f->device);
5852 Lisp_Object old_buffer = w->buffer;
5853 Lisp_Object the_buffer = w->buffer;
5855 int echo_active = 0;
5860 int selected_in_its_frame;
5861 int selected_globally;
5862 int skip_output = 0;
5863 int truncation_changed;
5864 int inactive_minibuffer =
5865 (MINI_WINDOW_P (w) &&
5866 (f != device_selected_frame (d)) &&
5867 !is_surrogate_for_selected_frame (f));
5869 /* #### In the new world this function actually does a bunch of
5870 optimizations such as buffer-based scrolling, but none of that is
5873 /* If this is a combination window, do its children; that's all.
5874 The selected window is always a leaf so we don't check for
5875 skip_selected here. */
5876 if (!NILP (w->vchild))
5878 redisplay_windows (w->vchild, skip_selected);
5881 if (!NILP (w->hchild))
5883 redisplay_windows (w->hchild, skip_selected);
5887 /* Is this window the selected window on its frame? */
5888 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
5890 selected_in_its_frame &&
5891 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5892 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
5893 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5894 if (skip_selected && selected_in_its_frame)
5897 /* It is possible that the window is not fully initialized yet. */
5898 if (NILP (w->buffer))
5901 if (MINI_WINDOW_P (w) && echo_area_active (f))
5903 w->buffer = the_buffer = Vecho_area_buffer;
5907 b = XBUFFER (w->buffer);
5911 old_pointm = selected_globally
5913 : marker_position (w->pointm[CURRENT_DISP]);
5918 if (selected_globally)
5920 pointm = BUF_PT (b);
5924 pointm = marker_position (w->pointm[CURRENT_DISP]);
5926 if (pointm < BUF_BEGV (b))
5927 pointm = BUF_BEGV (b);
5928 else if (pointm > BUF_ZV (b))
5929 pointm = BUF_ZV (b);
5932 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
5934 /* If the buffer has changed we have to invalidate all of our face
5936 if ((!echo_active && b != window_display_buffer (w))
5937 || !Dynarr_length (w->face_cachels)
5938 || f->faces_changed)
5939 reset_face_cachels (w);
5941 mark_face_cachels_as_not_updated (w);
5943 /* Ditto the glyph cache elements, although we do *not* invalidate
5944 the cache purely because glyphs have changed - this is now
5945 handled by the dirty flag.*/
5946 if ((!echo_active && b != window_display_buffer (w))
5947 || !Dynarr_length (w->glyph_cachels) || f->faces_changed)
5948 reset_glyph_cachels (w);
5950 mark_glyph_cachels_as_not_updated (w);
5952 /* If the marker's buffer is not the window's buffer, then we need
5953 to find a new starting position. */
5954 if (!MINI_WINDOW_P (w)
5955 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5957 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5959 goto regeneration_done;
5964 old_startp = marker_position (w->start[CURRENT_DISP]);
5969 startp = marker_position (w->start[CURRENT_DISP]);
5970 if (startp < BUF_BEGV (b))
5971 startp = BUF_BEGV (b);
5972 else if (startp > BUF_ZV (b))
5973 startp = BUF_ZV (b);
5975 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5977 truncation_changed = (find_window_mirror (w)->truncate_win !=
5978 window_truncation_on (w));
5980 /* If w->force_start is set, then some function set w->start and we
5981 should display from there and change point, if necessary, to
5982 ensure that it is visible. */
5983 if (w->force_start || inactive_minibuffer)
5986 w->last_modified[DESIRED_DISP] = Qzero;
5987 w->last_facechange[DESIRED_DISP] = Qzero;
5989 regenerate_window (w, startp, pointm, DESIRED_DISP);
5991 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5993 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5995 if (selected_globally)
5996 BUF_SET_PT (b, pointm);
5998 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
6001 /* #### BUFU amounts of overkill just to get the cursor
6002 location marked properly. FIX ME FIX ME FIX ME */
6003 regenerate_window (w, startp, pointm, DESIRED_DISP);
6006 goto regeneration_done;
6009 /* If nothing has changed since the last redisplay, then we just
6010 need to make sure that point is still visible. */
6011 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
6012 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
6014 /* This check is to make sure we restore the minibuffer after a
6015 temporary change to the echo area. */
6016 && !(MINI_WINDOW_P (w) && f->buffers_changed)
6017 && !f->frame_changed
6018 && !truncation_changed
6019 /* check whether start is really at the begining of a line GE */
6020 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
6023 /* Check if the cursor has actually moved. */
6024 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
6025 && pointm == marker_position (w->last_point[CURRENT_DISP])
6026 && selected_globally
6027 && !w->windows_changed
6029 && !f->extents_changed
6030 && !f->faces_changed
6031 && !f->glyphs_changed
6032 && !f->subwindows_changed
6033 /* && !f->subwindows_state_changed*/
6034 && !f->point_changed
6035 && !f->windows_structure_changed)
6037 /* If not, we're done. */
6038 if (f->modeline_changed)
6039 regenerate_modeline (w);
6042 goto regeneration_done;
6046 /* If the new point is visible in the redisplay structures,
6047 then let the output update routines handle it, otherwise
6048 do things the hard way. */
6049 if (!w->windows_changed
6051 && !f->extents_changed
6052 && !f->faces_changed
6053 && !f->glyphs_changed
6054 && !f->subwindows_changed
6055 /* && !f->subwindows_state_changed*/
6056 && !f->windows_structure_changed)
6058 if (point_visible (w, pointm, CURRENT_DISP)
6059 && w->last_point_x[CURRENT_DISP] != -1
6060 && w->last_point_y[CURRENT_DISP] != -1)
6062 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
6064 /* Always regenerate in case it is displaying
6065 the current line or column. */
6066 regenerate_modeline (w);
6069 goto regeneration_done;
6072 else if (!selected_in_its_frame && !f->point_changed)
6074 if (f->modeline_changed)
6075 regenerate_modeline (w);
6078 goto regeneration_done;
6082 /* If we weren't able to take the shortcut method, then use
6083 the brute force method. */
6084 regenerate_window (w, startp, pointm, DESIRED_DISP);
6086 if (point_visible (w, pointm, DESIRED_DISP))
6087 goto regeneration_done;
6091 /* Check if the starting point is no longer at the beginning of a
6092 line, in which case find a new starting point. We also recenter
6093 if our start position is equal to point-max. Otherwise we'll end
6094 up with a blank window. */
6095 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
6096 && !(startp == BUF_BEGV (b)
6097 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
6098 || (pointm == startp &&
6099 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
6100 startp < marker_position (w->last_start[CURRENT_DISP]))
6101 || (startp == BUF_ZV (b)))
6103 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6105 goto regeneration_done;
6107 /* See if we can update the data structures locally based on
6108 knowledge of what changed in the buffer. */
6109 else if (!w->windows_changed
6111 && !f->faces_changed
6112 && !f->glyphs_changed
6113 && !f->subwindows_changed
6114 /* && !f->subwindows_state_changed*/
6115 && !f->windows_structure_changed
6116 && !f->frame_changed
6117 && !truncation_changed
6119 && regenerate_window_incrementally (w, startp, pointm))
6121 if (f->modeline_changed
6122 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
6123 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
6124 regenerate_modeline (w);
6127 goto regeneration_done;
6129 /* #### This is where a check for structure based scrolling would go. */
6130 /* If all else fails, try just regenerating and see what happens. */
6133 regenerate_window (w, startp, pointm, DESIRED_DISP);
6135 if (point_visible (w, pointm, DESIRED_DISP))
6136 goto regeneration_done;
6139 /* We still haven't gotten the window regenerated with point
6140 visible. Next we try scrolling a little and see if point comes
6141 back onto the screen. */
6142 if (scroll_step > 0)
6144 int scrolled = scroll_conservatively;
6145 for (; scrolled >= 0; scrolled -= scroll_step)
6147 startp = vmotion (w, startp,
6148 (pointm < startp) ? -scroll_step : scroll_step, 0);
6149 regenerate_window (w, startp, pointm, DESIRED_DISP);
6151 if (point_visible (w, pointm, DESIRED_DISP))
6152 goto regeneration_done;
6156 /* We still haven't managed to get the screen drawn with point on
6157 the screen, so just center it and be done with it. */
6158 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6163 /* If the window's frame is changed then reset the current display
6164 lines in order to force a full repaint. */
6165 if (f->frame_changed)
6167 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
6172 /* Must do this before calling redisplay_output_window because it
6173 sets some markers on the window. */
6176 w->buffer = old_buffer;
6177 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
6178 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
6181 /* These also have to be set before calling redisplay_output_window
6182 since it sets the CURRENT_DISP values based on them. */
6183 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
6184 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
6185 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
6186 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
6190 Bufpos start = marker_position (w->start[DESIRED_DISP]);
6191 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
6193 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
6194 /* Don't pollute the cache if not sure if we are correct */
6195 if (w->start_at_line_beg)
6196 update_line_start_cache (w, start, end, pointm, 1);
6197 redisplay_output_window (w);
6199 * If we just displayed the echo area, the line start cache is
6200 * no longer valid, because the minibuffer window is associated
6201 * with the window now.
6204 w->line_cache_last_updated = make_int (-1);
6207 /* #### This should be dependent on face changes and will need to be
6208 somewhere else once tty updates occur on a per-frame basis. */
6209 mark_face_cachels_as_clean (w);
6211 /* The glyph cachels only get dirty if someone changed something.
6212 Since redisplay has now effectively ended we can reset the dirty
6213 flag since everything must be up-to-date. */
6215 mark_glyph_cachels_as_clean (w);
6217 w->windows_changed = 0;
6220 /* Call buffer_reset_changes for all buffers present in any window
6221 currently visible in all frames on all devices. #### There has to
6222 be a better way to do this. */
6225 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
6227 buffer_reset_changes (XBUFFER (w->buffer));
6232 reset_buffer_changes (void)
6234 Lisp_Object frmcons, devcons, concons;
6236 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6238 struct frame *f = XFRAME (XCAR (frmcons));
6240 if (FRAME_REPAINT_P (f))
6241 map_windows (f, reset_buffer_changes_mapfun, 0);
6245 /* Ensure that all windows underneath the given window in the window
6246 hierarchy are correctly displayed. */
6249 redisplay_windows (Lisp_Object window, int skip_selected)
6251 for (; !NILP (window) ; window = XWINDOW (window)->next)
6253 redisplay_window (window, skip_selected);
6258 call_redisplay_end_triggers (struct window *w, void *closure)
6260 Bufpos lrpos = w->last_redisplay_pos;
6261 w->last_redisplay_pos = 0;
6262 if (!NILP (w->buffer)
6263 && !NILP (w->redisplay_end_trigger)
6268 if (MARKERP (w->redisplay_end_trigger)
6269 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
6270 pos = marker_position (w->redisplay_end_trigger);
6271 else if (INTP (w->redisplay_end_trigger))
6272 pos = XINT (w->redisplay_end_trigger);
6275 w->redisplay_end_trigger = Qnil;
6282 XSETWINDOW (window, w);
6283 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
6284 Qredisplay_end_trigger_functions,
6286 w->redisplay_end_trigger);
6287 w->redisplay_end_trigger = Qnil;
6294 /* Ensure that all windows on the given frame are correctly displayed. */
6297 redisplay_frame (struct frame *f, int preemption_check)
6299 struct device *d = XDEVICE (f->device);
6301 if (preemption_check)
6303 /* The preemption check itself takes a lot of time,
6304 so normally don't do it here. We do it if called
6305 from Lisp, though (`redisplay-frame'). */
6308 REDISPLAY_PREEMPTION_CHECK;
6313 /* Before we put a hold on frame size changes, attempt to process
6314 any which are already pending. */
6315 if (f->size_change_pending)
6316 change_frame_size (f, f->new_height, f->new_width, 0);
6318 /* If frame size might need to be changed, due to changed size
6319 of toolbars, scrollbars etc, change it now */
6320 if (f->size_slipped)
6322 adjust_frame_size (f);
6323 assert (!f->size_slipped);
6326 /* The menubar, toolbar, and icon updates must be done before
6327 hold_frame_size_changes is called and we are officially
6328 'in_display'. They may eval lisp code which may call Fsignal.
6329 If in_display is set Fsignal will abort. */
6331 #ifdef HAVE_MENUBARS
6332 /* Update the menubar. It is done first since it could change
6333 the menubar's visibility. This way we avoid having flashing
6334 caused by an Expose event generated by the visibility change
6336 update_frame_menubars (f);
6337 #endif /* HAVE_MENUBARS */
6338 #ifdef HAVE_TOOLBARS
6339 /* Update the toolbars. */
6340 update_frame_toolbars (f);
6341 #endif /* HAVE_TOOLBARS */
6342 /* Gutter update proper has to be done inside display when no frame
6343 size changes can occur, thus we separately update the gutter
6344 geometry here if it needs it. */
6345 update_frame_gutter_geometry (f);
6347 /* If we clear the frame we have to force its contents to be redrawn. */
6349 f->frame_changed = 1;
6351 /* Invalidate the subwindow cache. We use subwindows_changed here to
6352 cause subwindows to get instantiated. This is because
6353 subwindows_state_changed is less strict - dealing with things
6354 like the clicked state of button. We have to do this before
6355 redisplaying the gutters as subwindows get unmapped in the
6357 if (f->frame_changed || f->subwindows_changed)
6359 reset_subwindow_cachels (f);
6360 /* we have to do this so the gutter gets regenerated. */
6361 reset_gutter_display_lines (f);
6364 mark_subwindow_cachels_as_not_updated (f);
6366 hold_frame_size_changes ();
6368 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6369 /* Within this section, we are defenseless and assume that the
6370 following cannot happen:
6372 1) garbage collection
6373 2) Lisp code evaluation
6374 3) frame size changes
6376 We ensure (3) by calling hold_frame_size_changes(), which
6377 will cause any pending frame size changes to get put on hold
6378 till after the end of the critical section. (1) follows
6379 automatically if (2) is met. #### Unfortunately, there are
6380 some places where Lisp code can be called within this section.
6381 We need to remove them.
6383 If Fsignal() is called during this critical section, we
6386 If garbage collection is called during this critical section,
6387 we simply return. #### We should abort instead.
6389 #### If a frame-size change does occur we should probably
6390 actually be preempting redisplay. */
6392 /* We can now update the gutters, safe in the knowledge that our
6393 efforts won't get undone. */
6395 /* This can call lisp, but redisplay is protected by binding
6396 inhibit_quit. More importantly the code involving display lines
6397 *assumes* that GC will not happen and so does not GCPRO
6398 anything. Since we use this code the whole time with the gutters
6399 we cannot allow GC to happen when manipulating the gutters. */
6400 update_frame_gutters (f);
6402 /* Erase the frame before outputting its contents. */
6405 DEVMETH (d, clear_frame, (f));
6408 /* Do the selected window first. */
6409 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
6411 /* Then do the rest. */
6412 redisplay_windows (f->root_window, 1);
6414 /* We now call the output_end routine for tty frames. We delay
6415 doing so in order to avoid cursor flicker. So much for 100%
6417 if (FRAME_TTY_P (f))
6418 DEVMETH (d, output_end, (d));
6420 update_frame_title (f);
6422 CLASS_RESET_CHANGED_FLAGS (f);
6423 f->window_face_cache_reset = 0;
6424 f->echo_area_garbaged = 0;
6427 if (!f->size_change_pending)
6428 f->size_changed = 0;
6430 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6432 /* Allow frame size changes to occur again.
6434 #### what happens if changes to other frames happen? */
6435 unhold_one_frame_size_changes (f);
6437 map_windows (f, call_redisplay_end_triggers, 0);
6441 /* Ensure that all frames on the given device are correctly displayed.
6442 If AUTOMATIC is non-zero, and the device implementation indicates
6443 no automatic redisplay, as printers do, then the device is not
6444 redisplayed. AUTOMATIC is set to zero when called from lisp
6445 functions (redraw-device) and (redisplay-device), and to non-zero
6446 when called from "lazy" redisplay();
6450 redisplay_device (struct device *d, int automatic)
6452 Lisp_Object frame, frmcons;
6454 int size_change_failed = 0;
6458 && (MAYBE_INT_DEVMETH (d, device_implementation_flags, ())
6459 & XDEVIMPF_NO_AUTO_REDISPLAY))
6462 if (DEVICE_STREAM_P (d)) /* nothing to do */
6465 /* It is possible that redisplay has been called before the
6466 device is fully initialized. If so then continue with the
6468 if (NILP (DEVICE_SELECTED_FRAME (d)))
6471 REDISPLAY_PREEMPTION_CHECK;
6475 /* Always do the selected frame first. */
6476 frame = DEVICE_SELECTED_FRAME (d);
6480 if (f->icon_changed || f->windows_changed)
6481 update_frame_icon (f);
6483 if (FRAME_REPAINT_P (f))
6485 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
6487 preempted = redisplay_frame (f, 0);
6493 /* If the frame redisplay did not get preempted, then this flag
6494 should have gotten set to 0. It might be possible for that
6495 not to happen if a size change event were to occur at an odd
6496 time. To make sure we don't miss anything we simply don't
6497 reset the top level flags until the condition ends up being
6498 in the right state. */
6499 if (f->size_changed)
6500 size_change_failed = 1;
6503 DEVICE_FRAME_LOOP (frmcons, d)
6505 f = XFRAME (XCAR (frmcons));
6507 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
6510 if (f->icon_changed || f->windows_changed)
6511 update_frame_icon (f);
6513 if (FRAME_REPAINT_P (f))
6515 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
6517 preempted = redisplay_frame (f, 0);
6523 if (f->size_change_pending)
6524 size_change_failed = 1;
6528 /* If we get here then we redisplayed all of our frames without
6529 getting preempted so mark ourselves as clean. */
6530 CLASS_RESET_CHANGED_FLAGS (d);
6532 if (!size_change_failed)
6533 d->size_changed = 0;
6539 restore_profiling_redisplay_flag (Lisp_Object val)
6541 profiling_redisplay_flag = XINT (val);
6545 /* Ensure that all windows on all frames on all devices are displaying
6546 the current contents of their respective buffers. */
6549 redisplay_without_hooks (void)
6551 Lisp_Object devcons, concons;
6552 int size_change_failed = 0;
6553 int count = specpdl_depth ();
6555 if (profiling_active)
6557 record_unwind_protect (restore_profiling_redisplay_flag,
6558 make_int (profiling_redisplay_flag));
6559 profiling_redisplay_flag = 1;
6562 if (asynch_device_change_pending)
6563 handle_asynch_device_change ();
6565 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6566 !disable_preemption && preemption_count < max_preempts)
6569 DEVICE_LOOP_NO_BREAK (devcons, concons)
6571 struct device *d = XDEVICE (XCAR (devcons));
6574 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d))
6576 preempted = redisplay_device (d, 1);
6581 RESET_CHANGED_SET_FLAGS;
6585 /* See comment in redisplay_device. */
6586 if (d->size_changed)
6587 size_change_failed = 1;
6590 preemption_count = 0;
6592 /* Mark redisplay as accurate */
6593 GLOBAL_RESET_CHANGED_FLAGS;
6594 RESET_CHANGED_SET_FLAGS;
6598 mark_all_faces_as_clean ();
6602 if (!size_change_failed)
6605 reset_buffer_changes ();
6608 unbind_to (count, Qnil);
6614 if (last_display_warning_tick != display_warning_tick &&
6615 !inhibit_warning_display)
6617 /* If an error occurs during this function, oh well.
6618 If we report another warning, we could get stuck in an
6619 infinite loop reporting warnings. */
6620 call0_trapping_errors (0, Qdisplay_warning_buffer);
6621 last_display_warning_tick = display_warning_tick;
6623 /* The run_hook_trapping_errors functions are smart enough not
6624 to do any evalling if the hook function is empty, so there
6625 should not be any significant time loss. All places in the
6626 C code that call redisplay() are prepared to handle GCing,
6627 so we should be OK. */
6628 #ifndef INHIBIT_REDISPLAY_HOOKS
6629 run_hook_trapping_errors ("Error in pre-redisplay-hook",
6630 Qpre_redisplay_hook);
6631 #endif /* INHIBIT_REDISPLAY_HOOKS */
6633 redisplay_without_hooks ();
6635 #ifndef INHIBIT_REDISPLAY_HOOKS
6636 run_hook_trapping_errors ("Error in post-redisplay-hook",
6637 Qpost_redisplay_hook);
6638 #endif /* INHIBIT_REDISPLAY_HOOKS */
6642 static char window_line_number_buf[32];
6644 /* Efficiently determine the window line number, and return a pointer
6645 to its printed representation. Do this regardless of whether
6646 line-number-mode is on. The first line in the buffer is counted as
6647 1. If narrowing is in effect, the lines are counted from the
6648 beginning of the visible portion of the buffer. */
6650 window_line_number (struct window *w, int type)
6652 struct device *d = XDEVICE (XFRAME (w->frame)->device);
6653 struct buffer *b = XBUFFER (w->buffer);
6654 /* Be careful in the order of these tests. The first clause will
6655 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6656 This can occur when the frame title is computed really early */
6658 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6659 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
6660 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6661 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
6663 : marker_position (w->pointm[type]));
6666 line = buffer_line_number (b, pos, 1);
6668 long_to_string (window_line_number_buf, line + 1);
6670 return window_line_number_buf;
6674 /* Given a character representing an object in a modeline
6675 specification, return a string (stored into the global array
6676 `mode_spec_bufbyte_string') with the information that object
6679 This function is largely unchanged from previous versions of the
6682 Warning! This code is also used for frame titles and can be called
6683 very early in the device/frame update process! JV
6687 decode_mode_spec (struct window *w, Emchar spec, int type)
6689 Lisp_Object obj = Qnil;
6690 const char *str = NULL;
6691 struct buffer *b = XBUFFER (w->buffer);
6693 Dynarr_reset (mode_spec_bufbyte_string);
6697 /* print buffer name */
6702 /* print visited file name */
6707 /* print the current column */
6710 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
6712 : marker_position (w->pointm[type]);
6713 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
6716 long_to_string (buf, col);
6718 Dynarr_add_many (mode_spec_bufbyte_string,
6719 (const Bufbyte *) buf, strlen (buf));
6721 goto decode_mode_spec_done;
6723 /* print the file coding system */
6727 Lisp_Object codesys = b->buffer_file_coding_system;
6728 /* Be very careful here not to get an error. */
6729 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
6731 codesys = Ffind_coding_system (codesys);
6732 if (CODING_SYSTEMP (codesys))
6733 obj = XCODING_SYSTEM_MNEMONIC (codesys);
6736 #endif /* FILE_CODING */
6739 /* print the current line number */
6741 str = window_line_number (w, type);
6744 /* print value of mode-name (obsolete) */
6749 /* print hyphen and frame number, if != 1 */
6753 struct frame *f = XFRAME (w->frame);
6754 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
6756 /* Naughty, naughty */
6757 char * writable_str = alloca_array (char, 10);
6758 sprintf (writable_str, "-%d", f->order_count);
6762 #endif /* HAVE_TTY */
6765 /* print Narrow if appropriate */
6767 if (BUF_BEGV (b) > BUF_BEG (b)
6768 || BUF_ZV (b) < BUF_Z (b))
6772 /* print %, * or hyphen, if buffer is read-only, modified or neither */
6774 str = (!NILP (b->read_only)
6776 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6781 /* print * or hyphen -- XEmacs change to allow a buffer to be
6782 read-only but still indicate whether it is modified. */
6784 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6786 : (!NILP (b->read_only)
6791 /* #### defined in 19.29 decode_mode_spec, but not in
6792 modeline-format doc string. */
6793 /* This differs from %* in that it ignores read-only-ness. */
6795 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6800 /* print process status */
6802 obj = Fget_buffer_process (w->buffer);
6804 str = GETTEXT ("no process");
6806 obj = Fsymbol_name (Fprocess_status (obj));
6809 /* Print name of selected frame. */
6811 obj = XFRAME (w->frame)->name;
6814 /* indicate TEXT or BINARY */
6816 /* #### NT does not use this any more. Now what? */
6820 /* print percent of buffer above top of window, or Top, Bot or All */
6823 Bufpos pos = marker_position (w->start[type]);
6825 /* This had better be while the desired lines are being done. */
6826 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
6828 if (pos <= BUF_BEGV (b))
6833 else if (pos <= BUF_BEGV (b))
6837 /* This hard limit is ok since the string it will hold has a
6838 fixed maximum length of 3. But just to be safe... */
6840 Charcount chars = pos - BUF_BEGV (b);
6841 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6843 /* Avoid overflow on big buffers */
6844 int percent = total > LONG_MAX/200 ?
6845 (chars + total/200) / (total / 100) :
6846 (chars * 100 + total/2) / total;
6848 /* We can't normally display a 3-digit number, so get us a
6849 2-digit number that is close. */
6853 sprintf (buf, "%d%%", percent);
6854 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6857 goto decode_mode_spec_done;
6862 /* print percent of buffer above bottom of window, perhaps plus
6863 Top, or print Bottom or All */
6866 Bufpos toppos = marker_position (w->start[type]);
6867 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
6869 /* botpos is only accurate as of the last redisplay, so we can
6870 only treat it as a hint. In particular, after erase-buffer,
6871 botpos may be negative. */
6872 if (botpos < toppos)
6875 if (botpos >= BUF_ZV (b))
6877 if (toppos <= BUF_BEGV (b))
6884 /* This hard limit is ok since the string it will hold has a
6885 fixed maximum length of around 6. But just to be safe... */
6887 Charcount chars = botpos - BUF_BEGV (b);
6888 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6890 /* Avoid overflow on big buffers */
6891 int percent = total > LONG_MAX/200 ?
6892 (chars + total/200) / (total / 100) :
6893 (chars * 100 + total/2) / max (total, 1);
6895 /* We can't normally display a 3-digit number, so get us a
6896 2-digit number that is close. */
6900 if (toppos <= BUF_BEGV (b))
6901 sprintf (buf, "Top%d%%", percent);
6903 sprintf (buf, "%d%%", percent);
6905 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6908 goto decode_mode_spec_done;
6918 /* print one [ for each recursive editing level. */
6923 if (command_loop_level > 5)
6929 for (i = 0; i < command_loop_level; i++)
6930 Dynarr_add (mode_spec_bufbyte_string, '[');
6932 goto decode_mode_spec_done;
6935 /* print one ] for each recursive editing level. */
6940 if (command_loop_level > 5)
6946 for (i = 0; i < command_loop_level; i++)
6947 Dynarr_add (mode_spec_bufbyte_string, ']');
6949 goto decode_mode_spec_done;
6952 /* print infinitely many dashes -- handle at top level now */
6959 Dynarr_add_many (mode_spec_bufbyte_string,
6961 XSTRING_LENGTH (obj));
6963 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6965 decode_mode_spec_done:
6966 Dynarr_add (mode_spec_bufbyte_string, '\0');
6969 /* Given a display line, free all of its data structures. */
6972 free_display_line (struct display_line *dl)
6976 if (dl->display_blocks)
6978 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6980 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6982 Dynarr_free (db->runes);
6985 Dynarr_free (dl->display_blocks);
6986 dl->display_blocks = NULL;
6989 if (dl->left_glyphs)
6991 Dynarr_free (dl->left_glyphs);
6992 dl->left_glyphs = NULL;
6995 if (dl->right_glyphs)
6997 Dynarr_free (dl->right_glyphs);
6998 dl->right_glyphs = NULL;
7003 /* Given an array of display lines, free them and all data structures
7004 contained within them. */
7007 free_display_lines (display_line_dynarr *dla)
7011 for (line = 0; line < Dynarr_largest (dla); line++)
7013 free_display_line (Dynarr_atp (dla, line));
7019 /* Call internal free routine for each set of display lines. */
7022 free_display_structs (struct window_mirror *mir)
7024 if (mir->current_display_lines)
7026 free_display_lines (mir->current_display_lines);
7027 mir->current_display_lines = 0;
7030 if (mir->desired_display_lines)
7032 free_display_lines (mir->desired_display_lines);
7033 mir->desired_display_lines = 0;
7039 mark_glyph_block_dynarr (glyph_block_dynarr *gba)
7043 glyph_block *gb = Dynarr_atp (gba, 0);
7044 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
7046 for (; gb < gb_last; gb++)
7048 if (!NILP (gb->glyph))
7049 mark_object (gb->glyph);
7050 if (!NILP (gb->extent))
7051 mark_object (gb->extent);
7056 /* See the comment in image_instantiate_cache_result as to why marking
7057 the glyph will also mark the image_instance. */
7059 mark_redisplay_structs (display_line_dynarr *dla)
7061 display_line *dl = Dynarr_atp (dla, 0);
7062 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
7064 for (; dl < dl_last; dl++)
7066 display_block_dynarr *dba = dl->display_blocks;
7067 display_block *db = Dynarr_atp (dba, 0);
7068 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
7070 for (; db < db_last; db++)
7072 rune_dynarr *ra = db->runes;
7073 rune *r = Dynarr_atp (ra, 0);
7074 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
7076 for (; r < r_last; r++)
7078 if (r->type == RUNE_DGLYPH)
7080 if (!NILP (r->object.dglyph.glyph))
7081 mark_object (r->object.dglyph.glyph);
7082 if (!NILP (r->object.dglyph.extent))
7083 mark_object (r->object.dglyph.extent);
7088 mark_glyph_block_dynarr (dl->left_glyphs);
7089 mark_glyph_block_dynarr (dl->right_glyphs);
7094 mark_window_mirror (struct window_mirror *mir)
7096 mark_redisplay_structs (mir->current_display_lines);
7097 mark_redisplay_structs (mir->desired_display_lines);
7100 mark_window_mirror (mir->next);
7103 mark_window_mirror (mir->hchild);
7104 else if (mir->vchild)
7105 mark_window_mirror (mir->vchild);
7109 mark_redisplay (void)
7111 Lisp_Object frmcons, devcons, concons;
7113 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
7115 struct frame *f = XFRAME (XCAR (frmcons));
7116 update_frame_window_mirror (f);
7117 mark_window_mirror (f->root_mirror);
7122 /*****************************************************************************
7123 Line Start Cache Description and Rationale
7125 The traditional scrolling code in Emacs breaks in a variable height world.
7126 It depends on the key assumption that the number of lines that can be
7127 displayed at any given time is fixed. This led to a complete separation
7128 of the scrolling code from the redisplay code. In order to fully support
7129 variable height lines, the scrolling code must actually be tightly
7130 integrated with redisplay. Only redisplay can determine how many lines
7131 will be displayed on a screen for any given starting point.
7133 What is ideally wanted is a complete list of the starting buffer position
7134 for every possible display line of a buffer along with the height of that
7135 display line. Maintaining such a full list would be very expensive. We
7136 settle for having it include information for all areas which we happen to
7137 generate anyhow (i.e. the region currently being displayed) and for those
7138 areas we need to work with.
7140 In order to ensure that the cache accurately represents what redisplay
7141 would actually show, it is necessary to invalidate it in many situations.
7142 If the buffer changes, the starting positions may no longer be correct.
7143 If a face or an extent has changed then the line heights may have altered.
7144 These events happen frequently enough that the cache can end up being
7145 constantly disabled. With this potentially constant invalidation when is
7146 the cache ever useful?
7148 Even if the cache is invalidated before every single usage, it is
7149 necessary. Scrolling often requires knowledge about display lines which
7150 are actually above or below the visible region. The cache provides a
7151 convenient light-weight method of storing this information for multiple
7152 display regions. This knowledge is necessary for the scrolling code to
7153 always obey the First Golden Rule of Redisplay.
7155 If the cache already contains all of the information that the scrolling
7156 routines happen to need so that it doesn't have to go generate it, then we
7157 are able to obey the Third Golden Rule of Redisplay. The first thing we
7158 do to help out the cache is to always add the displayed region. This
7159 region had to be generated anyway, so the cache ends up getting the
7160 information basically for free. In those cases where a user is simply
7161 scrolling around viewing a buffer there is a high probability that this is
7162 sufficient to always provide the needed information. The second thing we
7163 can do is be smart about invalidating the cache.
7165 TODO -- Be smart about invalidating the cache. Potential places:
7167 + Insertions at end-of-line which don't cause line-wraps do not alter the
7168 starting positions of any display lines. These types of buffer
7169 modifications should not invalidate the cache. This is actually a large
7170 optimization for redisplay speed as well.
7172 + Buffer modifications frequently only affect the display of lines at and
7173 below where they occur. In these situations we should only invalidate
7174 the part of the cache starting at where the modification occurs.
7176 In case you're wondering, the Second Golden Rule of Redisplay is not
7178 ****************************************************************************/
7180 /* This will get used quite a bit so we don't want to be constantly
7181 allocating and freeing it. */
7182 static line_start_cache_dynarr *internal_cache;
7184 /* Makes internal_cache represent the TYPE display structs and only
7185 the TYPE display structs. */
7188 update_internal_cache_list (struct window *w, int type)
7191 display_line_dynarr *dla = window_display_lines (w, type);
7193 Dynarr_reset (internal_cache);
7194 for (line = 0; line < Dynarr_length (dla); line++)
7196 struct display_line *dl = Dynarr_atp (dla, line);
7202 struct line_start_cache lsc;
7204 lsc.start = dl->bufpos;
7205 lsc.end = dl->end_bufpos;
7206 lsc.height = dl->ascent + dl->descent;
7208 Dynarr_add (internal_cache, lsc);
7213 /* Reset the line cache if necessary. This should be run at the
7214 beginning of any function which access the cache. */
7217 validate_line_start_cache (struct window *w)
7219 struct buffer *b = XBUFFER (w->buffer);
7220 struct frame *f = XFRAME (w->frame);
7222 if (!w->line_cache_validation_override)
7224 /* f->extents_changed used to be in here because extent face and
7225 size changes can cause text shifting. However, the extent
7226 covering the region is constantly having its face set and
7227 priority altered by the mouse code. This means that the line
7228 start cache is constantly being invalidated. This is bad
7229 since the mouse code also triggers heavy usage of the cache.
7230 Since it is an unlikely that f->extents being changed
7231 indicates that the cache really needs to be updated and if it
7232 does redisplay will catch it pretty quickly we no longer
7233 invalidate the cache if it is set. This greatly speeds up
7234 dragging out regions with the mouse. */
7235 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
7239 Dynarr_reset (w->line_start_cache);
7244 /* Return the very first buffer position contained in the given
7245 window's cache, or -1 if the cache is empty. Assumes that the
7249 line_start_cache_start (struct window *w)
7251 line_start_cache_dynarr *cache = w->line_start_cache;
7253 if (!Dynarr_length (cache))
7256 return Dynarr_atp (cache, 0)->start;
7259 /* Return the very last buffer position contained in the given
7260 window's cache, or -1 if the cache is empty. Assumes that the
7264 line_start_cache_end (struct window *w)
7266 line_start_cache_dynarr *cache = w->line_start_cache;
7268 if (!Dynarr_length (cache))
7271 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7274 /* Return the index of the line POINT is contained within in window
7275 W's line start cache. It will enlarge the cache or move the cache
7276 window in order to have POINT be present in the cache. MIN_PAST is
7277 a guarantee of the number of entries in the cache present on either
7278 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7279 then it will be treated as 0, but the cache window will not be
7280 allowed to shift. Returns -1 if POINT cannot be found in the cache
7284 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
7286 struct buffer *b = XBUFFER (w->buffer);
7287 line_start_cache_dynarr *cache = w->line_start_cache;
7288 unsigned int top, bottom, pos;
7290 validate_line_start_cache (w);
7291 w->line_cache_validation_override++;
7293 /* Let functions pass in negative values, but we still treat -1
7295 /* #### bogosity alert */
7296 if (min_past < 0 && min_past != -1)
7297 min_past = -min_past;
7299 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
7300 || line_start_cache_end (w) < point)
7303 int win_char_height = window_char_height (w, 1);
7305 /* Occasionally we get here with a 0 height
7306 window. find_next_newline_no_quit will abort if we pass it a
7307 count of 0 so handle that case. */
7308 if (!win_char_height)
7309 win_char_height = 1;
7311 if (!Dynarr_length (cache))
7313 Bufpos from = find_next_newline_no_quit (b, point, -1);
7314 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
7316 update_line_start_cache (w, from, to, point, 0);
7318 if (!Dynarr_length (cache))
7320 w->line_cache_validation_override--;
7325 assert (Dynarr_length (cache));
7328 while (line_start_cache_start (w) > point
7329 && (loop < cache_adjustment || min_past == -1))
7333 from = line_start_cache_start (w);
7334 if (from <= BUF_BEGV (b))
7337 from = find_next_newline_no_quit (b, from, -win_char_height);
7338 to = line_start_cache_end (w);
7340 update_line_start_cache (w, from, to, point, 0);
7344 if (line_start_cache_start (w) > point)
7348 from = find_next_newline_no_quit (b, point, -1);
7349 if (from >= BUF_ZV (b))
7351 to = find_next_newline_no_quit (b, from, -win_char_height);
7356 to = find_next_newline_no_quit (b, from, win_char_height);
7358 update_line_start_cache (w, from, to, point, 0);
7362 while (line_start_cache_end (w) < point
7363 && (loop < cache_adjustment || min_past == -1))
7367 to = line_start_cache_end (w);
7368 if (to >= BUF_ZV (b))
7371 from = line_start_cache_end (w);
7372 to = find_next_newline_no_quit (b, from, win_char_height);
7374 update_line_start_cache (w, from, to, point, 0);
7378 if (line_start_cache_end (w) < point)
7382 from = find_next_newline_no_quit (b, point, -1);
7383 if (from >= BUF_ZV (b))
7385 to = find_next_newline_no_quit (b, from, -win_char_height);
7390 to = find_next_newline_no_quit (b, from, win_char_height);
7392 update_line_start_cache (w, from, to, point, 0);
7396 assert (Dynarr_length (cache));
7401 /* This could happen if the buffer is narrowed. */
7402 if (line_start_cache_start (w) > point
7403 || line_start_cache_end (w) < point)
7405 w->line_cache_validation_override--;
7411 top = Dynarr_length (cache) - 1;
7416 unsigned int new_pos;
7419 pos = (bottom + top + 1) >> 1;
7420 start = Dynarr_atp (cache, pos)->start;
7421 end = Dynarr_atp (cache, pos)->end;
7423 if (point >= start && point <= end)
7425 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
7428 find_next_newline_no_quit (b, line_start_cache_start (w),
7430 Bufpos to = line_start_cache_end (w);
7432 update_line_start_cache (w, from, to, point, 0);
7433 goto find_point_loop;
7435 else if ((Dynarr_length (cache) - pos - 1) < min_past
7436 && line_start_cache_end (w) < BUF_ZV (b))
7438 Bufpos from = line_start_cache_end (w);
7439 Bufpos to = find_next_newline_no_quit (b, from,
7444 update_line_start_cache (w, from, to, point, 0);
7445 goto find_point_loop;
7449 w->line_cache_validation_override--;
7453 else if (point > end)
7455 else if (point < start)
7460 new_pos = (bottom + top + 1) >> 1;
7463 w->line_cache_validation_override--;
7469 /* Return a boolean indicating if POINT would be visible in window W
7470 if display of the window was to begin at STARTP. */
7473 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
7475 struct buffer *b = XBUFFER (w->buffer);
7476 int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
7477 int bottom = WINDOW_TEXT_HEIGHT (w);
7480 /* If point is before the intended start it obviously can't be visible. */
7484 /* If point or start are not in the accessible buffer range, then
7486 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
7487 || point < BUF_BEGV (b) || point > BUF_ZV (b))
7490 validate_line_start_cache (w);
7491 w->line_cache_validation_override++;
7493 start_elt = point_in_line_start_cache (w, startp, 0);
7494 if (start_elt == -1)
7496 w->line_cache_validation_override--;
7500 assert (line_start_cache_start (w) <= startp
7501 && line_start_cache_end (w) >= startp);
7507 /* Expand the cache if necessary. */
7508 if (start_elt == Dynarr_length (w->line_start_cache))
7511 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
7513 start_elt = point_in_line_start_cache (w, old_startp,
7514 window_char_height (w, 0));
7516 /* We've already actually processed old_startp, so increment
7520 /* If this happens we didn't add any extra elements. Bummer. */
7521 if (start_elt == Dynarr_length (w->line_start_cache))
7523 w->line_cache_validation_override--;
7528 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
7530 if (pixpos + height > bottom)
7532 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7534 w->line_cache_validation_override--;
7540 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
7542 w->line_cache_validation_override--;
7550 /* For the given window W, if display starts at STARTP, what will be
7551 the buffer position at the beginning or end of the last line
7552 displayed. The end of the last line is also know as the window end
7555 WARNING: It is possible that rediplay failed to layout any lines for the
7556 windows. Under normal circumstances this is rare. However it seems that it
7557 does occur in the following situation: A mouse event has come in and we
7558 need to compute its location in a window. That code (in
7559 pixel_to_glyph_translation) already can handle 0 as an error return value.
7561 #### With a little work this could probably be reworked as just a
7562 call to start_with_line_at_pixpos. */
7565 start_end_of_last_line (struct window *w, Bufpos startp, int end,
7568 struct buffer *b = XBUFFER (w->buffer);
7569 line_start_cache_dynarr *cache = w->line_start_cache;
7571 int bottom = WINDOW_TEXT_HEIGHT (w);
7575 validate_line_start_cache (w);
7576 w->line_cache_validation_override++;
7578 if (startp < BUF_BEGV (b))
7579 startp = BUF_BEGV (b);
7580 else if (startp > BUF_ZV (b))
7581 startp = BUF_ZV (b);
7584 start_elt = point_in_line_start_cache (w, cur_start, 0);
7585 if (start_elt == -1)
7586 return may_error ? 0 : startp;
7590 int height = Dynarr_atp (cache, start_elt)->height;
7592 cur_start = Dynarr_atp (cache, start_elt)->start;
7594 if (pixpos + height > bottom)
7596 /* Adjust for any possible clip. */
7597 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7602 w->line_cache_validation_override--;
7606 return BUF_BEGV (b);
7610 w->line_cache_validation_override--;
7612 return Dynarr_atp (cache, start_elt)->end;
7614 return Dynarr_atp (cache, start_elt)->start;
7620 if (start_elt == Dynarr_length (cache))
7622 Bufpos from = line_start_cache_end (w);
7623 int win_char_height = window_char_height (w, 0);
7624 Bufpos to = find_next_newline_no_quit (b, from,
7629 /* We've hit the end of the bottom so that's what it is. */
7630 if (from >= BUF_ZV (b))
7632 w->line_cache_validation_override--;
7636 update_line_start_cache (w, from, to, BUF_PT (b), 0);
7638 /* Updating the cache invalidates any current indexes. */
7639 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
7644 /* For the given window W, if display starts at STARTP, what will be
7645 the buffer position at the beginning of the last line displayed. */
7648 start_of_last_line (struct window *w, Bufpos startp)
7650 return start_end_of_last_line (w, startp, 0 , 0);
7653 /* For the given window W, if display starts at STARTP, what will be
7654 the buffer position at the end of the last line displayed. This is
7655 also know as the window end position. */
7658 end_of_last_line (struct window *w, Bufpos startp)
7660 return start_end_of_last_line (w, startp, 1, 0);
7664 end_of_last_line_may_error (struct window *w, Bufpos startp)
7666 return start_end_of_last_line (w, startp, 1, 1);
7670 /* For window W, what does the starting position have to be so that
7671 the line containing POINT will cover pixel position PIXPOS. */
7674 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
7676 struct buffer *b = XBUFFER (w->buffer);
7678 Bufpos cur_pos, prev_pos = point;
7679 int point_line_height;
7680 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
7682 validate_line_start_cache (w);
7683 w->line_cache_validation_override++;
7685 cur_elt = point_in_line_start_cache (w, point, 0);
7686 /* #### See comment in update_line_start_cache about big minibuffers. */
7689 w->line_cache_validation_override--;
7693 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
7697 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7699 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7701 /* Do not take into account the value of vertical_clip here.
7702 That is the responsibility of the calling functions. */
7705 w->line_cache_validation_override--;
7706 if (-pixheight > point_line_height)
7707 /* We can't make the target line cover pixpos, so put it
7708 above pixpos. That way it will at least be visible. */
7718 int win_char_height;
7720 if (cur_pos <= BUF_BEGV (b))
7722 w->line_cache_validation_override--;
7723 return BUF_BEGV (b);
7726 win_char_height = window_char_height (w, 0);
7727 if (!win_char_height)
7728 win_char_height = 1;
7730 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
7731 to = line_start_cache_end (w);
7732 update_line_start_cache (w, from, to, point, 0);
7734 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
7735 assert (cur_elt >= -1);
7736 /* This used to be cur_elt>=0 under the assumption that if
7737 point is in the top line and not at BUF_BEGV, then
7738 setting the window_start to a newline before the start of
7739 the first line will always cause scrolling.
7741 However in my (jv) opinion this is wrong. That new line
7742 can be hidden in various ways: invisible extents, an
7743 explicit window-start not at a newline character etc.
7744 The existence of those are indeed known to create crashes
7745 on that assert. So we have no option but to continue the
7746 search if we found point at the top of the line_start_cache
7748 cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
7754 /* For window W, what does the starting position have to be so that
7755 the line containing point is on display line LINE. If LINE is
7756 positive it is considered to be the number of lines from the top of
7757 the window (0 is the top line). If it is negative the number is
7758 considered to be the number of lines from the bottom (-1 is the
7762 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
7764 validate_line_start_cache (w);
7765 w->line_cache_validation_override++;
7769 int cur_elt = point_in_line_start_cache (w, point, line);
7771 if (cur_elt - line < 0)
7772 cur_elt = 0; /* Hit the top */
7776 w->line_cache_validation_override--;
7777 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
7781 /* The calculated value of pixpos is correct for the bottom line
7782 or what we want when line is -1. Therefore we subtract one
7783 because we have already handled one line. */
7784 int new_line = -line - 1;
7785 int cur_elt = point_in_line_start_cache (w, point, new_line);
7786 int pixpos = WINDOW_TEXT_BOTTOM (w);
7787 Bufpos retval, search_point;
7789 /* If scroll_on_clipped_lines is false, the last "visible" line of
7790 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7791 If s_o_c_l is true, then we don't want to count a clipped
7792 line, so back up from the bottom by the height of the line
7793 containing point. */
7794 if (scroll_on_clipped_lines)
7795 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7799 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
7801 /* Hit the bottom of the buffer. */
7803 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
7807 XSETWINDOW (window, w);
7808 default_face_height_and_width (window, &defheight, 0);
7810 cur_elt = Dynarr_length (w->line_start_cache) - 1;
7812 pixpos -= (adjustment * defheight);
7813 if (pixpos < WINDOW_TEXT_TOP (w))
7814 pixpos = WINDOW_TEXT_TOP (w);
7817 cur_elt = cur_elt + new_line;
7819 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7821 retval = start_with_line_at_pixpos (w, search_point, pixpos);
7822 w->line_cache_validation_override--;
7827 /* This is used to speed up vertical scrolling by caching the known
7828 buffer starting positions for display lines. This allows the
7829 scrolling routines to avoid costly calls to regenerate_window. If
7830 NO_REGEN is true then it will only add the values in the DESIRED
7831 display structs which are in the given range.
7833 Note also that the FROM/TO values are minimums. It is possible
7834 that this function will actually add information outside of the
7835 lines containing those positions. This can't hurt but it could
7838 #### We currently force the cache to have only 1 contiguous region.
7839 It might help to make the cache a dynarr of caches so that we can
7840 cover more areas. This might, however, turn out to be a lot of
7841 overhead for too little gain. */
7844 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
7845 Bufpos point, int no_regen)
7847 struct buffer *b = XBUFFER (w->buffer);
7848 line_start_cache_dynarr *cache = w->line_start_cache;
7849 Bufpos low_bound, high_bound;
7851 validate_line_start_cache (w);
7852 w->line_cache_validation_override++;
7853 updating_line_start_cache = 1;
7855 if (from < BUF_BEGV (b))
7856 from = BUF_BEGV (b);
7857 if (to > BUF_ZV (b))
7862 updating_line_start_cache = 0;
7863 w->line_cache_validation_override--;
7867 if (Dynarr_length (cache))
7869 low_bound = line_start_cache_start (w);
7870 high_bound = line_start_cache_end (w);
7872 /* Check to see if the desired range is already in the cache. */
7873 if (from >= low_bound && to <= high_bound)
7875 updating_line_start_cache = 0;
7876 w->line_cache_validation_override--;
7880 /* Check to make sure that the desired range is adjacent to the
7881 current cache. If not, invalidate the cache. */
7882 if (to < low_bound || from > high_bound)
7884 Dynarr_reset (cache);
7885 low_bound = high_bound = -1;
7890 low_bound = high_bound = -1;
7893 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
7895 /* This could be integrated into the next two sections, but it is easier
7896 to follow what's going on by having it separate. */
7901 update_internal_cache_list (w, DESIRED_DISP);
7902 if (!Dynarr_length (internal_cache))
7904 updating_line_start_cache = 0;
7905 w->line_cache_validation_override--;
7909 start = Dynarr_atp (internal_cache, 0)->start;
7911 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
7913 /* We aren't allowed to generate additional information to fill in
7914 gaps, so if the DESIRED structs don't overlap the cache, reset the
7916 if (Dynarr_length (cache))
7918 if (end < low_bound || start > high_bound)
7919 Dynarr_reset (cache);
7921 /* #### What should really happen if what we are doing is
7922 extending a line (the last line)? */
7923 if (Dynarr_length (cache) == 1
7924 && Dynarr_length (internal_cache) == 1)
7925 Dynarr_reset (cache);
7928 if (!Dynarr_length (cache))
7930 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7931 Dynarr_length (internal_cache));
7932 updating_line_start_cache = 0;
7933 w->line_cache_validation_override--;
7937 /* An extra check just in case the calling function didn't pass in
7938 the bounds of the DESIRED structs in the first place. */
7939 if (start >= low_bound && end <= high_bound)
7941 updating_line_start_cache = 0;
7942 w->line_cache_validation_override--;
7946 /* At this point we know that the internal cache partially overlaps
7948 if (start < low_bound)
7950 int ic_elt = Dynarr_length (internal_cache) - 1;
7953 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7961 Dynarr_reset (cache);
7962 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7963 Dynarr_length (internal_cache));
7964 updating_line_start_cache = 0;
7965 w->line_cache_validation_override--;
7969 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7973 if (end > high_bound)
7977 while (ic_elt < Dynarr_length (internal_cache))
7979 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7985 if (!(ic_elt < Dynarr_length (internal_cache)))
7987 Dynarr_reset (cache);
7988 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7989 Dynarr_length (internal_cache));
7990 updating_line_start_cache = 0;
7991 w->line_cache_validation_override--;
7995 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7996 Dynarr_length (internal_cache) - ic_elt);
7999 updating_line_start_cache = 0;
8000 w->line_cache_validation_override--;
8004 if (!Dynarr_length (cache) || from < low_bound)
8006 Bufpos startp = find_next_newline_no_quit (b, from, -1);
8008 int old_lb = low_bound;
8010 while (startp < old_lb || low_bound == -1)
8015 regenerate_window (w, startp, point, CMOTION_DISP);
8016 update_internal_cache_list (w, CMOTION_DISP);
8018 /* If this assert is triggered then regenerate_window failed
8019 to layout a single line. That is not supposed to be
8020 possible because we impose a minimum height on the buffer
8021 and override vertical clip when we are in here. */
8022 /* #### Ah, but it is because the window may temporarily
8023 exist but not have any lines at all if the minibuffer is
8024 real big. Look into that situation better. */
8025 if (!Dynarr_length (internal_cache))
8027 if (old_lb == -1 && low_bound == -1)
8029 updating_line_start_cache = 0;
8030 w->line_cache_validation_override--;
8034 assert (Dynarr_length (internal_cache));
8036 assert (startp == Dynarr_atp (internal_cache, 0)->start);
8038 ic_elt = Dynarr_length (internal_cache) - 1;
8039 if (low_bound != -1)
8043 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
8049 assert (ic_elt >= 0);
8051 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
8054 * Handle invisible text properly:
8055 * If the last line we're inserting has the same end as the
8056 * line before which it will be added, merge the two lines.
8058 if (Dynarr_length (cache) &&
8059 Dynarr_atp (internal_cache, ic_elt)->end ==
8060 Dynarr_atp (cache, marker)->end)
8062 Dynarr_atp (cache, marker)->start
8063 = Dynarr_atp (internal_cache, ic_elt)->start;
8064 Dynarr_atp (cache, marker)->height
8065 = Dynarr_atp (internal_cache, ic_elt)->height;
8069 if (ic_elt >= 0) /* we still have lines to add.. */
8071 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
8072 ic_elt + 1, marker);
8073 marker += (ic_elt + 1);
8076 if (startp < low_bound || low_bound == -1)
8078 startp = new_startp;
8079 if (startp > BUF_ZV (b))
8081 updating_line_start_cache = 0;
8082 w->line_cache_validation_override--;
8088 assert (Dynarr_length (cache));
8089 assert (from >= low_bound);
8091 /* Readjust the high_bound to account for any changes made while
8092 correcting the low_bound. */
8093 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8095 if (to > high_bound)
8097 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
8101 regenerate_window (w, startp, point, CMOTION_DISP);
8102 update_internal_cache_list (w, CMOTION_DISP);
8104 /* See comment above about regenerate_window failing. */
8105 assert (Dynarr_length (internal_cache));
8107 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
8108 Dynarr_length (internal_cache));
8109 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8110 startp = high_bound + 1;
8112 while (to > high_bound);
8115 updating_line_start_cache = 0;
8116 w->line_cache_validation_override--;
8117 assert (to <= high_bound);
8121 /* Given x and y coordinates in characters, relative to a window,
8122 return the pixel location corresponding to those coordinates. The
8123 pixel location returned is the center of the given character
8124 position. The pixel values are generated relative to the window,
8127 The modeline is considered to be part of the window. */
8130 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
8131 int *pix_x, int *pix_y)
8133 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
8134 int num_disp_lines, modeline;
8136 int defheight, defwidth;
8138 XSETWINDOW (window, w);
8139 default_face_height_and_width (window, &defheight, &defwidth);
8141 /* If we get a bogus value indicating somewhere above or to the left of
8142 the window, use the first window line or character position
8149 num_disp_lines = Dynarr_length (dla);
8153 if (Dynarr_atp (dla, 0)->modeline)
8160 /* First check if the y position intersects the display lines. */
8161 if (char_y < num_disp_lines)
8163 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
8164 struct display_block *db = get_display_block_from_line (dl, TEXT);
8166 *pix_y = (dl->ypos - dl->ascent +
8167 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
8169 if (char_x < Dynarr_length (db->runes))
8171 struct rune *rb = Dynarr_atp (db->runes, char_x);
8173 *pix_x = rb->xpos + (rb->width >> 1);
8177 int last_rune = Dynarr_length (db->runes) - 1;
8178 struct rune *rb = Dynarr_atp (db->runes, last_rune);
8180 char_x -= last_rune;
8182 *pix_x = rb->xpos + rb->width;
8183 *pix_x += ((char_x - 1) * defwidth);
8184 *pix_x += (defwidth >> 1);
8189 /* It didn't intersect, so extrapolate. #### For now, we include the
8190 modeline in this since we don't have true character positions in
8193 if (!Dynarr_length (w->face_cachels))
8194 reset_face_cachels (w);
8196 char_y -= num_disp_lines;
8198 if (Dynarr_length (dla))
8200 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
8201 *pix_y = dl->ypos + dl->descent - dl->clip;
8204 *pix_y = WINDOW_TEXT_TOP (w);
8206 *pix_y += (char_y * defheight);
8207 *pix_y += (defheight >> 1);
8209 *pix_x = WINDOW_TEXT_LEFT (w);
8210 /* Don't adjust by one because this is still the unadjusted value. */
8211 *pix_x += (char_x * defwidth);
8212 *pix_x += (defwidth >> 1);
8215 if (*pix_x > w->pixel_left + w->pixel_width)
8216 *pix_x = w->pixel_left + w->pixel_width;
8217 if (*pix_y > w->pixel_top + w->pixel_height)
8218 *pix_y = w->pixel_top + w->pixel_height;
8220 *pix_x -= w->pixel_left;
8221 *pix_y -= w->pixel_top;
8224 /* Given a display line and a position, determine if there is a glyph
8225 there and return information about it if there is. */
8228 get_position_object (struct display_line *dl, Lisp_Object *obj1,
8229 Lisp_Object *obj2, int x_coord, int *low_x_coord,
8232 struct display_block *db;
8235 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
8237 /* We use get_next_display_block to get the actual display block
8238 that would be displayed at x_coord. */
8240 if (block == NO_BLOCK)
8243 db = Dynarr_atp (dl->display_blocks, block);
8245 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
8247 struct rune *rb = Dynarr_atp (db->runes, elt);
8249 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
8251 if (rb->type == RUNE_DGLYPH)
8253 *obj1 = rb->object.dglyph.glyph;
8254 *obj2 = rb->object.dglyph.extent;
8263 *low_x_coord = rb->xpos;
8265 *high_x_coord = rb->xpos + rb->width;
8272 #define UPDATE_CACHE_RETURN \
8274 d->pixel_to_glyph_cache.valid = 1; \
8275 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8276 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8277 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8278 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8279 d->pixel_to_glyph_cache.frame = f; \
8280 d->pixel_to_glyph_cache.col = *col; \
8281 d->pixel_to_glyph_cache.row = *row; \
8282 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8283 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8284 d->pixel_to_glyph_cache.w = *w; \
8285 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8286 d->pixel_to_glyph_cache.closest = *closest; \
8287 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8288 d->pixel_to_glyph_cache.obj1 = *obj1; \
8289 d->pixel_to_glyph_cache.obj2 = *obj2; \
8290 d->pixel_to_glyph_cache.retval = position; \
8291 RETURN_SANS_WARNINGS position; \
8294 /* Given x and y coordinates in pixels relative to a frame, return
8295 information about what is located under those coordinates.
8297 The return value will be one of:
8299 OVER_TOOLBAR: over one of the 4 frame toolbars
8300 OVER_MODELINE: over a modeline
8301 OVER_BORDER: over an internal border
8302 OVER_NOTHING: over the text area, but not over text
8303 OVER_OUTSIDE: outside of the frame border
8304 OVER_TEXT: over text in the text area
8310 -- nil if the coordinates are not over a glyph or a toolbar button.
8314 -- an extent, if the coordinates are over a glyph in the text area
8317 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8318 equivalent coordinates relative to the upper-left corner of the glyph.
8320 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8321 equivalent coordinates relative to the upper-left corner of the character.
8323 Otherwise, OBJ_X and OBJ_Y are undefined.
8327 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
8328 int *col, int *row, int *obj_x, int *obj_y,
8329 struct window **w, Bufpos *bufpos,
8330 Bufpos *closest, Charcount *modeline_closest,
8331 Lisp_Object *obj1, Lisp_Object *obj2)
8334 struct pixel_to_glyph_translation_cache *cache;
8336 int frm_left, frm_right, frm_top, frm_bottom;
8337 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8338 int position = OVER_NOTHING;
8339 int device_check_failed = 0;
8340 display_line_dynarr *dla;
8342 /* This is a safety valve in case this got called with a frame in
8343 the middle of being deleted. */
8344 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
8346 device_check_failed = 1;
8347 d = NULL, cache = NULL; /* Warning suppression */
8351 d = XDEVICE (f->device);
8352 cache = &d->pixel_to_glyph_cache;
8355 if (!device_check_failed
8357 && cache->frame == f
8358 && cache->low_x_coord <= x_coord
8359 && cache->high_x_coord > x_coord
8360 && cache->low_y_coord <= y_coord
8361 && cache->high_y_coord > y_coord)
8365 *obj_x = cache->obj_x;
8366 *obj_y = cache->obj_y;
8368 *bufpos = cache->bufpos;
8369 *closest = cache->closest;
8370 *modeline_closest = cache->modeline_closest;
8371 *obj1 = cache->obj1;
8372 *obj2 = cache->obj2;
8374 return cache->retval;
8385 *modeline_closest = -1;
8389 low_x_coord = x_coord;
8390 high_x_coord = x_coord + 1;
8391 low_y_coord = y_coord;
8392 high_y_coord = y_coord + 1;
8395 if (device_check_failed)
8396 return OVER_NOTHING;
8398 frm_left = FRAME_LEFT_BORDER_END (f);
8399 frm_right = FRAME_RIGHT_BORDER_START (f);
8400 frm_top = FRAME_TOP_BORDER_END (f);
8401 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
8403 /* Check if the mouse is outside of the text area actually used by
8405 if (y_coord < frm_top)
8407 if (y_coord >= FRAME_TOP_BORDER_START (f))
8409 low_y_coord = FRAME_TOP_BORDER_START (f);
8410 high_y_coord = frm_top;
8411 position = OVER_BORDER;
8413 else if (y_coord >= 0)
8416 high_y_coord = FRAME_TOP_BORDER_START (f);
8417 position = OVER_TOOLBAR;
8421 low_y_coord = y_coord;
8423 position = OVER_OUTSIDE;
8426 else if (y_coord >= frm_bottom)
8428 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
8430 low_y_coord = frm_bottom;
8431 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
8432 position = OVER_BORDER;
8434 else if (y_coord < FRAME_PIXHEIGHT (f))
8436 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
8437 high_y_coord = FRAME_PIXHEIGHT (f);
8438 position = OVER_TOOLBAR;
8442 low_y_coord = FRAME_PIXHEIGHT (f);
8443 high_y_coord = y_coord;
8444 position = OVER_OUTSIDE;
8448 if (position != OVER_TOOLBAR && position != OVER_BORDER)
8450 if (x_coord < frm_left)
8452 if (x_coord >= FRAME_LEFT_BORDER_START (f))
8454 low_x_coord = FRAME_LEFT_BORDER_START (f);
8455 high_x_coord = frm_left;
8456 position = OVER_BORDER;
8458 else if (x_coord >= 0)
8461 high_x_coord = FRAME_LEFT_BORDER_START (f);
8462 position = OVER_TOOLBAR;
8466 low_x_coord = x_coord;
8468 position = OVER_OUTSIDE;
8471 else if (x_coord >= frm_right)
8473 if (x_coord < FRAME_RIGHT_BORDER_END (f))
8475 low_x_coord = frm_right;
8476 high_x_coord = FRAME_RIGHT_BORDER_END (f);
8477 position = OVER_BORDER;
8479 else if (x_coord < FRAME_PIXWIDTH (f))
8481 low_x_coord = FRAME_RIGHT_BORDER_END (f);
8482 high_x_coord = FRAME_PIXWIDTH (f);
8483 position = OVER_TOOLBAR;
8487 low_x_coord = FRAME_PIXWIDTH (f);
8488 high_x_coord = x_coord;
8489 position = OVER_OUTSIDE;
8494 #ifdef HAVE_TOOLBARS
8495 if (position == OVER_TOOLBAR)
8497 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
8500 UPDATE_CACHE_RETURN;
8502 #endif /* HAVE_TOOLBARS */
8504 /* We still have to return the window the pointer is next to and its
8505 relative y position even if it is outside the x boundary. */
8506 if (x_coord < frm_left)
8508 else if (x_coord > frm_right)
8509 x_coord = frm_right;
8511 /* Same in reverse. */
8512 if (y_coord < frm_top)
8514 else if (y_coord > frm_bottom)
8515 y_coord = frm_bottom;
8517 /* Find what window the given coordinates are actually in. */
8518 window = f->root_window;
8519 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
8521 /* If we didn't find a window, we're done. */
8524 UPDATE_CACHE_RETURN;
8526 else if (position != OVER_NOTHING)
8529 *modeline_closest = -1;
8531 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
8534 UPDATE_CACHE_RETURN;
8538 /* Check if the window is a minibuffer but isn't active. */
8539 if (MINI_WINDOW_P (*w) && !minibuf_level)
8541 /* Must reset the window value since some callers will ignore
8542 the return value if it is set. */
8544 UPDATE_CACHE_RETURN;
8547 /* See if the point is over window vertical divider */
8548 if (window_needs_vertical_divider (*w))
8550 int div_x_high = WINDOW_RIGHT (*w);
8551 int div_x_low = div_x_high - window_divider_width (*w);
8552 int div_y_high = WINDOW_BOTTOM (*w);
8553 int div_y_low = WINDOW_TOP (*w);
8555 if (div_x_low < x_coord && x_coord <= div_x_high &&
8556 div_y_low < y_coord && y_coord <= div_y_high)
8558 low_x_coord = div_x_low;
8559 high_x_coord = div_x_high;
8560 low_y_coord = div_y_low;
8561 high_y_coord = div_y_high;
8562 position = OVER_V_DIVIDER;
8563 UPDATE_CACHE_RETURN;
8567 dla = window_display_lines (*w, CURRENT_DISP);
8569 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
8571 int really_over_nothing = 0;
8572 struct display_line *dl = Dynarr_atp (dla, *row);
8574 if ((int) (dl->ypos - dl->ascent) <= y_coord
8575 && y_coord <= (int) (dl->ypos + dl->descent))
8577 int check_margin_glyphs = 0;
8578 struct display_block *db = get_display_block_from_line (dl, TEXT);
8579 struct rune *rb = 0;
8581 if (x_coord < dl->bounds.left_white
8582 || x_coord >= dl->bounds.right_white)
8583 check_margin_glyphs = 1;
8585 low_y_coord = dl->ypos - dl->ascent;
8586 high_y_coord = dl->ypos + dl->descent + 1;
8588 if (position == OVER_BORDER
8589 || position == OVER_OUTSIDE
8590 || check_margin_glyphs)
8592 int x_check, left_bound;
8594 if (check_margin_glyphs)
8597 left_bound = dl->bounds.left_white;
8601 x_check = high_x_coord;
8602 left_bound = frm_left;
8605 if (Dynarr_length (db->runes))
8607 if (x_check <= left_bound)
8610 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
8612 *closest = Dynarr_atp (db->runes, 0)->bufpos;
8618 Dynarr_atp (db->runes,
8619 Dynarr_length (db->runes) - 1)->bufpos;
8622 Dynarr_atp (db->runes,
8623 Dynarr_length (db->runes) - 1)->bufpos;
8627 *modeline_closest += dl->offset;
8629 *closest += dl->offset;
8633 /* #### What should be here. */
8635 *modeline_closest = 0;
8640 if (check_margin_glyphs)
8642 if (x_coord < dl->bounds.left_in
8643 || x_coord >= dl->bounds.right_in)
8645 /* If we are over the outside margins then we
8646 know the loop over the text block isn't going
8647 to accomplish anything. So we go ahead and
8648 set what information we can right here and
8651 *obj_y = y_coord - (dl->ypos - dl->ascent);
8652 get_position_object (dl, obj1, obj2, x_coord,
8653 &low_x_coord, &high_x_coord);
8655 UPDATE_CACHE_RETURN;
8659 UPDATE_CACHE_RETURN;
8662 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
8664 int past_end = (*col == Dynarr_length (db->runes));
8667 rb = Dynarr_atp (db->runes, *col);
8670 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
8675 rb = Dynarr_atp (db->runes, *col);
8678 *bufpos = rb->bufpos + dl->offset;
8679 low_x_coord = rb->xpos;
8680 high_x_coord = rb->xpos + rb->width;
8682 if (rb->type == RUNE_DGLYPH)
8686 /* Find the first character after the glyph. */
8687 while (elt < Dynarr_length (db->runes))
8689 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
8693 (Dynarr_atp (db->runes, elt)->bufpos +
8697 (Dynarr_atp (db->runes, elt)->bufpos +
8705 /* In this case we failed to find a non-glyph
8706 character so we return the last position
8707 displayed on the line. */
8708 if (elt == Dynarr_length (db->runes))
8711 *modeline_closest = dl->end_bufpos + dl->offset;
8713 *closest = dl->end_bufpos + dl->offset;
8714 really_over_nothing = 1;
8720 *modeline_closest = rb->bufpos + dl->offset;
8722 *closest = rb->bufpos + dl->offset;
8727 *row = window_displayed_height (*w);
8729 if (position == OVER_NOTHING)
8730 position = OVER_MODELINE;
8732 if (rb->type == RUNE_DGLYPH)
8734 *obj1 = rb->object.dglyph.glyph;
8735 *obj2 = rb->object.dglyph.extent;
8737 else if (rb->type == RUNE_CHAR)
8748 UPDATE_CACHE_RETURN;
8751 || (rb->type == RUNE_CHAR
8752 && rb->object.chr.ch == '\n'))
8755 /* At this point we may have glyphs in the right
8757 if (check_margin_glyphs)
8758 get_position_object (dl, obj1, obj2, x_coord,
8759 &low_x_coord, &high_x_coord);
8760 UPDATE_CACHE_RETURN;
8765 if (rb->type == RUNE_DGLYPH)
8767 *obj1 = rb->object.dglyph.glyph;
8768 *obj2 = rb->object.dglyph.extent;
8770 else if (rb->type == RUNE_CHAR)
8781 *obj_x = x_coord - rb->xpos;
8782 *obj_y = y_coord - (dl->ypos - dl->ascent);
8784 /* At this point we may have glyphs in the left
8786 if (check_margin_glyphs)
8787 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
8789 if (position == OVER_NOTHING && !really_over_nothing)
8790 position = OVER_TEXT;
8792 UPDATE_CACHE_RETURN;
8799 *row = Dynarr_length (dla) - 1;
8800 if (FRAME_WIN_P (f))
8802 int bot_elt = Dynarr_length (dla) - 1;
8806 struct display_line *dl = Dynarr_atp (dla, bot_elt);
8807 int adj_area = y_coord - (dl->ypos + dl->descent);
8811 XSETWINDOW (lwin, *w);
8812 default_face_height_and_width (lwin, 0, &defheight);
8814 *row += (adj_area / defheight);
8818 /* #### This should be checked out some more to determine what
8819 should really be going on. */
8820 if (!MARKERP ((*w)->start[CURRENT_DISP]))
8823 *closest = end_of_last_line_may_error (*w,
8824 marker_position ((*w)->start[CURRENT_DISP]));
8826 UPDATE_CACHE_RETURN;
8828 #undef UPDATE_CACHE_RETURN
8831 /***************************************************************************/
8833 /* Lisp functions */
8835 /***************************************************************************/
8837 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8838 Ensure that all minibuffers are correctly showing the echo area.
8842 Lisp_Object devcons, concons;
8844 DEVICE_LOOP_NO_BREAK (devcons, concons)
8846 struct device *d = XDEVICE (XCAR (devcons));
8847 Lisp_Object frmcons;
8849 DEVICE_FRAME_LOOP (frmcons, d)
8851 struct frame *f = XFRAME (XCAR (frmcons));
8853 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
8855 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
8857 * If the frame size has changed, there may be random
8858 * chud on the screen left from previous messages
8859 * because redisplay_frame hasn't been called yet.
8860 * Clear the screen to get rid of the potential mess.
8862 if (f->echo_area_garbaged)
8864 DEVMETH (d, clear_frame, (f));
8865 f->echo_area_garbaged = 0;
8867 redisplay_window (window, 0);
8868 call_redisplay_end_triggers (XWINDOW (window), 0);
8872 /* We now call the output_end routine for tty frames. We delay
8873 doing so in order to avoid cursor flicker. So much for 100%
8875 if (DEVICE_TTY_P (d))
8876 DEVMETH (d, output_end, (d));
8883 restore_disable_preemption_value (Lisp_Object value)
8885 disable_preemption = XINT (value);
8889 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8890 Clear frame FRAME and output again what is supposed to appear on it.
8891 FRAME defaults to the selected frame if omitted.
8892 Normally, redisplay is preempted as normal if input arrives. However,
8893 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8894 input and is guaranteed to proceed to completion.
8896 (frame, no_preempt))
8898 struct frame *f = decode_frame (frame);
8899 int count = specpdl_depth ();
8901 if (!NILP (no_preempt))
8903 record_unwind_protect (restore_disable_preemption_value,
8904 make_int (disable_preemption));
8905 disable_preemption++;
8909 redisplay_frame (f, 1);
8911 /* See the comment in Fredisplay_frame. */
8912 RESET_CHANGED_SET_FLAGS;
8914 return unbind_to (count, Qnil);
8917 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8918 Ensure that FRAME's contents are correctly displayed.
8919 This differs from `redraw-frame' in that it only redraws what needs to
8920 be updated, as opposed to unconditionally clearing and redrawing
8922 FRAME defaults to the selected frame 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 (frame, no_preempt))
8929 struct frame *f = decode_frame (frame);
8930 int count = specpdl_depth ();
8932 if (!NILP (no_preempt))
8934 record_unwind_protect (restore_disable_preemption_value,
8935 make_int (disable_preemption));
8936 disable_preemption++;
8939 redisplay_frame (f, 1);
8941 /* If we don't reset the global redisplay flafs here, subsequent
8942 changes to the display will not get registered by redisplay
8943 because it thinks it already has registered changes. If you
8944 really knew what you were doing you could confuse redisplay by
8945 calling Fredisplay_frame while updating another frame. We assume
8946 that if you know what you are doing you will not be that
8948 RESET_CHANGED_SET_FLAGS;
8950 return unbind_to (count, Qnil);
8953 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
8954 Clear device DEVICE and output again what is supposed to appear on it.
8955 DEVICE defaults to the selected device if omitted.
8956 Normally, redisplay is preempted as normal if input arrives. However,
8957 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8958 input and is guaranteed to proceed to completion.
8960 (device, no_preempt))
8962 struct device *d = decode_device (device);
8963 Lisp_Object frmcons;
8964 int count = specpdl_depth ();
8966 if (!NILP (no_preempt))
8968 record_unwind_protect (restore_disable_preemption_value,
8969 make_int (disable_preemption));
8970 disable_preemption++;
8973 DEVICE_FRAME_LOOP (frmcons, d)
8975 XFRAME (XCAR (frmcons))->clear = 1;
8977 redisplay_device (d, 0);
8979 /* See the comment in Fredisplay_frame. */
8980 RESET_CHANGED_SET_FLAGS;
8982 return unbind_to (count, Qnil);
8985 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8986 Ensure that DEVICE's contents are correctly displayed.
8987 This differs from `redraw-device' in that it only redraws what needs to
8988 be updated, as opposed to unconditionally clearing and redrawing
8990 DEVICE defaults to the selected device if omitted.
8991 Normally, redisplay is preempted as normal if input arrives. However,
8992 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8993 input and is guaranteed to proceed to completion.
8995 (device, no_preempt))
8997 struct device *d = decode_device (device);
8998 int count = specpdl_depth ();
9000 if (!NILP (no_preempt))
9002 record_unwind_protect (restore_disable_preemption_value,
9003 make_int (disable_preemption));
9004 disable_preemption++;
9007 redisplay_device (d, 0);
9009 /* See the comment in Fredisplay_frame. */
9010 RESET_CHANGED_SET_FLAGS;
9012 return unbind_to (count, Qnil);
9015 /* Big lie. Big lie. This will force all modelines to be updated
9016 regardless if the all flag is set or not. It remains in existence
9017 solely for backwards compatibility. */
9018 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
9019 Force the modeline of the current buffer to be redisplayed.
9020 With optional non-nil ALL, force redisplay of all modelines.
9024 MARK_MODELINE_CHANGED;
9028 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
9029 Force an immediate update of the cursor on FRAME.
9030 FRAME defaults to the selected frame if omitted.
9034 redisplay_redraw_cursor (decode_frame (frame), 1);
9039 /***************************************************************************/
9041 /* Lisp-variable change triggers */
9043 /***************************************************************************/
9046 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
9049 /* Nothing to be done? */
9053 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
9054 Lisp_Object in_object, int flags)
9056 /* #### clip_changed should really be renamed something like
9057 global_redisplay_change. */
9062 /* This is called if the built-in glyphs have their properties
9065 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
9068 if (WINDOWP (locale))
9070 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
9072 else if (FRAMEP (locale))
9074 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
9076 else if (DEVICEP (locale))
9078 Lisp_Object frmcons;
9079 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
9080 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9082 else if (CONSOLEP (locale))
9084 Lisp_Object frmcons, devcons;
9085 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
9086 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9088 else /* global or buffer */
9090 Lisp_Object frmcons, devcons, concons;
9091 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
9092 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9097 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
9100 if (XFRAME (w->frame)->init_finished)
9101 Fforce_cursor_redisplay (w->frame);
9104 #ifdef MEMORY_USAGE_STATS
9107 /***************************************************************************/
9109 /* memory usage computation */
9111 /***************************************************************************/
9114 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
9116 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9120 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
9121 struct overhead_stats *ovstats)
9128 total = Dynarr_memory_usage (dyn, ovstats);
9129 for (i = 0; i < Dynarr_largest (dyn); i++)
9130 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
9136 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
9137 struct overhead_stats *ovstats)
9139 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9143 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
9144 struct overhead_stats *ovstats)
9151 total = Dynarr_memory_usage (dyn, ovstats);
9152 for (i = 0; i < Dynarr_largest (dyn); i++)
9154 struct display_line *dl = &Dynarr_at (dyn, i);
9155 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
9156 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
9157 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
9164 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
9165 struct overhead_stats *ovstats)
9167 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9170 #endif /* MEMORY_USAGE_STATS */
9173 /***************************************************************************/
9175 /* initialization */
9177 /***************************************************************************/
9180 init_redisplay (void)
9182 disable_preemption = 0;
9183 preemption_count = 0;
9184 max_preempts = INIT_MAX_PREEMPTS;
9190 if (!cmotion_display_lines)
9191 cmotion_display_lines = Dynarr_new (display_line);
9192 if (!mode_spec_bufbyte_string)
9193 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
9194 if (!formatted_string_extent_dynarr)
9195 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
9196 if (!formatted_string_extent_start_dynarr)
9197 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
9198 if (!formatted_string_extent_end_dynarr)
9199 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
9200 if (!internal_cache)
9201 internal_cache = Dynarr_new (line_start_cache);
9204 /* window system is nil when in -batch mode */
9205 if (!initialized || noninteractive)
9208 /* If the user wants to use a window system, we shouldn't bother
9209 initializing the terminal. This is especially important when the
9210 terminal is so dumb that emacs gives up before and doesn't bother
9211 using the window system.
9213 If the DISPLAY environment variable is set, try to use X, and die
9214 with an error message if that doesn't work. */
9216 #ifdef HAVE_X_WINDOWS
9217 if (!strcmp (display_use, "x"))
9219 /* Some stuff checks this way early. */
9220 Vwindow_system = Qx;
9221 Vinitial_window_system = Qx;
9224 #endif /* HAVE_X_WINDOWS */
9226 #ifdef HAVE_MS_WINDOWS
9227 if (!strcmp (display_use, "mswindows"))
9229 /* Some stuff checks this way early. */
9230 Vwindow_system = Qmswindows;
9231 Vinitial_window_system = Qmswindows;
9234 #endif /* HAVE_MS_WINDOWS */
9237 /* If no window system has been specified, try to use the terminal. */
9240 stderr_out ("XEmacs: standard input is not a tty\n");
9244 /* Look at the TERM variable */
9245 if (!getenv ("TERM"))
9247 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
9251 Vinitial_window_system = Qtty;
9253 #else /* not HAVE_TTY */
9254 /* No DISPLAY specified, and no TTY support. */
9255 stderr_out ("XEmacs: Cannot open display.\n\
9256 Please set the environmental variable DISPLAY to an appropriate value.\n");
9263 syms_of_redisplay (void)
9265 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
9266 #ifndef INHIBIT_REDISPLAY_HOOKS
9267 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
9268 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
9269 #endif /* INHIBIT_REDISPLAY_HOOKS */
9270 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
9271 defsymbol (&Qbar_cursor, "bar-cursor");
9272 defsymbol (&Qredisplay_end_trigger_functions,
9273 "redisplay-end-trigger-functions");
9274 defsymbol (&Qtop_bottom, "top-bottom");
9276 DEFSUBR (Fredisplay_echo_area);
9277 DEFSUBR (Fredraw_frame);
9278 DEFSUBR (Fredisplay_frame);
9279 DEFSUBR (Fredraw_device);
9280 DEFSUBR (Fredisplay_device);
9281 DEFSUBR (Fredraw_modeline);
9282 DEFSUBR (Fforce_cursor_redisplay);
9286 reinit_vars_of_redisplay (void)
9288 updating_line_start_cache = 0;
9292 vars_of_redisplay (void)
9294 reinit_vars_of_redisplay ();
9297 staticpro (&last_arrow_position);
9298 staticpro (&last_arrow_string);
9299 last_arrow_position = Qnil;
9300 last_arrow_string = Qnil;
9303 /* #### Probably temporary */
9304 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
9305 \(Temporary) Setting this will impact the performance of the internal
9308 cache_adjustment = 2;
9310 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
9311 Minimum pixel height for clipped bottom display line.
9312 A clipped line shorter than this won't be displayed.
9314 redisplay_variable_changed);
9317 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
9318 Minimum visible area for clipped glyphs at right boundary.
9319 Clipped glyphs shorter than this won't be displayed.
9320 Only pixmap glyph instances are currently allowed to be clipped.
9322 redisplay_variable_changed);
9323 horizontal_clip = 5;
9325 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
9326 String displayed by modeline-format's "%m" specification.
9328 Vglobal_mode_string = Qnil;
9330 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
9331 Marker for where to display an arrow on top of the buffer text.
9332 This must be the beginning of a line in order to work.
9333 See also `overlay-arrow-string'.
9335 redisplay_variable_changed);
9336 Voverlay_arrow_position = Qnil;
9338 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
9339 String to display as an arrow. See also `overlay-arrow-position'.
9341 redisplay_variable_changed);
9342 Voverlay_arrow_string = Qnil;
9344 DEFVAR_INT ("scroll-step", &scroll_step /*
9345 *The number of lines to try scrolling a window by when point moves out.
9346 If that fails to bring point back on frame, point is centered instead.
9347 If this is zero, point is always centered after it moves off screen.
9351 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
9352 *Scroll up to this many lines, to bring point back on screen.
9354 scroll_conservatively = 0;
9356 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
9357 &truncate_partial_width_windows /*
9358 *Non-nil means truncate lines in all windows less than full frame wide.
9360 redisplay_variable_changed);
9361 truncate_partial_width_windows = 1;
9363 DEFVAR_LISP ("visible-bell", &Vvisible_bell /*
9364 *Non-nil substitutes a visual signal for the audible bell.
9366 Default behavior is to flash the whole screen. On some platforms,
9367 special effects are available using the following values:
9369 'display Flash the whole screen (ie, the default behavior).
9370 'top-bottom Flash only the top and bottom lines of the selected frame.
9372 When effects are unavailable on a platform, the visual bell is the
9373 default, whole screen. (Currently only X supports any special effects.)
9375 Vvisible_bell = Qnil;
9377 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
9378 *Non-nil means no need to redraw entire frame after suspending.
9379 A non-nil value is useful if the terminal can automatically preserve
9380 Emacs's frame display when you reenter Emacs.
9381 It is up to you to set this variable if your terminal can do that.
9383 no_redraw_on_reenter = 0;
9385 DEFVAR_LISP ("window-system", &Vwindow_system /*
9386 A symbol naming the window-system under which Emacs is running,
9387 such as `x', or nil if emacs is running on an ordinary terminal.
9389 Do not use this variable, except for GNU Emacs compatibility, as it
9390 gives wrong values in a multi-device environment. Use `console-type'
9393 Vwindow_system = Qnil;
9395 /* #### Temporary shit until window-system is eliminated. */
9396 DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /*
9399 Vinitial_window_system = Qnil;
9401 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
9402 Non-nil means put cursor in minibuffer, at end of any message there.
9404 cursor_in_echo_area = 0;
9406 /* #### Shouldn't this be generalized as follows:
9408 if nil, use block cursor.
9409 if a number, use a bar cursor of that width.
9410 Otherwise, use a 1-pixel bar cursor.
9412 #### Or better yet, this variable should be trashed entirely
9413 (use a Lisp-magic variable to maintain compatibility)
9414 and a specifier `cursor-shape' added, which allows a block
9415 cursor, a bar cursor, a flashing block or bar cursor,
9416 maybe a caret cursor, etc. */
9418 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
9419 Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9423 #ifndef INHIBIT_REDISPLAY_HOOKS
9424 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
9425 Function or functions to run before every redisplay.
9426 Functions on this hook must be careful to avoid signalling errors!
9428 Vpre_redisplay_hook = Qnil;
9430 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
9431 Function or functions to run after every redisplay.
9432 Functions on this hook must be careful to avoid signalling errors!
9434 Vpost_redisplay_hook = Qnil;
9435 #endif /* INHIBIT_REDISPLAY_HOOKS */
9437 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
9438 Bump this to tell the C code to call `display-warning-buffer'
9439 at next redisplay. You should not normally change this; the function
9440 `display-warning' automatically does this at appropriate times.
9442 display_warning_tick = 0;
9444 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
9445 Non-nil means inhibit display of warning messages.
9446 You should *bind* this, not set it. Any pending warning messages
9447 will be displayed when the binding no longer applies.
9449 /* reset to 0 by startup.el after the splash screen has displayed.
9450 This way, the warnings don't obliterate the splash screen. */
9451 inhibit_warning_display = 1;
9453 DEFVAR_LISP ("window-size-change-functions",
9454 &Vwindow_size_change_functions /*
9455 Not currently implemented.
9456 Functions called before redisplay, if window sizes have changed.
9457 The value should be a list of functions that take one argument.
9458 Just before redisplay, for each frame, if any of its windows have changed
9459 size since the last redisplay, or have been split or deleted,
9460 all the functions in the list are called, with the frame as argument.
9462 Vwindow_size_change_functions = Qnil;
9464 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
9465 Not currently implemented.
9466 Functions to call before redisplaying a window with scrolling.
9467 Each function is called with two arguments, the window
9468 and its new display-start position. Note that the value of `window-end'
9469 is not valid when these functions are called.
9471 Vwindow_scroll_functions = Qnil;
9473 DEFVAR_LISP ("redisplay-end-trigger-functions",
9474 &Vredisplay_end_trigger_functions /*
9475 See `set-window-redisplay-end-trigger'.
9477 Vredisplay_end_trigger_functions = Qnil;
9479 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
9480 *Non-nil means column display number starts at 1.
9482 column_number_start_at_one = 0;
9486 specifier_vars_of_redisplay (void)
9488 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
9489 *Width of left margin.
9490 This is a specifier; use `set-specifier' to change it.
9492 Vleft_margin_width = Fmake_specifier (Qnatnum);
9493 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
9494 set_specifier_caching (Vleft_margin_width,
9495 offsetof (struct window, left_margin_width),
9496 some_window_value_changed,
9497 offsetof (struct frame, left_margin_width),
9498 margin_width_changed_in_frame);
9500 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
9501 *Width of right margin.
9502 This is a specifier; use `set-specifier' to change it.
9504 Vright_margin_width = Fmake_specifier (Qnatnum);
9505 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
9506 set_specifier_caching (Vright_margin_width,
9507 offsetof (struct window, right_margin_width),
9508 some_window_value_changed,
9509 offsetof (struct frame, right_margin_width),
9510 margin_width_changed_in_frame);
9512 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
9513 *Minimum ascent height of lines.
9514 This is a specifier; use `set-specifier' to change it.
9516 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
9517 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
9518 set_specifier_caching (Vminimum_line_ascent,
9519 offsetof (struct window, minimum_line_ascent),
9520 some_window_value_changed,
9523 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
9524 *Minimum descent height of lines.
9525 This is a specifier; use `set-specifier' to change it.
9527 Vminimum_line_descent = Fmake_specifier (Qnatnum);
9528 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
9529 set_specifier_caching (Vminimum_line_descent,
9530 offsetof (struct window, minimum_line_descent),
9531 some_window_value_changed,
9534 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
9535 *Non-nil means use the left outside margin as extra whitespace when
9536 displaying 'whitespace or 'inside-margin glyphs.
9537 This is a specifier; use `set-specifier' to change it.
9539 Vuse_left_overflow = Fmake_specifier (Qboolean);
9540 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
9541 set_specifier_caching (Vuse_left_overflow,
9542 offsetof (struct window, use_left_overflow),
9543 some_window_value_changed,
9546 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
9547 *Non-nil means use the right outside margin as extra whitespace when
9548 displaying 'whitespace or 'inside-margin glyphs.
9549 This is a specifier; use `set-specifier' to change it.
9551 Vuse_right_overflow = Fmake_specifier (Qboolean);
9552 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
9553 set_specifier_caching (Vuse_right_overflow,
9554 offsetof (struct window, use_right_overflow),
9555 some_window_value_changed,
9558 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9559 *Non-nil means the text cursor is visible (this is usually the case).
9560 This is a specifier; use `set-specifier' to change it.
9562 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
9563 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
9564 set_specifier_caching (Vtext_cursor_visible_p,
9565 offsetof (struct window, text_cursor_visible_p),
9566 text_cursor_visible_p_changed,