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;
158 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
159 glyph differs from space_width (w).
160 0 if no hscroll glyph was used,
161 i.e. the window is not scrolled
162 horizontally. Used in tab
165 /* Information about the face the text should be displayed in and
166 any begin-glyphs and end-glyphs. */
167 struct extent_fragment *ef;
170 /* The height of a pixmap may either be predetermined if the user
171 has set a baseline value, or it may be dependent on whatever the
172 line ascent and descent values end up being, based just on font
173 information. In the first case we can immediately update the
174 values, thus their inclusion here. In the last case we cannot
175 determine the actual contribution to the line height until we
176 have finished laying out all text on the line. Thus we propagate
177 the max height of such pixmaps and do a final calculation after
178 all text has been added to the line. */
181 int max_pixmap_height;
183 Lisp_Object result_str; /* String where we put the result of
184 generating a formatted string in the modeline. */
185 int is_modeline; /* Non-zero if we're generating the modeline. */
186 Charcount modeline_charpos; /* Number of chars used in result_str so far;
187 corresponds to bytepos. */
188 Bytecount bytepos; /* Number of bytes used in result_str so far.
189 We don't actually copy the bytes into result_str
190 until the end because we don't know how big the
191 string is going to be until then. */
202 /* Data that should be propagated to the next line. Either a single
203 Emchar or a string of Bufbyte's.
205 The actual data that is propagated ends up as a Dynarr of these
208 #### It's unclean that both Emchars and Bufbytes are here.
211 typedef struct prop_block prop_block;
221 Bytecount len; /* length of the string. */
227 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
228 unsigned int cursor_type :3;
241 Dynarr_declare (prop_block);
245 static void generate_formatted_string_db (Lisp_Object format_str,
246 Lisp_Object result_str,
248 struct display_line *dl,
249 struct display_block *db,
250 face_index findex, int min_pixpos,
251 int max_pixpos, int type);
252 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
253 Charcount pos, Charcount min_pos,
254 Charcount max_pos, Lisp_Object elt,
255 int depth, int max_pixsize,
256 face_index findex, int type);
257 static prop_block_dynarr *add_glyph_rune (pos_data *data,
258 struct glyph_block *gb,
259 int pos_type, int allow_cursor,
260 struct glyph_cachel *cachel);
261 static Bytind create_text_block (struct window *w, struct display_line *dl,
262 Bytind bi_start_pos, int start_col,
263 prop_block_dynarr **prop,
265 static int create_overlay_glyph_block (struct window *w,
266 struct display_line *dl);
267 static void create_left_glyph_block (struct window *w,
268 struct display_line *dl,
270 static void create_right_glyph_block (struct window *w,
271 struct display_line *dl);
272 static void redisplay_windows (Lisp_Object window, int skip_selected);
273 static void decode_mode_spec (struct window *w, Emchar spec, int type);
274 static void free_display_line (struct display_line *dl);
275 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
276 Bufpos point, int no_regen);
277 static int point_visible (struct window *w, Bufpos point, int type);
278 extern Bytind bi_find_next_emchar_in_string (struct Lisp_String* str, Emchar target,
279 Bytind st, EMACS_INT count);
280 extern int string_column_at_point (struct Lisp_String* s, Bufpos init_pos, int tab_width);
282 /* This used to be 10 but 30 seems to give much better performance. */
283 #define INIT_MAX_PREEMPTS 30
284 static int max_preempts;
286 #define REDISPLAY_PREEMPTION_CHECK \
289 (!disable_preemption && \
290 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
291 (!INTERACTIVE || detect_input_pending ()))))
294 * Redisplay global variables.
297 /* We need a third set of display structures for the cursor motion
298 routines. We used to just give each window a third set. However,
299 we always fully regenerate the structures when needed so there
300 isn't any reason we need more than a single set. */
301 display_line_dynarr *cmotion_display_lines;
303 /* Used by generate_formatted_string. Global because they get used so
304 much that the dynamic allocation time adds up. */
305 Emchar_dynarr *formatted_string_emchar_dynarr;
306 struct display_line formatted_string_display_line;
307 /* We store the extents that we need to generate in a Dynarr and then
308 frob them all on at the end of generating the string. We do it
309 this way rather than adding them as we generate the string because
310 we don't store the text into the resulting string until we're done
311 (to avoid having to resize the string multiple times), and we don't
312 want to go around adding extents to a string when the extents might
313 stretch off the end of the string. */
314 EXTENT_dynarr *formatted_string_extent_dynarr;
315 Bytecount_dynarr *formatted_string_extent_start_dynarr;
316 Bytecount_dynarr *formatted_string_extent_end_dynarr;
319 /* #### probably temporary */
320 int cache_adjustment;
322 /* This holds a string representing the text corresponding to a single
324 static Bufbyte_dynarr *mode_spec_bufbyte_string;
326 int in_display; /* 1 if in redisplay. */
328 int disable_preemption; /* Used for debugging redisplay and for
331 /* We only allow max_preempts preemptions before we force a redisplay. */
332 static int preemption_count;
334 /* Minimum pixel height of clipped bottom display line. */
337 /* Minimum visible pixel width of clipped glyphs at right margin. */
340 /* Set if currently inside update_line_start_cache. */
341 int updating_line_start_cache;
343 /* Nonzero means reading single-character input with prompt
344 so put cursor on minibuffer after the prompt. */
345 int cursor_in_echo_area;
346 Lisp_Object Qcursor_in_echo_area;
348 /* Nonzero means truncate lines in all windows less wide than the frame */
349 int truncate_partial_width_windows;
351 /* non-nil if a buffer has changed since the last time redisplay completed */
353 int buffers_changed_set;
355 /* non-nil if hscroll has changed somewhere or a buffer has been
356 narrowed or widened */
358 int clip_changed_set;
360 /* non-nil if any extent has changed since the last time redisplay completed */
362 int extents_changed_set;
364 /* non-nil if any face has changed since the last time redisplay completed */
367 /* Nonzero means some frames have been marked as garbaged */
370 /* non-zero if any of the builtin display glyphs (continuation,
371 hscroll, control-arrow, etc) is in need of updating
374 int glyphs_changed_set;
376 /* non-zero if any displayed subwindow is in need of updating
378 int subwindows_changed;
379 int subwindows_changed_set;
381 /* This variable is 1 if the icon has to be updated.
382 It is set to 1 when `frame-icon-glyph' changes. */
384 int icon_changed_set;
386 /* This variable is 1 if the menubar widget has to be updated.
387 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
390 int menubar_changed_set;
392 /* true iff we should redraw the modelines on the next redisplay */
393 int modeline_changed;
394 int modeline_changed_set;
396 /* non-nil if point has changed in some buffer since the last time
397 redisplay completed */
399 int point_changed_set;
401 /* non-nil if some frame has changed its size */
404 /* non-nil if some device has signaled that it wants to change size */
405 int asynch_device_change_pending;
407 /* non-nil if any toolbar has changed */
409 int toolbar_changed_set;
411 /* non-nil if any gutter has changed */
413 int gutter_changed_set;
415 /* non-nil if any window has changed since the last time redisplay completed */
418 /* non-nil if any frame's window structure has changed since the last
419 time redisplay completed */
420 int windows_structure_changed;
422 /* If non-nil, use vertical bar cursor. */
423 Lisp_Object Vbar_cursor;
424 Lisp_Object Qbar_cursor;
427 int visible_bell; /* If true and the terminal will support it
428 then the frame will flash instead of
429 beeping when an error occurs */
431 /* Nonzero means no need to redraw the entire frame on resuming
432 a suspended Emacs. This is useful on terminals with multiple pages,
433 where one page is used for Emacs and another for all else. */
434 int no_redraw_on_reenter;
436 Lisp_Object Vwindow_system; /* nil or a symbol naming the window system
437 under which emacs is running
438 ('x is the only current possibility) */
439 Lisp_Object Vinitial_window_system;
441 Lisp_Object Vglobal_mode_string;
443 /* The number of lines scroll a window by when point leaves the window; if
444 it is <=0 then point is centered in the window */
447 /* Scroll up to this many lines, to bring point back on screen. */
448 int scroll_conservatively;
450 /* Marker for where to display an arrow on top of the buffer text. */
451 Lisp_Object Voverlay_arrow_position;
452 /* String to display for the arrow. */
453 Lisp_Object Voverlay_arrow_string;
455 Lisp_Object Vwindow_size_change_functions;
456 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
457 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
459 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
461 #ifndef INHIBIT_REDISPLAY_HOOKS
462 /* #### Chuck says: I think this needs more thought.
463 Think about this for 19.14. */
464 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
465 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
466 #endif /* INHIBIT_REDISPLAY_HOOKS */
468 int last_display_warning_tick, display_warning_tick;
469 Lisp_Object Qdisplay_warning_buffer;
470 int inhibit_warning_display;
472 Lisp_Object Vleft_margin_width, Vright_margin_width;
473 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
474 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
475 Lisp_Object Vtext_cursor_visible_p;
477 int column_number_start_at_one;
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. */
648 n_pos -= space_width (w) * (w->hscroll - 1);
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, int start_col,
701 prop_block_dynarr **prop,
706 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
708 /* If our caller hasn't already set the boundaries, then do so now. */
710 dl->bounds = calculate_display_line_boundaries (w, 0);
712 /* Reset what this line is using. */
713 if (dl->display_blocks)
714 Dynarr_reset (dl->display_blocks);
717 Dynarr_free (dl->left_glyphs);
720 if (dl->right_glyphs)
722 Dynarr_free (dl->right_glyphs);
723 dl->right_glyphs = 0;
726 /* We aren't generating a modeline at the moment. */
729 /* Create a display block for the text region of the line. */
731 /* #### urk urk urk!!! Chuck fix this shit! */
732 Bytind hacked_up_bytind =
733 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
734 start_col, prop, type);
735 if (hacked_up_bytind > BI_BUF_ZV (b))
736 ret_bufpos = BUF_ZV (b) + 1;
738 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
740 dl->bufpos = start_pos;
741 if (dl->end_bufpos < dl->bufpos)
742 dl->end_bufpos = dl->bufpos;
744 if (MARKERP (Voverlay_arrow_position)
745 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
746 && start_pos == marker_position (Voverlay_arrow_position)
747 && (STRINGP (Voverlay_arrow_string)
748 || GLYPHP (Voverlay_arrow_string)))
750 overlay_width = create_overlay_glyph_block (w, dl);
755 /* If there are left glyphs associated with any character in the
756 text block, then create a display block to handle them. */
757 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
758 create_left_glyph_block (w, dl, overlay_width);
760 /* If there are right glyphs associated with any character in the
761 text block, then create a display block to handle them. */
762 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
763 create_right_glyph_block (w, dl);
765 /* In the future additional types of display blocks may be generated
768 w->last_redisplay_pos = ret_bufpos;
773 /* Adds an hscroll glyph to a display block. If this is called, then
774 the block had better be empty.
776 Yes, there are multiple places where this function is called but
777 that is the way it has to be. Each calling function has to deal
778 with bi_start_col_enabled a little differently depending on the
779 object being worked with. */
781 static prop_block_dynarr *
782 add_hscroll_rune (pos_data *data)
784 struct glyph_block gb;
785 prop_block_dynarr *retval;
786 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
787 unsigned int old_cursor_type = data->cursor_type;
788 Bytind bi_old_bufpos = data->bi_bufpos;
790 if (data->cursor_type == CURSOR_ON
791 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
792 && data->bi_cursor_bufpos <= data->bi_bufpos)
794 data->bi_cursor_bufpos = data->bi_start_col_enabled;
798 data->cursor_type = NO_CURSOR;
801 data->bi_endpos = data->bi_bufpos;
802 data->bi_bufpos = data->bi_start_col_enabled;
805 gb.glyph = Vhscroll_glyph;
807 int oldpixpos = data->pixpos;
808 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
809 GLYPH_CACHEL (XWINDOW (data->window),
810 HSCROLL_GLYPH_INDEX));
811 data->hscroll_glyph_width_adjust =
812 data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
815 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
816 data->cursor_type = old_cursor_type;
817 data->bi_bufpos = bi_old_bufpos;
819 data->bi_start_col_enabled = 0;
823 /* Adds a character rune to a display block. If there is not enough
824 room to fit the rune on the display block (as determined by the
825 MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
827 static prop_block_dynarr *
828 add_emchar_rune (pos_data *data)
830 struct rune rb, *crb;
841 if (data->bi_start_col_enabled)
843 return add_hscroll_rune (data);
846 if (data->ch == '\n')
848 data->font_is_bogus = 0;
849 /* Cheesy end-of-line pseudo-character. */
850 width = data->blank_width;
854 Lisp_Object charset = CHAR_CHARSET (data->ch);
855 if (!EQ (charset, data->last_charset) ||
856 data->findex != data->last_findex)
858 /* OK, we need to do things the hard way. */
859 struct window *w = XWINDOW (data->window);
860 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
861 Lisp_Object font_instance =
862 ensure_face_cachel_contains_charset (cachel, data->window,
864 struct Lisp_Font_Instance *fi;
866 if (EQ (font_instance, Vthe_null_font_instance))
868 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
869 data->font_is_bogus = 1;
872 data->font_is_bogus = 0;
874 fi = XFONT_INSTANCE (font_instance);
875 if (!fi->proportional_p)
876 /* sweetness and light. */
877 data->last_char_width = fi->width;
879 data->last_char_width = -1;
880 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
881 data->new_descent = max (data->new_descent, (int) fi->descent);
882 data->last_charset = charset;
883 data->last_findex = data->findex;
886 width = data->last_char_width;
889 /* bummer. Proportional fonts. */
890 width = redisplay_text_width_emchar_string (XWINDOW (data->window),
896 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
901 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
903 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
912 crb->findex = data->findex;
913 crb->xpos = data->pixpos;
917 if (NILP (data->string))
919 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
923 bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
925 else if (data->is_modeline)
926 crb->bufpos = data->modeline_charpos;
928 /* fuckme if this shouldn't be an abort. */
929 /* abort (); fuckme harder, this abort gets tripped quite often,
930 in propagation and whatnot. #### fixme */
932 crb->type = RUNE_CHAR;
933 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
936 if (data->cursor_type == CURSOR_ON)
938 if (data->bi_bufpos == data->bi_cursor_bufpos)
940 crb->cursor_type = CURSOR_ON;
941 data->cursor_x = Dynarr_length (data->db->runes);
944 crb->cursor_type = CURSOR_OFF;
946 else if (data->cursor_type == NEXT_CURSOR)
948 crb->cursor_type = CURSOR_ON;
949 data->cursor_x = Dynarr_length (data->db->runes);
950 data->cursor_type = NO_CURSOR;
952 else if (data->cursor_type == IGNORE_CURSOR)
953 crb->cursor_type = IGNORE_CURSOR;
955 crb->cursor_type = CURSOR_OFF;
958 Dynarr_add (data->db->runes, *crb);
960 Dynarr_increment (data->db->runes);
962 data->pixpos += width;
967 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
968 for each character in the string. Propagate any left-over data
969 unless NO_PROP is non-zero. */
971 static prop_block_dynarr *
972 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
973 Bytecount c_length, int no_prop)
975 Bufbyte *pos, *end = c_string + c_length;
976 prop_block_dynarr *prop;
978 /* #### This function is too simplistic. It needs to do the same
979 sort of character interpretation (display-table lookup,
980 ctl-arrow checking), etc. that create_text_block() does.
981 The functionality to do this in that routine needs to be
984 for (pos = c_string; pos < end;)
986 data->ch = charptr_emchar (pos);
988 prop = add_emchar_rune (data);
996 struct prop_block pb;
997 Bytecount len = end - pos;
998 prop = Dynarr_new (prop_block);
1000 pb.type = PROP_STRING;
1001 pb.data.p_string.str = xnew_array (Bufbyte, len);
1002 strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
1003 pb.data.p_string.len = len;
1005 Dynarr_add (prop, pb);
1010 assert (pos <= end);
1016 /* Add a single rune of the specified width. The area covered by this
1017 rune will be displayed in the foreground color of the associated
1020 static prop_block_dynarr *
1021 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1025 /* If data->start_col is not 0 then this call to add_blank_rune must have
1026 been to add it as a tab. */
1027 if (data->start_col)
1029 /* assert (w != NULL) */
1030 prop_block_dynarr *retval;
1032 /* If we have still not fully scrolled horizontally, subtract
1033 the width of this tab and return. */
1034 if (char_tab_width < data->start_col)
1036 data->start_col -= char_tab_width;
1039 else if (char_tab_width == data->start_col)
1040 data->blank_width = 0;
1043 int spcwid = space_width (w);
1045 if (spcwid >= data->blank_width)
1046 data->blank_width = 0;
1048 data->blank_width -= spcwid;
1051 data->start_col = 0;
1052 retval = add_hscroll_rune (data);
1054 /* Could be caused by the handling of the hscroll rune. */
1055 if (retval != NULL || !data->blank_width)
1059 /* Blank runes are always calculated to fit. */
1060 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1062 rb.findex = data->findex;
1063 rb.xpos = data->pixpos;
1064 rb.width = data->blank_width;
1065 if (data->bi_bufpos)
1067 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1070 /* #### and this is really correct too? */
1073 rb.type = RUNE_BLANK;
1075 if (data->cursor_type == CURSOR_ON)
1077 if (data->bi_bufpos == data->bi_cursor_bufpos)
1079 rb.cursor_type = CURSOR_ON;
1080 data->cursor_x = Dynarr_length (data->db->runes);
1083 rb.cursor_type = CURSOR_OFF;
1085 else if (data->cursor_type == NEXT_CURSOR)
1087 rb.cursor_type = CURSOR_ON;
1088 data->cursor_x = Dynarr_length (data->db->runes);
1089 data->cursor_type = NO_CURSOR;
1092 rb.cursor_type = CURSOR_OFF;
1094 Dynarr_add (data->db->runes, rb);
1095 data->pixpos += data->blank_width;
1100 /* Add runes representing a character in octal. */
1102 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1104 if (add_failed || (add_failed = add_emchar_rune (data))) \
1106 struct prop_block pb; \
1108 prop = Dynarr_new (prop_block); \
1110 pb.type = PROP_CHAR; \
1111 pb.data.p_char.ch = data->ch; \
1112 pb.data.p_char.cursor_type = data->cursor_type; \
1113 Dynarr_add (prop, pb); \
1117 static prop_block_dynarr *
1118 add_octal_runes (pos_data *data)
1120 prop_block_dynarr *prop, *add_failed;
1121 Emchar orig_char = data->ch;
1122 unsigned int orig_cursor_type = data->cursor_type;
1128 if (data->start_col)
1131 if (!data->start_col)
1133 if (data->bi_start_col_enabled)
1135 add_failed = add_hscroll_rune (data);
1139 struct glyph_block gb;
1140 struct window *w = XWINDOW (data->window);
1143 gb.glyph = Voctal_escape_glyph;
1145 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1146 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1150 /* We only propagate information if the glyph was partially
1155 data->cursor_type = IGNORE_CURSOR;
1157 if (data->ch >= 0x100)
1159 /* If the character is an extended Mule character, it could have
1160 up to 19 bits. For the moment, we treat it as a seven-digit
1161 octal number. This is not that pretty, but whatever. */
1162 data->ch = (7 & (orig_char >> 18)) + '0';
1163 ADD_NEXT_OCTAL_RUNE_CHAR;
1165 data->ch = (7 & (orig_char >> 15)) + '0';
1166 ADD_NEXT_OCTAL_RUNE_CHAR;
1168 data->ch = (7 & (orig_char >> 12)) + '0';
1169 ADD_NEXT_OCTAL_RUNE_CHAR;
1171 data->ch = (7 & (orig_char >> 9)) + '0';
1172 ADD_NEXT_OCTAL_RUNE_CHAR;
1175 data->ch = (7 & (orig_char >> 6)) + '0';
1176 ADD_NEXT_OCTAL_RUNE_CHAR;
1178 data->ch = (7 & (orig_char >> 3)) + '0';
1179 ADD_NEXT_OCTAL_RUNE_CHAR;
1181 data->ch = (7 & orig_char) + '0';
1182 ADD_NEXT_OCTAL_RUNE_CHAR;
1184 data->cursor_type = orig_cursor_type;
1188 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1190 /* Add runes representing a control character to a display block. */
1192 static prop_block_dynarr *
1193 add_control_char_runes (pos_data *data, struct buffer *b)
1195 if (!NILP (b->ctl_arrow))
1197 prop_block_dynarr *prop;
1198 Emchar orig_char = data->ch;
1199 unsigned int old_cursor_type = data->cursor_type;
1204 if (data->start_col)
1207 if (!data->start_col)
1209 if (data->bi_start_col_enabled)
1211 prop_block_dynarr *retval;
1213 retval = add_hscroll_rune (data);
1219 struct glyph_block gb;
1220 struct window *w = XWINDOW (data->window);
1223 gb.glyph = Vcontrol_arrow_glyph;
1225 /* We only propagate information if the glyph was partially
1227 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1228 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1233 if (orig_char == 0177)
1236 data->ch = orig_char ^ 0100;
1237 data->cursor_type = IGNORE_CURSOR;
1239 if (add_emchar_rune (data))
1241 struct prop_block pb;
1243 prop = Dynarr_new (prop_block);
1245 pb.type = PROP_CHAR;
1246 pb.data.p_char.ch = data->ch;
1247 pb.data.p_char.cursor_type = data->cursor_type;
1248 Dynarr_add (prop, pb);
1251 data->cursor_type = old_cursor_type;
1256 return add_octal_runes (data);
1260 static prop_block_dynarr *
1261 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
1263 prop_block_dynarr *prop = NULL;
1265 if (STRINGP (entry))
1267 prop = add_bufbyte_string_runes (data,
1268 XSTRING_DATA (entry),
1269 XSTRING_LENGTH (entry),
1272 else if (GLYPHP (entry))
1274 if (data->start_col)
1277 if (!data->start_col && data->bi_start_col_enabled)
1279 prop = add_hscroll_rune (data);
1283 struct glyph_block gb;
1287 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1290 else if (CHAR_OR_CHAR_INTP (entry))
1292 data->ch = XCHAR_OR_CHAR_INT (entry);
1293 prop = add_emchar_rune (data);
1295 else if (CONSP (entry))
1297 if (EQ (XCAR (entry), Qformat)
1298 && CONSP (XCDR (entry))
1299 && STRINGP (XCAR (XCDR (entry))))
1301 Lisp_Object format = XCAR (XCDR (entry));
1302 Bytind len = XSTRING_LENGTH (format);
1303 Bufbyte *src = XSTRING_DATA (format), *end = src + len;
1304 Bufbyte *result = alloca_array (Bufbyte, len);
1305 Bufbyte *dst = result;
1309 Emchar c = charptr_emchar (src);
1311 if (c != '%' || src == end)
1312 dst += set_charptr_emchar (dst, c);
1315 c = charptr_emchar (src);
1320 dst += long_to_string_base ((char *)dst, data->ch, 16);
1323 dst += set_charptr_emchar (dst, '%');
1328 prop = add_bufbyte_string_runes (data, result, dst - result, 0);
1332 /* Else blow it off because someone added a bad entry and we don't
1333 have any safe way of signaling an error. */
1337 /* Given a display table entry, call the appropriate functions to
1338 display each element of the entry. */
1340 static prop_block_dynarr *
1341 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1343 prop_block_dynarr *prop = NULL;
1344 if (VECTORP (entry))
1346 struct Lisp_Vector *de = XVECTOR (entry);
1347 EMACS_INT len = vector_length (de);
1350 for (elt = 0; elt < len; elt++)
1352 if (NILP (vector_data (de)[elt]))
1355 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
1356 /* Else blow it off because someone added a bad entry and we
1357 don't have any safe way of signaling an error. Hey, this
1358 comment sounds familiar. */
1360 /* #### Still need to add any remaining elements to the
1361 propagation information. */
1367 prop = add_disp_table_entry_runes_1 (data, entry);
1371 /* Add runes which were propagated from the previous line. */
1373 static prop_block_dynarr *
1374 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1376 /* #### Remember to handle start_col parameter of data when the rest of
1377 this is finished. */
1378 /* #### Chuck -- I've redone this function a bit. It looked like the
1379 case of not all the propagation blocks being added was not handled
1381 /* #### Chuck -- I also think the double indirection of PROP is kind
1382 of bogus. A cleaner solution is just to check for
1383 Dynarr_length (prop) > 0. */
1384 /* #### This function also doesn't even pay attention to ADD_FAILED!
1385 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1388 prop_block_dynarr *add_failed;
1389 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1390 unsigned int old_cursor_type = data->cursor_type;
1392 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1394 struct prop_block *pb = Dynarr_atp (*prop, elt);
1399 data->ch = pb->data.p_char.ch;
1400 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1401 data->cursor_type = pb->data.p_char.cursor_type;
1402 add_failed = add_emchar_rune (data);
1405 goto oops_no_more_space;
1408 if (pb->data.p_string.str)
1409 xfree (pb->data.p_string.str);
1410 /* #### bogus bogus -- this doesn't do anything!
1411 Should probably call add_bufbyte_string_runes(),
1412 once that function is fixed. */
1414 case PROP_MINIBUF_PROMPT:
1416 face_index old_findex = data->findex;
1417 Bytind bi_old_bufpos = data->bi_bufpos;
1419 data->findex = DEFAULT_INDEX;
1420 data->bi_bufpos = 0;
1421 data->cursor_type = NO_CURSOR;
1423 while (pb->data.p_string.len > 0)
1425 data->ch = charptr_emchar (pb->data.p_string.str);
1426 add_failed = add_emchar_rune (data);
1430 data->findex = old_findex;
1431 data->bi_bufpos = bi_old_bufpos;
1432 goto oops_no_more_space;
1436 /* Complicated equivalent of ptr++, len-- */
1437 Bufbyte *oldpos = pb->data.p_string.str;
1438 INC_CHARPTR (pb->data.p_string.str);
1439 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1443 data->findex = old_findex;
1444 /* ##### FIXME FIXME FIXME -- Upon successful return from
1445 this function, data->bi_bufpos is automatically incremented.
1446 However, we don't want that to happen if we were adding
1447 the minibuffer prompt. */
1449 struct buffer *buf =
1450 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1451 /* #### Chuck fix this shit or I'm gonna scream! */
1452 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1453 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1455 /* #### is this correct? Does anyone know?
1456 Does anyone care? Is this a cheesy hack or what? */
1457 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1463 /* #### I think it's unnecessary and misleading to preserve
1464 the blank_width, as it implies that the value carries
1465 over from one rune to the next, which is wrong. */
1466 int old_width = data->blank_width;
1467 face_index old_findex = data->findex;
1469 data->findex = pb->data.p_blank.findex;
1470 data->blank_width = pb->data.p_blank.width;
1471 data->bi_cursor_bufpos = 0;
1472 data->cursor_type = IGNORE_CURSOR;
1474 if (data->pixpos + data->blank_width > data->max_pixpos)
1475 data->blank_width = data->max_pixpos - data->pixpos;
1477 /* We pass a bogus value of char_tab_width. It shouldn't
1478 matter because unless something is really screwed up
1479 this call won't cause that arg to be used. */
1480 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1482 /* This can happen in the case where we have a tab which
1483 is wider than the window. */
1484 if (data->blank_width != pb->data.p_blank.width)
1486 pb->data.p_blank.width -= data->blank_width;
1487 add_failed = ADD_FAILED;
1490 data->findex = old_findex;
1491 data->blank_width = old_width;
1494 goto oops_no_more_space;
1504 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1505 data->cursor_type = old_cursor_type;
1506 if (elt < Dynarr_length (*prop))
1508 Dynarr_delete_many (*prop, 0, elt);
1513 Dynarr_free (*prop);
1518 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1519 the display block, but add all other types to the appropriate list
1520 of the display line. They will be added later by different
1523 static prop_block_dynarr *
1524 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1525 int allow_cursor, struct glyph_cachel *cachel)
1527 struct window *w = XWINDOW (data->window);
1529 /* A nil extent indicates a special glyph (ex. truncator). */
1530 if (NILP (gb->extent)
1531 || (pos_type == BEGIN_GLYPHS &&
1532 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1533 || (pos_type == END_GLYPHS &&
1534 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
1539 int ascent, descent;
1540 Lisp_Object baseline;
1544 width = cachel->width;
1546 width = glyph_width (gb->glyph, Qnil, data->findex, data->window);
1551 if (data->start_col)
1553 prop_block_dynarr *retval;
1554 int glyph_char_width = width / space_width (w);
1556 /* If we still have not fully scrolled horizontally after
1557 taking into account the width of the glyph, subtract its
1558 width and return. */
1559 if (glyph_char_width < data->start_col)
1561 data->start_col -= glyph_char_width;
1564 else if (glyph_char_width == data->start_col)
1568 xoffset = space_width (w) * data->start_col;
1571 /* #### Can this happen? */
1576 data->start_col = 0;
1577 retval = add_hscroll_rune (data);
1579 /* Could be caused by the handling of the hscroll rune. */
1580 if (retval != NULL || !width)
1586 if (data->pixpos + width > data->max_pixpos)
1588 /* If this is the first object we are attempting to add to
1589 the line then we ignore the horizontal_clip threshold.
1590 Otherwise we will loop until the bottom of the window
1591 continually failing to add this glyph because it is wider
1592 than the window. We could alternatively just completely
1593 ignore the glyph and proceed from there but I think that
1594 this is a better solution. */
1595 if (Dynarr_length (data->db->runes)
1596 && data->max_pixpos - data->pixpos < horizontal_clip)
1599 width = data->max_pixpos - data->pixpos;
1604 ascent = cachel->ascent;
1605 descent = cachel->descent;
1609 ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window);
1610 descent = glyph_descent (gb->glyph, Qnil, data->findex,
1614 baseline = glyph_baseline (gb->glyph, data->window);
1616 if (glyph_contrib_p (gb->glyph, data->window))
1618 /* A pixmap that has not had a baseline explicitly set. Its
1619 contribution will be determined later. */
1620 if (NILP (baseline))
1622 int height = ascent + descent;
1623 data->max_pixmap_height = max (data->max_pixmap_height, height);
1626 /* A string so determine contribution normally. */
1627 else if (EQ (baseline, Qt))
1629 data->new_ascent = max (data->new_ascent, ascent);
1630 data->new_descent = max (data->new_descent, descent);
1633 /* A pixmap with an explicitly set baseline. We determine the
1634 contribution here. */
1635 else if (INTP (baseline))
1637 int height = ascent + descent;
1638 int pix_ascent, pix_descent;
1640 pix_ascent = height * XINT (baseline) / 100;
1641 pix_descent = height - pix_ascent;
1643 data->new_ascent = max (data->new_ascent, pix_ascent);
1644 data->new_descent = max (data->new_descent, pix_descent);
1647 /* Otherwise something is screwed up. */
1652 face = glyph_face (gb->glyph, data->window);
1654 rb.findex = data->findex;
1656 rb.findex = get_builtin_face_cache_index (w, face);
1658 rb.xpos = data->pixpos;
1660 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1661 if (data->bi_endpos)
1662 /* #### is this necessary at all? */
1663 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1667 rb.type = RUNE_DGLYPH;
1668 /* #### Ben sez: this is way bogus if the glyph is a string.
1669 You should not make the output routines have to cope with
1670 this. The string could contain Mule characters, or non-
1671 printable characters, or characters to be passed through
1672 the display table, or non-character objects (when this gets
1673 implemented), etc. Instead, this routine here should parse
1674 the string into a series of runes. */
1675 rb.object.dglyph.glyph = gb->glyph;
1676 rb.object.dglyph.extent = gb->extent;
1677 rb.object.dglyph.xoffset = xoffset;
1681 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1684 if (data->cursor_type == CURSOR_ON)
1686 if (data->bi_bufpos == data->bi_cursor_bufpos)
1688 rb.cursor_type = CURSOR_ON;
1689 data->cursor_x = Dynarr_length (data->db->runes);
1692 rb.cursor_type = CURSOR_OFF;
1694 else if (data->cursor_type == NEXT_CURSOR)
1696 rb.cursor_type = CURSOR_ON;
1697 data->cursor_x = Dynarr_length (data->db->runes);
1698 data->cursor_type = NO_CURSOR;
1700 else if (data->cursor_type == IGNORE_CURSOR)
1701 rb.cursor_type = IGNORE_CURSOR;
1702 else if (data->cursor_type == NO_CURSOR)
1703 rb.cursor_type = NO_CURSOR;
1705 rb.cursor_type = CURSOR_OFF;
1708 rb.cursor_type = CURSOR_OFF;
1710 Dynarr_add (data->db->runes, rb);
1711 data->pixpos += width;
1717 if (!NILP (glyph_face (gb->glyph, data->window)))
1719 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1722 gb->findex = data->findex;
1724 if (pos_type == BEGIN_GLYPHS)
1726 if (!data->dl->left_glyphs)
1727 data->dl->left_glyphs = Dynarr_new (glyph_block);
1728 Dynarr_add (data->dl->left_glyphs, *gb);
1731 else if (pos_type == END_GLYPHS)
1733 if (!data->dl->right_glyphs)
1734 data->dl->right_glyphs = Dynarr_new (glyph_block);
1735 Dynarr_add (data->dl->right_glyphs, *gb);
1739 abort (); /* there are no unknown types */
1742 return NULL; /* shut up compiler */
1745 /* Add all glyphs at position POS_TYPE that are contained in the given
1748 static prop_block_dynarr *
1749 add_glyph_runes (pos_data *data, int pos_type)
1751 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1752 why didn't you just modify add_glyph_rune in the first place? */
1754 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1755 ? data->ef->begin_glyphs
1756 : data->ef->end_glyphs);
1757 prop_block_dynarr *prop;
1759 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1761 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1766 /* #### Add some propagation information. */
1771 Dynarr_reset (glyph_arr);
1776 /* Given a position for a buffer in a window, ensure that the given
1777 display line DL accurately represents the text on a line starting
1778 at the given position.
1780 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1781 You must do appropriate conversion. */
1784 create_text_block (struct window *w, struct display_line *dl,
1785 Bytind bi_start_pos, int start_col,
1786 prop_block_dynarr **prop,
1789 struct frame *f = XFRAME (w->frame);
1790 struct buffer *b = XBUFFER (w->buffer);
1791 struct device *d = XDEVICE (f->device);
1795 /* Don't display anything in the minibuffer if this window is not on
1796 a selected frame. We consider all other windows to be active
1797 minibuffers as it simplifies the coding. */
1798 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1799 (f == device_selected_frame (d)) ||
1800 is_surrogate_for_selected_frame (f));
1802 int truncate_win = window_truncation_on (w);
1803 int end_glyph_width;
1805 /* If the buffer's value of selective_display is an integer then
1806 only lines that start with less than selective_display columns of
1807 space will be displayed. If selective_display is t then all text
1808 after a ^M is invisible. */
1809 int selective = (INTP (b->selective_display)
1810 ? XINT (b->selective_display)
1811 : ((!NILP (b->selective_display) ? -1 : 0)));
1813 /* The variable ctl-arrow allows the user to specify what characters
1814 can actually be displayed and which octal should be used for.
1815 #### This variable should probably have some rethought done to
1818 #### It would also be really nice if you could specify that
1819 the characters come out in hex instead of in octal. Mule
1820 does that by adding a ctl-hexa variable similar to ctl-arrow,
1821 but that's bogus -- we need a more general solution. I
1822 think you need to extend the concept of display tables
1823 into a more general conversion mechanism. Ideally you
1824 could specify a Lisp function that converts characters,
1825 but this violates the Second Golden Rule and besides would
1826 make things way way way way slow.
1828 So instead, we extend the display-table concept, which was
1829 historically limited to 256-byte vectors, to one of the
1832 a) A 256-entry vector, for backward compatibility;
1833 b) char-table, mapping characters to values;
1834 c) range-table, mapping ranges of characters to values;
1835 d) a list of the above.
1837 The (d) option allows you to specify multiple display tables
1838 instead of just one. Each display table can specify conversions
1839 for some characters and leave others unchanged. The way the
1840 character gets displayed is determined by the first display table
1841 with a binding for that character. This way, you could call a
1842 function `enable-hex-display' that adds a hex display-table to
1843 the list of display tables for the current buffer.
1845 #### ...not yet implemented... Also, we extend the concept of
1846 "mapping" to include a printf-like spec. Thus you can make all
1847 extended characters show up as hex with a display table like
1850 #s(range-table data ((256 524288) (format "%x")))
1852 Since more than one display table is possible, you have
1853 great flexibility in mapping ranges of characters. */
1854 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1855 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1856 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1859 Lisp_Object face_dt, window_dt;
1861 /* The text display block for this display line. */
1862 struct display_block *db = get_display_block_from_line (dl, TEXT);
1864 /* The first time through the main loop we need to force the glyph
1865 data to be updated. */
1868 /* Apparently the new extent_fragment_update returns an end position
1869 equal to the position passed in if there are no more runs to be
1871 int no_more_frags = 0;
1873 Lisp_Object synch_minibuffers_value =
1874 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1876 dl->used_prop_data = 0;
1880 data.ef = extent_fragment_new (w->buffer, f);
1882 /* These values are used by all of the rune addition routines. We add
1883 them to this structure for ease of passing. */
1885 XSETWINDOW (data.window, w);
1890 data.bi_bufpos = bi_start_pos;
1891 data.pixpos = dl->bounds.left_in;
1892 data.last_charset = Qunbound;
1893 data.last_findex = DEFAULT_INDEX;
1894 data.result_str = Qnil;
1896 /* Set the right boundary adjusting it to take into account any end
1897 glyph. Save the width of the end glyph for later use. */
1898 data.max_pixpos = dl->bounds.right_in;
1900 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1902 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1903 data.max_pixpos -= end_glyph_width;
1905 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1907 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1908 data.cursor_type = CURSOR_ON;
1910 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1911 data.cursor_type = NO_CURSOR;
1912 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1913 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1914 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1915 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1917 data.bi_cursor_bufpos = BI_BUF_PT (b);
1918 data.cursor_type = CURSOR_ON;
1920 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1922 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1923 data.cursor_type = CURSOR_ON;
1926 data.cursor_type = NO_CURSOR;
1929 data.start_col = w->hscroll;
1930 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1931 data.hscroll_glyph_width_adjust = 0;
1933 /* We regenerate the line from the very beginning. */
1934 Dynarr_reset (db->runes);
1936 /* Why is this less than or equal and not just less than? If the
1937 starting position is already equal to the maximum we can't add
1938 anything else, right? Wrong. We might still have a newline to
1939 add. A newline can use the room allocated for an end glyph since
1940 if we add it we know we aren't going to be adding any end
1943 /* #### Chuck -- I think this condition should be while (1).
1944 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1945 and the begin-glyph ends exactly at the end of the window, the
1946 end-glyph and text might not be displayed. while (1) ensures
1947 that the loop terminates only when either (a) there is
1948 propagation data or (b) the end-of-line or end-of-buffer is hit.
1950 #### Also I think you need to ensure that the operation
1951 "add begin glyphs; add end glyphs; add text" is atomic and
1952 can't get interrupted in the middle. If you run off the end
1953 of the line during that operation, then you keep accumulating
1954 propagation data until you're done. Otherwise, if the (e.g.)
1955 there's a begin glyph at a particular position and attempting
1956 to display that glyph results in window-end being hit and
1957 propagation data being generated, then the character at that
1958 position won't be displayed.
1960 #### See also the comment after the end of this loop, below.
1962 while (data.pixpos <= data.max_pixpos
1963 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1965 /* #### This check probably should not be necessary. */
1966 if (data.bi_bufpos > BI_BUF_ZV (b))
1968 /* #### urk! More of this lossage! */
1973 /* If selective display was an integer and we aren't working on
1974 a continuation line then find the next line we are actually
1975 supposed to display. */
1977 && (data.bi_bufpos == BI_BUF_BEGV (b)
1978 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
1980 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
1983 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
1984 if (data.bi_bufpos >= BI_BUF_ZV (b))
1986 data.bi_bufpos = BI_BUF_ZV (b);
1992 /* Check for face changes. */
1993 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
1995 /* Now compute the face and begin/end-glyph information. */
1997 /* Remember that the extent-fragment routines deal in Bytind's. */
1998 extent_fragment_update (w, data.ef, data.bi_bufpos);
2000 get_display_tables (w, data.findex, &face_dt, &window_dt);
2002 if (data.bi_bufpos == data.ef->end)
2007 /* Determine what is next to be displayed. We first handle any
2008 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2009 display then we determine what to do based on the character at the
2010 current buffer position. */
2012 /* If the current position is covered by an invisible extent, do
2013 nothing (except maybe add some ellipses).
2015 #### The behavior of begin and end-glyphs at the edge of an
2016 invisible extent should be investigated further. This is
2017 fairly low priority though. */
2018 if (data.ef->invisible)
2020 /* #### Chuck, perhaps you could look at this code? I don't
2021 really know what I'm doing. */
2024 Dynarr_free (*prop);
2028 /* The extent fragment code only sets this when we should
2029 really display the ellipses. It makes sure the ellipses
2030 don't get displayed more than once in a row. */
2031 if (data.ef->invisible_ellipses)
2033 struct glyph_block gb;
2035 data.ef->invisible_ellipses_already_displayed = 1;
2036 data.ef->invisible_ellipses = 0;
2038 gb.glyph = Vinvisible_text_glyph;
2039 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2040 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2041 /* Perhaps they shouldn't propagate if the very next thing
2042 is to display a newline (for compatibility with
2043 selective-display-ellipses)? Maybe that's too
2049 /* If point is in an invisible region we place it on the
2050 next visible character. */
2051 if (data.cursor_type == CURSOR_ON
2052 && data.bi_bufpos == data.bi_cursor_bufpos)
2054 data.cursor_type = NEXT_CURSOR;
2057 /* #### What if we we're dealing with a display table? */
2061 if (data.bi_bufpos == BI_BUF_ZV (b))
2064 INC_BYTIND (b, data.bi_bufpos);
2067 /* If there is propagation data, then it represents the current
2068 buffer position being displayed. Add them and advance the
2069 position counter. This might also add the minibuffer
2073 dl->used_prop_data = 1;
2074 *prop = add_propagation_runes (prop, &data);
2077 goto done; /* gee, a really narrow window */
2078 else if (data.bi_bufpos == BI_BUF_ZV (b))
2080 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2081 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2082 data.bi_bufpos = BI_BUF_BEGV (b);
2084 INC_BYTIND (b, data.bi_bufpos);
2087 /* If there are end glyphs, add them to the line. These are
2088 the end glyphs for the previous run of text. We add them
2089 here rather than doing them at the end of handling the
2090 previous run so that glyphs at the beginning and end of
2091 a line are handled correctly. */
2092 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2094 *prop = add_glyph_runes (&data, END_GLYPHS);
2099 /* If there are begin glyphs, add them to the line. */
2100 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2102 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2107 /* If at end-of-buffer, we've already processed begin and
2108 end-glyphs at this point and there's no text to process,
2110 else if (data.bi_bufpos == BI_BUF_ZV (b))
2115 Lisp_Object entry = Qnil;
2116 /* Get the character at the current buffer position. */
2117 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2118 if (!NILP (face_dt) || !NILP (window_dt))
2119 entry = display_table_entry (data.ch, face_dt, window_dt);
2121 /* If there is a display table entry for it, hand it off to
2122 add_disp_table_entry_runes and let it worry about it. */
2123 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
2125 *prop = add_disp_table_entry_runes (&data, entry);
2131 /* Check if we have hit a newline character. If so, add a marker
2132 to the line and end this loop. */
2133 else if (data.ch == '\n')
2135 /* We aren't going to be adding an end glyph so give its
2136 space back in order to make sure that the cursor can
2138 data.max_pixpos += end_glyph_width;
2141 && (bi_spaces_at_point
2142 (b, next_bytind (b, data.bi_bufpos))
2145 if (!NILP (b->selective_display_ellipses))
2147 struct glyph_block gb;
2150 gb.glyph = Vinvisible_text_glyph;
2151 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2152 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2156 /* Cheesy, cheesy, cheesy. We mark the end of the
2157 line with a special "character rune" whose width
2158 is the EOL cursor width and whose character is
2159 the non-printing character '\n'. */
2160 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2161 *prop = add_emchar_rune (&data);
2164 /* We need to set data.bi_bufpos to the start of the
2165 next visible region in order to make this line
2166 appear to contain all of the invisible area.
2167 Otherwise, the line cache won't work
2169 INC_BYTIND (b, data.bi_bufpos);
2170 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2173 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2174 if (data.bi_bufpos >= BI_BUF_ZV (b))
2176 data.bi_bufpos = BI_BUF_ZV (b);
2180 if (BI_BUF_FETCH_CHAR
2181 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2182 DEC_BYTIND (b, data.bi_bufpos);
2186 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2187 *prop = add_emchar_rune (&data);
2193 /* If the current character is ^M, and selective display is
2194 enabled, then add the invisible-text-glyph if
2195 selective-display-ellipses is set. In any case, this
2197 else if (data.ch == (('M' & 037)) && selective == -1)
2199 Bytind bi_next_bufpos;
2201 /* Find the buffer position at the end of the line. */
2203 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2204 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2206 DEC_BYTIND (b, bi_next_bufpos);
2208 /* If the cursor is somewhere in the elided text make
2209 sure that the cursor gets drawn appropriately. */
2210 if (data.cursor_type == CURSOR_ON
2211 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2212 data.bi_cursor_bufpos < bi_next_bufpos))
2214 data.cursor_type = NEXT_CURSOR;
2217 /* We won't be adding a truncation or continuation glyph
2218 so give up the room allocated for them. */
2219 data.max_pixpos += end_glyph_width;
2221 if (!NILP (b->selective_display_ellipses))
2223 /* We don't propagate anything from the invisible
2224 text glyph if it fails to fit. This is
2226 struct glyph_block gb;
2229 gb.glyph = Vinvisible_text_glyph;
2230 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2231 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2234 /* Set the buffer position to the end of the line. We
2235 need to do this before potentially adding a newline
2236 so that the cursor flag will get set correctly (if
2238 data.bi_bufpos = bi_next_bufpos;
2240 if (NILP (b->selective_display_ellipses)
2241 || data.bi_cursor_bufpos == bi_next_bufpos)
2243 /* We have to at least add a newline character so
2244 that the cursor shows up properly. */
2246 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2247 data.findex = DEFAULT_INDEX;
2249 data.bi_start_col_enabled = 0;
2251 add_emchar_rune (&data);
2254 /* This had better be a newline but doing it this way
2255 we'll see obvious incorrect results if it isn't. No
2256 need to abort here. */
2257 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2262 /* If the current character is considered to be printable, then
2264 else if (data.ch >= printable_min)
2266 *prop = add_emchar_rune (&data);
2271 /* If the current character is a tab, determine the next tab
2272 starting position and add a blank rune which extends from the
2273 current pixel position to that starting position. */
2274 else if (data.ch == '\t')
2276 int tab_start_pixpos = data.pixpos;
2281 if (data.start_col > 1)
2282 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
2285 next_tab_position (w, tab_start_pixpos,
2286 dl->bounds.left_in +
2287 data.hscroll_glyph_width_adjust);
2288 if (next_tab_start > data.max_pixpos)
2290 prop_width = next_tab_start - data.max_pixpos;
2291 next_tab_start = data.max_pixpos;
2293 data.blank_width = next_tab_start - data.pixpos;
2295 (next_tab_start - tab_start_pixpos) / space_width (w);
2297 *prop = add_blank_rune (&data, w, char_tab_width);
2299 /* add_blank_rune is only supposed to be called with
2300 sizes guaranteed to fit in the available space. */
2305 struct prop_block pb;
2306 *prop = Dynarr_new (prop_block);
2308 pb.type = PROP_BLANK;
2309 pb.data.p_blank.width = prop_width;
2310 pb.data.p_blank.findex = data.findex;
2311 Dynarr_add (*prop, pb);
2317 /* If character is a control character, pass it off to
2318 add_control_char_runes.
2320 The is_*() routines have undefined results on
2321 arguments outside of the range [-1, 255]. (This
2322 often bites people who carelessly use `char' instead
2323 of `unsigned char'.)
2325 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2327 *prop = add_control_char_runes (&data, b);
2333 /* If the character is above the ASCII range and we have not
2334 already handled it, then print it as an octal number. */
2335 else if (data.ch >= 0200)
2337 *prop = add_octal_runes (&data);
2343 /* Assume the current character is considered to be printable,
2344 then just add it. */
2347 *prop = add_emchar_rune (&data);
2352 INC_BYTIND (b, data.bi_bufpos);
2358 /* Determine the starting point of the next line if we did not hit the
2359 end of the buffer. */
2360 if (data.bi_bufpos < BI_BUF_ZV (b)
2361 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2363 /* #### This check is not correct. If the line terminated
2364 due to a begin-glyph or end-glyph hitting window-end, then
2365 data.ch will not point to the character at data.bi_bufpos. If
2366 you make the two changes mentioned at the top of this loop,
2367 you should be able to say '(if (*prop))'. That should also
2368 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2371 /* The common case is that the line ended because we hit a newline.
2372 In that case, the next character is just the next buffer
2374 if (data.ch == '\n')
2376 /* If data.start_col_enabled is still true, then the window is
2377 scrolled far enough so that nothing on this line is visible.
2378 We need to stick a truncation glyph at the beginning of the
2379 line in that case unless the line is completely blank. */
2380 if (data.bi_start_col_enabled)
2382 if (data.cursor_type == CURSOR_ON)
2384 if (data.bi_cursor_bufpos >= bi_start_pos
2385 && data.bi_cursor_bufpos <= data.bi_bufpos)
2386 data.bi_cursor_bufpos = data.bi_bufpos;
2388 data.findex = DEFAULT_INDEX;
2390 data.bi_start_col_enabled = 0;
2392 if (data.bi_bufpos != bi_start_pos)
2394 struct glyph_block gb;
2397 gb.glyph = Vhscroll_glyph;
2398 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2399 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2403 /* This duplicates code down below to add a newline to
2404 the end of an otherwise empty line.*/
2406 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2408 add_emchar_rune (&data);
2412 INC_BYTIND (b, data.bi_bufpos);
2415 /* Otherwise we have a buffer line which cannot fit on one display
2419 struct glyph_block gb;
2420 struct glyph_cachel *cachel;
2422 /* If the line is to be truncated then we actually have to look
2423 for the next newline. We also add the end-of-line glyph which
2424 we know will fit because we adjusted the right border before
2425 we starting laying out the line. */
2426 data.max_pixpos += end_glyph_width;
2427 data.findex = DEFAULT_INDEX;
2434 /* Now find the start of the next line. */
2435 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2437 /* If the cursor is past the truncation line then we
2438 make it appear on the truncation glyph. If we've hit
2439 the end of the buffer then we also make the cursor
2440 appear unless eob is immediately preceded by a
2441 newline. In that case the cursor should actually
2442 appear on the next line. */
2443 if (data.cursor_type == CURSOR_ON
2444 && data.bi_cursor_bufpos >= data.bi_bufpos
2445 && (data.bi_cursor_bufpos < bi_pos ||
2446 (bi_pos == BI_BUF_ZV (b)
2447 && (bi_pos == BI_BUF_BEGV (b)
2448 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2450 data.bi_cursor_bufpos = bi_pos;
2452 data.cursor_type = NO_CURSOR;
2454 data.bi_bufpos = bi_pos;
2455 gb.glyph = Vtruncation_glyph;
2456 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2460 /* The cursor can never be on the continuation glyph. */
2461 data.cursor_type = NO_CURSOR;
2463 /* data.bi_bufpos is already at the start of the next line. */
2465 gb.glyph = Vcontinuation_glyph;
2466 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2469 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
2471 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2472 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2473 /* #### Damn this losing shit. */
2477 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2478 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2480 /* We need to add a marker to the end of the line since there is no
2481 newline character in order for the cursor to get drawn. We label
2482 it as a newline so that it gets handled correctly by the
2483 whitespace routines below. */
2486 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2487 data.findex = DEFAULT_INDEX;
2489 data.bi_start_col_enabled = 0;
2491 data.max_pixpos += data.blank_width;
2492 add_emchar_rune (&data);
2493 data.max_pixpos -= data.blank_width;
2495 /* #### urk! Chuck, this shit is bad news. Going around
2496 manipulating invalid positions is guaranteed to result in
2497 trouble sooner or later. */
2498 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2501 /* Calculate left whitespace boundary. */
2505 /* Whitespace past a newline is considered right whitespace. */
2506 while (elt < Dynarr_length (db->runes))
2508 struct rune *rb = Dynarr_atp (db->runes, elt);
2510 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2511 || rb->type == RUNE_BLANK)
2513 dl->bounds.left_white += rb->width;
2517 elt = Dynarr_length (db->runes);
2521 /* Calculate right whitespace boundary. */
2523 int elt = Dynarr_length (db->runes) - 1;
2526 while (!done && elt >= 0)
2528 struct rune *rb = Dynarr_atp (db->runes, elt);
2530 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2531 && isspace (rb->object.chr.ch))
2532 && !rb->type == RUNE_BLANK)
2534 dl->bounds.right_white = rb->xpos + rb->width;
2542 /* The line is blank so everything is considered to be right
2545 dl->bounds.right_white = dl->bounds.left_in;
2548 /* Set the display blocks bounds. */
2549 db->start_pos = dl->bounds.left_in;
2550 if (Dynarr_length (db->runes))
2552 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2554 db->end_pos = rb->xpos + rb->width;
2557 db->end_pos = dl->bounds.right_white;
2559 /* update line height parameters */
2560 if (!data.new_ascent && !data.new_descent)
2562 /* We've got a blank line so initialize these values from the default
2564 default_face_font_info (data.window, &data.new_ascent,
2565 &data.new_descent, 0, 0, 0);
2568 if (data.max_pixmap_height)
2570 int height = data.new_ascent + data.new_descent;
2571 int pix_ascent, pix_descent;
2573 pix_descent = data.max_pixmap_height * data.new_descent / height;
2574 pix_ascent = data.max_pixmap_height - pix_descent;
2576 data.new_ascent = max (data.new_ascent, pix_ascent);
2577 data.new_descent = max (data.new_descent, pix_descent);
2580 dl->ascent = data.new_ascent;
2581 dl->descent = data.new_descent;
2584 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2586 if (dl->ascent < ascent)
2587 dl->ascent = ascent;
2590 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2592 if (dl->descent < descent)
2593 dl->descent = descent;
2596 dl->cursor_elt = data.cursor_x;
2597 /* #### lossage lossage lossage! Fix this shit! */
2598 if (data.bi_bufpos > BI_BUF_ZV (b))
2599 dl->end_bufpos = BUF_ZV (b);
2601 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2603 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2605 /* This doesn't correctly take into account tabs and control
2606 characters but if the window isn't being truncated then this
2607 value isn't going to end up being used anyhow. */
2608 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2610 /* #### handle horizontally scrolled line with text none of which
2611 was actually laid out. */
2613 /* #### handle any remainder of overlay arrow */
2615 if (*prop == ADD_FAILED)
2618 if (truncate_win && *prop)
2620 Dynarr_free (*prop);
2624 extent_fragment_delete (data.ef);
2626 /* #### If we started at EOB, then make sure we return a value past
2627 it so that regenerate_window will exit properly. This is bogus.
2628 The main loop should get fixed so that it isn't necessary to call
2629 this function if we are already at EOB. */
2631 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2632 return data.bi_bufpos + 1; /* Yuck! */
2634 return data.bi_bufpos;
2637 /* Display the overlay arrow at the beginning of the given line. */
2640 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2642 struct frame *f = XFRAME (w->frame);
2643 struct device *d = XDEVICE (f->device);
2646 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2647 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2653 XSETWINDOW (data.window, w);
2654 data.db = get_display_block_from_line (dl, OVERWRITE);
2656 data.pixpos = dl->bounds.left_in;
2657 data.max_pixpos = dl->bounds.right_in;
2658 data.cursor_type = NO_CURSOR;
2660 data.findex = DEFAULT_INDEX;
2661 data.last_charset = Qunbound;
2662 data.last_findex = DEFAULT_INDEX;
2663 data.result_str = Qnil;
2666 Dynarr_reset (data.db->runes);
2668 if (STRINGP (Voverlay_arrow_string))
2670 add_bufbyte_string_runes
2672 XSTRING_DATA (Voverlay_arrow_string),
2673 XSTRING_LENGTH (Voverlay_arrow_string),
2676 else if (GLYPHP (Voverlay_arrow_string))
2678 struct glyph_block gb;
2680 gb.glyph = Voverlay_arrow_string;
2682 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2685 if (data.max_pixmap_height)
2687 int height = data.new_ascent + data.new_descent;
2688 int pix_ascent, pix_descent;
2690 pix_descent = data.max_pixmap_height * data.new_descent / height;
2691 pix_ascent = data.max_pixmap_height - pix_descent;
2693 data.new_ascent = max (data.new_ascent, pix_ascent);
2694 data.new_descent = max (data.new_descent, pix_descent);
2697 dl->ascent = data.new_ascent;
2698 dl->descent = data.new_descent;
2700 data.db->start_pos = dl->bounds.left_in;
2701 data.db->end_pos = data.pixpos;
2703 return data.pixpos - dl->bounds.left_in;
2706 /* Add a type of glyph to a margin display block. */
2709 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2710 int count, enum glyph_layout layout, int side, Lisp_Object window)
2712 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2714 : dl->right_glyphs);
2719 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2720 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2723 elt = Dynarr_length (gbd) - 1;
2730 end = Dynarr_length (gbd);
2733 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2735 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2737 if (NILP (gb->extent))
2738 abort (); /* these should have been handled in add_glyph_rune */
2741 ((side == LEFT_GLYPHS &&
2742 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2743 || (side == RIGHT_GLYPHS &&
2744 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2748 rb.width = gb->width;
2749 rb.findex = gb->findex;
2753 rb.type = RUNE_DGLYPH;
2754 rb.object.dglyph.glyph = gb->glyph;
2755 rb.object.dglyph.extent = gb->extent;
2756 rb.object.dglyph.xoffset = 0;
2757 rb.cursor_type = CURSOR_OFF;
2759 Dynarr_add (db->runes, rb);
2764 if (glyph_contrib_p (gb->glyph, window))
2766 unsigned short ascent, descent;
2767 Lisp_Object baseline = glyph_baseline (gb->glyph, window);
2769 ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window);
2770 descent = glyph_descent (gb->glyph, Qnil, gb->findex, window);
2772 /* A pixmap that has not had a baseline explicitly set.
2773 We use the existing ascent / descent ratio of the
2775 if (NILP (baseline))
2777 int gheight = ascent + descent;
2778 int line_height = dl->ascent + dl->descent;
2779 int pix_ascent, pix_descent;
2781 pix_descent = (int) (gheight * dl->descent) / line_height;
2782 pix_ascent = gheight - pix_descent;
2784 dl->ascent = max ((int) dl->ascent, pix_ascent);
2785 dl->descent = max ((int) dl->descent, pix_descent);
2788 /* A string so determine contribution normally. */
2789 else if (EQ (baseline, Qt))
2791 dl->ascent = max (dl->ascent, ascent);
2792 dl->descent = max (dl->descent, descent);
2795 /* A pixmap with an explicitly set baseline. We determine the
2796 contribution here. */
2797 else if (INTP (baseline))
2799 int height = ascent + descent;
2800 int pix_ascent, pix_descent;
2802 pix_ascent = height * XINT (baseline) / 100;
2803 pix_descent = height - pix_ascent;
2805 dl->ascent = max ((int) dl->ascent, pix_ascent);
2806 dl->descent = max ((int) dl->descent, pix_descent);
2809 /* Otherwise something is screwed up. */
2815 (reverse ? elt-- : elt++);
2821 /* Add a blank to a margin display block. */
2824 add_margin_blank (struct display_line *dl, struct display_block *db,
2825 struct window *w, int xpos, int width, int side)
2829 rb.findex = (side == LEFT_GLYPHS
2830 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2831 : get_builtin_face_cache_index (w, Vright_margin_face));
2836 rb.type = RUNE_BLANK;
2837 rb.cursor_type = CURSOR_OFF;
2839 Dynarr_add (db->runes, rb);
2842 /* Display glyphs in the left outside margin, left inside margin and
2843 left whitespace area. */
2846 create_left_glyph_block (struct window *w, struct display_line *dl,
2851 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2853 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2854 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2855 int left_in_start = dl->bounds.left_in;
2856 int left_in_end = dl->bounds.left_in + overlay_width;
2858 struct display_block *odb, *idb;
2860 XSETWINDOW (window, w);
2862 /* We have to add the glyphs to the line in the order outside,
2863 inside, whitespace. However the precedence dictates that we
2864 determine how many will fit in the reverse order. */
2866 /* Determine how many whitespace glyphs we can display and where
2867 they should start. */
2868 white_in_start = dl->bounds.left_white;
2869 white_out_start = left_in_start;
2870 white_out_cnt = white_in_cnt = 0;
2873 while (elt < Dynarr_length (dl->left_glyphs))
2875 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2877 if (NILP (gb->extent))
2878 abort (); /* these should have been handled in add_glyph_rune */
2880 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2884 width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2886 if (white_in_start - width >= left_in_end)
2889 white_in_start -= width;
2893 else if (use_overflow
2894 && (white_out_start - width > dl->bounds.left_out))
2897 white_out_start -= width;
2908 /* Determine how many inside margin glyphs we can display and where
2909 they should start. The inside margin glyphs get whatever space
2910 is left after the whitespace glyphs have been displayed. These
2911 are tricky to calculate since if we decide to use the overflow
2912 area we basically have to start over. So for these we build up a
2913 list of just the inside margin glyphs and manipulate it to
2914 determine the needed info. */
2916 glyph_block_dynarr *ib;
2917 int avail_in, avail_out;
2920 int used_in, used_out;
2923 used_in = used_out = 0;
2924 ib = Dynarr_new (glyph_block);
2925 while (elt < Dynarr_length (dl->left_glyphs))
2927 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2929 if (NILP (gb->extent))
2930 abort (); /* these should have been handled in add_glyph_rune */
2932 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2935 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2936 used_in += gb->width;
2937 Dynarr_add (ib, *gb);
2947 avail_in = white_in_start - left_in_end;
2955 avail_out = white_out_start - dl->bounds.left_out;
2958 while (!done && marker < Dynarr_length (ib))
2960 int width = Dynarr_atp (ib, marker)->width;
2962 /* If everything now fits in the available inside margin
2963 space, we're done. */
2964 if (used_in <= avail_in)
2968 /* Otherwise see if we have room to move a glyph to the
2970 if (used_out + width <= avail_out)
2983 /* At this point we now know that everything from marker on goes in
2984 the inside margin and everything before it goes in the outside
2985 margin. The stuff going into the outside margin is guaranteed
2986 to fit, but we may have to trim some stuff from the inside. */
2988 in_in_end = left_in_end;
2989 in_out_start = white_out_start;
2990 in_out_cnt = in_in_cnt = 0;
2994 while (elt < Dynarr_length (dl->left_glyphs))
2996 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2998 if (NILP (gb->extent))
2999 abort (); /* these should have been handled in add_glyph_rune */
3001 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3004 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3009 in_out_start -= width;
3014 else if (in_in_end + width < white_in_start)
3029 /* Determine how many outside margin glyphs we can display. They
3030 always start at the left outside margin and can only use the
3031 outside margin space. */
3032 out_end = dl->bounds.left_out;
3036 while (elt < Dynarr_length (dl->left_glyphs))
3038 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3040 if (NILP (gb->extent))
3041 abort (); /* these should have been handled in add_glyph_rune */
3043 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3046 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3048 if (out_end + width <= in_out_start)
3062 /* Now that we know where everything goes, we add the glyphs as
3063 runes to the appropriate display blocks. */
3064 if (out_cnt || in_out_cnt || white_out_cnt)
3066 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3067 odb->start_pos = dl->bounds.left_out;
3068 /* #### We should stop adding a blank to account for the space
3069 between the end of the glyphs and the margin and instead set
3070 this accordingly. */
3071 odb->end_pos = dl->bounds.left_in;
3072 Dynarr_reset (odb->runes);
3077 if (in_in_cnt || white_in_cnt)
3079 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3080 idb->start_pos = dl->bounds.left_in;
3081 /* #### See above comment for odb->end_pos */
3082 idb->end_pos = dl->bounds.left_white;
3083 Dynarr_reset (idb->runes);
3088 /* First add the outside margin glyphs. */
3090 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3091 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3093 end_xpos = dl->bounds.left_out;
3095 /* There may be blank space between the outside margin glyphs and
3096 the inside margin glyphs. If so, add a blank. */
3097 if (in_out_cnt && (in_out_start - end_xpos))
3099 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3103 /* Next add the inside margin glyphs which are actually in the
3107 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3108 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3111 /* If we didn't add any inside margin glyphs to the outside margin,
3112 but are adding whitespace glyphs, then we need to add a blank
3114 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3116 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3120 /* Next add the whitespace margin glyphs which are actually in the
3124 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3125 GL_WHITESPACE, LEFT_GLYPHS, window);
3128 /* We take care of clearing between the end of the glyphs and the
3129 start of the inside margin for lines which have glyphs. */
3130 if (odb && (left_in_start - end_xpos))
3132 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3136 /* Next add the inside margin glyphs which are actually in the
3140 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3141 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3144 end_xpos = left_in_end;
3146 /* Make sure that the area between the end of the inside margin
3147 glyphs and the whitespace glyphs is cleared. */
3148 if (idb && (white_in_start - end_xpos > 0))
3150 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3154 /* Next add the whitespace margin glyphs which are actually in the
3158 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3159 LEFT_GLYPHS, window);
3162 /* Whitespace glyphs always end right next to the text block so
3163 there is nothing we have to make sure is cleared after them. */
3166 /* Display glyphs in the right outside margin, right inside margin and
3167 right whitespace area. */
3170 create_right_glyph_block (struct window *w, struct display_line *dl)
3174 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3176 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3177 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3179 struct display_block *odb, *idb;
3181 XSETWINDOW (window, w);
3183 /* We have to add the glyphs to the line in the order outside,
3184 inside, whitespace. However the precedence dictates that we
3185 determine how many will fit in the reverse order. */
3187 /* Determine how many whitespace glyphs we can display and where
3188 they should start. */
3189 white_in_end = dl->bounds.right_white;
3190 white_out_end = dl->bounds.right_in;
3191 white_out_cnt = white_in_cnt = 0;
3194 while (elt < Dynarr_length (dl->right_glyphs))
3196 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3198 if (NILP (gb->extent))
3199 abort (); /* these should have been handled in add_glyph_rune */
3201 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3203 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3205 if (white_in_end + width <= dl->bounds.right_in)
3208 white_in_end += width;
3212 else if (use_overflow
3213 && (white_out_end + width <= dl->bounds.right_out))
3216 white_out_end += width;
3227 /* Determine how many inside margin glyphs we can display and where
3228 they should start. The inside margin glyphs get whatever space
3229 is left after the whitespace glyphs have been displayed. These
3230 are tricky to calculate since if we decide to use the overflow
3231 area we basically have to start over. So for these we build up a
3232 list of just the inside margin glyphs and manipulate it to
3233 determine the needed info. */
3235 glyph_block_dynarr *ib;
3236 int avail_in, avail_out;
3239 int used_in, used_out;
3242 used_in = used_out = 0;
3243 ib = Dynarr_new (glyph_block);
3244 while (elt < Dynarr_length (dl->right_glyphs))
3246 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3248 if (NILP (gb->extent))
3249 abort (); /* these should have been handled in add_glyph_rune */
3251 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3253 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3254 used_in += gb->width;
3255 Dynarr_add (ib, *gb);
3264 avail_in = dl->bounds.right_in - white_in_end;
3269 avail_out = dl->bounds.right_out - white_out_end;
3272 while (!done && marker < Dynarr_length (ib))
3274 int width = Dynarr_atp (ib, marker)->width;
3276 /* If everything now fits in the available inside margin
3277 space, we're done. */
3278 if (used_in <= avail_in)
3282 /* Otherwise see if we have room to move a glyph to the
3284 if (used_out + width <= avail_out)
3297 /* At this point we now know that everything from marker on goes in
3298 the inside margin and everything before it goes in the outside
3299 margin. The stuff going into the outside margin is guaranteed
3300 to fit, but we may have to trim some stuff from the inside. */
3302 in_in_start = dl->bounds.right_in;
3303 in_out_end = dl->bounds.right_in;
3304 in_out_cnt = in_in_cnt = 0;
3308 while (elt < Dynarr_length (dl->right_glyphs))
3310 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3312 if (NILP (gb->extent))
3313 abort (); /* these should have been handled in add_glyph_rune */
3315 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3317 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3322 in_out_end += width;
3327 else if (in_in_start - width >= white_in_end)
3330 in_in_start -= width;
3342 /* Determine how many outside margin glyphs we can display. They
3343 always start at the right outside margin and can only use the
3344 outside margin space. */
3345 out_start = dl->bounds.right_out;
3349 while (elt < Dynarr_length (dl->right_glyphs))
3351 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3353 if (NILP (gb->extent))
3354 abort (); /* these should have been handled in add_glyph_rune */
3356 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3358 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3360 if (out_start - width >= in_out_end)
3374 /* Now that we now where everything goes, we add the glyphs as runes
3375 to the appropriate display blocks. */
3376 if (out_cnt || in_out_cnt || white_out_cnt)
3378 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3379 /* #### See comments before odb->start_pos init in
3380 create_left_glyph_block */
3381 odb->start_pos = dl->bounds.right_in;
3382 odb->end_pos = dl->bounds.right_out;
3383 Dynarr_reset (odb->runes);
3388 if (in_in_cnt || white_in_cnt)
3390 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3391 idb->start_pos = dl->bounds.right_white;
3392 /* #### See comments before odb->start_pos init in
3393 create_left_glyph_block */
3394 idb->end_pos = dl->bounds.right_in;
3395 Dynarr_reset (idb->runes);
3400 /* First add the whitespace margin glyphs which are actually in the
3404 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3405 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3409 end_xpos = dl->bounds.right_white;
3411 /* Make sure that the area between the end of the whitespace glyphs
3412 and the inside margin glyphs is cleared. */
3413 if (in_in_cnt && (in_in_start - end_xpos))
3415 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3419 /* Next add the inside margin glyphs which are actually in the
3423 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3424 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3427 /* If we didn't add any inside margin glyphs then make sure the rest
3428 of the inside margin area gets cleared. */
3429 if (idb && (dl->bounds.right_in - end_xpos))
3431 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3435 /* Next add any whitespace glyphs in the outside margin. */
3438 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3439 GL_WHITESPACE, RIGHT_GLYPHS, window);
3442 end_xpos = dl->bounds.right_in;
3444 /* Next add any inside margin glyphs in the outside margin. */
3447 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3448 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3451 /* There may be space between any whitespace or inside margin glyphs
3452 in the outside margin and the actual outside margin glyphs. */
3453 if (odb && (out_start - end_xpos))
3455 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3459 /* Finally, add the outside margin glyphs. */
3462 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3463 RIGHT_GLYPHS, window);
3468 /***************************************************************************/
3470 /* modeline routines */
3472 /***************************************************************************/
3474 /* Ensure that the given display line DL accurately represents the
3475 modeline for the given window. */
3478 generate_modeline (struct window *w, struct display_line *dl, int type)
3480 struct buffer *b = XBUFFER (w->buffer);
3481 struct frame *f = XFRAME (w->frame);
3482 struct device *d = XDEVICE (f->device);
3484 /* Unlike display line and rune pointers, this one can't change underneath
3486 struct display_block *db = get_display_block_from_line (dl, TEXT);
3487 int max_pixpos, min_pixpos, ypos_adj;
3488 Lisp_Object font_inst;
3490 /* This will actually determine incorrect inside boundaries for the
3491 modeline since it ignores the margins. However being aware of this fact
3492 we never use those values anywhere so it doesn't matter. */
3493 dl->bounds = calculate_display_line_boundaries (w, 1);
3495 /* We are generating a modeline. */
3497 dl->cursor_elt = -1;
3499 /* Reset the runes on the modeline. */
3500 Dynarr_reset (db->runes);
3502 if (!WINDOW_HAS_MODELINE_P (w))
3506 /* If there is a horizontal scrollbar, don't add anything. */
3507 if (window_scrollbar_height (w))
3510 dl->ascent = DEVMETH (d, divider_height, ());
3512 /* The modeline is at the bottom of the gutters. */
3513 dl->ypos = WINDOW_BOTTOM (w);
3515 /* adjust for the bottom gutter */
3516 if (window_is_lowest (w))
3517 dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
3519 rb.findex = MODELINE_INDEX;
3520 rb.xpos = dl->bounds.left_out;
3521 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3524 rb.type = RUNE_HLINE;
3525 rb.object.hline.thickness = 1;
3526 rb.object.hline.yoffset = 0;
3527 rb.cursor_type = NO_CURSOR;
3529 if (!EQ (Qzero, w->modeline_shadow_thickness)
3532 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3534 dl->ypos -= shadow_thickness;
3535 rb.xpos += shadow_thickness;
3536 rb.width -= 2 * shadow_thickness;
3539 Dynarr_add (db->runes, rb);
3543 /* !!#### not right; needs to compute the max height of
3545 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3547 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3548 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3550 min_pixpos = dl->bounds.left_out;
3551 max_pixpos = dl->bounds.right_out;
3553 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3555 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3557 ypos_adj = shadow_thickness;
3558 min_pixpos += shadow_thickness;
3559 max_pixpos -= shadow_thickness;
3564 generate_formatted_string_db (b->modeline_format,
3565 b->generated_modeline_string, w, dl, db,
3566 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3568 /* The modeline is at the bottom of the gutters. We have to wait to
3569 set this until we've generated the modeline in order to account
3570 for any embedded faces. */
3571 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3572 /* adjust for the bottom gutter */
3573 if (window_is_lowest (w))
3574 dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
3578 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3579 struct window *w, struct display_line *dl,
3580 struct display_block *db, face_index findex,
3581 int min_pixpos, int max_pixpos, int type)
3583 struct frame *f = XFRAME (w->frame);
3584 struct device *d = XDEVICE (f->device);
3593 data.findex = findex;
3594 data.pixpos = min_pixpos;
3595 data.max_pixpos = max_pixpos;
3596 data.cursor_type = NO_CURSOR;
3597 data.last_charset = Qunbound;
3598 data.last_findex = DEFAULT_INDEX;
3599 data.result_str = result_str;
3600 data.is_modeline = 1;
3602 XSETWINDOW (data.window, w);
3604 Dynarr_reset (formatted_string_extent_dynarr);
3605 Dynarr_reset (formatted_string_extent_start_dynarr);
3606 Dynarr_reset (formatted_string_extent_end_dynarr);
3608 /* This recursively builds up the modeline. */
3609 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3610 max_pixpos - min_pixpos, findex, type);
3612 if (Dynarr_length (db->runes))
3615 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3616 c_pixpos = rb->xpos + rb->width;
3619 c_pixpos = min_pixpos;
3621 /* If we don't reach the right side of the window, add a blank rune
3622 to make up the difference. This usually only occurs if the
3623 modeline face is using a proportional width font or a fixed width
3624 font of a different size from the default face font. */
3626 if (c_pixpos < max_pixpos)
3628 data.pixpos = c_pixpos;
3629 data.blank_width = max_pixpos - data.pixpos;
3631 add_blank_rune (&data, NULL, 0);
3634 /* Now create the result string and frob the extents into it. */
3635 if (!NILP (result_str))
3640 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3642 detach_all_extents (result_str);
3643 resize_string (XSTRING (result_str), -1,
3644 data.bytepos - XSTRING_LENGTH (result_str));
3646 strdata = XSTRING_DATA (result_str);
3648 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3650 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3652 len += (set_charptr_emchar
3653 (strdata + len, Dynarr_atp (db->runes,
3654 elt)->object.chr.ch));
3658 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3661 Lisp_Object extent = Qnil;
3664 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3665 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3668 child = Fmake_extent (Qnil, Qnil, result_str);
3669 Fputhash (extent, child, buf->modeline_extent_table);
3671 Fset_extent_parent (child, extent);
3672 set_extent_endpoints
3674 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3675 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3682 add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
3683 Charcount pos, Charcount min_pos, Charcount max_pos)
3685 /* This function has been Mule-ized. */
3687 CONST Bufbyte *cur_pos = str;
3688 struct display_block *db = data->db;
3690 data->blank_width = space_width (XWINDOW (data->window));
3691 while (Dynarr_length (db->runes) < pos)
3692 add_blank_rune (data, NULL, 0);
3694 end = (Dynarr_length (db->runes) +
3695 bytecount_to_charcount (str, strlen ((CONST char *) str)));
3697 end = min (max_pos, end);
3699 while (pos < end && *cur_pos)
3701 CONST Bufbyte *old_cur_pos = cur_pos;
3704 data->ch = charptr_emchar (cur_pos);
3705 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3706 INC_CHARPTR (cur_pos);
3710 data->modeline_charpos++;
3711 data->bytepos += cur_pos - old_cur_pos;
3715 while (Dynarr_length (db->runes) < min_pos &&
3716 (data->pixpos + data->blank_width <= data->max_pixpos))
3717 add_blank_rune (data, NULL, 0);
3719 return Dynarr_length (db->runes);
3722 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3723 modeline extents. */
3725 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3726 Charcount pos, Charcount min_pos, Charcount max_pos)
3728 /* This function has been Mule-ized. */
3730 struct display_block *db = data->db;
3731 struct glyph_block gb;
3733 data->blank_width = space_width (XWINDOW (data->window));
3734 while (Dynarr_length (db->runes) < pos)
3735 add_blank_rune (data, NULL, 0);
3737 end = Dynarr_length (db->runes) + 1;
3739 end = min (max_pos, end);
3743 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3746 while (Dynarr_length (db->runes) < pos &&
3747 (data->pixpos + data->blank_width <= data->max_pixpos))
3748 add_blank_rune (data, NULL, 0);
3750 return Dynarr_length (db->runes);
3753 /* If max_pos is == -1, it is considered to be infinite. The same is
3754 true of max_pixsize. */
3755 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3756 if (Dynarr_length (data->db->runes)) \
3757 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3761 /* Note that this function does "positions" in terms of characters and
3762 not in terms of columns. This is necessary to make the formatting
3763 work correctly when proportional width fonts are used in the
3766 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3767 Charcount min_pos, Charcount max_pos,
3768 Lisp_Object elt, int depth, int max_pixsize,
3769 face_index findex, int type)
3771 /* This function has been Mule-ized. */
3772 /* #### The other losing things in this function are:
3774 -- C zero-terminated-string lossage.
3775 -- Non-printable characters should be converted into something
3776 appropriate (e.g. ^F) instead of blindly being printed anyway.
3787 /* A string. Add to the display line and check for %-constructs
3790 Bufbyte *this = XSTRING_DATA (elt);
3792 while ((pos < max_pos || max_pos == -1) && *this)
3794 Bufbyte *last = this;
3796 while (*this && *this != '%')
3801 /* The string is just a string. */
3803 bytecount_to_charcount (last, this - last) + pos;
3804 Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos));
3806 pos = add_string_to_fstring_db_runes (data, last, pos, pos,
3809 else /* *this == '%' */
3811 Charcount spec_width = 0;
3813 this++; /* skip over '%' */
3815 /* We can't allow -ve args due to the "%-" construct.
3816 * Argument specifies minwidth but not maxwidth
3817 * (maxwidth can be specified by
3818 * (<negative-number> . <stuff>) modeline elements)
3820 while (isdigit (*this))
3822 spec_width = spec_width * 10 + (*this - '0');
3829 pos = generate_fstring_runes (w, data, pos, spec_width,
3830 max_pos, Vglobal_mode_string,
3831 depth, max_pixsize, findex,
3834 else if (*this == '-')
3836 Charcount num_to_add;
3838 if (max_pixsize < 0)
3840 else if (max_pos != -1)
3841 num_to_add = max_pos - pos;
3847 SET_CURRENT_MODE_CHARS_PIXSIZE;
3850 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3853 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3857 while (num_to_add--)
3858 pos = add_string_to_fstring_db_runes
3859 (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
3861 else if (*this != 0)
3864 Emchar ch = charptr_emchar (this);
3865 decode_mode_spec (w, ch, type);
3867 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3868 pos = add_string_to_fstring_db_runes (data,str, pos, pos,
3872 /* NOT this++. There could be any sort of character at
3873 the current position. */
3877 if (max_pixsize > 0)
3880 SET_CURRENT_MODE_CHARS_PIXSIZE;
3882 if (cur_pixsize >= max_pixsize)
3887 else if (SYMBOLP (elt))
3889 /* A symbol: process the value of the symbol recursively
3890 as if it appeared here directly. */
3891 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3893 if (!UNBOUNDP (tem))
3895 /* If value is a string, output that string literally:
3896 don't check for % within it. */
3900 add_string_to_fstring_db_runes
3901 (data, XSTRING_DATA (tem), pos, min_pos, max_pos);
3903 /* Give up right away for nil or t. */
3904 else if (!EQ (tem, elt))
3911 else if (GENERIC_SPECIFIERP (elt))
3913 Lisp_Object window, tem;
3914 XSETWINDOW (window, w);
3915 tem = specifier_instance_no_quit (elt, Qunbound, window,
3916 ERROR_ME_NOT, 0, Qzero);
3917 if (!UNBOUNDP (tem))
3923 else if (CONSP (elt))
3925 /* A cons cell: four distinct cases.
3926 * If first element is a string or a cons, process all the elements
3927 * and effectively concatenate them.
3928 * If first element is a negative number, truncate displaying cdr to
3929 * at most that many characters. If positive, pad (with spaces)
3930 * to at least that many characters.
3931 * If first element is a symbol, process the cadr or caddr recursively
3932 * according to whether the symbol's value is non-nil or nil.
3933 * If first element is a face, process the cdr recursively
3934 * without altering the depth.
3936 Lisp_Object car, tem;
3944 tem = symbol_value_in_buffer (car, w->buffer);
3945 /* elt is now the cdr, and we know it is a cons cell.
3946 Use its car if CAR has a non-nil value. */
3947 if (!UNBOUNDP (tem))
3955 /* Symbol's value is nil (or symbol is unbound)
3956 * Get the cddr of the original list
3957 * and if possible find the caddr and use that.
3962 else if (!CONSP (elt))
3970 else if (INTP (car))
3972 Charcount lim = XINT (car);
3978 /* Negative int means reduce maximum width.
3979 * DO NOT change MIN_PIXPOS here!
3980 * (20 -10 . foo) should truncate foo to 10 col
3981 * and then pad to 20.
3984 max_pos = pos - lim;
3986 max_pos = min (max_pos, pos - lim);
3990 /* Padding specified. Don't let it be more than
3994 if (max_pos != -1 && lim > max_pos)
3996 /* If that's more padding than already wanted, queue it.
3997 * But don't reduce padding already specified even if
3998 * that is beyond the current truncation point.
4005 else if (STRINGP (car) || CONSP (car))
4008 /* LIMIT is to protect against circular lists. */
4009 while (CONSP (elt) && --limit > 0
4010 && (pos < max_pos || max_pos == -1))
4012 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4014 max_pixsize, findex, type);
4018 else if (EXTENTP (car))
4020 struct extent *ext = XEXTENT (car);
4022 if (EXTENT_LIVE_P (ext))
4024 face_index old_findex = data->findex;
4026 Lisp_Object font_inst;
4027 face_index new_findex;
4028 Bytecount start = data->bytepos;
4030 face = extent_face (ext);
4033 /* #### needs to merge faces, sigh */
4034 /* #### needs to handle list of faces */
4035 new_findex = get_builtin_face_cache_index (w, face);
4036 /* !!#### not right; needs to compute the max height of
4038 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
4041 data->dl->ascent = max (data->dl->ascent,
4042 XFONT_INSTANCE (font_inst)->ascent);
4043 data->dl->descent = max (data->dl->descent,
4044 XFONT_INSTANCE (font_inst)->
4048 new_findex = old_findex;
4050 data->findex = new_findex;
4051 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4052 XCDR (elt), depth - 1,
4053 max_pixsize, new_findex, type);
4054 data->findex = old_findex;
4055 Dynarr_add (formatted_string_extent_dynarr, ext);
4056 Dynarr_add (formatted_string_extent_start_dynarr, start);
4057 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4061 else if (GLYPHP (elt))
4063 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos);
4069 add_string_to_fstring_db_runes
4070 (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos,
4076 add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos,
4083 /* The caller is responsible for freeing the returned string. */
4085 generate_formatted_string (struct window *w, Lisp_Object format_str,
4086 Lisp_Object result_str, face_index findex, int type)
4088 struct display_line *dl;
4089 struct display_block *db;
4092 dl = &formatted_string_display_line;
4093 db = get_display_block_from_line (dl, TEXT);
4094 Dynarr_reset (db->runes);
4096 generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
4099 Dynarr_reset (formatted_string_emchar_dynarr);
4100 while (elt < Dynarr_length (db->runes))
4102 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
4103 Dynarr_add (formatted_string_emchar_dynarr,
4104 Dynarr_atp (db->runes, elt)->object.chr.ch);
4109 convert_emchar_string_into_malloced_string
4110 ( Dynarr_atp (formatted_string_emchar_dynarr, 0),
4111 Dynarr_length (formatted_string_emchar_dynarr), 0);
4114 /* Update just the modeline. Assumes the desired display structs. If
4115 they do not have a modeline block, it does nothing. */
4117 regenerate_modeline (struct window *w)
4119 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4121 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4125 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4126 redisplay_update_line (w, 0, 0, 0);
4130 /* Make sure that modeline display line is present in the given
4131 display structs if the window has a modeline and update that
4132 line. Returns true if a modeline was needed. */
4134 ensure_modeline_generated (struct window *w, int type)
4138 /* minibuffer windows don't have modelines */
4139 if (MINI_WINDOW_P (w))
4141 /* windows which haven't had it turned off do */
4142 else if (WINDOW_HAS_MODELINE_P (w))
4144 /* windows which have it turned off don't have a divider if there is
4145 a horizontal scrollbar */
4146 else if (window_scrollbar_height (w))
4148 /* and in this case there is none */
4154 display_line_dynarr *dla;
4156 dla = window_display_lines (w, type);
4158 /* We don't care if there is a display line which is not
4159 currently a modeline because it is definitely going to become
4160 one if we have gotten to this point. */
4161 if (Dynarr_length (dla) == 0)
4163 if (Dynarr_largest (dla) > 0)
4165 struct display_line *mlp = Dynarr_atp (dla, 0);
4166 Dynarr_add (dla, *mlp);
4170 struct display_line modeline;
4172 Dynarr_add (dla, modeline);
4176 /* If we're adding a new place marker go ahead and generate the
4177 modeline so that it is available for use by
4178 window_modeline_height. */
4179 generate_modeline (w, Dynarr_atp (dla, 0), type);
4182 return need_modeline;
4185 /* #### Kludge or not a kludge. I tend towards the former. */
4187 real_current_modeline_height (struct window *w)
4189 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4190 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4192 if (ensure_modeline_generated (w, CMOTION_DISP))
4194 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4196 if (Dynarr_length (dla))
4198 if (Dynarr_atp (dla, 0)->modeline)
4199 return (Dynarr_atp (dla, 0)->ascent +
4200 Dynarr_atp (dla, 0)->descent);
4207 /***************************************************************************/
4209 /* displayable string routines */
4211 /***************************************************************************/
4213 /* Given a position for a string in a window, ensure that the given
4214 display line DL accurately represents the text on a line starting
4215 at the given position.
4217 Yes, this is duplicating the code of create_text_block, but it
4218 looked just too hard to change create_text_block to handle strings
4219 *and* buffers. We already make a distinction between the two
4220 elsewhere in the code so I think unifying them would require a
4221 complete MULE rewrite. Besides, the other distinction is that these
4222 functions cover text that the user *cannot edit* so we can remove
4223 everything to do with cursors, minibuffers etc. Eventually the
4224 modeline routines should be modified to use this code as it copes
4225 with many more types of display situation. */
4228 create_string_text_block (struct window *w, Lisp_Object disp_string,
4229 struct display_line *dl,
4231 prop_block_dynarr **prop,
4232 face_index default_face)
4234 struct frame *f = XFRAME (w->frame);
4235 /* Note that a lot of the buffer controlled stuff has been left in
4236 because you might well want to make use of it (selective display
4237 etc), its just the buffer text that we do not use. */
4238 struct buffer *b = XBUFFER (w->buffer);
4239 struct device *d = XDEVICE (f->device);
4240 struct Lisp_String* s = XSTRING (disp_string);
4242 /* we're working with these a lot so precalculate them */
4243 Bytecount slen = XSTRING_LENGTH (disp_string);
4244 Bytecount bi_string_zv = slen;
4245 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4249 int truncate_win = window_truncation_on (w);
4250 int end_glyph_width = 0;
4252 /* we're going to ditch selective display for static text, its an
4253 FSF thing and invisble extents are the way to go
4254 here. Implementing it also relies on a number of buffer-specific
4255 functions that we don't have the luxury of being able to use
4258 /* The variable ctl-arrow allows the user to specify what characters
4259 can actually be displayed and which octal should be used for.
4260 #### This variable should probably have some rethought done to
4263 #### It would also be really nice if you could specify that
4264 the characters come out in hex instead of in octal. Mule
4265 does that by adding a ctl-hexa variable similar to ctl-arrow,
4266 but that's bogus -- we need a more general solution. I
4267 think you need to extend the concept of display tables
4268 into a more general conversion mechanism. Ideally you
4269 could specify a Lisp function that converts characters,
4270 but this violates the Second Golden Rule and besides would
4271 make things way way way way slow.
4273 So instead, we extend the display-table concept, which was
4274 historically limited to 256-byte vectors, to one of the
4277 a) A 256-entry vector, for backward compatibility;
4278 b) char-table, mapping characters to values;
4279 c) range-table, mapping ranges of characters to values;
4280 d) a list of the above.
4282 The (d) option allows you to specify multiple display tables
4283 instead of just one. Each display table can specify conversions
4284 for some characters and leave others unchanged. The way the
4285 character gets displayed is determined by the first display table
4286 with a binding for that character. This way, you could call a
4287 function `enable-hex-display' that adds a hex display-table to
4288 the list of display tables for the current buffer.
4290 #### ...not yet implemented... Also, we extend the concept of
4291 "mapping" to include a printf-like spec. Thus you can make all
4292 extended characters show up as hex with a display table like
4295 #s(range-table data ((256 524288) (format "%x")))
4297 Since more than one display table is possible, you have
4298 great flexibility in mapping ranges of characters. */
4299 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4300 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4301 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4304 Lisp_Object face_dt, window_dt;
4306 /* The text display block for this display line. */
4307 struct display_block *db = get_display_block_from_line (dl, TEXT);
4309 /* The first time through the main loop we need to force the glyph
4310 data to be updated. */
4313 /* Apparently the new extent_fragment_update returns an end position
4314 equal to the position passed in if there are no more runs to be
4316 int no_more_frags = 0;
4318 dl->used_prop_data = 0;
4321 /* set up faces to use for clearing areas, used by
4322 output_display_line */
4323 dl->default_findex = default_face;
4326 dl->left_margin_findex = default_face;
4327 dl->right_margin_findex = default_face;
4331 dl->left_margin_findex =
4332 get_builtin_face_cache_index (w, Vleft_margin_face);
4333 dl->right_margin_findex =
4334 get_builtin_face_cache_index (w, Vright_margin_face);
4338 data.ef = extent_fragment_new (disp_string, f);
4340 /* These values are used by all of the rune addition routines. We add
4341 them to this structure for ease of passing. */
4343 XSETWINDOW (data.window, w);
4347 data.bi_bufpos = bi_start_pos;
4348 data.pixpos = dl->bounds.left_in;
4349 data.last_charset = Qunbound;
4350 data.last_findex = default_face;
4351 data.result_str = Qnil;
4352 data.string = disp_string;
4354 /* Set the right boundary adjusting it to take into account any end
4355 glyph. Save the width of the end glyph for later use. */
4356 data.max_pixpos = dl->bounds.right_in;
4359 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
4361 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
4363 data.max_pixpos -= end_glyph_width;
4365 data.cursor_type = NO_CURSOR;
4369 /* I don't think we want this, string areas should not scroll with
4371 data.start_col = w->hscroll;
4372 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4374 data.bi_start_col_enabled = 0;
4375 data.hscroll_glyph_width_adjust = 0;
4377 /* We regenerate the line from the very beginning. */
4378 Dynarr_reset (db->runes);
4380 /* Why is this less than or equal and not just less than? If the
4381 starting position is already equal to the maximum we can't add
4382 anything else, right? Wrong. We might still have a newline to
4383 add. A newline can use the room allocated for an end glyph since
4384 if we add it we know we aren't going to be adding any end
4387 /* #### Chuck -- I think this condition should be while (1).
4388 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4389 and the begin-glyph ends exactly at the end of the window, the
4390 end-glyph and text might not be displayed. while (1) ensures
4391 that the loop terminates only when either (a) there is
4392 propagation data or (b) the end-of-line or end-of-buffer is hit.
4394 #### Also I think you need to ensure that the operation
4395 "add begin glyphs; add end glyphs; add text" is atomic and
4396 can't get interrupted in the middle. If you run off the end
4397 of the line during that operation, then you keep accumulating
4398 propagation data until you're done. Otherwise, if the (e.g.)
4399 there's a begin glyph at a particular position and attempting
4400 to display that glyph results in window-end being hit and
4401 propagation data being generated, then the character at that
4402 position won't be displayed.
4404 #### See also the comment after the end of this loop, below.
4406 while (data.pixpos <= data.max_pixpos)
4408 /* #### This check probably should not be necessary. */
4409 if (data.bi_bufpos > bi_string_zv)
4411 /* #### urk! More of this lossage! */
4416 /* Check for face changes. */
4417 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
4419 /* Now compute the face and begin/end-glyph information. */
4421 /* Remember that the extent-fragment routines deal in Bytind's. */
4422 extent_fragment_update (w, data.ef, data.bi_bufpos);
4423 /* This is somewhat cheesy but the alternative is to
4424 propagate default_face into extent_fragment_update. */
4425 if (data.findex == DEFAULT_INDEX)
4426 data.findex = default_face;
4428 get_display_tables (w, data.findex, &face_dt, &window_dt);
4430 if (data.bi_bufpos == data.ef->end)
4435 /* Determine what is next to be displayed. We first handle any
4436 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4437 display then we determine what to do based on the character at the
4438 current buffer position. */
4440 /* If the current position is covered by an invisible extent, do
4441 nothing (except maybe add some ellipses).
4443 #### The behavior of begin and end-glyphs at the edge of an
4444 invisible extent should be investigated further. This is
4445 fairly low priority though. */
4446 if (data.ef->invisible)
4448 /* #### Chuck, perhaps you could look at this code? I don't
4449 really know what I'm doing. */
4452 Dynarr_free (*prop);
4456 /* The extent fragment code only sets this when we should
4457 really display the ellipses. It makes sure the ellipses
4458 don't get displayed more than once in a row. */
4459 if (data.ef->invisible_ellipses)
4461 struct glyph_block gb;
4463 data.ef->invisible_ellipses_already_displayed = 1;
4464 data.ef->invisible_ellipses = 0;
4466 gb.glyph = Vinvisible_text_glyph;
4467 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
4468 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
4469 /* Perhaps they shouldn't propagate if the very next thing
4470 is to display a newline (for compatibility with
4471 selective-display-ellipses)? Maybe that's too
4477 /* #### What if we we're dealing with a display table? */
4481 if (data.bi_bufpos == bi_string_zv)
4484 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4487 /* If there is propagation data, then it represents the current
4488 buffer position being displayed. Add them and advance the
4489 position counter. This might also add the minibuffer
4493 dl->used_prop_data = 1;
4494 *prop = add_propagation_runes (prop, &data);
4497 goto done; /* gee, a really narrow window */
4498 else if (data.bi_bufpos == bi_string_zv)
4500 else if (data.bi_bufpos < 0)
4501 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4504 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4507 /* If there are end glyphs, add them to the line. These are
4508 the end glyphs for the previous run of text. We add them
4509 here rather than doing them at the end of handling the
4510 previous run so that glyphs at the beginning and end of
4511 a line are handled correctly. */
4512 else if (Dynarr_length (data.ef->end_glyphs) > 0)
4514 *prop = add_glyph_runes (&data, END_GLYPHS);
4519 /* If there are begin glyphs, add them to the line. */
4520 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
4522 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
4527 /* If at end-of-buffer, we've already processed begin and
4528 end-glyphs at this point and there's no text to process,
4530 else if (data.bi_bufpos == bi_string_zv)
4535 Lisp_Object entry = Qnil;
4536 /* Get the character at the current buffer position. */
4537 data.ch = string_char (s, data.bi_bufpos);
4538 if (!NILP (face_dt) || !NILP (window_dt))
4539 entry = display_table_entry (data.ch, face_dt, window_dt);
4541 /* If there is a display table entry for it, hand it off to
4542 add_disp_table_entry_runes and let it worry about it. */
4543 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
4545 *prop = add_disp_table_entry_runes (&data, entry);
4551 /* Check if we have hit a newline character. If so, add a marker
4552 to the line and end this loop. */
4553 else if (data.ch == '\n')
4555 /* We aren't going to be adding an end glyph so give its
4556 space back in order to make sure that the cursor can
4558 data.max_pixpos += end_glyph_width;
4562 /* If the current character is considered to be printable, then
4564 else if (data.ch >= printable_min)
4566 *prop = add_emchar_rune (&data);
4571 /* If the current character is a tab, determine the next tab
4572 starting position and add a blank rune which extends from the
4573 current pixel position to that starting position. */
4574 else if (data.ch == '\t')
4576 int tab_start_pixpos = data.pixpos;
4581 if (data.start_col > 1)
4582 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
4585 next_tab_position (w, tab_start_pixpos,
4586 dl->bounds.left_in +
4587 data.hscroll_glyph_width_adjust);
4588 if (next_tab_start > data.max_pixpos)
4590 prop_width = next_tab_start - data.max_pixpos;
4591 next_tab_start = data.max_pixpos;
4593 data.blank_width = next_tab_start - data.pixpos;
4595 (next_tab_start - tab_start_pixpos) / space_width (w);
4597 *prop = add_blank_rune (&data, w, char_tab_width);
4599 /* add_blank_rune is only supposed to be called with
4600 sizes guaranteed to fit in the available space. */
4605 struct prop_block pb;
4606 *prop = Dynarr_new (prop_block);
4608 pb.type = PROP_BLANK;
4609 pb.data.p_blank.width = prop_width;
4610 pb.data.p_blank.findex = data.findex;
4611 Dynarr_add (*prop, pb);
4617 /* If character is a control character, pass it off to
4618 add_control_char_runes.
4620 The is_*() routines have undefined results on
4621 arguments outside of the range [-1, 255]. (This
4622 often bites people who carelessly use `char' instead
4623 of `unsigned char'.)
4625 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
4627 *prop = add_control_char_runes (&data, b);
4633 /* If the character is above the ASCII range and we have not
4634 already handled it, then print it as an octal number. */
4635 else if (data.ch >= 0200)
4637 *prop = add_octal_runes (&data);
4643 /* Assume the current character is considered to be printable,
4644 then just add it. */
4647 *prop = add_emchar_rune (&data);
4652 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4658 /* Determine the starting point of the next line if we did not hit the
4659 end of the buffer. */
4660 if (data.bi_bufpos < bi_string_zv)
4662 /* #### This check is not correct. If the line terminated
4663 due to a begin-glyph or end-glyph hitting window-end, then
4664 data.ch will not point to the character at data.bi_bufpos. If
4665 you make the two changes mentioned at the top of this loop,
4666 you should be able to say '(if (*prop))'. That should also
4667 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4670 /* The common case is that the line ended because we hit a newline.
4671 In that case, the next character is just the next buffer
4673 if (data.ch == '\n')
4675 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4678 /* Otherwise we have a buffer line which cannot fit on one display
4682 struct glyph_block gb;
4683 struct glyph_cachel *cachel;
4685 /* If the line is to be truncated then we actually have to look
4686 for the next newline. We also add the end-of-line glyph which
4687 we know will fit because we adjusted the right border before
4688 we starting laying out the line. */
4689 data.max_pixpos += end_glyph_width;
4690 data.findex = default_face;
4697 /* Now find the start of the next line. */
4698 bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
4700 data.cursor_type = NO_CURSOR;
4701 data.bi_bufpos = bi_pos;
4702 gb.glyph = Vtruncation_glyph;
4703 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
4707 /* The cursor can never be on the continuation glyph. */
4708 data.cursor_type = NO_CURSOR;
4710 /* data.bi_bufpos is already at the start of the next line. */
4712 gb.glyph = Vcontinuation_glyph;
4713 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
4716 if (end_glyph_width)
4717 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
4719 if (truncate_win && data.bi_bufpos == bi_string_zv)
4721 CONST Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
4723 if (charptr_emchar (endb) != '\n')
4725 /* #### Damn this losing shit. */
4731 else if (data.bi_bufpos == bi_string_zv)
4733 /* We need to add a marker to the end of the line since there is no
4734 newline character in order for the cursor to get drawn. We label
4735 it as a newline so that it gets handled correctly by the
4736 whitespace routines below. */
4739 data.blank_width = DEVMETH (d, eol_cursor_width, ());
4740 data.findex = default_face;
4742 data.bi_start_col_enabled = 0;
4744 data.max_pixpos += data.blank_width;
4745 add_emchar_rune (&data);
4746 data.max_pixpos -= data.blank_width;
4748 /* #### urk! Chuck, this shit is bad news. Going around
4749 manipulating invalid positions is guaranteed to result in
4750 trouble sooner or later. */
4751 data.bi_bufpos = bi_string_zv + 1;
4754 /* Calculate left whitespace boundary. */
4758 /* Whitespace past a newline is considered right whitespace. */
4759 while (elt < Dynarr_length (db->runes))
4761 struct rune *rb = Dynarr_atp (db->runes, elt);
4763 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4764 || rb->type == RUNE_BLANK)
4766 dl->bounds.left_white += rb->width;
4770 elt = Dynarr_length (db->runes);
4774 /* Calculate right whitespace boundary. */
4776 int elt = Dynarr_length (db->runes) - 1;
4779 while (!done && elt >= 0)
4781 struct rune *rb = Dynarr_atp (db->runes, elt);
4783 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4784 && isspace (rb->object.chr.ch))
4785 && !rb->type == RUNE_BLANK)
4787 dl->bounds.right_white = rb->xpos + rb->width;
4795 /* The line is blank so everything is considered to be right
4798 dl->bounds.right_white = dl->bounds.left_in;
4801 /* Set the display blocks bounds. */
4802 db->start_pos = dl->bounds.left_in;
4803 if (Dynarr_length (db->runes))
4805 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4807 db->end_pos = rb->xpos + rb->width;
4810 db->end_pos = dl->bounds.right_white;
4812 /* update line height parameters */
4813 if (!data.new_ascent && !data.new_descent)
4815 /* We've got a blank line so initialize these values from the default
4817 default_face_font_info (data.window, &data.new_ascent,
4818 &data.new_descent, 0, 0, 0);
4821 if (data.max_pixmap_height)
4823 int height = data.new_ascent + data.new_descent;
4824 int pix_ascent, pix_descent;
4826 pix_descent = data.max_pixmap_height * data.new_descent / height;
4827 pix_ascent = data.max_pixmap_height - pix_descent;
4829 data.new_ascent = max (data.new_ascent, pix_ascent);
4830 data.new_descent = max (data.new_descent, pix_descent);
4833 dl->ascent = data.new_ascent;
4834 dl->descent = data.new_descent;
4837 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
4839 if (dl->ascent < ascent)
4840 dl->ascent = ascent;
4843 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
4845 if (dl->descent < descent)
4846 dl->descent = descent;
4849 dl->cursor_elt = data.cursor_x;
4850 /* #### lossage lossage lossage! Fix this shit! */
4851 if (data.bi_bufpos > bi_string_zv)
4852 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4854 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4856 data.dl->num_chars =
4857 string_column_at_point (s, dl->end_bufpos, XINT (b->tab_width));
4859 /* This doesn't correctly take into account tabs and control
4860 characters but if the window isn't being truncated then this
4861 value isn't going to end up being used anyhow. */
4862 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4864 /* #### handle horizontally scrolled line with text none of which
4865 was actually laid out. */
4867 /* #### handle any remainder of overlay arrow */
4869 if (*prop == ADD_FAILED)
4872 if (truncate_win && *prop)
4874 Dynarr_free (*prop);
4878 extent_fragment_delete (data.ef);
4880 /* #### If we started at EOB, then make sure we return a value past
4881 it so that regenerate_window will exit properly. This is bogus.
4882 The main loop should get fixed so that it isn't necessary to call
4883 this function if we are already at EOB. */
4885 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4886 return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
4888 return bytecount_to_charcount (string_data (s), data.bi_bufpos);
4891 /* Given a display line and a starting position, ensure that the
4892 contents of the display line accurately represent the visual
4893 representation of the buffer contents starting from the given
4894 position when displayed in the given window. The display line ends
4895 when the contents of the line reach the right boundary of the given
4898 This is very similar to generate_display_line but with the same
4899 limitations as create_string_text_block. I have taken the liberty
4900 of fixing the bytind stuff though.*/
4903 generate_string_display_line (struct window *w, Lisp_Object disp_string,
4904 struct display_line *dl,
4906 prop_block_dynarr **prop,
4907 face_index default_face)
4911 /* you must set bounds before calling this. */
4913 /* Reset what this line is using. */
4914 if (dl->display_blocks)
4915 Dynarr_reset (dl->display_blocks);
4916 if (dl->left_glyphs)
4918 Dynarr_free (dl->left_glyphs);
4919 dl->left_glyphs = 0;
4921 if (dl->right_glyphs)
4923 Dynarr_free (dl->right_glyphs);
4924 dl->right_glyphs = 0;
4927 /* We aren't generating a modeline at the moment. */
4930 /* Create a display block for the text region of the line. */
4931 ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
4932 prop, default_face);
4933 dl->bufpos = start_pos;
4934 if (dl->end_bufpos < dl->bufpos)
4935 dl->end_bufpos = dl->bufpos;
4937 /* If there are left glyphs associated with any character in the
4938 text block, then create a display block to handle them. */
4939 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
4940 create_left_glyph_block (w, dl, 0);
4942 /* If there are right glyphs associated with any character in the
4943 text block, then create a display block to handle them. */
4944 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
4945 create_right_glyph_block (w, dl);
4950 /* This is ripped off from regenerate_window. All we want to do is
4951 loop through elements in the string creating display lines until we
4952 have covered the provided area. Simple really. */
4954 generate_displayable_area (struct window *w, Lisp_Object disp_string,
4955 int xpos, int ypos, int width, int height,
4956 display_line_dynarr* dla,
4958 face_index default_face)
4960 int yend = ypos + height;
4963 prop_block_dynarr *prop = 0;
4964 layout_bounds bounds;
4968 /* if there's nothing to do then do nothing. code after this assumes
4969 there is something to do. */
4970 if (NILP (disp_string))
4973 s_zv = XSTRING_CHAR_LENGTH (disp_string) - 1;
4975 bounds.left_out = xpos;
4976 bounds.right_out = xpos + width;
4977 /* The inner boundaries mark where the glyph margins are located. */
4978 bounds.left_in = bounds.left_out + window_left_margin_width (w);
4979 bounds.right_in = bounds.right_out - window_right_margin_width (w);
4980 /* We cannot fully calculate the whitespace boundaries as they
4981 depend on the contents of the line being displayed. */
4982 bounds.left_white = bounds.left_in;
4983 bounds.right_white = bounds.right_in;
4987 struct display_line dl;
4988 struct display_line *dlp;
4992 if (Dynarr_length (dla) < Dynarr_largest (dla))
4994 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5005 dlp->bounds = bounds;
5007 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5008 &prop, default_face);
5009 /* we need to make sure that we continue along the line if there
5010 is more left to display otherwise we just end up redisplaying
5011 the same chunk over and over again. */
5012 if (next_pos == start_pos && next_pos < s_zv)
5015 start_pos = next_pos;
5017 dlp->ypos = ypos + dlp->ascent;
5018 ypos = dlp->ypos + dlp->descent;
5022 int visible_height = dlp->ascent + dlp->descent;
5024 dlp->clip = (ypos - yend);
5025 visible_height -= dlp->clip;
5027 if (visible_height < VERTICAL_CLIP (w, 1))
5030 free_display_line (dlp);
5037 Dynarr_add (dla, *dlp);
5039 /* #### This type of check needs to be done down in the
5040 generate_display_line call. */
5041 if (start_pos >= s_zv)
5050 /***************************************************************************/
5052 /* window-regeneration routines */
5054 /***************************************************************************/
5056 /* For a given window and starting position in the buffer it contains,
5057 ensure that the TYPE display lines accurately represent the
5058 presentation of the window. We pass the buffer instead of getting
5059 it from the window since redisplay_window may have temporarily
5060 changed it to the echo area buffer. */
5063 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
5065 struct frame *f = XFRAME (w->frame);
5066 struct buffer *b = XBUFFER (w->buffer);
5067 int ypos = WINDOW_TEXT_TOP (w);
5068 int yend; /* set farther down */
5070 prop_block_dynarr *prop;
5071 layout_bounds bounds;
5072 display_line_dynarr *dla;
5075 /* The lines had better exist by this point. */
5076 if (!(dla = window_display_lines (w, type)))
5079 w->max_line_len = 0;
5081 /* Normally these get updated in redisplay_window but it is possible
5082 for this function to get called from some other points where that
5083 update may not have occurred. This acts as a safety check. */
5084 if (!Dynarr_length (w->face_cachels))
5085 reset_face_cachels (w);
5086 if (!Dynarr_length (w->glyph_cachels))
5087 reset_glyph_cachels (w);
5089 Fset_marker (w->start[type], make_int (start_pos), w->buffer);
5090 Fset_marker (w->pointm[type], make_int (point), w->buffer);
5091 w->last_point_x[type] = -1;
5092 w->last_point_y[type] = -1;
5094 /* Make sure a modeline is in the structs if needed. */
5095 need_modeline = ensure_modeline_generated (w, type);
5097 /* Wait until here to set this so that the structs have a modeline
5098 generated in the case where one didn't exist. */
5099 yend = WINDOW_TEXT_BOTTOM (w);
5101 bounds = calculate_display_line_boundaries (w, 0);
5103 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5104 if (MINI_WINDOW_P (w)
5105 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
5106 && !echo_area_active (f)
5107 && start_pos == BUF_BEGV (b))
5109 struct prop_block pb;
5111 prop = Dynarr_new (prop_block);
5113 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5114 pb.type = PROP_MINIBUF_PROMPT;
5115 pb.data.p_string.str = XSTRING_DATA(string);
5116 pb.data.p_string.len = XSTRING_LENGTH(string);
5117 Dynarr_add (prop, pb);
5124 struct display_line dl;
5125 struct display_line *dlp;
5128 if (Dynarr_length (dla) < Dynarr_largest (dla))
5130 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5141 dlp->bounds = bounds;
5143 start_pos = generate_display_line (w, dlp, 1, start_pos,
5144 w->hscroll, &prop, type);
5145 dlp->ypos = ypos + dlp->ascent;
5146 ypos = dlp->ypos + dlp->descent;
5150 int visible_height = dlp->ascent + dlp->descent;
5152 dlp->clip = (ypos - yend);
5153 visible_height -= dlp->clip;
5155 if (visible_height < VERTICAL_CLIP (w, 1))
5158 free_display_line (dlp);
5165 if (dlp->cursor_elt != -1)
5167 /* #### This check is steaming crap. Have to get things
5168 fixed so when create_text_block hits EOB, we're done,
5170 if (w->last_point_x[type] == -1)
5172 w->last_point_x[type] = dlp->cursor_elt;
5173 w->last_point_y[type] = Dynarr_length (dla);
5177 /* #### This means that we've added a cursor at EOB
5178 twice. Yuck oh yuck. */
5179 struct display_block *db =
5180 get_display_block_from_line (dlp, TEXT);
5182 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
5183 dlp->cursor_elt = -1;
5187 if (dlp->num_chars > w->max_line_len)
5188 w->max_line_len = dlp->num_chars;
5190 Dynarr_add (dla, *dlp);
5192 /* #### This isn't right, but it is close enough for now. */
5193 w->window_end_pos[type] = start_pos;
5195 /* #### This type of check needs to be done down in the
5196 generate_display_line call. */
5197 if (start_pos > BUF_ZV (b))
5204 /* #### More not quite right, but close enough. */
5205 /* #### Ben sez: apparently window_end_pos[] is measured
5206 as the number of characters between the window end and the
5207 end of the buffer? This seems rather weirdo. What's
5208 the justification for this? */
5209 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
5213 /* We know that this is the right thing to use because we put it
5214 there when we first started working in this function. */
5215 generate_modeline (w, Dynarr_atp (dla, 0), type);
5219 #define REGEN_INC_FIND_START_END \
5221 /* Determine start and end of lines. */ \
5222 if (!Dynarr_length (cdla)) \
5226 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5230 else if (!Dynarr_atp (cdla, 0)->modeline \
5231 && !Dynarr_atp (ddla, 0)->modeline) \
5236 abort (); /* structs differ */ \
5238 dla_end = Dynarr_length (cdla) - 1; \
5241 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5242 + Dynarr_atp (cdla, dla_start)->offset); \
5243 /* If this isn't true, then startp has changed and we need to do a \
5245 if (startp != start_pos) \
5248 /* Point is outside the visible region so give up. */ \
5249 if (pointm < start_pos) \
5254 /* This attempts to incrementally update the display structures. It
5255 returns a boolean indicating success or failure. This function is
5256 very similar to regenerate_window_incrementally and is in fact only
5257 called from that function. However, because of the nature of the
5258 changes it deals with it sometimes makes different assumptions
5259 which can lead to success which are much more difficult to make
5260 when dealing with buffer changes. */
5263 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
5265 Charcount beg_unchanged,
5266 Charcount end_unchanged)
5268 struct buffer *b = XBUFFER (w->buffer);
5269 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5270 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5274 int first_line, last_line;
5276 /* Don't define this in the loop where it is used because we
5277 definitely want its value to survive between passes. */
5278 prop_block_dynarr *prop = NULL;
5280 /* If we don't have any buffer change recorded but the modiff flag has
5281 been incremented, then fail. I'm not sure of the exact circumstances
5282 under which this can happen, but I believe that it is probably a
5283 reasonable happening. */
5284 if (!point_visible (w, pointm, CURRENT_DISP)
5285 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
5288 /* If the cursor is moved we attempt to update it. If we succeed we
5289 go ahead and proceed with the optimization attempt. */
5290 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5291 || pointm != marker_position (w->last_point[CURRENT_DISP]))
5293 struct frame *f = XFRAME (w->frame);
5294 struct device *d = XDEVICE (f->device);
5295 struct frame *sel_f = device_selected_frame (d);
5298 if (w->last_point_x[CURRENT_DISP] != -1
5299 && w->last_point_y[CURRENT_DISP] != -1)
5302 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
5304 /* Always regenerate the modeline in case it is
5305 displaying the current line or column. */
5306 regenerate_modeline (w);
5310 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
5312 if (f->modeline_changed)
5313 regenerate_modeline (w);
5321 if (beg_unchanged == -1 && end_unchanged == -1)
5324 /* assert: There are no buffer modifications or they are all below the
5325 visible region. We assume that regenerate_window_incrementally has
5326 not called us unless this is true. */
5328 REGEN_INC_FIND_START_END;
5330 /* If the changed are starts before the visible area, give up. */
5331 if (beg_unchanged < startp)
5334 /* Find what display line the extent changes first affect. */
5336 while (line <= dla_end)
5338 struct display_line *dl = Dynarr_atp (cdla, line);
5339 Bufpos lstart = dl->bufpos + dl->offset;
5340 Bufpos lend = dl->end_bufpos + dl->offset;
5342 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5348 /* If the changes are below the visible area then if point hasn't
5349 moved return success otherwise fail in order to be safe. */
5352 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5353 && pointm == marker_position (w->last_point[CURRENT_DISP]))
5359 /* At this point we know what line the changes first affect. We now
5360 begin redrawing lines as long as we are still in the affected
5361 region and the line's size and positioning don't change.
5362 Otherwise we fail. If we fail we will have altered the desired
5363 structs which could lead to an assertion failure. However, if we
5364 fail the next thing that is going to happen is a full regen so we
5365 will actually end up being safe. */
5366 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5367 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5368 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5369 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5371 first_line = last_line = line;
5372 while (line <= dla_end)
5374 Bufpos old_start, old_end, new_start;
5375 struct display_line *cdl = Dynarr_atp (cdla, line);
5376 struct display_line *ddl = Dynarr_atp (ddla, line);
5377 struct display_block *db;
5380 assert (cdl->bufpos == ddl->bufpos);
5381 assert (cdl->end_bufpos == ddl->end_bufpos);
5382 assert (cdl->offset == ddl->offset);
5384 db = get_display_block_from_line (ddl, TEXT);
5385 initial_size = Dynarr_length (db->runes);
5386 old_start = ddl->bufpos + ddl->offset;
5387 old_end = ddl->end_bufpos + ddl->offset;
5389 /* If this is the first line being updated and it used
5390 propagation data, fail. Otherwise we'll be okay because
5391 we'll have the necessary propagation data. */
5392 if (line == first_line && ddl->used_prop_data)
5395 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5396 w->hscroll, &prop, DESIRED_DISP);
5399 /* #### If there is propagated stuff the fail. We could
5400 probably actually deal with this if the line had propagated
5401 information when originally created by a full
5409 /* If any line position parameters have changed or a
5410 cursor has disappeared or disappeared, fail. */
5411 db = get_display_block_from_line (ddl, TEXT);
5412 if (cdl->ypos != ddl->ypos
5413 || cdl->ascent != ddl->ascent
5414 || cdl->descent != ddl->descent
5415 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5416 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5417 || old_start != ddl->bufpos
5418 || old_end != ddl->end_bufpos
5419 || initial_size != Dynarr_length (db->runes))
5424 if (ddl->cursor_elt != -1)
5426 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5427 w->last_point_y[DESIRED_DISP] = line;
5432 /* If the extent changes end on the line we just updated then
5433 we're done. Otherwise go on to the next line. */
5434 if (end_unchanged <= ddl->end_bufpos)
5440 redisplay_update_line (w, first_line, last_line, 1);
5444 /* Attempt to update the display data structures based on knowledge of
5445 the changed region in the buffer. Returns a boolean indicating
5446 success or failure. If this function returns a failure then a
5447 regenerate_window _must_ be performed next in order to maintain
5448 invariants located here. */
5451 regenerate_window_incrementally (struct window *w, Bufpos startp,
5454 struct buffer *b = XBUFFER (w->buffer);
5455 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5456 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5457 Charcount beg_unchanged, end_unchanged;
5458 Charcount extent_beg_unchanged, extent_end_unchanged;
5464 /* If this function is called, the current and desired structures
5465 had better be identical. If they are not, then that is a bug. */
5466 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
5468 /* We don't handle minibuffer windows yet. The minibuffer prompt
5470 if (MINI_WINDOW_P (w))
5473 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
5474 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
5476 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
5478 /* If nothing has changed in the buffer, then make sure point is ok
5480 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
5481 return regenerate_window_extents_only_changed (w, startp, pointm,
5482 extent_beg_unchanged,
5483 extent_end_unchanged);
5485 /* We can't deal with deleted newlines. */
5486 if (BUF_NEWLINE_WAS_DELETED (b))
5489 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
5490 end_unchanged = (BUF_END_UNCHANGED (b) == -1
5492 : BUF_Z (b) - BUF_END_UNCHANGED (b));
5494 REGEN_INC_FIND_START_END;
5496 /* If the changed area starts before the visible area, give up. */
5497 if (beg_unchanged < startp)
5500 /* Find what display line the buffer changes first affect. */
5502 while (line <= dla_end)
5504 struct display_line *dl = Dynarr_atp (cdla, line);
5505 Bufpos lstart = dl->bufpos + dl->offset;
5506 Bufpos lend = dl->end_bufpos + dl->offset;
5508 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5514 /* If the changes are below the visible area then if point hasn't
5515 moved return success otherwise fail in order to be safe. */
5517 return regenerate_window_extents_only_changed (w, startp, pointm,
5518 extent_beg_unchanged,
5519 extent_end_unchanged);
5521 /* At this point we know what line the changes first affect. We
5522 now redraw that line. If the changes are contained within it
5523 we are going to succeed and can update just that one line.
5524 Otherwise we fail. If we fail we will have altered the desired
5525 structs which could lead to an assertion failure. However, if
5526 we fail the next thing that is going to happen is a full regen
5527 so we will actually end up being safe. */
5530 prop_block_dynarr *prop = NULL;
5531 struct display_line *cdl = Dynarr_atp (cdla, line);
5532 struct display_line *ddl = Dynarr_atp (ddla, line);
5534 assert (cdl->bufpos == ddl->bufpos);
5535 assert (cdl->end_bufpos == ddl->end_bufpos);
5536 assert (cdl->offset == ddl->offset);
5538 /* If the last rune is already a continuation glyph, fail.
5539 #### We should be able to handle this better. */
5541 struct display_block *db = get_display_block_from_line (ddl, TEXT);
5542 if (Dynarr_length (db->runes))
5545 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
5547 if (rb->type == RUNE_DGLYPH
5548 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
5553 /* If the line was generated using propagation data, fail. */
5554 if (ddl->used_prop_data)
5557 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5558 w->hscroll, &prop, DESIRED_DISP);
5561 /* If there is propagated stuff then it is pretty much a
5562 guarantee that more than just the one line is affected. */
5569 /* If the last rune is now a continuation glyph, fail. */
5571 struct display_block *db = get_display_block_from_line (ddl, TEXT);
5572 if (Dynarr_length (db->runes))
5575 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
5577 if (rb->type == RUNE_DGLYPH
5578 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
5583 /* If any line position parameters have changed or a
5584 cursor has disappeared or disappeared, fail. */
5585 if (cdl->ypos != ddl->ypos
5586 || cdl->ascent != ddl->ascent
5587 || cdl->descent != ddl->descent
5588 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5589 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
5594 /* If the changed area also ends on this line, then we may be in
5595 business. Update everything and return success. */
5596 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
5598 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5599 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5600 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
5602 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
5605 if (ddl->cursor_elt != -1)
5607 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5608 w->last_point_y[DESIRED_DISP] = line;
5611 redisplay_update_line (w, line, line, 1);
5612 regenerate_modeline (w);
5614 /* #### For now we just flush the cache until this has been
5615 tested. After that is done, this should correct the
5617 Dynarr_reset (w->line_start_cache);
5619 /* Adjust the extent changed boundaries to remove any
5620 overlap with the buffer changes since we've just
5621 successfully updated that area. */
5622 if (extent_beg_unchanged != -1
5623 && extent_beg_unchanged >= beg_unchanged
5624 && extent_beg_unchanged < end_unchanged)
5625 extent_beg_unchanged = end_unchanged;
5627 if (extent_end_unchanged != -1
5628 && extent_end_unchanged >= beg_unchanged
5629 && extent_end_unchanged < end_unchanged)
5630 extent_end_unchanged = beg_unchanged - 1;
5632 if (extent_end_unchanged <= extent_beg_unchanged)
5633 extent_beg_unchanged = extent_end_unchanged = -1;
5635 /* This could lead to odd results if it fails, but since the
5636 buffer changes update succeeded this probably will to.
5637 We already know that the extent changes start at or after
5638 the line because we checked before entering the loop. */
5639 if (extent_beg_unchanged != -1
5640 && extent_end_unchanged != -1
5641 && ((extent_beg_unchanged < ddl->bufpos)
5642 || (extent_end_unchanged > ddl->end_bufpos)))
5643 return regenerate_window_extents_only_changed (w, startp, pointm,
5644 extent_beg_unchanged,
5645 extent_end_unchanged);
5655 /* Given a window and a point, update the given display lines such
5656 that point is displayed in the middle of the window.
5657 Return the window's new start position. */
5660 regenerate_window_point_center (struct window *w, Bufpos point, int type)
5664 /* We need to make sure that the modeline is generated so that the
5665 window height can be calculated correctly. */
5666 ensure_modeline_generated (w, type);
5668 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
5669 regenerate_window (w, startp, point, type);
5670 Fset_marker (w->start[type], make_int (startp), w->buffer);
5675 /* Given a window and a set of display lines, return a boolean
5676 indicating whether the given point is contained within. */
5679 point_visible (struct window *w, Bufpos point, int type)
5681 struct buffer *b = XBUFFER (w->buffer);
5682 display_line_dynarr *dla = window_display_lines (w, type);
5685 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5690 if (Dynarr_length (dla) > first_line)
5693 struct display_line *dl = Dynarr_atp (dla, first_line);
5696 end = BUF_Z (b) - w->window_end_pos[type] - 1;
5698 if (point >= start && point <= end)
5700 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
5702 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
5704 if (point >= (dl->bufpos + dl->offset)
5705 && point <= (dl->end_bufpos + dl->offset))
5720 /* Return pixel position the middle of the window, not including the
5721 modeline and any potential horizontal scrollbar. */
5724 window_half_pixpos (struct window *w)
5726 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
5729 /* Return the display line which is currently in the middle of the
5730 window W for display lines TYPE. */
5733 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5735 display_line_dynarr *dla;
5738 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
5740 if (type == CMOTION_DISP)
5741 regenerate_window (w, start, point, type);
5743 dla = window_display_lines (w, type);
5744 half = window_half_pixpos (w);
5746 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
5748 struct display_line *dl = Dynarr_atp (dla, elt);
5749 int line_bot = dl->ypos + dl->descent;
5751 if (line_bot > half)
5755 /* We may not have a line at the middle if the end of the buffer is
5760 /* Return a value for point that would place it at the beginning of
5761 the line which is in the middle of the window. */
5764 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5766 /* line_at_center will regenerate the display structures, if necessary. */
5767 int line = line_at_center (w, type, start, point);
5770 return BUF_ZV (XBUFFER (w->buffer));
5773 display_line_dynarr *dla = window_display_lines (w, type);
5774 struct display_line *dl = Dynarr_atp (dla, line);
5780 /* For a given window, ensure that the current visual representation
5784 redisplay_window (Lisp_Object window, int skip_selected)
5786 struct window *w = XWINDOW (window);
5787 struct frame *f = XFRAME (w->frame);
5788 struct device *d = XDEVICE (f->device);
5789 Lisp_Object old_buffer = w->buffer;
5790 Lisp_Object the_buffer = w->buffer;
5792 int echo_active = 0;
5797 int selected_in_its_frame;
5798 int selected_globally;
5799 int skip_output = 0;
5800 int truncation_changed;
5801 int inactive_minibuffer =
5802 (MINI_WINDOW_P (w) &&
5803 (f != device_selected_frame (d)) &&
5804 !is_surrogate_for_selected_frame (f));
5806 /* #### In the new world this function actually does a bunch of
5807 optimizations such as buffer-based scrolling, but none of that is
5810 /* If this is a combination window, do its children; that's all.
5811 The selected window is always a leaf so we don't check for
5812 skip_selected here. */
5813 if (!NILP (w->vchild))
5815 redisplay_windows (w->vchild, skip_selected);
5818 if (!NILP (w->hchild))
5820 redisplay_windows (w->hchild, skip_selected);
5824 /* Is this window the selected window on its frame? */
5825 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
5827 selected_in_its_frame &&
5828 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5829 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
5830 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5831 if (skip_selected && selected_in_its_frame)
5834 /* It is possible that the window is not fully initialized yet. */
5835 if (NILP (w->buffer))
5838 if (MINI_WINDOW_P (w) && echo_area_active (f))
5840 w->buffer = the_buffer = Vecho_area_buffer;
5844 b = XBUFFER (w->buffer);
5848 old_pointm = selected_globally
5850 : marker_position (w->pointm[CURRENT_DISP]);
5855 if (selected_globally)
5857 pointm = BUF_PT (b);
5861 pointm = marker_position (w->pointm[CURRENT_DISP]);
5863 if (pointm < BUF_BEGV (b))
5864 pointm = BUF_BEGV (b);
5865 else if (pointm > BUF_ZV (b))
5866 pointm = BUF_ZV (b);
5869 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
5871 /* If the buffer has changed we have to invalidate all of our face
5873 if ((!echo_active && b != window_display_buffer (w))
5874 || !Dynarr_length (w->face_cachels)
5875 || f->faces_changed)
5876 reset_face_cachels (w);
5878 mark_face_cachels_as_not_updated (w);
5880 /* Ditto the glyph cache elements. */
5881 if ((!echo_active && b != window_display_buffer (w))
5882 || !Dynarr_length (w->glyph_cachels)
5883 || f->glyphs_changed)
5884 reset_glyph_cachels (w);
5886 mark_glyph_cachels_as_not_updated (w);
5888 /* If the marker's buffer is not the window's buffer, then we need
5889 to find a new starting position. */
5890 if (!MINI_WINDOW_P (w)
5891 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5893 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5895 goto regeneration_done;
5900 old_startp = marker_position (w->start[CURRENT_DISP]);
5905 startp = marker_position (w->start[CURRENT_DISP]);
5906 if (startp < BUF_BEGV (b))
5907 startp = BUF_BEGV (b);
5908 else if (startp > BUF_ZV (b))
5909 startp = BUF_ZV (b);
5911 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5913 truncation_changed = (find_window_mirror (w)->truncate_win !=
5914 window_truncation_on (w));
5916 /* If w->force_start is set, then some function set w->start and we
5917 should display from there and change point, if necessary, to
5918 ensure that it is visible. */
5919 if (w->force_start || inactive_minibuffer)
5922 w->last_modified[DESIRED_DISP] = Qzero;
5923 w->last_facechange[DESIRED_DISP] = Qzero;
5925 regenerate_window (w, startp, pointm, DESIRED_DISP);
5927 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5929 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5931 if (selected_globally)
5932 BUF_SET_PT (b, pointm);
5934 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5937 /* #### BUFU amounts of overkill just to get the cursor
5938 location marked properly. FIX ME FIX ME FIX ME */
5939 regenerate_window (w, startp, pointm, DESIRED_DISP);
5942 goto regeneration_done;
5945 /* If nothing has changed since the last redisplay, then we just
5946 need to make sure that point is still visible. */
5947 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5948 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
5950 /* This check is to make sure we restore the minibuffer after a
5951 temporary change to the echo area. */
5952 && !(MINI_WINDOW_P (w) && f->buffers_changed)
5953 && !f->frame_changed
5954 && !truncation_changed
5955 /* check whether start is really at the begining of a line GE */
5956 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
5959 /* Check if the cursor has actually moved. */
5960 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5961 && pointm == marker_position (w->last_point[CURRENT_DISP])
5962 && selected_globally
5963 && !w->windows_changed
5965 && !f->extents_changed
5966 && !f->faces_changed
5967 && !f->glyphs_changed
5968 && !f->subwindows_changed
5969 && !f->point_changed
5970 && !f->windows_structure_changed)
5972 /* If not, we're done. */
5973 if (f->modeline_changed)
5974 regenerate_modeline (w);
5977 goto regeneration_done;
5981 /* If the new point is visible in the redisplay structures,
5982 then let the output update routines handle it, otherwise
5983 do things the hard way. */
5984 if (!w->windows_changed
5986 && !f->extents_changed
5987 && !f->faces_changed
5988 && !f->glyphs_changed
5989 && !f->subwindows_changed
5990 && !f->windows_structure_changed)
5992 if (point_visible (w, pointm, CURRENT_DISP)
5993 && w->last_point_x[CURRENT_DISP] != -1
5994 && w->last_point_y[CURRENT_DISP] != -1)
5996 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
5998 /* Always regenerate in case it is displaying
5999 the current line or column. */
6000 regenerate_modeline (w);
6003 goto regeneration_done;
6006 else if (!selected_in_its_frame && !f->point_changed)
6008 if (f->modeline_changed)
6009 regenerate_modeline (w);
6012 goto regeneration_done;
6016 /* If we weren't able to take the shortcut method, then use
6017 the brute force method. */
6018 regenerate_window (w, startp, pointm, DESIRED_DISP);
6020 if (point_visible (w, pointm, DESIRED_DISP))
6021 goto regeneration_done;
6025 /* Check if the starting point is no longer at the beginning of a
6026 line, in which case find a new starting point. We also recenter
6027 if our start position is equal to point-max. Otherwise we'll end
6028 up with a blank window. */
6029 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
6030 && !(startp == BUF_BEGV (b)
6031 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
6032 || (pointm == startp &&
6033 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
6034 startp < marker_position (w->last_start[CURRENT_DISP]))
6035 || (startp == BUF_ZV (b)))
6037 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6039 goto regeneration_done;
6041 /* See if we can update the data structures locally based on
6042 knowledge of what changed in the buffer. */
6043 else if (!w->windows_changed
6045 && !f->faces_changed
6046 && !f->glyphs_changed
6047 && !f->subwindows_changed
6048 && !f->windows_structure_changed
6049 && !f->frame_changed
6050 && !truncation_changed
6052 && regenerate_window_incrementally (w, startp, pointm))
6054 if (f->modeline_changed
6055 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
6056 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
6057 regenerate_modeline (w);
6060 goto regeneration_done;
6062 /* #### This is where a check for structure based scrolling would go. */
6063 /* If all else fails, try just regenerating and see what happens. */
6066 regenerate_window (w, startp, pointm, DESIRED_DISP);
6068 if (point_visible (w, pointm, DESIRED_DISP))
6069 goto regeneration_done;
6072 /* We still haven't gotten the window regenerated with point
6073 visible. Next we try scrolling a little and see if point comes
6074 back onto the screen. */
6075 if (scroll_step > 0)
6077 int scrolled = scroll_conservatively;
6078 for (; scrolled >= 0; scrolled -= scroll_step)
6080 startp = vmotion (w, startp,
6081 (pointm < startp) ? -scroll_step : scroll_step, 0);
6082 regenerate_window (w, startp, pointm, DESIRED_DISP);
6084 if (point_visible (w, pointm, DESIRED_DISP))
6085 goto regeneration_done;
6089 /* We still haven't managed to get the screen drawn with point on
6090 the screen, so just center it and be done with it. */
6091 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6096 /* If the window's frame is changed then reset the current display
6097 lines in order to force a full repaint. */
6098 if (f->frame_changed)
6100 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
6105 /* Must do this before calling redisplay_output_window because it
6106 sets some markers on the window. */
6109 w->buffer = old_buffer;
6110 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
6111 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
6114 /* These also have to be set before calling redisplay_output_window
6115 since it sets the CURRENT_DISP values based on them. */
6116 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
6117 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
6118 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
6119 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
6123 Bufpos start = marker_position (w->start[DESIRED_DISP]);
6124 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
6126 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
6127 /* Don't pollute the cache if not sure if we are correct */
6128 if (w->start_at_line_beg)
6129 update_line_start_cache (w, start, end, pointm, 1);
6130 redisplay_output_window (w);
6132 * If we just displayed the echo area, the line start cache is
6133 * no longer valid, because the minibuffer window is associated
6134 * with the window now.
6137 w->line_cache_last_updated = make_int (-1);
6140 /* #### This should be dependent on face changes and will need to be
6141 somewhere else once tty updates occur on a per-frame basis. */
6142 mark_face_cachels_as_clean (w);
6144 w->windows_changed = 0;
6147 /* Call buffer_reset_changes for all buffers present in any window
6148 currently visible in all frames on all devices. #### There has to
6149 be a better way to do this. */
6152 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
6154 buffer_reset_changes (XBUFFER (w->buffer));
6159 reset_buffer_changes (void)
6161 Lisp_Object frmcons, devcons, concons;
6163 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6165 struct frame *f = XFRAME (XCAR (frmcons));
6167 if (FRAME_REPAINT_P (f))
6168 map_windows (f, reset_buffer_changes_mapfun, 0);
6172 /* Ensure that all windows underneath the given window in the window
6173 hierarchy are correctly displayed. */
6176 redisplay_windows (Lisp_Object window, int skip_selected)
6178 for (; !NILP (window) ; window = XWINDOW (window)->next)
6180 redisplay_window (window, skip_selected);
6185 call_redisplay_end_triggers (struct window *w, void *closure)
6187 Bufpos lrpos = w->last_redisplay_pos;
6188 w->last_redisplay_pos = 0;
6189 if (!NILP (w->buffer)
6190 && !NILP (w->redisplay_end_trigger)
6195 if (MARKERP (w->redisplay_end_trigger)
6196 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
6197 pos = marker_position (w->redisplay_end_trigger);
6198 else if (INTP (w->redisplay_end_trigger))
6199 pos = XINT (w->redisplay_end_trigger);
6202 w->redisplay_end_trigger = Qnil;
6209 XSETWINDOW (window, w);
6210 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
6211 Qredisplay_end_trigger_functions,
6213 w->redisplay_end_trigger);
6214 w->redisplay_end_trigger = Qnil;
6221 /* Ensure that all windows on the given frame are correctly displayed. */
6224 redisplay_frame (struct frame *f, int preemption_check)
6226 struct device *d = XDEVICE (f->device);
6228 if (preemption_check)
6230 /* The preemption check itself takes a lot of time,
6231 so normally don't do it here. We do it if called
6232 from Lisp, though (`redisplay-frame'). */
6235 REDISPLAY_PREEMPTION_CHECK;
6240 /* Before we put a hold on frame size changes, attempt to process
6241 any which are already pending. */
6242 if (f->size_change_pending)
6243 change_frame_size (f, f->new_height, f->new_width, 0);
6245 /* If frame size might need to be changed, due to changed size
6246 of toolbars, scrollbars etc, change it now */
6247 if (f->size_slipped)
6249 adjust_frame_size (f);
6250 assert (!f->size_slipped);
6253 /* The menubar, toolbar, and icon updates must be done before
6254 hold_frame_size_changes is called and we are officially
6255 'in_display'. They may eval lisp code which may call Fsignal.
6256 If in_display is set Fsignal will abort. */
6258 #ifdef HAVE_MENUBARS
6259 /* Update the menubar. It is done first since it could change
6260 the menubar's visibility. This way we avoid having flashing
6261 caused by an Expose event generated by the visibility change
6263 update_frame_menubars (f);
6264 #endif /* HAVE_MENUBARS */
6265 update_frame_gutters (f);
6266 /* widgets are similar to menus in that they can call lisp to
6267 determine activation etc. Therefore update them before we get
6268 into redisplay. This is primarily for connected widgets such as
6270 update_frame_subwindows (f);
6271 #ifdef HAVE_TOOLBARS
6272 /* Update the toolbars. */
6273 update_frame_toolbars (f);
6274 #endif /* HAVE_TOOLBARS */
6276 hold_frame_size_changes ();
6278 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6279 /* Within this section, we are defenseless and assume that the
6280 following cannot happen:
6282 1) garbage collection
6283 2) Lisp code evaluation
6284 3) frame size changes
6286 We ensure (3) by calling hold_frame_size_changes(), which
6287 will cause any pending frame size changes to get put on hold
6288 till after the end of the critical section. (1) follows
6289 automatically if (2) is met. #### Unfortunately, there are
6290 some places where Lisp code can be called within this section.
6291 We need to remove them.
6293 If Fsignal() is called during this critical section, we
6296 If garbage collection is called during this critical section,
6297 we simply return. #### We should abort instead.
6299 #### If a frame-size change does occur we should probably
6300 actually be preempting redisplay. */
6302 /* If we clear the frame we have to force its contents to be redrawn. */
6304 f->frame_changed = 1;
6306 /* Erase the frame before outputting its contents. */
6309 DEVMETH (d, clear_frame, (f));
6312 /* invalidate the subwindow cache. we are going to reuse the glyphs
6313 flag here to cause subwindows to get instantiated. This is
6314 because subwindows changed is less strict - dealing with things
6315 like the clicked state of button. */
6316 if (!Dynarr_length (f->subwindow_cachels)
6317 || f->glyphs_changed
6318 || f->frame_changed)
6319 reset_subwindow_cachels (f);
6321 mark_subwindow_cachels_as_not_updated (f);
6323 /* Do the selected window first. */
6324 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
6326 /* Then do the rest. */
6327 redisplay_windows (f->root_window, 1);
6329 /* We now call the output_end routine for tty frames. We delay
6330 doing so in order to avoid cursor flicker. So much for 100%
6332 if (FRAME_TTY_P (f))
6333 DEVMETH (d, output_end, (d));
6335 update_frame_title (f);
6337 f->buffers_changed = 0;
6338 f->clip_changed = 0;
6339 f->extents_changed = 0;
6340 f->faces_changed = 0;
6341 f->frame_changed = 0;
6342 f->glyphs_changed = 0;
6343 f->subwindows_changed = 0;
6344 f->icon_changed = 0;
6345 f->menubar_changed = 0;
6346 f->modeline_changed = 0;
6347 f->point_changed = 0;
6348 f->toolbar_changed = 0;
6349 f->gutter_changed = 0;
6350 f->windows_changed = 0;
6351 f->windows_structure_changed = 0;
6352 f->window_face_cache_reset = 0;
6353 f->echo_area_garbaged = 0;
6357 if (!f->size_change_pending)
6358 f->size_changed = 0;
6360 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6362 /* Allow frame size changes to occur again.
6364 #### what happens if changes to other frames happen? */
6365 unhold_one_frame_size_changes (f);
6367 map_windows (f, call_redisplay_end_triggers, 0);
6371 /* Ensure that all frames on the given device are correctly displayed. */
6374 redisplay_device (struct device *d)
6376 Lisp_Object frame, frmcons;
6378 int size_change_failed = 0;
6381 if (DEVICE_STREAM_P (d)) /* nothing to do */
6384 /* It is possible that redisplay has been called before the
6385 device is fully initialized. If so then continue with the
6387 if (NILP (DEVICE_SELECTED_FRAME (d)))
6390 REDISPLAY_PREEMPTION_CHECK;
6394 /* Always do the selected frame first. */
6395 frame = DEVICE_SELECTED_FRAME (d);
6399 if (f->icon_changed || f->windows_changed)
6400 update_frame_icon (f);
6402 if (FRAME_REPAINT_P (f))
6404 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
6405 f->faces_changed || f->frame_changed || f->menubar_changed ||
6406 f->modeline_changed || f->point_changed || f->size_changed ||
6407 f->toolbar_changed || f->windows_changed || f->size_slipped ||
6408 f->windows_structure_changed || f->glyphs_changed ||
6409 f->subwindows_changed || f->gutter_changed)
6411 preempted = redisplay_frame (f, 0);
6417 /* If the frame redisplay did not get preempted, then this flag
6418 should have gotten set to 0. It might be possible for that
6419 not to happen if a size change event were to occur at an odd
6420 time. To make sure we don't miss anything we simply don't
6421 reset the top level flags until the condition ends up being
6422 in the right state. */
6423 if (f->size_changed)
6424 size_change_failed = 1;
6427 DEVICE_FRAME_LOOP (frmcons, d)
6429 f = XFRAME (XCAR (frmcons));
6431 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
6434 if (f->icon_changed || f->windows_changed)
6435 update_frame_icon (f);
6437 if (FRAME_REPAINT_P (f))
6439 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
6440 f->faces_changed || f->frame_changed || f->menubar_changed ||
6441 f->modeline_changed || f->point_changed || f->size_changed ||
6442 f->toolbar_changed || f->windows_changed ||
6443 f->windows_structure_changed || f->gutter_changed ||
6444 f->glyphs_changed || f->subwindows_changed)
6446 preempted = redisplay_frame (f, 0);
6452 if (f->size_change_pending)
6453 size_change_failed = 1;
6457 /* If we get here then we redisplayed all of our frames without
6458 getting preempted so mark ourselves as clean. */
6459 d->buffers_changed = 0;
6460 d->clip_changed = 0;
6461 d->extents_changed = 0;
6462 d->faces_changed = 0;
6463 d->frame_changed = 0;
6464 d->glyphs_changed = 0;
6465 d->subwindows_changed = 0;
6466 d->icon_changed = 0;
6467 d->menubar_changed = 0;
6468 d->modeline_changed = 0;
6469 d->point_changed = 0;
6470 d->toolbar_changed = 0;
6471 d->gutter_changed = 0;
6472 d->windows_changed = 0;
6473 d->windows_structure_changed = 0;
6475 if (!size_change_failed)
6476 d->size_changed = 0;
6482 restore_profiling_redisplay_flag (Lisp_Object val)
6484 profiling_redisplay_flag = XINT (val);
6488 /* Ensure that all windows on all frames on all devices are displaying
6489 the current contents of their respective buffers. */
6492 redisplay_without_hooks (void)
6494 Lisp_Object devcons, concons;
6495 int size_change_failed = 0;
6496 int count = specpdl_depth ();
6498 if (profiling_active)
6500 record_unwind_protect (restore_profiling_redisplay_flag,
6501 make_int (profiling_redisplay_flag));
6502 profiling_redisplay_flag = 1;
6505 if (asynch_device_change_pending)
6506 handle_asynch_device_change ();
6508 if (!buffers_changed && !clip_changed && !extents_changed &&
6509 !faces_changed && !frame_changed && !icon_changed &&
6510 !menubar_changed && !modeline_changed && !point_changed &&
6511 !size_changed && !toolbar_changed && !windows_changed &&
6512 !glyphs_changed && !subwindows_changed &&
6513 !gutter_changed && !windows_structure_changed &&
6514 !disable_preemption && preemption_count < max_preempts)
6517 DEVICE_LOOP_NO_BREAK (devcons, concons)
6519 struct device *d = XDEVICE (XCAR (devcons));
6522 if (d->buffers_changed || d->clip_changed || d->extents_changed ||
6523 d->faces_changed || d->frame_changed || d->icon_changed ||
6524 d->menubar_changed || d->modeline_changed || d->point_changed ||
6525 d->size_changed || d->toolbar_changed || d->windows_changed ||
6526 d->windows_structure_changed || d->gutter_changed ||
6527 d->glyphs_changed || d->subwindows_changed)
6529 preempted = redisplay_device (d);
6534 RESET_CHANGED_SET_FLAGS;
6538 /* See comment in redisplay_device. */
6539 if (d->size_changed)
6540 size_change_failed = 1;
6543 preemption_count = 0;
6545 /* Mark redisplay as accurate */
6546 buffers_changed = 0;
6548 extents_changed = 0;
6551 subwindows_changed = 0;
6553 menubar_changed = 0;
6554 modeline_changed = 0;
6556 toolbar_changed = 0;
6558 windows_changed = 0;
6559 windows_structure_changed = 0;
6560 RESET_CHANGED_SET_FLAGS;
6564 mark_all_faces_as_clean ();
6568 if (!size_change_failed)
6571 reset_buffer_changes ();
6574 unbind_to (count, Qnil);
6580 if (last_display_warning_tick != display_warning_tick &&
6581 !inhibit_warning_display)
6583 /* If an error occurs during this function, oh well.
6584 If we report another warning, we could get stuck in an
6585 infinite loop reporting warnings. */
6586 call0_trapping_errors (0, Qdisplay_warning_buffer);
6587 last_display_warning_tick = display_warning_tick;
6589 /* The run_hook_trapping_errors functions are smart enough not
6590 to do any evalling if the hook function is empty, so there
6591 should not be any significant time loss. All places in the
6592 C code that call redisplay() are prepared to handle GCing,
6593 so we should be OK. */
6594 #ifndef INHIBIT_REDISPLAY_HOOKS
6595 run_hook_trapping_errors ("Error in pre-redisplay-hook",
6596 Qpre_redisplay_hook);
6597 #endif /* INHIBIT_REDISPLAY_HOOKS */
6599 redisplay_without_hooks ();
6601 #ifndef INHIBIT_REDISPLAY_HOOKS
6602 run_hook_trapping_errors ("Error in post-redisplay-hook",
6603 Qpost_redisplay_hook);
6604 #endif /* INHIBIT_REDISPLAY_HOOKS */
6608 static char window_line_number_buf[32];
6610 /* Efficiently determine the window line number, and return a pointer
6611 to its printed representation. Do this regardless of whether
6612 line-number-mode is on. The first line in the buffer is counted as
6613 1. If narrowing is in effect, the lines are counted from the
6614 beginning of the visible portion of the buffer. */
6616 window_line_number (struct window *w, int type)
6618 struct device *d = XDEVICE (XFRAME (w->frame)->device);
6619 struct buffer *b = XBUFFER (w->buffer);
6620 /* Be careful in the order of these tests. The first clause will
6621 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6622 This can occur when the frame title is computed really early */
6624 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6625 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
6626 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6627 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
6629 : marker_position (w->pointm[type]));
6632 line = buffer_line_number (b, pos, 1);
6634 long_to_string (window_line_number_buf, line + 1);
6636 return window_line_number_buf;
6640 /* Given a character representing an object in a modeline
6641 specification, return a string (stored into the global array
6642 `mode_spec_bufbyte_string') with the information that object
6645 This function is largely unchanged from previous versions of the
6648 Warning! This code is also used for frame titles and can be called
6649 very early in the device/frame update process! JV
6653 decode_mode_spec (struct window *w, Emchar spec, int type)
6655 Lisp_Object obj = Qnil;
6656 CONST char *str = NULL;
6657 struct buffer *b = XBUFFER (w->buffer);
6659 Dynarr_reset (mode_spec_bufbyte_string);
6663 /* print buffer name */
6668 /* print visited file name */
6673 /* print the current column */
6676 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
6678 : marker_position (w->pointm[type]);
6679 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
6682 long_to_string (buf, col);
6684 Dynarr_add_many (mode_spec_bufbyte_string,
6685 (CONST Bufbyte *) buf, strlen (buf));
6687 goto decode_mode_spec_done;
6689 /* print the file coding system */
6693 Lisp_Object codesys = b->buffer_file_coding_system;
6694 /* Be very careful here not to get an error. */
6695 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
6697 codesys = Ffind_coding_system (codesys);
6698 if (CODING_SYSTEMP (codesys))
6699 obj = XCODING_SYSTEM_MNEMONIC (codesys);
6702 #endif /* FILE_CODING */
6705 /* print the current line number */
6707 str = window_line_number (w, type);
6710 /* print value of mode-name (obsolete) */
6715 /* print hyphen and frame number, if != 1 */
6719 struct frame *f = XFRAME (w->frame);
6720 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
6722 /* Naughty, naughty */
6723 char * writable_str = alloca_array (char, 10);
6724 sprintf (writable_str, "-%d", f->order_count);
6728 #endif /* HAVE_TTY */
6731 /* print Narrow if appropriate */
6733 if (BUF_BEGV (b) > BUF_BEG (b)
6734 || BUF_ZV (b) < BUF_Z (b))
6738 /* print %, * or hyphen, if buffer is read-only, modified or neither */
6740 str = (!NILP (b->read_only)
6742 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6747 /* print * or hyphen -- XEmacs change to allow a buffer to be
6748 read-only but still indicate whether it is modified. */
6750 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6752 : (!NILP (b->read_only)
6757 /* #### defined in 19.29 decode_mode_spec, but not in
6758 modeline-format doc string. */
6759 /* This differs from %* in that it ignores read-only-ness. */
6761 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6766 /* print process status */
6768 obj = Fget_buffer_process (w->buffer);
6770 str = GETTEXT ("no process");
6772 obj = Fsymbol_name (Fprocess_status (obj));
6775 /* Print name of selected frame. */
6777 obj = XFRAME (w->frame)->name;
6780 /* indicate TEXT or BINARY */
6782 /* #### NT does not use this any more. Now what? */
6786 /* print percent of buffer above top of window, or Top, Bot or All */
6789 Bufpos pos = marker_position (w->start[type]);
6790 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6792 /* This had better be while the desired lines are being done. */
6793 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
6795 if (pos <= BUF_BEGV (b))
6800 else if (pos <= BUF_BEGV (b))
6804 /* This hard limit is ok since the string it will hold has a
6805 fixed maximum length of 3. But just to be safe... */
6808 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
6810 /* We can't normally display a 3-digit number, so get us a
6811 2-digit number that is close. */
6815 sprintf (buf, "%2d%%", total);
6816 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6819 goto decode_mode_spec_done;
6824 /* print percent of buffer above bottom of window, perhaps plus
6825 Top, or print Bottom or All */
6828 Bufpos toppos = marker_position (w->start[type]);
6829 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
6830 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6832 /* botpos is only accurate as of the last redisplay, so we can
6833 only treat it as a hint. In particular, after erase-buffer,
6834 botpos may be negative. */
6835 if (botpos < toppos)
6838 if (botpos >= BUF_ZV (b))
6840 if (toppos <= BUF_BEGV (b))
6847 /* This hard limit is ok since the string it will hold has a
6848 fixed maximum length of around 6. But just to be safe... */
6851 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
6853 /* We can't normally display a 3-digit number, so get us a
6854 2-digit number that is close. */
6858 if (toppos <= BUF_BEGV (b))
6859 sprintf (buf, "Top%2d%%", total);
6861 sprintf (buf, "%2d%%", total);
6863 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6866 goto decode_mode_spec_done;
6876 /* print one [ for each recursive editing level. */
6881 if (command_loop_level > 5)
6887 for (i = 0; i < command_loop_level; i++)
6888 Dynarr_add (mode_spec_bufbyte_string, '[');
6890 goto decode_mode_spec_done;
6893 /* print one ] for each recursive editing level. */
6898 if (command_loop_level > 5)
6904 for (i = 0; i < command_loop_level; i++)
6905 Dynarr_add (mode_spec_bufbyte_string, ']');
6907 goto decode_mode_spec_done;
6910 /* print infinitely many dashes -- handle at top level now */
6917 Dynarr_add_many (mode_spec_bufbyte_string,
6919 XSTRING_LENGTH (obj));
6921 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6923 decode_mode_spec_done:
6924 Dynarr_add (mode_spec_bufbyte_string, '\0');
6927 /* Given a display line, free all of its data structures. */
6930 free_display_line (struct display_line *dl)
6934 if (dl->display_blocks)
6936 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6938 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6940 Dynarr_free (db->runes);
6943 Dynarr_free (dl->display_blocks);
6944 dl->display_blocks = NULL;
6947 if (dl->left_glyphs)
6949 Dynarr_free (dl->left_glyphs);
6950 dl->left_glyphs = NULL;
6953 if (dl->right_glyphs)
6955 Dynarr_free (dl->right_glyphs);
6956 dl->right_glyphs = NULL;
6961 /* Given an array of display lines, free them and all data structures
6962 contained within them. */
6965 free_display_lines (display_line_dynarr *dla)
6969 for (line = 0; line < Dynarr_largest (dla); line++)
6971 free_display_line (Dynarr_atp (dla, line));
6977 /* Call internal free routine for each set of display lines. */
6980 free_display_structs (struct window_mirror *mir)
6982 if (mir->current_display_lines)
6984 free_display_lines (mir->current_display_lines);
6985 mir->current_display_lines = 0;
6988 if (mir->desired_display_lines)
6990 free_display_lines (mir->desired_display_lines);
6991 mir->desired_display_lines = 0;
6997 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object))
7001 glyph_block *gb = Dynarr_atp (gba, 0);
7002 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
7004 for (; gb < gb_last; gb++)
7006 if (!NILP (gb->glyph))
7007 markobj (gb->glyph);
7008 if (!NILP (gb->extent))
7009 markobj (gb->extent);
7015 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object))
7017 display_line *dl = Dynarr_atp (dla, 0);
7018 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
7020 for (; dl < dl_last; dl++)
7022 display_block_dynarr *dba = dl->display_blocks;
7023 display_block *db = Dynarr_atp (dba, 0);
7024 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
7026 for (; db < db_last; db++)
7028 rune_dynarr *ra = db->runes;
7029 rune *r = Dynarr_atp (ra, 0);
7030 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
7032 for (; r < r_last; r++)
7034 if (r->type == RUNE_DGLYPH)
7036 if (!NILP (r->object.dglyph.glyph))
7037 markobj (r->object.dglyph.glyph);
7038 if (!NILP (r->object.dglyph.extent))
7039 markobj (r->object.dglyph.extent);
7044 mark_glyph_block_dynarr (dl->left_glyphs, markobj);
7045 mark_glyph_block_dynarr (dl->right_glyphs, markobj);
7050 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object))
7052 mark_redisplay_structs (mir->current_display_lines, markobj);
7053 mark_redisplay_structs (mir->desired_display_lines, markobj);
7056 mark_window_mirror (mir->next, markobj);
7059 mark_window_mirror (mir->hchild, markobj);
7060 else if (mir->vchild)
7061 mark_window_mirror (mir->vchild, markobj);
7065 mark_redisplay (void (*markobj)(Lisp_Object))
7067 Lisp_Object frmcons, devcons, concons;
7069 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
7071 struct frame *f = XFRAME (XCAR (frmcons));
7072 update_frame_window_mirror (f);
7073 mark_window_mirror (f->root_mirror, markobj);
7077 /*****************************************************************************
7078 Line Start Cache Description and Rationale
7080 The traditional scrolling code in Emacs breaks in a variable height world.
7081 It depends on the key assumption that the number of lines that can be
7082 displayed at any given time is fixed. This led to a complete separation
7083 of the scrolling code from the redisplay code. In order to fully support
7084 variable height lines, the scrolling code must actually be tightly
7085 integrated with redisplay. Only redisplay can determine how many lines
7086 will be displayed on a screen for any given starting point.
7088 What is ideally wanted is a complete list of the starting buffer position
7089 for every possible display line of a buffer along with the height of that
7090 display line. Maintaining such a full list would be very expensive. We
7091 settle for having it include information for all areas which we happen to
7092 generate anyhow (i.e. the region currently being displayed) and for those
7093 areas we need to work with.
7095 In order to ensure that the cache accurately represents what redisplay
7096 would actually show, it is necessary to invalidate it in many situations.
7097 If the buffer changes, the starting positions may no longer be correct.
7098 If a face or an extent has changed then the line heights may have altered.
7099 These events happen frequently enough that the cache can end up being
7100 constantly disabled. With this potentially constant invalidation when is
7101 the cache ever useful?
7103 Even if the cache is invalidated before every single usage, it is
7104 necessary. Scrolling often requires knowledge about display lines which
7105 are actually above or below the visible region. The cache provides a
7106 convenient light-weight method of storing this information for multiple
7107 display regions. This knowledge is necessary for the scrolling code to
7108 always obey the First Golden Rule of Redisplay.
7110 If the cache already contains all of the information that the scrolling
7111 routines happen to need so that it doesn't have to go generate it, then we
7112 are able to obey the Third Golden Rule of Redisplay. The first thing we
7113 do to help out the cache is to always add the displayed region. This
7114 region had to be generated anyway, so the cache ends up getting the
7115 information basically for free. In those cases where a user is simply
7116 scrolling around viewing a buffer there is a high probability that this is
7117 sufficient to always provide the needed information. The second thing we
7118 can do is be smart about invalidating the cache.
7120 TODO -- Be smart about invalidating the cache. Potential places:
7122 + Insertions at end-of-line which don't cause line-wraps do not alter the
7123 starting positions of any display lines. These types of buffer
7124 modifications should not invalidate the cache. This is actually a large
7125 optimization for redisplay speed as well.
7127 + Buffer modifications frequently only affect the display of lines at and
7128 below where they occur. In these situations we should only invalidate
7129 the part of the cache starting at where the modification occurs.
7131 In case you're wondering, the Second Golden Rule of Redisplay is not
7133 ****************************************************************************/
7135 /* This will get used quite a bit so we don't want to be constantly
7136 allocating and freeing it. */
7137 line_start_cache_dynarr *internal_cache;
7139 /* Makes internal_cache represent the TYPE display structs and only
7140 the TYPE display structs. */
7143 update_internal_cache_list (struct window *w, int type)
7146 display_line_dynarr *dla = window_display_lines (w, type);
7148 Dynarr_reset (internal_cache);
7149 for (line = 0; line < Dynarr_length (dla); line++)
7151 struct display_line *dl = Dynarr_atp (dla, line);
7157 struct line_start_cache lsc;
7159 lsc.start = dl->bufpos;
7160 lsc.end = dl->end_bufpos;
7161 lsc.height = dl->ascent + dl->descent;
7163 Dynarr_add (internal_cache, lsc);
7168 /* Reset the line cache if necessary. This should be run at the
7169 beginning of any function which access the cache. */
7172 validate_line_start_cache (struct window *w)
7174 struct buffer *b = XBUFFER (w->buffer);
7175 struct frame *f = XFRAME (w->frame);
7177 if (!w->line_cache_validation_override)
7179 /* f->extents_changed used to be in here because extent face and
7180 size changes can cause text shifting. However, the extent
7181 covering the region is constantly having its face set and
7182 priority altered by the mouse code. This means that the line
7183 start cache is constantly being invalidated. This is bad
7184 since the mouse code also triggers heavy usage of the cache.
7185 Since it is an unlikely that f->extents being changed
7186 indicates that the cache really needs to be updated and if it
7187 does redisplay will catch it pretty quickly we no longer
7188 invalidate the cache if it is set. This greatly speeds up
7189 dragging out regions with the mouse. */
7190 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
7194 Dynarr_reset (w->line_start_cache);
7199 /* Return the very first buffer position contained in the given
7200 window's cache, or -1 if the cache is empty. Assumes that the
7204 line_start_cache_start (struct window *w)
7206 line_start_cache_dynarr *cache = w->line_start_cache;
7208 if (!Dynarr_length (cache))
7211 return Dynarr_atp (cache, 0)->start;
7214 /* Return the very last buffer position contained in the given
7215 window's cache, or -1 if the cache is empty. Assumes that the
7219 line_start_cache_end (struct window *w)
7221 line_start_cache_dynarr *cache = w->line_start_cache;
7223 if (!Dynarr_length (cache))
7226 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7229 /* Return the index of the line POINT is contained within in window
7230 W's line start cache. It will enlarge the cache or move the cache
7231 window in order to have POINT be present in the cache. MIN_PAST is
7232 a guarantee of the number of entries in the cache present on either
7233 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7234 then it will be treated as 0, but the cache window will not be
7235 allowed to shift. Returns -1 if POINT cannot be found in the cache
7239 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
7241 struct buffer *b = XBUFFER (w->buffer);
7242 line_start_cache_dynarr *cache = w->line_start_cache;
7243 unsigned int top, bottom, pos;
7245 validate_line_start_cache (w);
7246 w->line_cache_validation_override++;
7248 /* Let functions pass in negative values, but we still treat -1
7250 /* #### bogosity alert */
7251 if (min_past < 0 && min_past != -1)
7252 min_past = -min_past;
7254 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
7255 || line_start_cache_end (w) < point)
7258 int win_char_height = window_char_height (w, 1);
7260 /* Occasionally we get here with a 0 height
7261 window. find_next_newline_no_quit will abort if we pass it a
7262 count of 0 so handle that case. */
7263 if (!win_char_height)
7264 win_char_height = 1;
7266 if (!Dynarr_length (cache))
7268 Bufpos from = find_next_newline_no_quit (b, point, -1);
7269 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
7271 update_line_start_cache (w, from, to, point, 0);
7273 if (!Dynarr_length (cache))
7275 w->line_cache_validation_override--;
7280 assert (Dynarr_length (cache));
7283 while (line_start_cache_start (w) > point
7284 && (loop < cache_adjustment || min_past == -1))
7288 from = line_start_cache_start (w);
7289 if (from <= BUF_BEGV (b))
7292 from = find_next_newline_no_quit (b, from, -win_char_height);
7293 to = line_start_cache_end (w);
7295 update_line_start_cache (w, from, to, point, 0);
7299 if (line_start_cache_start (w) > point)
7303 from = find_next_newline_no_quit (b, point, -1);
7304 if (from >= BUF_ZV (b))
7306 to = find_next_newline_no_quit (b, from, -win_char_height);
7311 to = find_next_newline_no_quit (b, from, win_char_height);
7313 update_line_start_cache (w, from, to, point, 0);
7317 while (line_start_cache_end (w) < point
7318 && (loop < cache_adjustment || min_past == -1))
7322 to = line_start_cache_end (w);
7323 if (to >= BUF_ZV (b))
7326 from = line_start_cache_end (w);
7327 to = find_next_newline_no_quit (b, from, win_char_height);
7329 update_line_start_cache (w, from, to, point, 0);
7333 if (line_start_cache_end (w) < point)
7337 from = find_next_newline_no_quit (b, point, -1);
7338 if (from >= BUF_ZV (b))
7340 to = find_next_newline_no_quit (b, from, -win_char_height);
7345 to = find_next_newline_no_quit (b, from, win_char_height);
7347 update_line_start_cache (w, from, to, point, 0);
7351 assert (Dynarr_length (cache));
7356 /* This could happen if the buffer is narrowed. */
7357 if (line_start_cache_start (w) > point
7358 || line_start_cache_end (w) < point)
7360 w->line_cache_validation_override--;
7366 top = Dynarr_length (cache) - 1;
7371 unsigned int new_pos;
7374 pos = (bottom + top + 1) >> 1;
7375 start = Dynarr_atp (cache, pos)->start;
7376 end = Dynarr_atp (cache, pos)->end;
7378 if (point >= start && point <= end)
7380 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
7383 find_next_newline_no_quit (b, line_start_cache_start (w),
7385 Bufpos to = line_start_cache_end (w);
7387 update_line_start_cache (w, from, to, point, 0);
7388 goto find_point_loop;
7390 else if ((Dynarr_length (cache) - pos - 1) < min_past
7391 && line_start_cache_end (w) < BUF_ZV (b))
7393 Bufpos from = line_start_cache_end (w);
7394 Bufpos to = find_next_newline_no_quit (b, from,
7399 update_line_start_cache (w, from, to, point, 0);
7400 goto find_point_loop;
7404 w->line_cache_validation_override--;
7408 else if (point > end)
7410 else if (point < start)
7415 new_pos = (bottom + top + 1) >> 1;
7418 w->line_cache_validation_override--;
7424 /* Return a boolean indicating if POINT would be visible in window W
7425 if display of the window was to begin at STARTP. */
7428 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
7430 struct buffer *b = XBUFFER (w->buffer);
7432 int bottom = WINDOW_TEXT_HEIGHT (w);
7435 /* If point is before the intended start it obviously can't be visible. */
7439 /* If point or start are not in the accessible buffer range, then
7441 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
7442 || point < BUF_BEGV (b) || point > BUF_ZV (b))
7445 validate_line_start_cache (w);
7446 w->line_cache_validation_override++;
7448 start_elt = point_in_line_start_cache (w, startp, 0);
7449 if (start_elt == -1)
7451 w->line_cache_validation_override--;
7455 assert (line_start_cache_start (w) <= startp
7456 && line_start_cache_end (w) >= startp);
7462 /* Expand the cache if necessary. */
7463 if (start_elt == Dynarr_length (w->line_start_cache))
7466 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
7468 start_elt = point_in_line_start_cache (w, old_startp,
7469 window_char_height (w, 0));
7471 /* We've already actually processed old_startp, so increment
7475 /* If this happens we didn't add any extra elements. Bummer. */
7476 if (start_elt == Dynarr_length (w->line_start_cache))
7478 w->line_cache_validation_override--;
7483 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
7485 if (pixpos + height > bottom)
7487 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7489 w->line_cache_validation_override--;
7495 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
7497 w->line_cache_validation_override--;
7505 /* For the given window W, if display starts at STARTP, what will be
7506 the buffer position at the beginning or end of the last line
7507 displayed. The end of the last line is also know as the window end
7510 #### With a little work this could probably be reworked as just a
7511 call to start_with_line_at_pixpos. */
7514 start_end_of_last_line (struct window *w, Bufpos startp, int end)
7516 struct buffer *b = XBUFFER (w->buffer);
7517 line_start_cache_dynarr *cache = w->line_start_cache;
7519 int bottom = WINDOW_TEXT_HEIGHT (w);
7523 validate_line_start_cache (w);
7524 w->line_cache_validation_override++;
7526 if (startp < BUF_BEGV (b))
7527 startp = BUF_BEGV (b);
7528 else if (startp > BUF_ZV (b))
7529 startp = BUF_ZV (b);
7532 start_elt = point_in_line_start_cache (w, cur_start, 0);
7533 if (start_elt == -1)
7534 abort (); /* this had better never happen */
7538 int height = Dynarr_atp (cache, start_elt)->height;
7540 cur_start = Dynarr_atp (cache, start_elt)->start;
7542 if (pixpos + height > bottom)
7544 /* Adjust for any possible clip. */
7545 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7550 w->line_cache_validation_override--;
7554 return BUF_BEGV (b);
7558 w->line_cache_validation_override--;
7560 return Dynarr_atp (cache, start_elt)->end;
7562 return Dynarr_atp (cache, start_elt)->start;
7568 if (start_elt == Dynarr_length (cache))
7570 Bufpos from = line_start_cache_end (w);
7571 int win_char_height = window_char_height (w, 0);
7572 Bufpos to = find_next_newline_no_quit (b, from,
7577 /* We've hit the end of the bottom so that's what it is. */
7578 if (from >= BUF_ZV (b))
7580 w->line_cache_validation_override--;
7584 update_line_start_cache (w, from, to, BUF_PT (b), 0);
7586 /* Updating the cache invalidates any current indexes. */
7587 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
7592 /* For the given window W, if display starts at STARTP, what will be
7593 the buffer position at the beginning of the last line displayed. */
7596 start_of_last_line (struct window *w, Bufpos startp)
7598 return start_end_of_last_line (w, startp, 0);
7601 /* For the given window W, if display starts at STARTP, what will be
7602 the buffer position at the end of the last line displayed. This is
7603 also know as the window end position. */
7606 end_of_last_line (struct window *w, Bufpos startp)
7608 return start_end_of_last_line (w, startp, 1);
7611 /* For window W, what does the starting position have to be so that
7612 the line containing POINT will cover pixel position PIXPOS. */
7615 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
7617 struct buffer *b = XBUFFER (w->buffer);
7619 Bufpos cur_pos, prev_pos = point;
7620 int point_line_height;
7621 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
7623 validate_line_start_cache (w);
7624 w->line_cache_validation_override++;
7626 cur_elt = point_in_line_start_cache (w, point, 0);
7627 /* #### See comment in update_line_start_cache about big minibuffers. */
7630 w->line_cache_validation_override--;
7634 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
7638 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7640 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7642 /* Do not take into account the value of vertical_clip here.
7643 That is the responsibility of the calling functions. */
7646 w->line_cache_validation_override--;
7647 if (-pixheight > point_line_height)
7648 /* We can't make the target line cover pixpos, so put it
7649 above pixpos. That way it will at least be visible. */
7659 int win_char_height;
7661 if (cur_pos <= BUF_BEGV (b))
7663 w->line_cache_validation_override--;
7664 return BUF_BEGV (b);
7667 win_char_height = window_char_height (w, 0);
7668 if (!win_char_height)
7669 win_char_height = 1;
7671 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
7672 to = line_start_cache_end (w);
7673 update_line_start_cache (w, from, to, point, 0);
7675 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
7676 assert (cur_elt >= 0);
7682 /* For window W, what does the starting position have to be so that
7683 the line containing point is on display line LINE. If LINE is
7684 positive it is considered to be the number of lines from the top of
7685 the window (0 is the top line). If it is negative the number is
7686 considered to be the number of lines from the bottom (-1 is the
7690 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
7692 validate_line_start_cache (w);
7693 w->line_cache_validation_override++;
7697 int cur_elt = point_in_line_start_cache (w, point, line);
7699 if (cur_elt - line < 0)
7700 cur_elt = 0; /* Hit the top */
7704 w->line_cache_validation_override--;
7705 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
7709 /* The calculated value of pixpos is correct for the bottom line
7710 or what we want when line is -1. Therefore we subtract one
7711 because we have already handled one line. */
7712 int new_line = -line - 1;
7713 int cur_elt = point_in_line_start_cache (w, point, new_line);
7714 int pixpos = WINDOW_TEXT_BOTTOM (w);
7715 Bufpos retval, search_point;
7717 /* If scroll_on_clipped_lines is false, the last "visible" line of
7718 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7719 If s_o_c_l is true, then we don't want to count a clipped
7720 line, so back up from the bottom by the height of the line
7721 containing point. */
7722 if (scroll_on_clipped_lines)
7723 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7727 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
7729 /* Hit the bottom of the buffer. */
7731 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
7735 XSETWINDOW (window, w);
7736 default_face_height_and_width (window, &defheight, 0);
7738 cur_elt = Dynarr_length (w->line_start_cache) - 1;
7740 pixpos -= (adjustment * defheight);
7741 if (pixpos < WINDOW_TEXT_TOP (w))
7742 pixpos = WINDOW_TEXT_TOP (w);
7745 cur_elt = cur_elt + new_line;
7747 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7749 retval = start_with_line_at_pixpos (w, search_point, pixpos);
7750 w->line_cache_validation_override--;
7755 /* This is used to speed up vertical scrolling by caching the known
7756 buffer starting positions for display lines. This allows the
7757 scrolling routines to avoid costly calls to regenerate_window. If
7758 NO_REGEN is true then it will only add the values in the DESIRED
7759 display structs which are in the given range.
7761 Note also that the FROM/TO values are minimums. It is possible
7762 that this function will actually add information outside of the
7763 lines containing those positions. This can't hurt but it could
7766 #### We currently force the cache to have only 1 contiguous region.
7767 It might help to make the cache a dynarr of caches so that we can
7768 cover more areas. This might, however, turn out to be a lot of
7769 overhead for too little gain. */
7772 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
7773 Bufpos point, int no_regen)
7775 struct buffer *b = XBUFFER (w->buffer);
7776 line_start_cache_dynarr *cache = w->line_start_cache;
7777 Bufpos low_bound, high_bound;
7779 validate_line_start_cache (w);
7780 w->line_cache_validation_override++;
7781 updating_line_start_cache = 1;
7783 if (from < BUF_BEGV (b))
7784 from = BUF_BEGV (b);
7785 if (to > BUF_ZV (b))
7790 updating_line_start_cache = 0;
7791 w->line_cache_validation_override--;
7795 if (Dynarr_length (cache))
7797 low_bound = line_start_cache_start (w);
7798 high_bound = line_start_cache_end (w);
7800 /* Check to see if the desired range is already in the cache. */
7801 if (from >= low_bound && to <= high_bound)
7803 updating_line_start_cache = 0;
7804 w->line_cache_validation_override--;
7808 /* Check to make sure that the desired range is adjacent to the
7809 current cache. If not, invalidate the cache. */
7810 if (to < low_bound || from > high_bound)
7812 Dynarr_reset (cache);
7813 low_bound = high_bound = -1;
7818 low_bound = high_bound = -1;
7821 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
7823 /* This could be integrated into the next two sections, but it is easier
7824 to follow what's going on by having it separate. */
7829 update_internal_cache_list (w, DESIRED_DISP);
7830 if (!Dynarr_length (internal_cache))
7832 updating_line_start_cache = 0;
7833 w->line_cache_validation_override--;
7837 start = Dynarr_atp (internal_cache, 0)->start;
7839 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
7841 /* We aren't allowed to generate additional information to fill in
7842 gaps, so if the DESIRED structs don't overlap the cache, reset the
7844 if (Dynarr_length (cache))
7846 if (end < low_bound || start > high_bound)
7847 Dynarr_reset (cache);
7849 /* #### What should really happen if what we are doing is
7850 extending a line (the last line)? */
7851 if (Dynarr_length (cache) == 1
7852 && Dynarr_length (internal_cache) == 1)
7853 Dynarr_reset (cache);
7856 if (!Dynarr_length (cache))
7858 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7859 Dynarr_length (internal_cache));
7860 updating_line_start_cache = 0;
7861 w->line_cache_validation_override--;
7865 /* An extra check just in case the calling function didn't pass in
7866 the bounds of the DESIRED structs in the first place. */
7867 if (start >= low_bound && end <= high_bound)
7869 updating_line_start_cache = 0;
7870 w->line_cache_validation_override--;
7874 /* At this point we know that the internal cache partially overlaps
7876 if (start < low_bound)
7878 int ic_elt = Dynarr_length (internal_cache) - 1;
7881 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7889 Dynarr_reset (cache);
7890 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7891 Dynarr_length (internal_cache));
7892 updating_line_start_cache = 0;
7893 w->line_cache_validation_override--;
7897 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7901 if (end > high_bound)
7905 while (ic_elt < Dynarr_length (internal_cache))
7907 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7913 if (!(ic_elt < Dynarr_length (internal_cache)))
7915 Dynarr_reset (cache);
7916 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7917 Dynarr_length (internal_cache));
7918 updating_line_start_cache = 0;
7919 w->line_cache_validation_override--;
7923 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7924 Dynarr_length (internal_cache) - ic_elt);
7927 updating_line_start_cache = 0;
7928 w->line_cache_validation_override--;
7932 if (!Dynarr_length (cache) || from < low_bound)
7934 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7936 int old_lb = low_bound;
7938 while (startp < old_lb || low_bound == -1)
7943 regenerate_window (w, startp, point, CMOTION_DISP);
7944 update_internal_cache_list (w, CMOTION_DISP);
7946 /* If this assert is triggered then regenerate_window failed
7947 to layout a single line. That is not supposed to be
7948 possible because we impose a minimum height on the buffer
7949 and override vertical clip when we are in here. */
7950 /* #### Ah, but it is because the window may temporarily
7951 exist but not have any lines at all if the minibuffer is
7952 real big. Look into that situation better. */
7953 if (!Dynarr_length (internal_cache))
7955 if (old_lb == -1 && low_bound == -1)
7957 updating_line_start_cache = 0;
7958 w->line_cache_validation_override--;
7962 assert (Dynarr_length (internal_cache));
7964 assert (startp == Dynarr_atp (internal_cache, 0)->start);
7966 ic_elt = Dynarr_length (internal_cache) - 1;
7967 if (low_bound != -1)
7971 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
7977 assert (ic_elt >= 0);
7979 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
7982 * Handle invisible text properly:
7983 * If the last line we're inserting has the same end as the
7984 * line before which it will be added, merge the two lines.
7986 if (Dynarr_length (cache) &&
7987 Dynarr_atp (internal_cache, ic_elt)->end ==
7988 Dynarr_atp (cache, marker)->end)
7990 Dynarr_atp (cache, marker)->start
7991 = Dynarr_atp (internal_cache, ic_elt)->start;
7992 Dynarr_atp (cache, marker)->height
7993 = Dynarr_atp (internal_cache, ic_elt)->height;
7997 if (ic_elt >= 0) /* we still have lines to add.. */
7999 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
8000 ic_elt + 1, marker);
8001 marker += (ic_elt + 1);
8004 if (startp < low_bound || low_bound == -1)
8006 startp = new_startp;
8007 if (startp > BUF_ZV (b))
8009 updating_line_start_cache = 0;
8010 w->line_cache_validation_override--;
8016 assert (Dynarr_length (cache));
8017 assert (from >= low_bound);
8019 /* Readjust the high_bound to account for any changes made while
8020 correcting the low_bound. */
8021 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8023 if (to > high_bound)
8025 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
8029 regenerate_window (w, startp, point, CMOTION_DISP);
8030 update_internal_cache_list (w, CMOTION_DISP);
8032 /* See comment above about regenerate_window failing. */
8033 assert (Dynarr_length (internal_cache));
8035 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
8036 Dynarr_length (internal_cache));
8037 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8038 startp = high_bound + 1;
8040 while (to > high_bound);
8043 updating_line_start_cache = 0;
8044 w->line_cache_validation_override--;
8045 assert (to <= high_bound);
8049 /* Given x and y coordinates in characters, relative to a window,
8050 return the pixel location corresponding to those coordinates. The
8051 pixel location returned is the center of the given character
8052 position. The pixel values are generated relative to the window,
8055 The modeline is considered to be part of the window. */
8058 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
8059 int *pix_x, int *pix_y)
8061 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
8062 int num_disp_lines, modeline;
8064 int defheight, defwidth;
8066 XSETWINDOW (window, w);
8067 default_face_height_and_width (window, &defheight, &defwidth);
8069 /* If we get a bogus value indicating somewhere above or to the left of
8070 the window, use the first window line or character position
8077 num_disp_lines = Dynarr_length (dla);
8081 if (Dynarr_atp (dla, 0)->modeline)
8088 /* First check if the y position intersects the display lines. */
8089 if (char_y < num_disp_lines)
8091 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
8092 struct display_block *db = get_display_block_from_line (dl, TEXT);
8094 *pix_y = (dl->ypos - dl->ascent +
8095 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
8097 if (char_x < Dynarr_length (db->runes))
8099 struct rune *rb = Dynarr_atp (db->runes, char_x);
8101 *pix_x = rb->xpos + (rb->width >> 1);
8105 int last_rune = Dynarr_length (db->runes) - 1;
8106 struct rune *rb = Dynarr_atp (db->runes, last_rune);
8108 char_x -= last_rune;
8110 *pix_x = rb->xpos + rb->width;
8111 *pix_x += ((char_x - 1) * defwidth);
8112 *pix_x += (defwidth >> 1);
8117 /* It didn't intersect, so extrapolate. #### For now, we include the
8118 modeline in this since we don't have true character positions in
8121 if (!Dynarr_length (w->face_cachels))
8122 reset_face_cachels (w);
8124 char_y -= num_disp_lines;
8126 if (Dynarr_length (dla))
8128 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
8129 *pix_y = dl->ypos + dl->descent - dl->clip;
8132 *pix_y = WINDOW_TEXT_TOP (w);
8134 *pix_y += (char_y * defheight);
8135 *pix_y += (defheight >> 1);
8137 *pix_x = WINDOW_TEXT_LEFT (w);
8138 /* Don't adjust by one because this is still the unadjusted value. */
8139 *pix_x += (char_x * defwidth);
8140 *pix_x += (defwidth >> 1);
8143 if (*pix_x > w->pixel_left + w->pixel_width)
8144 *pix_x = w->pixel_left + w->pixel_width;
8145 if (*pix_y > w->pixel_top + w->pixel_height)
8146 *pix_y = w->pixel_top + w->pixel_height;
8148 *pix_x -= w->pixel_left;
8149 *pix_y -= w->pixel_top;
8152 /* Given a display line and a position, determine if there is a glyph
8153 there and return information about it if there is. */
8156 get_position_object (struct display_line *dl, Lisp_Object *obj1,
8157 Lisp_Object *obj2, int x_coord, int *low_x_coord,
8160 struct display_block *db;
8163 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
8165 /* We use get_next_display_block to get the actual display block
8166 that would be displayed at x_coord. */
8168 if (block == NO_BLOCK)
8171 db = Dynarr_atp (dl->display_blocks, block);
8173 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
8175 struct rune *rb = Dynarr_atp (db->runes, elt);
8177 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
8179 if (rb->type == RUNE_DGLYPH)
8181 *obj1 = rb->object.dglyph.glyph;
8182 *obj2 = rb->object.dglyph.extent;
8191 *low_x_coord = rb->xpos;
8193 *high_x_coord = rb->xpos + rb->width;
8200 #define UPDATE_CACHE_RETURN \
8202 d->pixel_to_glyph_cache.valid = 1; \
8203 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8204 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8205 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8206 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8207 d->pixel_to_glyph_cache.frame = f; \
8208 d->pixel_to_glyph_cache.col = *col; \
8209 d->pixel_to_glyph_cache.row = *row; \
8210 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8211 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8212 d->pixel_to_glyph_cache.w = *w; \
8213 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8214 d->pixel_to_glyph_cache.closest = *closest; \
8215 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8216 d->pixel_to_glyph_cache.obj1 = *obj1; \
8217 d->pixel_to_glyph_cache.obj2 = *obj2; \
8218 d->pixel_to_glyph_cache.retval = position; \
8219 RETURN_SANS_WARNINGS position; \
8222 /* Given x and y coordinates in pixels relative to a frame, return
8223 information about what is located under those coordinates.
8225 The return value will be one of:
8227 OVER_TOOLBAR: over one of the 4 frame toolbars
8228 OVER_MODELINE: over a modeline
8229 OVER_BORDER: over an internal border
8230 OVER_NOTHING: over the text area, but not over text
8231 OVER_OUTSIDE: outside of the frame border
8232 OVER_TEXT: over text in the text area
8238 -- nil if the coordinates are not over a glyph or a toolbar button.
8242 -- an extent, if the coordinates are over a glyph in the text area
8245 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8246 equivalent coordinates relative to the upper-left corner of the glyph.
8248 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8249 equivalent coordinates relative to the upper-left corner of the character.
8251 Otherwise, OBJ_X and OBJ_Y are undefined.
8255 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
8256 int *col, int *row, int *obj_x, int *obj_y,
8257 struct window **w, Bufpos *bufpos,
8258 Bufpos *closest, Charcount *modeline_closest,
8259 Lisp_Object *obj1, Lisp_Object *obj2)
8262 struct pixel_to_glyph_translation_cache *cache;
8264 int frm_left, frm_right, frm_top, frm_bottom;
8265 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8266 int position = OVER_NOTHING;
8267 int device_check_failed = 0;
8268 display_line_dynarr *dla;
8270 /* This is a safety valve in case this got called with a frame in
8271 the middle of being deleted. */
8272 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
8274 device_check_failed = 1;
8275 d = NULL, cache = NULL; /* Warning suppression */
8279 d = XDEVICE (f->device);
8280 cache = &d->pixel_to_glyph_cache;
8283 if (!device_check_failed
8285 && cache->frame == f
8286 && cache->low_x_coord <= x_coord
8287 && cache->high_x_coord > x_coord
8288 && cache->low_y_coord <= y_coord
8289 && cache->high_y_coord > y_coord)
8293 *obj_x = cache->obj_x;
8294 *obj_y = cache->obj_y;
8296 *bufpos = cache->bufpos;
8297 *closest = cache->closest;
8298 *modeline_closest = cache->modeline_closest;
8299 *obj1 = cache->obj1;
8300 *obj2 = cache->obj2;
8302 return cache->retval;
8313 *modeline_closest = -1;
8317 low_x_coord = x_coord;
8318 high_x_coord = x_coord + 1;
8319 low_y_coord = y_coord;
8320 high_y_coord = y_coord + 1;
8323 if (device_check_failed)
8324 return OVER_NOTHING;
8326 frm_left = FRAME_LEFT_BORDER_END (f);
8327 frm_right = FRAME_RIGHT_BORDER_START (f);
8328 frm_top = FRAME_TOP_BORDER_END (f);
8329 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
8331 /* Check if the mouse is outside of the text area actually used by
8333 if (y_coord < frm_top)
8335 if (y_coord >= FRAME_TOP_BORDER_START (f))
8337 low_y_coord = FRAME_TOP_BORDER_START (f);
8338 high_y_coord = frm_top;
8339 position = OVER_BORDER;
8341 else if (y_coord >= 0)
8344 high_y_coord = FRAME_TOP_BORDER_START (f);
8345 position = OVER_TOOLBAR;
8349 low_y_coord = y_coord;
8351 position = OVER_OUTSIDE;
8354 else if (y_coord >= frm_bottom)
8356 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
8358 low_y_coord = frm_bottom;
8359 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
8360 position = OVER_BORDER;
8362 else if (y_coord < FRAME_PIXHEIGHT (f))
8364 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
8365 high_y_coord = FRAME_PIXHEIGHT (f);
8366 position = OVER_TOOLBAR;
8370 low_y_coord = FRAME_PIXHEIGHT (f);
8371 high_y_coord = y_coord;
8372 position = OVER_OUTSIDE;
8376 if (position != OVER_TOOLBAR && position != OVER_BORDER)
8378 if (x_coord < frm_left)
8380 if (x_coord >= FRAME_LEFT_BORDER_START (f))
8382 low_x_coord = FRAME_LEFT_BORDER_START (f);
8383 high_x_coord = frm_left;
8384 position = OVER_BORDER;
8386 else if (x_coord >= 0)
8389 high_x_coord = FRAME_LEFT_BORDER_START (f);
8390 position = OVER_TOOLBAR;
8394 low_x_coord = x_coord;
8396 position = OVER_OUTSIDE;
8399 else if (x_coord >= frm_right)
8401 if (x_coord < FRAME_RIGHT_BORDER_END (f))
8403 low_x_coord = frm_right;
8404 high_x_coord = FRAME_RIGHT_BORDER_END (f);
8405 position = OVER_BORDER;
8407 else if (x_coord < FRAME_PIXWIDTH (f))
8409 low_x_coord = FRAME_RIGHT_BORDER_END (f);
8410 high_x_coord = FRAME_PIXWIDTH (f);
8411 position = OVER_TOOLBAR;
8415 low_x_coord = FRAME_PIXWIDTH (f);
8416 high_x_coord = x_coord;
8417 position = OVER_OUTSIDE;
8422 #ifdef HAVE_TOOLBARS
8423 if (position == OVER_TOOLBAR)
8425 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
8428 UPDATE_CACHE_RETURN;
8430 #endif /* HAVE_TOOLBARS */
8432 /* We still have to return the window the pointer is next to and its
8433 relative y position even if it is outside the x boundary. */
8434 if (x_coord < frm_left)
8436 else if (x_coord > frm_right)
8437 x_coord = frm_right;
8439 /* Same in reverse. */
8440 if (y_coord < frm_top)
8442 else if (y_coord > frm_bottom)
8443 y_coord = frm_bottom;
8445 /* Find what window the given coordinates are actually in. */
8446 window = f->root_window;
8447 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
8449 /* If we didn't find a window, we're done. */
8452 UPDATE_CACHE_RETURN;
8454 else if (position != OVER_NOTHING)
8457 *modeline_closest = -1;
8459 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
8462 UPDATE_CACHE_RETURN;
8466 /* Check if the window is a minibuffer but isn't active. */
8467 if (MINI_WINDOW_P (*w) && !minibuf_level)
8469 /* Must reset the window value since some callers will ignore
8470 the return value if it is set. */
8472 UPDATE_CACHE_RETURN;
8475 /* See if the point is over window vertical divider */
8476 if (window_needs_vertical_divider (*w))
8478 int div_x_high = WINDOW_RIGHT (*w);
8479 int div_x_low = div_x_high - window_divider_width (*w);
8480 int div_y_high = WINDOW_BOTTOM (*w);
8481 int div_y_low = WINDOW_TOP (*w);
8483 if (div_x_low < x_coord && x_coord <= div_x_high &&
8484 div_y_low < y_coord && y_coord <= div_y_high)
8486 low_x_coord = div_x_low;
8487 high_x_coord = div_x_high;
8488 low_y_coord = div_y_low;
8489 high_y_coord = div_y_high;
8490 position = OVER_V_DIVIDER;
8491 UPDATE_CACHE_RETURN;
8495 dla = window_display_lines (*w, CURRENT_DISP);
8497 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
8499 int really_over_nothing = 0;
8500 struct display_line *dl = Dynarr_atp (dla, *row);
8502 if ((int) (dl->ypos - dl->ascent) <= y_coord
8503 && y_coord <= (int) (dl->ypos + dl->descent))
8505 int check_margin_glyphs = 0;
8506 struct display_block *db = get_display_block_from_line (dl, TEXT);
8507 struct rune *rb = 0;
8509 if (x_coord < dl->bounds.left_white
8510 || x_coord >= dl->bounds.right_white)
8511 check_margin_glyphs = 1;
8513 low_y_coord = dl->ypos - dl->ascent;
8514 high_y_coord = dl->ypos + dl->descent + 1;
8516 if (position == OVER_BORDER
8517 || position == OVER_OUTSIDE
8518 || check_margin_glyphs)
8520 int x_check, left_bound;
8522 if (check_margin_glyphs)
8525 left_bound = dl->bounds.left_white;
8529 x_check = high_x_coord;
8530 left_bound = frm_left;
8533 if (Dynarr_length (db->runes))
8535 if (x_check <= left_bound)
8538 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
8540 *closest = Dynarr_atp (db->runes, 0)->bufpos;
8546 Dynarr_atp (db->runes,
8547 Dynarr_length (db->runes) - 1)->bufpos;
8550 Dynarr_atp (db->runes,
8551 Dynarr_length (db->runes) - 1)->bufpos;
8555 *modeline_closest += dl->offset;
8557 *closest += dl->offset;
8561 /* #### What should be here. */
8563 *modeline_closest = 0;
8568 if (check_margin_glyphs)
8570 if (x_coord < dl->bounds.left_in
8571 || x_coord >= dl->bounds.right_in)
8573 /* If we are over the outside margins then we
8574 know the loop over the text block isn't going
8575 to accomplish anything. So we go ahead and
8576 set what information we can right here and
8579 *obj_y = y_coord - (dl->ypos - dl->ascent);
8580 get_position_object (dl, obj1, obj2, x_coord,
8581 &low_x_coord, &high_x_coord);
8583 UPDATE_CACHE_RETURN;
8587 UPDATE_CACHE_RETURN;
8590 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
8592 int past_end = (*col == Dynarr_length (db->runes));
8595 rb = Dynarr_atp (db->runes, *col);
8598 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
8603 rb = Dynarr_atp (db->runes, *col);
8606 *bufpos = rb->bufpos + dl->offset;
8607 low_x_coord = rb->xpos;
8608 high_x_coord = rb->xpos + rb->width;
8610 if (rb->type == RUNE_DGLYPH)
8614 /* Find the first character after the glyph. */
8615 while (elt < Dynarr_length (db->runes))
8617 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
8621 (Dynarr_atp (db->runes, elt)->bufpos +
8625 (Dynarr_atp (db->runes, elt)->bufpos +
8633 /* In this case we failed to find a non-glyph
8634 character so we return the last position
8635 displayed on the line. */
8636 if (elt == Dynarr_length (db->runes))
8639 *modeline_closest = dl->end_bufpos + dl->offset;
8641 *closest = dl->end_bufpos + dl->offset;
8642 really_over_nothing = 1;
8648 *modeline_closest = rb->bufpos + dl->offset;
8650 *closest = rb->bufpos + dl->offset;
8655 *row = window_displayed_height (*w);
8657 if (position == OVER_NOTHING)
8658 position = OVER_MODELINE;
8660 if (rb->type == RUNE_DGLYPH)
8662 *obj1 = rb->object.dglyph.glyph;
8663 *obj2 = rb->object.dglyph.extent;
8665 else if (rb->type == RUNE_CHAR)
8676 UPDATE_CACHE_RETURN;
8679 || (rb->type == RUNE_CHAR
8680 && rb->object.chr.ch == '\n'))
8683 /* At this point we may have glyphs in the right
8685 if (check_margin_glyphs)
8686 get_position_object (dl, obj1, obj2, x_coord,
8687 &low_x_coord, &high_x_coord);
8688 UPDATE_CACHE_RETURN;
8693 if (rb->type == RUNE_DGLYPH)
8695 *obj1 = rb->object.dglyph.glyph;
8696 *obj2 = rb->object.dglyph.extent;
8698 else if (rb->type == RUNE_CHAR)
8709 *obj_x = x_coord - rb->xpos;
8710 *obj_y = y_coord - (dl->ypos - dl->ascent);
8712 /* At this point we may have glyphs in the left
8714 if (check_margin_glyphs)
8715 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
8717 if (position == OVER_NOTHING && !really_over_nothing)
8718 position = OVER_TEXT;
8720 UPDATE_CACHE_RETURN;
8727 *row = Dynarr_length (dla) - 1;
8728 if (FRAME_WIN_P (f))
8730 int bot_elt = Dynarr_length (dla) - 1;
8734 struct display_line *dl = Dynarr_atp (dla, bot_elt);
8735 int adj_area = y_coord - (dl->ypos + dl->descent);
8739 XSETWINDOW (lwin, *w);
8740 default_face_height_and_width (lwin, 0, &defheight);
8742 *row += (adj_area / defheight);
8746 /* #### This should be checked out some more to determine what
8747 should really be going on. */
8748 if (!MARKERP ((*w)->start[CURRENT_DISP]))
8751 *closest = end_of_last_line (*w,
8752 marker_position ((*w)->start[CURRENT_DISP]));
8754 UPDATE_CACHE_RETURN;
8756 #undef UPDATE_CACHE_RETURN
8759 /***************************************************************************/
8761 /* Lisp functions */
8763 /***************************************************************************/
8765 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8766 Ensure that all minibuffers are correctly showing the echo area.
8770 Lisp_Object devcons, concons;
8772 DEVICE_LOOP_NO_BREAK (devcons, concons)
8774 struct device *d = XDEVICE (XCAR (devcons));
8775 Lisp_Object frmcons;
8777 DEVICE_FRAME_LOOP (frmcons, d)
8779 struct frame *f = XFRAME (XCAR (frmcons));
8781 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
8783 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
8785 * If the frame size has changed, there may be random
8786 * chud on the screen left from previous messages
8787 * because redisplay_frame hasn't been called yet.
8788 * Clear the screen to get rid of the potential mess.
8790 if (f->echo_area_garbaged)
8792 DEVMETH (d, clear_frame, (f));
8793 f->echo_area_garbaged = 0;
8795 redisplay_window (window, 0);
8796 call_redisplay_end_triggers (XWINDOW (window), 0);
8800 /* We now call the output_end routine for tty frames. We delay
8801 doing so in order to avoid cursor flicker. So much for 100%
8803 if (DEVICE_TTY_P (d))
8804 DEVMETH (d, output_end, (d));
8811 restore_disable_preemption_value (Lisp_Object value)
8813 disable_preemption = XINT (value);
8817 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8818 Clear frame FRAME and output again what is supposed to appear on it.
8819 FRAME defaults to the selected frame if omitted.
8820 Normally, redisplay is preempted as normal if input arrives. However,
8821 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8822 input and is guaranteed to proceed to completion.
8824 (frame, no_preempt))
8826 struct frame *f = decode_frame (frame);
8827 int count = specpdl_depth ();
8829 if (!NILP (no_preempt))
8831 record_unwind_protect (restore_disable_preemption_value,
8832 make_int (disable_preemption));
8833 disable_preemption++;
8837 redisplay_frame (f, 1);
8839 return unbind_to (count, Qnil);
8842 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8843 Ensure that FRAME's contents are correctly displayed.
8844 This differs from `redraw-frame' in that it only redraws what needs to
8845 be updated, as opposed to unconditionally clearing and redrawing
8847 FRAME defaults to the selected frame if omitted.
8848 Normally, redisplay is preempted as normal if input arrives. However,
8849 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8850 input and is guaranteed to proceed to completion.
8852 (frame, no_preempt))
8854 struct frame *f = decode_frame (frame);
8855 int count = specpdl_depth ();
8857 if (!NILP (no_preempt))
8859 record_unwind_protect (restore_disable_preemption_value,
8860 make_int (disable_preemption));
8861 disable_preemption++;
8864 redisplay_frame (f, 1);
8866 return unbind_to (count, Qnil);
8869 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
8870 Clear device DEVICE and output again what is supposed to appear on it.
8871 DEVICE defaults to the selected device if omitted.
8872 Normally, redisplay is preempted as normal if input arrives. However,
8873 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8874 input and is guaranteed to proceed to completion.
8876 (device, no_preempt))
8878 struct device *d = decode_device (device);
8879 Lisp_Object frmcons;
8880 int count = specpdl_depth ();
8882 if (!NILP (no_preempt))
8884 record_unwind_protect (restore_disable_preemption_value,
8885 make_int (disable_preemption));
8886 disable_preemption++;
8889 DEVICE_FRAME_LOOP (frmcons, d)
8891 XFRAME (XCAR (frmcons))->clear = 1;
8893 redisplay_device (d);
8895 return unbind_to (count, Qnil);
8898 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8899 Ensure that DEVICE's contents are correctly displayed.
8900 This differs from `redraw-device' in that it only redraws what needs to
8901 be updated, as opposed to unconditionally clearing and redrawing
8903 DEVICE defaults to the selected device if omitted.
8904 Normally, redisplay is preempted as normal if input arrives. However,
8905 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8906 input and is guaranteed to proceed to completion.
8908 (device, no_preempt))
8910 struct device *d = decode_device (device);
8911 int count = specpdl_depth ();
8913 if (!NILP (no_preempt))
8915 record_unwind_protect (restore_disable_preemption_value,
8916 make_int (disable_preemption));
8917 disable_preemption++;
8920 redisplay_device (d);
8922 return unbind_to (count, Qnil);
8925 /* Big lie. Big lie. This will force all modelines to be updated
8926 regardless if the all flag is set or not. It remains in existence
8927 solely for backwards compatibility. */
8928 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8929 Force the modeline of the current buffer to be redisplayed.
8930 With optional non-nil ALL, force redisplay of all modelines.
8934 MARK_MODELINE_CHANGED;
8938 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8939 Force an immediate update of the cursor on FRAME.
8940 FRAME defaults to the selected frame if omitted.
8944 redisplay_redraw_cursor (decode_frame (frame), 1);
8949 /***************************************************************************/
8951 /* Lisp-variable change triggers */
8953 /***************************************************************************/
8956 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
8959 /* Nothing to be done? */
8963 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
8964 Lisp_Object in_object, int flags)
8966 /* #### clip_changed should really be renamed something like
8967 global_redisplay_change. */
8973 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8976 if (WINDOWP (locale))
8978 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
8980 else if (FRAMEP (locale))
8982 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
8984 else if (DEVICEP (locale))
8986 Lisp_Object frmcons;
8987 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
8988 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8990 else if (CONSOLEP (locale))
8992 Lisp_Object frmcons, devcons;
8993 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
8994 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8996 else /* global or buffer */
8998 Lisp_Object frmcons, devcons, concons;
8999 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
9000 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9005 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
9008 if (XFRAME (w->frame)->init_finished)
9009 Fforce_cursor_redisplay (w->frame);
9012 #ifdef MEMORY_USAGE_STATS
9015 /***************************************************************************/
9017 /* memory usage computation */
9019 /***************************************************************************/
9022 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
9024 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9028 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
9029 struct overhead_stats *ovstats)
9036 total = Dynarr_memory_usage (dyn, ovstats);
9037 for (i = 0; i < Dynarr_largest (dyn); i++)
9038 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
9044 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
9045 struct overhead_stats *ovstats)
9047 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9051 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
9052 struct overhead_stats *ovstats)
9059 total = Dynarr_memory_usage (dyn, ovstats);
9060 for (i = 0; i < Dynarr_largest (dyn); i++)
9062 struct display_line *dl = &Dynarr_at (dyn, i);
9063 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
9064 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
9065 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
9072 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
9073 struct overhead_stats *ovstats)
9075 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9078 #endif /* MEMORY_USAGE_STATS */
9081 /***************************************************************************/
9083 /* initialization */
9085 /***************************************************************************/
9088 init_redisplay (void)
9090 disable_preemption = 0;
9091 preemption_count = 0;
9092 max_preempts = INIT_MAX_PREEMPTS;
9096 cmotion_display_lines = Dynarr_new (display_line);
9097 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
9098 formatted_string_emchar_dynarr = Dynarr_new (Emchar);
9099 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
9100 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
9101 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
9102 internal_cache = Dynarr_new (line_start_cache);
9103 xzero (formatted_string_display_line);
9106 /* window system is nil when in -batch mode */
9107 if (!initialized || noninteractive)
9110 /* If the user wants to use a window system, we shouldn't bother
9111 initializing the terminal. This is especially important when the
9112 terminal is so dumb that emacs gives up before and doesn't bother
9113 using the window system.
9115 If the DISPLAY environment variable is set, try to use X, and die
9116 with an error message if that doesn't work. */
9118 #ifdef HAVE_X_WINDOWS
9119 if (!strcmp (display_use, "x"))
9121 /* Some stuff checks this way early. */
9122 Vwindow_system = Qx;
9123 Vinitial_window_system = Qx;
9126 #endif /* HAVE_X_WINDOWS */
9128 #ifdef HAVE_MS_WINDOWS
9129 if (!strcmp (display_use, "mswindows"))
9131 /* Some stuff checks this way early. */
9132 Vwindow_system = Qmswindows;
9133 Vinitial_window_system = Qmswindows;
9136 #endif /* HAVE_MS_WINDOWS */
9139 /* If no window system has been specified, try to use the terminal. */
9142 stderr_out ("XEmacs: standard input is not a tty\n");
9146 /* Look at the TERM variable */
9147 if (!getenv ("TERM"))
9149 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
9153 Vinitial_window_system = Qtty;
9155 #else /* not HAVE_TTY */
9156 /* No DISPLAY specified, and no TTY support. */
9157 stderr_out ("XEmacs: Cannot open display.\n\
9158 Please set the environmental variable DISPLAY to an appropriate value.\n");
9165 syms_of_redisplay (void)
9167 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
9168 #ifndef INHIBIT_REDISPLAY_HOOKS
9169 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
9170 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
9171 #endif /* INHIBIT_REDISPLAY_HOOKS */
9172 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
9173 defsymbol (&Qbar_cursor, "bar-cursor");
9174 defsymbol (&Qwindow_scroll_functions, "window-scroll-functions");
9175 defsymbol (&Qredisplay_end_trigger_functions,
9176 "redisplay-end-trigger-functions");
9178 DEFSUBR (Fredisplay_echo_area);
9179 DEFSUBR (Fredraw_frame);
9180 DEFSUBR (Fredisplay_frame);
9181 DEFSUBR (Fredraw_device);
9182 DEFSUBR (Fredisplay_device);
9183 DEFSUBR (Fredraw_modeline);
9184 DEFSUBR (Fforce_cursor_redisplay);
9188 vars_of_redisplay (void)
9191 staticpro (&last_arrow_position);
9192 staticpro (&last_arrow_string);
9193 last_arrow_position = Qnil;
9194 last_arrow_string = Qnil;
9197 updating_line_start_cache = 0;
9199 /* #### Probably temporary */
9200 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
9201 \(Temporary) Setting this will impact the performance of the internal
9204 cache_adjustment = 2;
9206 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
9207 Minimum pixel height for clipped bottom display line.
9208 A clipped line shorter than this won't be displayed.
9210 redisplay_variable_changed);
9213 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
9214 Minimum visible area for clipped glyphs at right boundary.
9215 Clipped glyphs shorter than this won't be displayed.
9216 Only pixmap glyph instances are currently allowed to be clipped.
9218 redisplay_variable_changed);
9219 horizontal_clip = 5;
9221 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
9222 String displayed by modeline-format's "%m" specification.
9224 Vglobal_mode_string = Qnil;
9226 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
9227 Marker for where to display an arrow on top of the buffer text.
9228 This must be the beginning of a line in order to work.
9229 See also `overlay-arrow-string'.
9231 redisplay_variable_changed);
9232 Voverlay_arrow_position = Qnil;
9234 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
9235 String to display as an arrow. See also `overlay-arrow-position'.
9237 redisplay_variable_changed);
9238 Voverlay_arrow_string = Qnil;
9240 DEFVAR_INT ("scroll-step", &scroll_step /*
9241 *The number of lines to try scrolling a window by when point moves out.
9242 If that fails to bring point back on frame, point is centered instead.
9243 If this is zero, point is always centered after it moves off screen.
9247 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
9248 *Scroll up to this many lines, to bring point back on screen.
9250 scroll_conservatively = 0;
9252 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
9253 &truncate_partial_width_windows /*
9254 *Non-nil means truncate lines in all windows less than full frame wide.
9256 redisplay_variable_changed);
9257 truncate_partial_width_windows = 1;
9259 DEFVAR_BOOL ("visible-bell", &visible_bell /*
9260 *Non-nil means try to flash the frame to represent a bell.
9264 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
9265 *Non-nil means no need to redraw entire frame after suspending.
9266 A non-nil value is useful if the terminal can automatically preserve
9267 Emacs's frame display when you reenter Emacs.
9268 It is up to you to set this variable if your terminal can do that.
9270 no_redraw_on_reenter = 0;
9272 DEFVAR_LISP ("window-system", &Vwindow_system /*
9273 A symbol naming the window-system under which Emacs is running,
9274 such as `x', or nil if emacs is running on an ordinary terminal.
9276 Do not use this variable, except for GNU Emacs compatibility, as it
9277 gives wrong values in a multi-device environment. Use `console-type'
9280 Vwindow_system = Qnil;
9282 /* #### Temporary shit until window-system is eliminated. */
9283 DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /*
9286 Vinitial_window_system = Qnil;
9288 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
9289 Non-nil means put cursor in minibuffer, at end of any message there.
9291 cursor_in_echo_area = 0;
9293 /* #### Shouldn't this be generalized as follows:
9295 if nil, use block cursor.
9296 if a number, use a bar cursor of that width.
9297 Otherwise, use a 1-pixel bar cursor.
9299 #### Or better yet, this variable should be trashed entirely
9300 (use a Lisp-magic variable to maintain compatibility)
9301 and a specifier `cursor-shape' added, which allows a block
9302 cursor, a bar cursor, a flashing block or bar cursor,
9303 maybe a caret cursor, etc. */
9305 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
9306 Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9310 #ifndef INHIBIT_REDISPLAY_HOOKS
9311 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
9312 Function or functions to run before every redisplay.
9313 Functions on this hook must be careful to avoid signalling errors!
9315 Vpre_redisplay_hook = Qnil;
9317 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
9318 Function or functions to run after every redisplay.
9319 Functions on this hook must be careful to avoid signalling errors!
9321 Vpost_redisplay_hook = Qnil;
9322 #endif /* INHIBIT_REDISPLAY_HOOKS */
9324 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
9325 Bump this to tell the C code to call `display-warning-buffer'
9326 at next redisplay. You should not normally change this; the function
9327 `display-warning' automatically does this at appropriate times.
9329 display_warning_tick = 0;
9331 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
9332 Non-nil means inhibit display of warning messages.
9333 You should *bind* this, not set it. Any pending warning messages
9334 will be displayed when the binding no longer applies.
9336 /* reset to 0 by startup.el after the splash screen has displayed.
9337 This way, the warnings don't obliterate the splash screen. */
9338 inhibit_warning_display = 1;
9340 DEFVAR_LISP ("window-size-change-functions",
9341 &Vwindow_size_change_functions /*
9342 Not currently implemented.
9343 Functions called before redisplay, if window sizes have changed.
9344 The value should be a list of functions that take one argument.
9345 Just before redisplay, for each frame, if any of its windows have changed
9346 size since the last redisplay, or have been split or deleted,
9347 all the functions in the list are called, with the frame as argument.
9349 Vwindow_size_change_functions = Qnil;
9351 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
9352 Not currently implemented.
9353 Functions to call before redisplaying a window with scrolling.
9354 Each function is called with two arguments, the window
9355 and its new display-start position. Note that the value of `window-end'
9356 is not valid when these functions are called.
9358 Vwindow_scroll_functions = Qnil;
9360 DEFVAR_LISP ("redisplay-end-trigger-functions",
9361 &Vredisplay_end_trigger_functions /*
9362 See `set-window-redisplay-end-trigger'.
9364 Vredisplay_end_trigger_functions = Qnil;
9366 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
9367 *Non-nil means column display number starts at 1.
9369 column_number_start_at_one = 0;
9373 specifier_vars_of_redisplay (void)
9375 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
9376 *Width of left margin.
9377 This is a specifier; use `set-specifier' to change it.
9379 Vleft_margin_width = Fmake_specifier (Qnatnum);
9380 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
9381 set_specifier_caching (Vleft_margin_width,
9382 slot_offset (struct window, left_margin_width),
9383 some_window_value_changed,
9384 slot_offset (struct frame, left_margin_width),
9385 margin_width_changed_in_frame);
9387 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
9388 *Width of right margin.
9389 This is a specifier; use `set-specifier' to change it.
9391 Vright_margin_width = Fmake_specifier (Qnatnum);
9392 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
9393 set_specifier_caching (Vright_margin_width,
9394 slot_offset (struct window, right_margin_width),
9395 some_window_value_changed,
9396 slot_offset (struct frame, right_margin_width),
9397 margin_width_changed_in_frame);
9399 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
9400 *Minimum ascent height of lines.
9401 This is a specifier; use `set-specifier' to change it.
9403 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
9404 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
9405 set_specifier_caching (Vminimum_line_ascent,
9406 slot_offset (struct window, minimum_line_ascent),
9407 some_window_value_changed,
9410 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
9411 *Minimum descent height of lines.
9412 This is a specifier; use `set-specifier' to change it.
9414 Vminimum_line_descent = Fmake_specifier (Qnatnum);
9415 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
9416 set_specifier_caching (Vminimum_line_descent,
9417 slot_offset (struct window, minimum_line_descent),
9418 some_window_value_changed,
9421 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
9422 *Non-nil means use the left outside margin as extra whitespace when
9423 displaying 'whitespace or 'inside-margin glyphs.
9424 This is a specifier; use `set-specifier' to change it.
9426 Vuse_left_overflow = Fmake_specifier (Qboolean);
9427 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
9428 set_specifier_caching (Vuse_left_overflow,
9429 slot_offset (struct window, use_left_overflow),
9430 some_window_value_changed,
9433 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
9434 *Non-nil means use the right outside margin as extra whitespace when
9435 displaying 'whitespace or 'inside-margin glyphs.
9436 This is a specifier; use `set-specifier' to change it.
9438 Vuse_right_overflow = Fmake_specifier (Qboolean);
9439 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
9440 set_specifier_caching (Vuse_right_overflow,
9441 slot_offset (struct window, use_right_overflow),
9442 some_window_value_changed,
9445 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9446 *Non-nil means the text cursor is visible (this is usually the case).
9447 This is a specifier; use `set-specifier' to change it.
9449 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
9450 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
9451 set_specifier_caching (Vtext_cursor_visible_p,
9452 slot_offset (struct window, text_cursor_visible_p),
9453 text_cursor_visible_p_changed,