1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Free Software Foundation, Inc.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1995 Sun Microsystems, Inc.
6 Copyright (C) 1996 Chuck Thompson.
8 This file is part of XEmacs.
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 /* Synched up with: Not in FSF. */
27 /* Author: Chuck Thompson */
29 /* Fixed up by Ben Wing for Mule */
31 /* This file has been Mule-ized. */
33 /*****************************************************************************
34 The Golden Rules of Redisplay
36 First: It Is Better To Be Correct Than Fast
37 Second: Thou Shalt Not Run Elisp From Within Redisplay
38 Third: It Is Better To Be Fast Than Not To Be
39 ****************************************************************************/
58 #include "redisplay.h"
61 #include "line-number.h"
63 #include "file-coding.h"
67 #include "console-tty.h"
69 #include <unistd.h> /* for isatty() */
73 /* Note: We have to be careful throughout this code to properly handle
74 and differentiate between Bufbytes and Emchars.
76 Since strings are generally composed of Bufbytes, I've taken the tack
77 that any contiguous set of Bufbytes is called a "string", while
78 any contiguous set of Emchars is called an "array". */
80 /* Return value to indicate a failure by an add_*_rune routine to add
81 a rune, but no propagation information needs to be returned. */
82 #define ADD_FAILED (prop_block_dynarr *) 1
84 #define BEGIN_GLYPHS 0
87 #define RIGHT_GLYPHS 3
89 /* Set the vertical clip to 0 if we are currently updating the line
90 start cache. Otherwise for buffers of line height 1 it may fail to
91 be able to work properly because regenerate_window will not layout
93 #define VERTICAL_CLIP(w, display) \
94 (updating_line_start_cache \
96 : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
100 /* The following structures are completely private to redisplay.c so
101 we put them here instead of in a header file, for modularity. */
103 /* NOTE: Bytinds not Bufpos's in this structure. */
105 typedef struct position_redisplay_data_type
107 /* This information is normally filled in by the create_*_block
108 routines and is used by the add_*_rune routines. */
111 struct display_block *db;
112 struct display_line *dl;
113 Emchar ch; /* Character that is to be added. This is
114 used to communicate this information to
115 add_emchar_rune(). */
116 Lisp_Object last_charset; /* The charset of the previous character.
117 Used to optimize some lookups -- we
118 only have to do some things when
119 the charset changes. */
120 face_index last_findex; /* The face index of the previous character.
121 Needed to ensure the validity of the
122 last_charset optimization. */
124 int last_char_width; /* The width of the previous character. */
125 int font_is_bogus; /* If true, it means we couldn't instantiate
126 the font for this charset, so we substitute
127 ~'s from the ASCII charset. */
132 int blank_width; /* Width of the blank that is to be added.
133 This is used to communicate this information
136 This is also used rather cheesily to
137 communicate the width of the eol-cursor-size
138 blank that exists at the end of the line.
139 add_emchar_rune() is called cheesily with
140 the non-printing char '\n', which is stuck
141 in the output routines with its width being
143 Bytind bi_cursor_bufpos;/* This stores the buffer position of the cursor. */
144 unsigned int cursor_type :3;
145 int cursor_x; /* rune block cursor is at */
146 int start_col; /* Number of character columns (each column has
147 a width of the default char width) that still
148 need to be skipped. This is used for horizontal
149 scrolling, where a certain number of columns
150 (those off the left side of the screen) need
151 to be skipped before anything is displayed. */
152 Bytind bi_start_col_enabled;
154 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
155 glyph differs from space_width (w).
156 0 if no hscroll glyph was used,
157 i.e. the window is not scrolled
158 horizontally. Used in tab
161 /* Information about the face the text should be displayed in and
162 any begin-glyphs and end-glyphs. */
163 struct extent_fragment *ef;
166 /* The height of a pixmap may either be predetermined if the user
167 has set a baseline value, or it may be dependent on whatever the
168 line ascent and descent values end up being, based just on font
169 information. In the first case we can immediately update the
170 values, thus their inclusion here. In the last case we cannot
171 determine the actual contribution to the line height until we
172 have finished laying out all text on the line. Thus we propagate
173 the max height of such pixmaps and do a final calculation after
174 all text has been added to the line. */
177 int max_pixmap_height;
179 Lisp_Object result_str; /* String where we put the result of
180 generating a formatted string in the modeline. */
181 int is_modeline; /* Non-zero if we're generating the modeline. */
182 Charcount modeline_charpos; /* Number of chars used in result_str so far;
183 corresponds to bytepos. */
184 Bytecount bytepos; /* Number of bytes used in result_str so far.
185 We don't actually copy the bytes into result_str
186 until the end because we don't know how big the
187 string is going to be until then. */
198 /* Data that should be propagated to the next line. Either a single
199 Emchar or a string of Bufbyte's.
201 The actual data that is propagated ends up as a Dynarr of these
204 #### It's unclean that both Emchars and Bufbytes are here.
207 typedef struct prop_block prop_block;
217 Bytecount len; /* length of the string. */
223 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
224 unsigned int cursor_type :3;
237 Dynarr_declare (prop_block);
241 static void generate_formatted_string_db (Lisp_Object format_str,
242 Lisp_Object result_str,
244 struct display_line *dl,
245 struct display_block *db,
246 face_index findex, int min_pixpos,
247 int max_pixpos, int type);
248 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
249 Charcount pos, Charcount min_pos,
250 Charcount max_pos, Lisp_Object elt,
251 int depth, int max_pixsize,
252 face_index findex, int type);
253 static prop_block_dynarr *add_glyph_rune (pos_data *data,
254 struct glyph_block *gb,
255 int pos_type, int allow_cursor,
256 struct glyph_cachel *cachel);
257 static Bytind create_text_block (struct window *w, struct display_line *dl,
258 Bytind bi_start_pos, int start_col,
259 prop_block_dynarr **prop,
261 static int create_overlay_glyph_block (struct window *w,
262 struct display_line *dl);
263 static void create_left_glyph_block (struct window *w,
264 struct display_line *dl,
266 static void create_right_glyph_block (struct window *w,
267 struct display_line *dl);
268 static void redisplay_windows (Lisp_Object window, int skip_selected);
269 static void decode_mode_spec (struct window *w, Emchar spec, int type);
270 static void free_display_line (struct display_line *dl);
271 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
272 Bufpos point, int no_regen);
273 static int point_visible (struct window *w, Bufpos point, int type);
275 /* This used to be 10 but 30 seems to give much better performance. */
276 #define INIT_MAX_PREEMPTS 30
277 static int max_preempts;
279 #define REDISPLAY_PREEMPTION_CHECK \
282 (!disable_preemption && \
283 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
284 (!INTERACTIVE || detect_input_pending ()))))
287 * Redisplay global variables.
290 /* We need a third set of display structures for the cursor motion
291 routines. We used to just give each window a third set. However,
292 we always fully regenerate the structures when needed so there
293 isn't any reason we need more than a single set. */
294 display_line_dynarr *cmotion_display_lines;
296 /* Used by generate_formatted_string. Global because they get used so
297 much that the dynamic allocation time adds up. */
298 Emchar_dynarr *formatted_string_emchar_dynarr;
299 struct display_line formatted_string_display_line;
300 /* We store the extents that we need to generate in a Dynarr and then
301 frob them all on at the end of generating the string. We do it
302 this way rather than adding them as we generate the string because
303 we don't store the text into the resulting string until we're done
304 (to avoid having to resize the string multiple times), and we don't
305 want to go around adding extents to a string when the extents might
306 stretch off the end of the string. */
307 EXTENT_dynarr *formatted_string_extent_dynarr;
308 Bytecount_dynarr *formatted_string_extent_start_dynarr;
309 Bytecount_dynarr *formatted_string_extent_end_dynarr;
312 /* #### probably temporary */
313 int cache_adjustment;
315 /* This holds a string representing the text corresponding to a single
317 static Bufbyte_dynarr *mode_spec_bufbyte_string;
319 int in_display; /* 1 if in redisplay. */
321 int disable_preemption; /* Used for debugging redisplay and for
324 /* We only allow max_preempts preemptions before we force a redisplay. */
325 static int preemption_count;
327 /* Minimum pixel height of clipped bottom display line. */
330 /* Minimum visible pixel width of clipped glyphs at right margin. */
333 /* Set if currently inside update_line_start_cache. */
334 int updating_line_start_cache;
336 /* Nonzero means reading single-character input with prompt
337 so put cursor on minibuffer after the prompt. */
338 int cursor_in_echo_area;
339 Lisp_Object Qcursor_in_echo_area;
341 /* Nonzero means truncate lines in all windows less wide than the frame */
342 int truncate_partial_width_windows;
344 /* non-nil if a buffer has changed since the last time redisplay completed */
346 int buffers_changed_set;
348 /* non-nil if hscroll has changed somewhere or a buffer has been
349 narrowed or widened */
351 int clip_changed_set;
353 /* non-nil if any extent has changed since the last time redisplay completed */
355 int extents_changed_set;
357 /* non-nil if any face has changed since the last time redisplay completed */
360 /* Nonzero means some frames have been marked as garbaged */
363 /* non-zero if any of the builtin display glyphs (continuation,
364 hscroll, control-arrow, etc) is in need of updating
367 int glyphs_changed_set;
369 /* non-zero if any displayed subwindow is in need of updating
371 int subwindows_changed;
372 int subwindows_changed_set;
374 /* This variable is 1 if the icon has to be updated.
375 It is set to 1 when `frame-icon-glyph' changes. */
377 int icon_changed_set;
379 /* This variable is 1 if the menubar widget has to be updated.
380 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
383 int menubar_changed_set;
385 /* true iff we should redraw the modelines on the next redisplay */
386 int modeline_changed;
387 int modeline_changed_set;
389 /* non-nil if point has changed in some buffer since the last time
390 redisplay completed */
392 int point_changed_set;
394 /* non-nil if some frame has changed its size */
397 /* non-nil if some device has signaled that it wants to change size */
398 int asynch_device_change_pending;
400 /* non-nil if any toolbar has changed */
402 int toolbar_changed_set;
404 /* non-nil if any window has changed since the last time redisplay completed */
407 /* non-nil if any frame's window structure has changed since the last
408 time redisplay completed */
409 int windows_structure_changed;
411 /* If non-nil, use vertical bar cursor. */
412 Lisp_Object Vbar_cursor;
413 Lisp_Object Qbar_cursor;
416 int visible_bell; /* If true and the terminal will support it
417 then the frame will flash instead of
418 beeping when an error occurs */
420 /* Nonzero means no need to redraw the entire frame on resuming
421 a suspended Emacs. This is useful on terminals with multiple pages,
422 where one page is used for Emacs and another for all else. */
423 int no_redraw_on_reenter;
425 Lisp_Object Vwindow_system; /* nil or a symbol naming the window system
426 under which emacs is running
427 ('x is the only current possibility) */
428 Lisp_Object Vinitial_window_system;
430 Lisp_Object Vglobal_mode_string;
432 /* The number of lines scroll a window by when point leaves the window; if
433 it is <=0 then point is centered in the window */
436 /* Scroll up to this many lines, to bring point back on screen. */
437 int scroll_conservatively;
439 /* Marker for where to display an arrow on top of the buffer text. */
440 Lisp_Object Voverlay_arrow_position;
441 /* String to display for the arrow. */
442 Lisp_Object Voverlay_arrow_string;
444 Lisp_Object Vwindow_size_change_functions;
445 Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
446 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
448 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
450 #ifndef INHIBIT_REDISPLAY_HOOKS
451 /* #### Chuck says: I think this needs more thought.
452 Think about this for 19.14. */
453 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
454 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
455 #endif /* INHIBIT_REDISPLAY_HOOKS */
457 int last_display_warning_tick, display_warning_tick;
458 Lisp_Object Qdisplay_warning_buffer;
459 int inhibit_warning_display;
461 Lisp_Object Vleft_margin_width, Vright_margin_width;
462 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
463 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
464 Lisp_Object Vtext_cursor_visible_p;
466 int column_number_start_at_one;
468 /***************************************************************************/
470 /* low-level interfaces onto device routines */
472 /***************************************************************************/
475 redisplay_text_width_emchar_string (struct window *w, int findex,
476 Emchar *str, Charcount len)
478 unsigned char charsets[NUM_LEADING_BYTES];
481 find_charsets_in_emchar_string (charsets, str, len);
482 XSETWINDOW (window, w);
483 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
485 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))),
486 text_width, (XFRAME (WINDOW_FRAME (w)),
487 WINDOW_FACE_CACHEL (w, findex), str, len));
490 static Emchar_dynarr *rtw_emchar_dynarr;
493 redisplay_text_width_string (struct window *w, int findex,
494 Bufbyte *nonreloc, Lisp_Object reloc,
495 Bytecount offset, Bytecount len)
497 if (!rtw_emchar_dynarr)
498 rtw_emchar_dynarr = Dynarr_new (Emchar);
499 Dynarr_reset (rtw_emchar_dynarr);
501 fixup_internal_substring (nonreloc, reloc, offset, &len);
503 nonreloc = XSTRING_DATA (reloc);
504 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
505 return redisplay_text_width_emchar_string
506 (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
507 Dynarr_length (rtw_emchar_dynarr));
511 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face,
512 Bufbyte *nonreloc, Lisp_Object reloc,
513 Bytecount offset, Bytecount len)
515 unsigned char charsets[NUM_LEADING_BYTES];
517 struct face_cachel cachel;
519 if (!rtw_emchar_dynarr)
520 rtw_emchar_dynarr = Dynarr_new (Emchar);
521 Dynarr_reset (rtw_emchar_dynarr);
523 fixup_internal_substring (nonreloc, reloc, offset, &len);
525 nonreloc = XSTRING_DATA (reloc);
526 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
527 find_charsets_in_bufbyte_string (charsets, nonreloc, len);
528 reset_face_cachel (&cachel);
530 XSETFRAME (frame, f);
531 ensure_face_cachel_complete (&cachel, frame, charsets);
532 return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
533 text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
534 Dynarr_length (rtw_emchar_dynarr)));
537 /* Return the display block from DL of the given TYPE. A display line
538 can have only one display block of each possible type. If DL does
539 not have a block of type TYPE, one will be created and added to DL. */
541 struct display_block *
542 get_display_block_from_line (struct display_line *dl, enum display_type type)
545 struct display_block db;
547 /* Check if this display line already has a block of the desired type and
549 if (dl->display_blocks)
551 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++)
553 if (Dynarr_at (dl->display_blocks, elt).type == type)
554 return Dynarr_atp (dl->display_blocks, elt);
557 /* There isn't an active block of the desired type, but there
558 might still be allocated blocks we need to reuse. */
559 if (elt < Dynarr_largest (dl->display_blocks))
561 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
563 /* 'add' the block to the list */
564 Dynarr_increment (dl->display_blocks);
566 /* initialize and return */
573 /* This line doesn't have any display blocks, so initialize the display
575 dl->display_blocks = Dynarr_new (display_block);
578 /* The line doesn't have a block of the desired type so go ahead and create
579 one and add it to the line. */
582 db.runes = Dynarr_new (rune);
583 Dynarr_add (dl->display_blocks, db);
585 /* Return the newly added display block. */
586 elt = Dynarr_length (dl->display_blocks) - 1;
588 return Dynarr_atp (dl->display_blocks, elt);
592 tab_char_width (struct window *w)
594 struct buffer *b = XBUFFER (w->buffer);
595 int char_tab_width = XINT (b->tab_width);
597 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8;
599 return char_tab_width;
603 space_width (struct window *w)
605 /* While tabs are traditional composed of spaces, for variable-width
606 fonts the space character tends to give too narrow a value. So
607 we use 'n' instead. Except that we don't. We use the default
608 character width for the default face. If this is actually
609 defined by the font then it is probably the best thing to
610 actually use. If it isn't, we have assumed it is 'n' and have
611 already calculated its width. Thus we can avoid a call to
612 XTextWidth on X frames by just querying the default width. */
613 return XFONT_INSTANCE
614 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width;
618 tab_pix_width (struct window *w)
620 return space_width (w) * tab_char_width (w);
623 /* Given a pixel position in a window, return the pixel location of
624 the next tabstop. Tabs are calculated from the left window edge in
625 terms of spaces displayed in the default face. Formerly the space
626 width was determined using the currently active face. That method
627 leads to tabstops which do not line up. */
630 next_tab_position (struct window *w, int start_pixpos, int left_pixpos)
632 int n_pos = left_pixpos;
633 int pix_tab_width = tab_pix_width (w);
635 /* Adjust n_pos for any hscrolling which has happened. */
637 n_pos -= space_width (w) * (w->hscroll - 1);
639 while (n_pos <= start_pixpos)
640 n_pos += pix_tab_width;
645 /* For the given window, calculate the outside and margin boundaries for a
646 display line. The whitespace boundaries must be calculated by the text
650 calculate_display_line_boundaries (struct window *w, int modeline)
652 layout_bounds bounds;
654 /* Set the outermost boundaries which are the boundaries of the
655 window itself minus the gutters (and minus the scrollbars if this
656 is for the modeline). */
659 bounds.left_out = WINDOW_TEXT_LEFT (w);
660 bounds.right_out = WINDOW_TEXT_RIGHT (w);
664 bounds.left_out = WINDOW_MODELINE_LEFT (w);
665 bounds.right_out = WINDOW_MODELINE_RIGHT (w);
668 /* The inner boundaries mark where the glyph margins are located. */
669 bounds.left_in = bounds.left_out + window_left_margin_width (w);
670 bounds.right_in = bounds.right_out - window_right_margin_width (w);
672 /* We cannot fully calculate the whitespace boundaries as they
673 depend on the contents of the line being displayed. */
674 bounds.left_white = bounds.left_in;
675 bounds.right_white = bounds.right_in;
680 /* Given a display line and a starting position, ensure that the
681 contents of the display line accurately represent the visual
682 representation of the buffer contents starting from the given
683 position when displayed in the given window. The display line ends
684 when the contents of the line reach the right boundary of the given
688 generate_display_line (struct window *w, struct display_line *dl, int bounds,
689 Bufpos start_pos, int start_col,
690 prop_block_dynarr **prop,
695 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
697 /* If our caller hasn't already set the boundaries, then do so now. */
699 dl->bounds = calculate_display_line_boundaries (w, 0);
701 /* Reset what this line is using. */
702 if (dl->display_blocks)
703 Dynarr_reset (dl->display_blocks);
706 Dynarr_free (dl->left_glyphs);
709 if (dl->right_glyphs)
711 Dynarr_free (dl->right_glyphs);
712 dl->right_glyphs = 0;
715 /* We aren't generating a modeline at the moment. */
718 /* Create a display block for the text region of the line. */
720 /* #### urk urk urk!!! Chuck fix this shit! */
721 Bytind hacked_up_bytind =
722 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
723 start_col, prop, type);
724 if (hacked_up_bytind > BI_BUF_ZV (b))
725 ret_bufpos = BUF_ZV (b) + 1;
727 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
729 dl->bufpos = start_pos;
730 if (dl->end_bufpos < dl->bufpos)
731 dl->end_bufpos = dl->bufpos;
733 if (MARKERP (Voverlay_arrow_position)
734 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
735 && start_pos == marker_position (Voverlay_arrow_position)
736 && (STRINGP (Voverlay_arrow_string)
737 || GLYPHP (Voverlay_arrow_string)))
739 overlay_width = create_overlay_glyph_block (w, dl);
744 /* If there are left glyphs associated with any character in the
745 text block, then create a display block to handle them. */
746 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
747 create_left_glyph_block (w, dl, overlay_width);
749 /* If there are right glyphs associated with any character in the
750 text block, then create a display block to handle them. */
751 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
752 create_right_glyph_block (w, dl);
754 /* In the future additional types of display blocks may be generated
757 w->last_redisplay_pos = ret_bufpos;
762 /* Adds an hscroll glyph to a display block. If this is called, then
763 the block had better be empty.
765 Yes, there are multiple places where this function is called but
766 that is the way it has to be. Each calling function has to deal
767 with bi_start_col_enabled a little differently depending on the
768 object being worked with. */
770 static prop_block_dynarr *
771 add_hscroll_rune (pos_data *data)
773 struct glyph_block gb;
774 prop_block_dynarr *retval;
775 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
776 unsigned int old_cursor_type = data->cursor_type;
777 Bytind bi_old_bufpos = data->bi_bufpos;
779 if (data->cursor_type == CURSOR_ON
780 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
781 && data->bi_cursor_bufpos <= data->bi_bufpos)
783 data->bi_cursor_bufpos = data->bi_start_col_enabled;
787 data->cursor_type = NO_CURSOR;
790 data->bi_endpos = data->bi_bufpos;
791 data->bi_bufpos = data->bi_start_col_enabled;
794 gb.glyph = Vhscroll_glyph;
796 int oldpixpos = data->pixpos;
797 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
798 GLYPH_CACHEL (XWINDOW (data->window),
799 HSCROLL_GLYPH_INDEX));
800 data->hscroll_glyph_width_adjust =
801 data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
804 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
805 data->cursor_type = old_cursor_type;
806 data->bi_bufpos = bi_old_bufpos;
808 data->bi_start_col_enabled = 0;
812 /* Adds a character rune to a display block. If there is not enough
813 room to fit the rune on the display block (as determined by the
814 MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
816 static prop_block_dynarr *
817 add_emchar_rune (pos_data *data)
819 struct rune rb, *crb;
830 if (data->bi_start_col_enabled)
832 return add_hscroll_rune (data);
835 if (data->ch == '\n')
837 data->font_is_bogus = 0;
838 /* Cheesy end-of-line pseudo-character. */
839 width = data->blank_width;
843 Lisp_Object charset = CHAR_CHARSET (data->ch);
844 if (!EQ (charset, data->last_charset) ||
845 data->findex != data->last_findex)
847 /* OK, we need to do things the hard way. */
848 struct window *w = XWINDOW (data->window);
849 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
850 Lisp_Object font_instance =
851 ensure_face_cachel_contains_charset (cachel, data->window,
853 struct Lisp_Font_Instance *fi;
855 if (EQ (font_instance, Vthe_null_font_instance))
857 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
858 data->font_is_bogus = 1;
861 data->font_is_bogus = 0;
863 fi = XFONT_INSTANCE (font_instance);
864 if (!fi->proportional_p)
865 /* sweetness and light. */
866 data->last_char_width = fi->width;
868 data->last_char_width = -1;
869 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
870 data->new_descent = max (data->new_descent, (int) fi->descent);
871 data->last_charset = charset;
872 data->last_findex = data->findex;
875 width = data->last_char_width;
878 /* bummer. Proportional fonts. */
879 width = redisplay_text_width_emchar_string (XWINDOW (data->window),
885 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
890 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
892 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
901 crb->findex = data->findex;
902 crb->xpos = data->pixpos;
906 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
908 else if (data->is_modeline)
909 crb->bufpos = data->modeline_charpos;
911 /* fuckme if this shouldn't be an abort. */
912 /* abort (); fuckme harder, this abort gets tripped quite often,
913 in propagation and whatnot. #### fixme */
915 crb->type = RUNE_CHAR;
916 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
919 if (data->cursor_type == CURSOR_ON)
921 if (data->bi_bufpos == data->bi_cursor_bufpos)
923 crb->cursor_type = CURSOR_ON;
924 data->cursor_x = Dynarr_length (data->db->runes);
927 crb->cursor_type = CURSOR_OFF;
929 else if (data->cursor_type == NEXT_CURSOR)
931 crb->cursor_type = CURSOR_ON;
932 data->cursor_x = Dynarr_length (data->db->runes);
933 data->cursor_type = NO_CURSOR;
935 else if (data->cursor_type == IGNORE_CURSOR)
936 crb->cursor_type = IGNORE_CURSOR;
938 crb->cursor_type = CURSOR_OFF;
941 Dynarr_add (data->db->runes, *crb);
943 Dynarr_increment (data->db->runes);
945 data->pixpos += width;
950 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
951 for each character in the string. Propagate any left-over data
952 unless NO_PROP is non-zero. */
954 static prop_block_dynarr *
955 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
956 Bytecount c_length, int no_prop)
958 Bufbyte *pos, *end = c_string + c_length;
959 prop_block_dynarr *prop;
961 /* #### This function is too simplistic. It needs to do the same
962 sort of character interpretation (display-table lookup,
963 ctl-arrow checking), etc. that create_text_block() does.
964 The functionality to do this in that routine needs to be
967 for (pos = c_string; pos < end;)
969 data->ch = charptr_emchar (pos);
971 prop = add_emchar_rune (data);
979 struct prop_block pb;
980 Bytecount len = end - pos;
981 prop = Dynarr_new (prop_block);
983 pb.type = PROP_STRING;
984 pb.data.p_string.str = xnew_array (Bufbyte, len);
985 strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
986 pb.data.p_string.len = len;
988 Dynarr_add (prop, pb);
999 /* Add a single rune of the specified width. The area covered by this
1000 rune will be displayed in the foreground color of the associated
1003 static prop_block_dynarr *
1004 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1008 /* If data->start_col is not 0 then this call to add_blank_rune must have
1009 been to add it as a tab. */
1010 if (data->start_col)
1012 /* assert (w != NULL) */
1013 prop_block_dynarr *retval;
1015 /* If we have still not fully scrolled horizontally, subtract
1016 the width of this tab and return. */
1017 if (char_tab_width < data->start_col)
1019 data->start_col -= char_tab_width;
1022 else if (char_tab_width == data->start_col)
1023 data->blank_width = 0;
1026 int spcwid = space_width (w);
1028 if (spcwid >= data->blank_width)
1029 data->blank_width = 0;
1031 data->blank_width -= spcwid;
1034 data->start_col = 0;
1035 retval = add_hscroll_rune (data);
1037 /* Could be caused by the handling of the hscroll rune. */
1038 if (retval != NULL || !data->blank_width)
1042 /* Blank runes are always calculated to fit. */
1043 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1045 rb.findex = data->findex;
1046 rb.xpos = data->pixpos;
1047 rb.width = data->blank_width;
1048 if (data->bi_bufpos)
1050 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1053 /* #### and this is really correct too? */
1056 rb.type = RUNE_BLANK;
1058 if (data->cursor_type == CURSOR_ON)
1060 if (data->bi_bufpos == data->bi_cursor_bufpos)
1062 rb.cursor_type = CURSOR_ON;
1063 data->cursor_x = Dynarr_length (data->db->runes);
1066 rb.cursor_type = CURSOR_OFF;
1068 else if (data->cursor_type == NEXT_CURSOR)
1070 rb.cursor_type = CURSOR_ON;
1071 data->cursor_x = Dynarr_length (data->db->runes);
1072 data->cursor_type = NO_CURSOR;
1075 rb.cursor_type = CURSOR_OFF;
1077 Dynarr_add (data->db->runes, rb);
1078 data->pixpos += data->blank_width;
1083 /* Add runes representing a character in octal. */
1085 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1087 if (add_failed || (add_failed = add_emchar_rune (data))) \
1089 struct prop_block pb; \
1091 prop = Dynarr_new (prop_block); \
1093 pb.type = PROP_CHAR; \
1094 pb.data.p_char.ch = data->ch; \
1095 pb.data.p_char.cursor_type = data->cursor_type; \
1096 Dynarr_add (prop, pb); \
1100 static prop_block_dynarr *
1101 add_octal_runes (pos_data *data)
1103 prop_block_dynarr *prop, *add_failed;
1104 Emchar orig_char = data->ch;
1105 unsigned int orig_cursor_type = data->cursor_type;
1111 if (data->start_col)
1114 if (!data->start_col)
1116 if (data->bi_start_col_enabled)
1118 add_failed = add_hscroll_rune (data);
1122 struct glyph_block gb;
1123 struct window *w = XWINDOW (data->window);
1126 gb.glyph = Voctal_escape_glyph;
1128 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1129 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1133 /* We only propagate information if the glyph was partially
1138 data->cursor_type = IGNORE_CURSOR;
1140 if (data->ch >= 0x100)
1142 /* If the character is an extended Mule character, it could have
1143 up to 19 bits. For the moment, we treat it as a seven-digit
1144 octal number. This is not that pretty, but whatever. */
1145 data->ch = (7 & (orig_char >> 18)) + '0';
1146 ADD_NEXT_OCTAL_RUNE_CHAR;
1148 data->ch = (7 & (orig_char >> 15)) + '0';
1149 ADD_NEXT_OCTAL_RUNE_CHAR;
1151 data->ch = (7 & (orig_char >> 12)) + '0';
1152 ADD_NEXT_OCTAL_RUNE_CHAR;
1154 data->ch = (7 & (orig_char >> 9)) + '0';
1155 ADD_NEXT_OCTAL_RUNE_CHAR;
1158 data->ch = (7 & (orig_char >> 6)) + '0';
1159 ADD_NEXT_OCTAL_RUNE_CHAR;
1161 data->ch = (7 & (orig_char >> 3)) + '0';
1162 ADD_NEXT_OCTAL_RUNE_CHAR;
1164 data->ch = (7 & orig_char) + '0';
1165 ADD_NEXT_OCTAL_RUNE_CHAR;
1167 data->cursor_type = orig_cursor_type;
1171 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1173 /* Add runes representing a control character to a display block. */
1175 static prop_block_dynarr *
1176 add_control_char_runes (pos_data *data, struct buffer *b)
1178 if (!NILP (b->ctl_arrow))
1180 prop_block_dynarr *prop;
1181 Emchar orig_char = data->ch;
1182 unsigned int old_cursor_type = data->cursor_type;
1187 if (data->start_col)
1190 if (!data->start_col)
1192 if (data->bi_start_col_enabled)
1194 prop_block_dynarr *retval;
1196 retval = add_hscroll_rune (data);
1202 struct glyph_block gb;
1203 struct window *w = XWINDOW (data->window);
1206 gb.glyph = Vcontrol_arrow_glyph;
1208 /* We only propagate information if the glyph was partially
1210 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1211 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1216 if (orig_char == 0177)
1219 data->ch = orig_char ^ 0100;
1220 data->cursor_type = IGNORE_CURSOR;
1222 if (add_emchar_rune (data))
1224 struct prop_block pb;
1226 prop = Dynarr_new (prop_block);
1228 pb.type = PROP_CHAR;
1229 pb.data.p_char.ch = data->ch;
1230 pb.data.p_char.cursor_type = data->cursor_type;
1231 Dynarr_add (prop, pb);
1234 data->cursor_type = old_cursor_type;
1239 return add_octal_runes (data);
1243 static prop_block_dynarr *
1244 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
1246 prop_block_dynarr *prop = NULL;
1248 if (STRINGP (entry))
1250 prop = add_bufbyte_string_runes (data,
1251 XSTRING_DATA (entry),
1252 XSTRING_LENGTH (entry),
1255 else if (GLYPHP (entry))
1257 if (data->start_col)
1260 if (!data->start_col && data->bi_start_col_enabled)
1262 prop = add_hscroll_rune (data);
1266 struct glyph_block gb;
1270 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1273 else if (CHAR_OR_CHAR_INTP (entry))
1275 data->ch = XCHAR_OR_CHAR_INT (entry);
1276 prop = add_emchar_rune (data);
1278 else if (CONSP (entry))
1280 if (EQ (XCAR (entry), Qformat)
1281 && CONSP (XCDR (entry))
1282 && STRINGP (XCAR (XCDR (entry))))
1284 Lisp_Object format = XCAR (XCDR (entry));
1285 Bytind len = XSTRING_LENGTH (format);
1286 Bufbyte *src = XSTRING_DATA (format), *end = src + len;
1287 Bufbyte *result = alloca_array (Bufbyte, len);
1288 Bufbyte *dst = result;
1292 Emchar c = charptr_emchar (src);
1294 if (c != '%' || src == end)
1295 dst += set_charptr_emchar (dst, c);
1298 c = charptr_emchar (src);
1303 dst += long_to_string_base ((char *)dst, data->ch, 16);
1306 dst += set_charptr_emchar (dst, '%');
1311 prop = add_bufbyte_string_runes (data, result, dst - result, 0);
1315 /* Else blow it off because someone added a bad entry and we don't
1316 have any safe way of signaling an error. */
1320 /* Given a display table entry, call the appropriate functions to
1321 display each element of the entry. */
1323 static prop_block_dynarr *
1324 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1326 prop_block_dynarr *prop = NULL;
1327 if (VECTORP (entry))
1329 struct Lisp_Vector *de = XVECTOR (entry);
1330 EMACS_INT len = vector_length (de);
1333 for (elt = 0; elt < len; elt++)
1335 if (NILP (vector_data (de)[elt]))
1338 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
1339 /* Else blow it off because someone added a bad entry and we
1340 don't have any safe way of signaling an error. Hey, this
1341 comment sounds familiar. */
1343 /* #### Still need to add any remaining elements to the
1344 propagation information. */
1350 prop = add_disp_table_entry_runes_1 (data, entry);
1354 /* Add runes which were propagated from the previous line. */
1356 static prop_block_dynarr *
1357 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1359 /* #### Remember to handle start_col parameter of data when the rest of
1360 this is finished. */
1361 /* #### Chuck -- I've redone this function a bit. It looked like the
1362 case of not all the propagation blocks being added was not handled
1364 /* #### Chuck -- I also think the double indirection of PROP is kind
1365 of bogus. A cleaner solution is just to check for
1366 Dynarr_length (prop) > 0. */
1367 /* #### This function also doesn't even pay attention to ADD_FAILED!
1368 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1371 prop_block_dynarr *add_failed;
1372 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1373 unsigned int old_cursor_type = data->cursor_type;
1375 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1377 struct prop_block *pb = Dynarr_atp (*prop, elt);
1382 data->ch = pb->data.p_char.ch;
1383 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1384 data->cursor_type = pb->data.p_char.cursor_type;
1385 add_failed = add_emchar_rune (data);
1388 goto oops_no_more_space;
1391 if (pb->data.p_string.str)
1392 xfree (pb->data.p_string.str);
1393 /* #### bogus bogus -- this doesn't do anything!
1394 Should probably call add_bufbyte_string_runes(),
1395 once that function is fixed. */
1397 case PROP_MINIBUF_PROMPT:
1399 face_index old_findex = data->findex;
1400 Bytind bi_old_bufpos = data->bi_bufpos;
1402 data->findex = DEFAULT_INDEX;
1403 data->bi_bufpos = 0;
1404 data->cursor_type = NO_CURSOR;
1406 while (pb->data.p_string.len > 0)
1408 data->ch = charptr_emchar (pb->data.p_string.str);
1409 add_failed = add_emchar_rune (data);
1413 data->findex = old_findex;
1414 data->bi_bufpos = bi_old_bufpos;
1415 goto oops_no_more_space;
1419 /* Complicated equivalent of ptr++, len-- */
1420 Bufbyte *oldpos = pb->data.p_string.str;
1421 INC_CHARPTR (pb->data.p_string.str);
1422 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1426 data->findex = old_findex;
1427 /* ##### FIXME FIXME FIXME -- Upon successful return from
1428 this function, data->bi_bufpos is automatically incremented.
1429 However, we don't want that to happen if we were adding
1430 the minibuffer prompt. */
1432 struct buffer *buf =
1433 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1434 /* #### Chuck fix this shit or I'm gonna scream! */
1435 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1436 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1438 /* #### is this correct? Does anyone know?
1439 Does anyone care? Is this a cheesy hack or what? */
1440 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1446 /* #### I think it's unnecessary and misleading to preserve
1447 the blank_width, as it implies that the value carries
1448 over from one rune to the next, which is wrong. */
1449 int old_width = data->blank_width;
1450 face_index old_findex = data->findex;
1452 data->findex = pb->data.p_blank.findex;
1453 data->blank_width = pb->data.p_blank.width;
1454 data->bi_cursor_bufpos = 0;
1455 data->cursor_type = IGNORE_CURSOR;
1457 if (data->pixpos + data->blank_width > data->max_pixpos)
1458 data->blank_width = data->max_pixpos - data->pixpos;
1460 /* We pass a bogus value of char_tab_width. It shouldn't
1461 matter because unless something is really screwed up
1462 this call won't cause that arg to be used. */
1463 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1465 /* This can happen in the case where we have a tab which
1466 is wider than the window. */
1467 if (data->blank_width != pb->data.p_blank.width)
1469 pb->data.p_blank.width -= data->blank_width;
1470 add_failed = ADD_FAILED;
1473 data->findex = old_findex;
1474 data->blank_width = old_width;
1477 goto oops_no_more_space;
1487 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1488 data->cursor_type = old_cursor_type;
1489 if (elt < Dynarr_length (*prop))
1491 Dynarr_delete_many (*prop, 0, elt);
1496 Dynarr_free (*prop);
1501 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1502 the display block, but add all other types to the appropriate list
1503 of the display line. They will be added later by different
1506 static prop_block_dynarr *
1507 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1508 int allow_cursor, struct glyph_cachel *cachel)
1510 struct window *w = XWINDOW (data->window);
1512 /* A nil extent indicates a special glyph (ex. truncator). */
1513 if (NILP (gb->extent)
1514 || (pos_type == BEGIN_GLYPHS &&
1515 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1516 || (pos_type == END_GLYPHS &&
1517 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
1522 int ascent, descent;
1523 Lisp_Object baseline;
1527 width = cachel->width;
1529 width = glyph_width (gb->glyph, Qnil, data->findex, data->window);
1534 if (data->start_col)
1536 prop_block_dynarr *retval;
1537 int glyph_char_width = width / space_width (w);
1539 /* If we still have not fully scrolled horizontally after
1540 taking into account the width of the glyph, subtract its
1541 width and return. */
1542 if (glyph_char_width < data->start_col)
1544 data->start_col -= glyph_char_width;
1547 else if (glyph_char_width == data->start_col)
1551 xoffset = space_width (w) * data->start_col;
1554 /* #### Can this happen? */
1559 data->start_col = 0;
1560 retval = add_hscroll_rune (data);
1562 /* Could be caused by the handling of the hscroll rune. */
1563 if (retval != NULL || !width)
1569 if (data->pixpos + width > data->max_pixpos)
1571 /* If this is the first object we are attempting to add to
1572 the line then we ignore the horizontal_clip threshold.
1573 Otherwise we will loop until the bottom of the window
1574 continually failing to add this glyph because it is wider
1575 than the window. We could alternatively just completely
1576 ignore the glyph and proceed from there but I think that
1577 this is a better solution. */
1578 if (Dynarr_length (data->db->runes)
1579 && data->max_pixpos - data->pixpos < horizontal_clip)
1582 width = data->max_pixpos - data->pixpos;
1587 ascent = cachel->ascent;
1588 descent = cachel->descent;
1592 ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window);
1593 descent = glyph_descent (gb->glyph, Qnil, data->findex,
1597 baseline = glyph_baseline (gb->glyph, data->window);
1599 if (glyph_contrib_p (gb->glyph, data->window))
1601 /* A pixmap that has not had a baseline explicitly set. Its
1602 contribution will be determined later. */
1603 if (NILP (baseline))
1605 int height = ascent + descent;
1606 data->max_pixmap_height = max (data->max_pixmap_height, height);
1609 /* A string so determine contribution normally. */
1610 else if (EQ (baseline, Qt))
1612 data->new_ascent = max (data->new_ascent, ascent);
1613 data->new_descent = max (data->new_descent, descent);
1616 /* A pixmap with an explicitly set baseline. We determine the
1617 contribution here. */
1618 else if (INTP (baseline))
1620 int height = ascent + descent;
1621 int pix_ascent, pix_descent;
1623 pix_ascent = height * XINT (baseline) / 100;
1624 pix_descent = height - pix_ascent;
1626 data->new_ascent = max (data->new_ascent, pix_ascent);
1627 data->new_descent = max (data->new_descent, pix_descent);
1630 /* Otherwise something is screwed up. */
1635 face = glyph_face (gb->glyph, data->window);
1637 rb.findex = data->findex;
1639 rb.findex = get_builtin_face_cache_index (w, face);
1641 rb.xpos = data->pixpos;
1643 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1644 if (data->bi_endpos)
1645 /* #### is this necessary at all? */
1646 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1650 rb.type = RUNE_DGLYPH;
1651 /* #### Ben sez: this is way bogus if the glyph is a string.
1652 You should not make the output routines have to cope with
1653 this. The string could contain Mule characters, or non-
1654 printable characters, or characters to be passed through
1655 the display table, or non-character objects (when this gets
1656 implemented), etc. Instead, this routine here should parse
1657 the string into a series of runes. */
1658 rb.object.dglyph.glyph = gb->glyph;
1659 rb.object.dglyph.extent = gb->extent;
1660 rb.object.dglyph.xoffset = xoffset;
1664 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1667 if (data->cursor_type == CURSOR_ON)
1669 if (data->bi_bufpos == data->bi_cursor_bufpos)
1671 rb.cursor_type = CURSOR_ON;
1672 data->cursor_x = Dynarr_length (data->db->runes);
1675 rb.cursor_type = CURSOR_OFF;
1677 else if (data->cursor_type == NEXT_CURSOR)
1679 rb.cursor_type = CURSOR_ON;
1680 data->cursor_x = Dynarr_length (data->db->runes);
1681 data->cursor_type = NO_CURSOR;
1683 else if (data->cursor_type == IGNORE_CURSOR)
1684 rb.cursor_type = IGNORE_CURSOR;
1685 else if (data->cursor_type == NO_CURSOR)
1686 rb.cursor_type = NO_CURSOR;
1688 rb.cursor_type = CURSOR_OFF;
1691 rb.cursor_type = CURSOR_OFF;
1693 Dynarr_add (data->db->runes, rb);
1694 data->pixpos += width;
1700 if (!NILP (glyph_face (gb->glyph, data->window)))
1702 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1705 gb->findex = data->findex;
1707 if (pos_type == BEGIN_GLYPHS)
1709 if (!data->dl->left_glyphs)
1710 data->dl->left_glyphs = Dynarr_new (glyph_block);
1711 Dynarr_add (data->dl->left_glyphs, *gb);
1714 else if (pos_type == END_GLYPHS)
1716 if (!data->dl->right_glyphs)
1717 data->dl->right_glyphs = Dynarr_new (glyph_block);
1718 Dynarr_add (data->dl->right_glyphs, *gb);
1722 abort (); /* there are no unknown types */
1725 return NULL; /* shut up compiler */
1728 /* Add all glyphs at position POS_TYPE that are contained in the given
1731 static prop_block_dynarr *
1732 add_glyph_runes (pos_data *data, int pos_type)
1734 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1735 why didn't you just modify add_glyph_rune in the first place? */
1737 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1738 ? data->ef->begin_glyphs
1739 : data->ef->end_glyphs);
1740 prop_block_dynarr *prop;
1742 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1744 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1749 /* #### Add some propagation information. */
1754 Dynarr_reset (glyph_arr);
1759 /* Given a position for a buffer in a window, ensure that the given
1760 display line DL accurately represents the text on a line starting
1761 at the given position.
1763 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1764 You must do appropriate conversion. */
1767 create_text_block (struct window *w, struct display_line *dl,
1768 Bytind bi_start_pos, int start_col,
1769 prop_block_dynarr **prop,
1772 struct frame *f = XFRAME (w->frame);
1773 struct buffer *b = XBUFFER (w->buffer);
1774 struct device *d = XDEVICE (f->device);
1778 /* Don't display anything in the minibuffer if this window is not on
1779 a selected frame. We consider all other windows to be active
1780 minibuffers as it simplifies the coding. */
1781 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1782 (f == device_selected_frame (d)) ||
1783 is_surrogate_for_selected_frame (f));
1785 int truncate_win = window_truncation_on (w);
1786 int end_glyph_width;
1788 /* If the buffer's value of selective_display is an integer then
1789 only lines that start with less than selective_display columns of
1790 space will be displayed. If selective_display is t then all text
1791 after a ^M is invisible. */
1792 int selective = (INTP (b->selective_display)
1793 ? XINT (b->selective_display)
1794 : ((!NILP (b->selective_display) ? -1 : 0)));
1796 /* The variable ctl-arrow allows the user to specify what characters
1797 can actually be displayed and which octal should be used for.
1798 #### This variable should probably have some rethought done to
1801 #### It would also be really nice if you could specify that
1802 the characters come out in hex instead of in octal. Mule
1803 does that by adding a ctl-hexa variable similar to ctl-arrow,
1804 but that's bogus -- we need a more general solution. I
1805 think you need to extend the concept of display tables
1806 into a more general conversion mechanism. Ideally you
1807 could specify a Lisp function that converts characters,
1808 but this violates the Second Golden Rule and besides would
1809 make things way way way way slow.
1811 So instead, we extend the display-table concept, which was
1812 historically limited to 256-byte vectors, to one of the
1815 a) A 256-entry vector, for backward compatibility;
1816 b) char-table, mapping characters to values;
1817 c) range-table, mapping ranges of characters to values;
1818 d) a list of the above.
1820 The (d) option allows you to specify multiple display tables
1821 instead of just one. Each display table can specify conversions
1822 for some characters and leave others unchanged. The way the
1823 character gets displayed is determined by the first display table
1824 with a binding for that character. This way, you could call a
1825 function `enable-hex-display' that adds a hex display-table to
1826 the list of display tables for the current buffer.
1828 #### ...not yet implemented... Also, we extend the concept of
1829 "mapping" to include a printf-like spec. Thus you can make all
1830 extended characters show up as hex with a display table like
1833 #s(range-table data ((256 524288) (format "%x")))
1835 Since more than one display table is possible, you have
1836 great flexibility in mapping ranges of characters. */
1837 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1838 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1839 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1842 Lisp_Object face_dt, window_dt;
1844 /* The text display block for this display line. */
1845 struct display_block *db = get_display_block_from_line (dl, TEXT);
1847 /* The first time through the main loop we need to force the glyph
1848 data to be updated. */
1851 /* Apparently the new extent_fragment_update returns an end position
1852 equal to the position passed in if there are no more runs to be
1854 int no_more_frags = 0;
1856 Lisp_Object synch_minibuffers_value =
1857 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1859 dl->used_prop_data = 0;
1863 data.ef = extent_fragment_new (w->buffer, f);
1865 /* These values are used by all of the rune addition routines. We add
1866 them to this structure for ease of passing. */
1868 XSETWINDOW (data.window, w);
1872 data.bi_bufpos = bi_start_pos;
1873 data.pixpos = dl->bounds.left_in;
1874 data.last_charset = Qunbound;
1875 data.last_findex = DEFAULT_INDEX;
1876 data.result_str = Qnil;
1878 /* Set the right boundary adjusting it to take into account any end
1879 glyph. Save the width of the end glyph for later use. */
1880 data.max_pixpos = dl->bounds.right_in;
1882 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1884 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1885 data.max_pixpos -= end_glyph_width;
1887 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1889 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1890 data.cursor_type = CURSOR_ON;
1892 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1893 data.cursor_type = NO_CURSOR;
1894 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1895 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1896 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1897 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1899 data.bi_cursor_bufpos = BI_BUF_PT (b);
1900 data.cursor_type = CURSOR_ON;
1902 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1904 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1905 data.cursor_type = CURSOR_ON;
1908 data.cursor_type = NO_CURSOR;
1911 data.start_col = w->hscroll;
1912 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1913 data.hscroll_glyph_width_adjust = 0;
1915 /* We regenerate the line from the very beginning. */
1916 Dynarr_reset (db->runes);
1918 /* Why is this less than or equal and not just less than? If the
1919 starting position is already equal to the maximum we can't add
1920 anything else, right? Wrong. We might still have a newline to
1921 add. A newline can use the room allocated for an end glyph since
1922 if we add it we know we aren't going to be adding any end
1925 /* #### Chuck -- I think this condition should be while (1).
1926 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1927 and the begin-glyph ends exactly at the end of the window, the
1928 end-glyph and text might not be displayed. while (1) ensures
1929 that the loop terminates only when either (a) there is
1930 propagation data or (b) the end-of-line or end-of-buffer is hit.
1932 #### Also I think you need to ensure that the operation
1933 "add begin glyphs; add end glyphs; add text" is atomic and
1934 can't get interrupted in the middle. If you run off the end
1935 of the line during that operation, then you keep accumulating
1936 propagation data until you're done. Otherwise, if the (e.g.)
1937 there's a begin glyph at a particular position and attempting
1938 to display that glyph results in window-end being hit and
1939 propagation data being generated, then the character at that
1940 position won't be displayed.
1942 #### See also the comment after the end of this loop, below.
1944 while (data.pixpos <= data.max_pixpos
1945 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1947 /* #### This check probably should not be necessary. */
1948 if (data.bi_bufpos > BI_BUF_ZV (b))
1950 /* #### urk! More of this lossage! */
1955 /* If selective display was an integer and we aren't working on
1956 a continuation line then find the next line we are actually
1957 supposed to display. */
1959 && (data.bi_bufpos == BI_BUF_BEGV (b)
1960 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
1962 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
1965 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
1966 if (data.bi_bufpos >= BI_BUF_ZV (b))
1968 data.bi_bufpos = BI_BUF_ZV (b);
1974 /* Check for face changes. */
1975 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
1977 /* Now compute the face and begin/end-glyph information. */
1979 /* Remember that the extent-fragment routines deal in Bytind's. */
1980 extent_fragment_update (w, data.ef, data.bi_bufpos);
1982 get_display_tables (w, data.findex, &face_dt, &window_dt);
1984 if (data.bi_bufpos == data.ef->end)
1989 /* Determine what is next to be displayed. We first handle any
1990 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
1991 display then we determine what to do based on the character at the
1992 current buffer position. */
1994 /* If the current position is covered by an invisible extent, do
1995 nothing (except maybe add some ellipses).
1997 #### The behavior of begin and end-glyphs at the edge of an
1998 invisible extent should be investigated further. This is
1999 fairly low priority though. */
2000 if (data.ef->invisible)
2002 /* #### Chuck, perhaps you could look at this code? I don't
2003 really know what I'm doing. */
2006 Dynarr_free (*prop);
2010 /* The extent fragment code only sets this when we should
2011 really display the ellipses. It makes sure the ellipses
2012 don't get displayed more than once in a row. */
2013 if (data.ef->invisible_ellipses)
2015 struct glyph_block gb;
2017 data.ef->invisible_ellipses_already_displayed = 1;
2018 data.ef->invisible_ellipses = 0;
2020 gb.glyph = Vinvisible_text_glyph;
2021 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2022 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2023 /* Perhaps they shouldn't propagate if the very next thing
2024 is to display a newline (for compatibility with
2025 selective-display-ellipses)? Maybe that's too
2031 /* If point is in an invisible region we place it on the
2032 next visible character. */
2033 if (data.cursor_type == CURSOR_ON
2034 && data.bi_bufpos == data.bi_cursor_bufpos)
2036 data.cursor_type = NEXT_CURSOR;
2039 /* #### What if we we're dealing with a display table? */
2043 if (data.bi_bufpos == BI_BUF_ZV (b))
2046 INC_BYTIND (b, data.bi_bufpos);
2049 /* If there is propagation data, then it represents the current
2050 buffer position being displayed. Add them and advance the
2051 position counter. This might also add the minibuffer
2055 dl->used_prop_data = 1;
2056 *prop = add_propagation_runes (prop, &data);
2059 goto done; /* gee, a really narrow window */
2060 else if (data.bi_bufpos == BI_BUF_ZV (b))
2062 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2063 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2064 data.bi_bufpos = BI_BUF_BEGV (b);
2066 INC_BYTIND (b, data.bi_bufpos);
2069 /* If there are end glyphs, add them to the line. These are
2070 the end glyphs for the previous run of text. We add them
2071 here rather than doing them at the end of handling the
2072 previous run so that glyphs at the beginning and end of
2073 a line are handled correctly. */
2074 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2076 *prop = add_glyph_runes (&data, END_GLYPHS);
2081 /* If there are begin glyphs, add them to the line. */
2082 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2084 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2089 /* If at end-of-buffer, we've already processed begin and
2090 end-glyphs at this point and there's no text to process,
2092 else if (data.bi_bufpos == BI_BUF_ZV (b))
2097 Lisp_Object entry = Qnil;
2098 /* Get the character at the current buffer position. */
2099 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2100 if (!NILP (face_dt) || !NILP (window_dt))
2101 entry = display_table_entry (data.ch, face_dt, window_dt);
2103 /* If there is a display table entry for it, hand it off to
2104 add_disp_table_entry_runes and let it worry about it. */
2105 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
2107 *prop = add_disp_table_entry_runes (&data, entry);
2113 /* Check if we have hit a newline character. If so, add a marker
2114 to the line and end this loop. */
2115 else if (data.ch == '\n')
2117 /* We aren't going to be adding an end glyph so give its
2118 space back in order to make sure that the cursor can
2120 data.max_pixpos += end_glyph_width;
2123 && (bi_spaces_at_point
2124 (b, next_bytind (b, data.bi_bufpos))
2127 if (!NILP (b->selective_display_ellipses))
2129 struct glyph_block gb;
2132 gb.glyph = Vinvisible_text_glyph;
2133 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2134 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2138 /* Cheesy, cheesy, cheesy. We mark the end of the
2139 line with a special "character rune" whose width
2140 is the EOL cursor width and whose character is
2141 the non-printing character '\n'. */
2142 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2143 *prop = add_emchar_rune (&data);
2146 /* We need to set data.bi_bufpos to the start of the
2147 next visible region in order to make this line
2148 appear to contain all of the invisible area.
2149 Otherwise, the line cache won't work
2151 INC_BYTIND (b, data.bi_bufpos);
2152 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2155 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2156 if (data.bi_bufpos >= BI_BUF_ZV (b))
2158 data.bi_bufpos = BI_BUF_ZV (b);
2162 if (BI_BUF_FETCH_CHAR
2163 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2164 DEC_BYTIND (b, data.bi_bufpos);
2168 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2169 *prop = add_emchar_rune (&data);
2175 /* If the current character is ^M, and selective display is
2176 enabled, then add the invisible-text-glyph if
2177 selective-display-ellipses is set. In any case, this
2179 else if (data.ch == (('M' & 037)) && selective == -1)
2181 Bytind bi_next_bufpos;
2183 /* Find the buffer position at the end of the line. */
2185 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2186 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2188 DEC_BYTIND (b, bi_next_bufpos);
2190 /* If the cursor is somewhere in the elided text make
2191 sure that the cursor gets drawn appropriately. */
2192 if (data.cursor_type == CURSOR_ON
2193 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2194 data.bi_cursor_bufpos < bi_next_bufpos))
2196 data.cursor_type = NEXT_CURSOR;
2199 /* We won't be adding a truncation or continuation glyph
2200 so give up the room allocated for them. */
2201 data.max_pixpos += end_glyph_width;
2203 if (!NILP (b->selective_display_ellipses))
2205 /* We don't propagate anything from the invisible
2206 text glyph if it fails to fit. This is
2208 struct glyph_block gb;
2211 gb.glyph = Vinvisible_text_glyph;
2212 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2213 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2216 /* Set the buffer position to the end of the line. We
2217 need to do this before potentially adding a newline
2218 so that the cursor flag will get set correctly (if
2220 data.bi_bufpos = bi_next_bufpos;
2222 if (NILP (b->selective_display_ellipses)
2223 || data.bi_cursor_bufpos == bi_next_bufpos)
2225 /* We have to at least add a newline character so
2226 that the cursor shows up properly. */
2228 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2229 data.findex = DEFAULT_INDEX;
2231 data.bi_start_col_enabled = 0;
2233 add_emchar_rune (&data);
2236 /* This had better be a newline but doing it this way
2237 we'll see obvious incorrect results if it isn't. No
2238 need to abort here. */
2239 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2244 /* If the current character is considered to be printable, then
2246 else if (data.ch >= printable_min)
2248 *prop = add_emchar_rune (&data);
2253 /* If the current character is a tab, determine the next tab
2254 starting position and add a blank rune which extends from the
2255 current pixel position to that starting position. */
2256 else if (data.ch == '\t')
2258 int tab_start_pixpos = data.pixpos;
2263 if (data.start_col > 1)
2264 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
2267 next_tab_position (w, tab_start_pixpos,
2268 dl->bounds.left_in +
2269 data.hscroll_glyph_width_adjust);
2270 if (next_tab_start > data.max_pixpos)
2272 prop_width = next_tab_start - data.max_pixpos;
2273 next_tab_start = data.max_pixpos;
2275 data.blank_width = next_tab_start - data.pixpos;
2277 (next_tab_start - tab_start_pixpos) / space_width (w);
2279 *prop = add_blank_rune (&data, w, char_tab_width);
2281 /* add_blank_rune is only supposed to be called with
2282 sizes guaranteed to fit in the available space. */
2287 struct prop_block pb;
2288 *prop = Dynarr_new (prop_block);
2290 pb.type = PROP_BLANK;
2291 pb.data.p_blank.width = prop_width;
2292 pb.data.p_blank.findex = data.findex;
2293 Dynarr_add (*prop, pb);
2299 /* If character is a control character, pass it off to
2300 add_control_char_runes.
2302 The is_*() routines have undefined results on
2303 arguments outside of the range [-1, 255]. (This
2304 often bites people who carelessly use `char' instead
2305 of `unsigned char'.)
2307 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2309 *prop = add_control_char_runes (&data, b);
2315 /* If the character is above the ASCII range and we have not
2316 already handled it, then print it as an octal number. */
2317 else if (data.ch >= 0200)
2319 *prop = add_octal_runes (&data);
2325 /* Assume the current character is considered to be printable,
2326 then just add it. */
2329 *prop = add_emchar_rune (&data);
2334 INC_BYTIND (b, data.bi_bufpos);
2340 /* Determine the starting point of the next line if we did not hit the
2341 end of the buffer. */
2342 if (data.bi_bufpos < BI_BUF_ZV (b)
2343 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2345 /* #### This check is not correct. If the line terminated
2346 due to a begin-glyph or end-glyph hitting window-end, then
2347 data.ch will not point to the character at data.bi_bufpos. If
2348 you make the two changes mentioned at the top of this loop,
2349 you should be able to say '(if (*prop))'. That should also
2350 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2353 /* The common case is that the line ended because we hit a newline.
2354 In that case, the next character is just the next buffer
2356 if (data.ch == '\n')
2358 /* If data.start_col_enabled is still true, then the window is
2359 scrolled far enough so that nothing on this line is visible.
2360 We need to stick a truncation glyph at the beginning of the
2361 line in that case unless the line is completely blank. */
2362 if (data.bi_start_col_enabled)
2364 if (data.cursor_type == CURSOR_ON)
2366 if (data.bi_cursor_bufpos >= bi_start_pos
2367 && data.bi_cursor_bufpos <= data.bi_bufpos)
2368 data.bi_cursor_bufpos = data.bi_bufpos;
2370 data.findex = DEFAULT_INDEX;
2372 data.bi_start_col_enabled = 0;
2374 if (data.bi_bufpos != bi_start_pos)
2376 struct glyph_block gb;
2379 gb.glyph = Vhscroll_glyph;
2380 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2381 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2385 /* This duplicates code down below to add a newline to
2386 the end of an otherwise empty line.*/
2388 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2390 add_emchar_rune (&data);
2394 INC_BYTIND (b, data.bi_bufpos);
2397 /* Otherwise we have a buffer line which cannot fit on one display
2401 struct glyph_block gb;
2402 struct glyph_cachel *cachel;
2404 /* If the line is to be truncated then we actually have to look
2405 for the next newline. We also add the end-of-line glyph which
2406 we know will fit because we adjusted the right border before
2407 we starting laying out the line. */
2408 data.max_pixpos += end_glyph_width;
2409 data.findex = DEFAULT_INDEX;
2416 /* Now find the start of the next line. */
2417 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2419 /* If the cursor is past the truncation line then we
2420 make it appear on the truncation glyph. If we've hit
2421 the end of the buffer then we also make the cursor
2422 appear unless eob is immediately preceded by a
2423 newline. In that case the cursor should actually
2424 appear on the next line. */
2425 if (data.cursor_type == CURSOR_ON
2426 && data.bi_cursor_bufpos >= data.bi_bufpos
2427 && (data.bi_cursor_bufpos < bi_pos ||
2428 (bi_pos == BI_BUF_ZV (b)
2429 && (bi_pos == BI_BUF_BEGV (b)
2430 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2432 data.bi_cursor_bufpos = bi_pos;
2434 data.cursor_type = NO_CURSOR;
2436 data.bi_bufpos = bi_pos;
2437 gb.glyph = Vtruncation_glyph;
2438 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2442 /* The cursor can never be on the continuation glyph. */
2443 data.cursor_type = NO_CURSOR;
2445 /* data.bi_bufpos is already at the start of the next line. */
2447 gb.glyph = Vcontinuation_glyph;
2448 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2451 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
2453 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2454 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2455 /* #### Damn this losing shit. */
2459 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2460 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2462 /* We need to add a marker to the end of the line since there is no
2463 newline character in order for the cursor to get drawn. We label
2464 it as a newline so that it gets handled correctly by the
2465 whitespace routines below. */
2468 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2469 data.findex = DEFAULT_INDEX;
2471 data.bi_start_col_enabled = 0;
2473 data.max_pixpos += data.blank_width;
2474 add_emchar_rune (&data);
2475 data.max_pixpos -= data.blank_width;
2477 /* #### urk! Chuck, this shit is bad news. Going around
2478 manipulating invalid positions is guaranteed to result in
2479 trouble sooner or later. */
2480 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2483 /* Calculate left whitespace boundary. */
2487 /* Whitespace past a newline is considered right whitespace. */
2488 while (elt < Dynarr_length (db->runes))
2490 struct rune *rb = Dynarr_atp (db->runes, elt);
2492 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2493 || rb->type == RUNE_BLANK)
2495 dl->bounds.left_white += rb->width;
2499 elt = Dynarr_length (db->runes);
2503 /* Calculate right whitespace boundary. */
2505 int elt = Dynarr_length (db->runes) - 1;
2508 while (!done && elt >= 0)
2510 struct rune *rb = Dynarr_atp (db->runes, elt);
2512 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2513 && isspace (rb->object.chr.ch))
2514 && !rb->type == RUNE_BLANK)
2516 dl->bounds.right_white = rb->xpos + rb->width;
2524 /* The line is blank so everything is considered to be right
2527 dl->bounds.right_white = dl->bounds.left_in;
2530 /* Set the display blocks bounds. */
2531 db->start_pos = dl->bounds.left_in;
2532 if (Dynarr_length (db->runes))
2534 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2536 db->end_pos = rb->xpos + rb->width;
2539 db->end_pos = dl->bounds.right_white;
2541 /* update line height parameters */
2542 if (!data.new_ascent && !data.new_descent)
2544 /* We've got a blank line so initialize these values from the default
2546 default_face_font_info (data.window, &data.new_ascent,
2547 &data.new_descent, 0, 0, 0);
2550 if (data.max_pixmap_height)
2552 int height = data.new_ascent + data.new_descent;
2553 int pix_ascent, pix_descent;
2555 pix_descent = data.max_pixmap_height * data.new_descent / height;
2556 pix_ascent = data.max_pixmap_height - pix_descent;
2558 data.new_ascent = max (data.new_ascent, pix_ascent);
2559 data.new_descent = max (data.new_descent, pix_descent);
2562 dl->ascent = data.new_ascent;
2563 dl->descent = data.new_descent;
2566 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2568 if (dl->ascent < ascent)
2569 dl->ascent = ascent;
2572 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2574 if (dl->descent < descent)
2575 dl->descent = descent;
2578 dl->cursor_elt = data.cursor_x;
2579 /* #### lossage lossage lossage! Fix this shit! */
2580 if (data.bi_bufpos > BI_BUF_ZV (b))
2581 dl->end_bufpos = BUF_ZV (b);
2583 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2585 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2587 /* This doesn't correctly take into account tabs and control
2588 characters but if the window isn't being truncated then this
2589 value isn't going to end up being used anyhow. */
2590 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2592 /* #### handle horizontally scrolled line with text none of which
2593 was actually laid out. */
2595 /* #### handle any remainder of overlay arrow */
2597 if (*prop == ADD_FAILED)
2600 if (truncate_win && *prop)
2602 Dynarr_free (*prop);
2606 extent_fragment_delete (data.ef);
2608 /* #### If we started at EOB, then make sure we return a value past
2609 it so that regenerate_window will exit properly. This is bogus.
2610 The main loop should get fixed so that it isn't necessary to call
2611 this function if we are already at EOB. */
2613 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2614 return data.bi_bufpos + 1; /* Yuck! */
2616 return data.bi_bufpos;
2619 /* Display the overlay arrow at the beginning of the given line. */
2622 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2624 struct frame *f = XFRAME (w->frame);
2625 struct device *d = XDEVICE (f->device);
2628 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2629 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2635 XSETWINDOW (data.window, w);
2636 data.db = get_display_block_from_line (dl, OVERWRITE);
2638 data.pixpos = dl->bounds.left_in;
2639 data.max_pixpos = dl->bounds.right_in;
2640 data.cursor_type = NO_CURSOR;
2642 data.findex = DEFAULT_INDEX;
2643 data.last_charset = Qunbound;
2644 data.last_findex = DEFAULT_INDEX;
2645 data.result_str = Qnil;
2647 Dynarr_reset (data.db->runes);
2649 if (STRINGP (Voverlay_arrow_string))
2651 add_bufbyte_string_runes
2653 XSTRING_DATA (Voverlay_arrow_string),
2654 XSTRING_LENGTH (Voverlay_arrow_string),
2657 else if (GLYPHP (Voverlay_arrow_string))
2659 struct glyph_block gb;
2661 gb.glyph = Voverlay_arrow_string;
2663 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2666 if (data.max_pixmap_height)
2668 int height = data.new_ascent + data.new_descent;
2669 int pix_ascent, pix_descent;
2671 pix_descent = data.max_pixmap_height * data.new_descent / height;
2672 pix_ascent = data.max_pixmap_height - pix_descent;
2674 data.new_ascent = max (data.new_ascent, pix_ascent);
2675 data.new_descent = max (data.new_descent, pix_descent);
2678 dl->ascent = data.new_ascent;
2679 dl->descent = data.new_descent;
2681 data.db->start_pos = dl->bounds.left_in;
2682 data.db->end_pos = data.pixpos;
2684 return data.pixpos - dl->bounds.left_in;
2687 /* Add a type of glyph to a margin display block. */
2690 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2691 int count, enum glyph_layout layout, int side, Lisp_Object window)
2693 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2695 : dl->right_glyphs);
2700 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2701 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2704 elt = Dynarr_length (gbd) - 1;
2711 end = Dynarr_length (gbd);
2714 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2716 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2718 if (NILP (gb->extent))
2719 abort (); /* these should have been handled in add_glyph_rune */
2722 ((side == LEFT_GLYPHS &&
2723 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2724 || (side == RIGHT_GLYPHS &&
2725 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2729 rb.width = gb->width;
2730 rb.findex = gb->findex;
2734 rb.type = RUNE_DGLYPH;
2735 rb.object.dglyph.glyph = gb->glyph;
2736 rb.object.dglyph.extent = gb->extent;
2737 rb.object.dglyph.xoffset = 0;
2738 rb.cursor_type = CURSOR_OFF;
2740 Dynarr_add (db->runes, rb);
2745 if (glyph_contrib_p (gb->glyph, window))
2747 unsigned short ascent, descent;
2748 Lisp_Object baseline = glyph_baseline (gb->glyph, window);
2750 ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window);
2751 descent = glyph_descent (gb->glyph, Qnil, gb->findex, window);
2753 /* A pixmap that has not had a baseline explicitly set.
2754 We use the existing ascent / descent ratio of the
2756 if (NILP (baseline))
2758 int gheight = ascent + descent;
2759 int line_height = dl->ascent + dl->descent;
2760 int pix_ascent, pix_descent;
2762 pix_descent = (int) (gheight * dl->descent) / line_height;
2763 pix_ascent = gheight - pix_descent;
2765 dl->ascent = max ((int) dl->ascent, pix_ascent);
2766 dl->descent = max ((int) dl->descent, pix_descent);
2769 /* A string so determine contribution normally. */
2770 else if (EQ (baseline, Qt))
2772 dl->ascent = max (dl->ascent, ascent);
2773 dl->descent = max (dl->descent, descent);
2776 /* A pixmap with an explicitly set baseline. We determine the
2777 contribution here. */
2778 else if (INTP (baseline))
2780 int height = ascent + descent;
2781 int pix_ascent, pix_descent;
2783 pix_ascent = height * XINT (baseline) / 100;
2784 pix_descent = height - pix_ascent;
2786 dl->ascent = max ((int) dl->ascent, pix_ascent);
2787 dl->descent = max ((int) dl->descent, pix_descent);
2790 /* Otherwise something is screwed up. */
2796 (reverse ? elt-- : elt++);
2802 /* Add a blank to a margin display block. */
2805 add_margin_blank (struct display_line *dl, struct display_block *db,
2806 struct window *w, int xpos, int width, int side)
2810 rb.findex = (side == LEFT_GLYPHS
2811 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2812 : get_builtin_face_cache_index (w, Vright_margin_face));
2817 rb.type = RUNE_BLANK;
2818 rb.cursor_type = CURSOR_OFF;
2820 Dynarr_add (db->runes, rb);
2823 /* Display glyphs in the left outside margin, left inside margin and
2824 left whitespace area. */
2827 create_left_glyph_block (struct window *w, struct display_line *dl,
2832 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2834 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2835 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2836 int left_in_start = dl->bounds.left_in;
2837 int left_in_end = dl->bounds.left_in + overlay_width;
2839 struct display_block *odb, *idb;
2841 XSETWINDOW (window, w);
2843 /* We have to add the glyphs to the line in the order outside,
2844 inside, whitespace. However the precedence dictates that we
2845 determine how many will fit in the reverse order. */
2847 /* Determine how many whitespace glyphs we can display and where
2848 they should start. */
2849 white_in_start = dl->bounds.left_white;
2850 white_out_start = left_in_start;
2851 white_out_cnt = white_in_cnt = 0;
2854 while (elt < Dynarr_length (dl->left_glyphs))
2856 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2858 if (NILP (gb->extent))
2859 abort (); /* these should have been handled in add_glyph_rune */
2861 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2865 width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2867 if (white_in_start - width >= left_in_end)
2870 white_in_start -= width;
2874 else if (use_overflow
2875 && (white_out_start - width > dl->bounds.left_out))
2878 white_out_start -= width;
2889 /* Determine how many inside margin glyphs we can display and where
2890 they should start. The inside margin glyphs get whatever space
2891 is left after the whitespace glyphs have been displayed. These
2892 are tricky to calculate since if we decide to use the overflow
2893 area we basically have to start over. So for these we build up a
2894 list of just the inside margin glyphs and manipulate it to
2895 determine the needed info. */
2897 glyph_block_dynarr *ib;
2898 int avail_in, avail_out;
2901 int used_in, used_out;
2904 used_in = used_out = 0;
2905 ib = Dynarr_new (glyph_block);
2906 while (elt < Dynarr_length (dl->left_glyphs))
2908 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2910 if (NILP (gb->extent))
2911 abort (); /* these should have been handled in add_glyph_rune */
2913 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2916 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2917 used_in += gb->width;
2918 Dynarr_add (ib, *gb);
2928 avail_in = white_in_start - left_in_end;
2936 avail_out = white_out_start - dl->bounds.left_out;
2939 while (!done && marker < Dynarr_length (ib))
2941 int width = Dynarr_atp (ib, marker)->width;
2943 /* If everything now fits in the available inside margin
2944 space, we're done. */
2945 if (used_in <= avail_in)
2949 /* Otherwise see if we have room to move a glyph to the
2951 if (used_out + width <= avail_out)
2964 /* At this point we now know that everything from marker on goes in
2965 the inside margin and everything before it goes in the outside
2966 margin. The stuff going into the outside margin is guaranteed
2967 to fit, but we may have to trim some stuff from the inside. */
2969 in_in_end = left_in_end;
2970 in_out_start = white_out_start;
2971 in_out_cnt = in_in_cnt = 0;
2975 while (elt < Dynarr_length (dl->left_glyphs))
2977 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2979 if (NILP (gb->extent))
2980 abort (); /* these should have been handled in add_glyph_rune */
2982 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2985 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2990 in_out_start -= width;
2995 else if (in_in_end + width < white_in_start)
3010 /* Determine how many outside margin glyphs we can display. They
3011 always start at the left outside margin and can only use the
3012 outside margin space. */
3013 out_end = dl->bounds.left_out;
3017 while (elt < Dynarr_length (dl->left_glyphs))
3019 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3021 if (NILP (gb->extent))
3022 abort (); /* these should have been handled in add_glyph_rune */
3024 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3027 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3029 if (out_end + width <= in_out_start)
3043 /* Now that we know where everything goes, we add the glyphs as
3044 runes to the appropriate display blocks. */
3045 if (out_cnt || in_out_cnt || white_out_cnt)
3047 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3048 odb->start_pos = dl->bounds.left_out;
3049 /* #### We should stop adding a blank to account for the space
3050 between the end of the glyphs and the margin and instead set
3051 this accordingly. */
3052 odb->end_pos = dl->bounds.left_in;
3053 Dynarr_reset (odb->runes);
3058 if (in_in_cnt || white_in_cnt)
3060 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3061 idb->start_pos = dl->bounds.left_in;
3062 /* #### See above comment for odb->end_pos */
3063 idb->end_pos = dl->bounds.left_white;
3064 Dynarr_reset (idb->runes);
3069 /* First add the outside margin glyphs. */
3071 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3072 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3074 end_xpos = dl->bounds.left_out;
3076 /* There may be blank space between the outside margin glyphs and
3077 the inside margin glyphs. If so, add a blank. */
3078 if (in_out_cnt && (in_out_start - end_xpos))
3080 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3084 /* Next add the inside margin glyphs which are actually in the
3088 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3089 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3092 /* If we didn't add any inside margin glyphs to the outside margin,
3093 but are adding whitespace glyphs, then we need to add a blank
3095 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3097 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3101 /* Next add the whitespace margin glyphs which are actually in the
3105 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3106 GL_WHITESPACE, LEFT_GLYPHS, window);
3109 /* We take care of clearing between the end of the glyphs and the
3110 start of the inside margin for lines which have glyphs. */
3111 if (odb && (left_in_start - end_xpos))
3113 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3117 /* Next add the inside margin glyphs which are actually in the
3121 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3122 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3125 end_xpos = left_in_end;
3127 /* Make sure that the area between the end of the inside margin
3128 glyphs and the whitespace glyphs is cleared. */
3129 if (idb && (white_in_start - end_xpos > 0))
3131 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3135 /* Next add the whitespace margin glyphs which are actually in the
3139 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3140 LEFT_GLYPHS, window);
3143 /* Whitespace glyphs always end right next to the text block so
3144 there is nothing we have to make sure is cleared after them. */
3147 /* Display glyphs in the right outside margin, right inside margin and
3148 right whitespace area. */
3151 create_right_glyph_block (struct window *w, struct display_line *dl)
3155 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3157 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3158 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3160 struct display_block *odb, *idb;
3162 XSETWINDOW (window, w);
3164 /* We have to add the glyphs to the line in the order outside,
3165 inside, whitespace. However the precedence dictates that we
3166 determine how many will fit in the reverse order. */
3168 /* Determine how many whitespace glyphs we can display and where
3169 they should start. */
3170 white_in_end = dl->bounds.right_white;
3171 white_out_end = dl->bounds.right_in;
3172 white_out_cnt = white_in_cnt = 0;
3175 while (elt < Dynarr_length (dl->right_glyphs))
3177 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3179 if (NILP (gb->extent))
3180 abort (); /* these should have been handled in add_glyph_rune */
3182 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3184 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3186 if (white_in_end + width <= dl->bounds.right_in)
3189 white_in_end += width;
3193 else if (use_overflow
3194 && (white_out_end + width <= dl->bounds.right_out))
3197 white_out_end += width;
3208 /* Determine how many inside margin glyphs we can display and where
3209 they should start. The inside margin glyphs get whatever space
3210 is left after the whitespace glyphs have been displayed. These
3211 are tricky to calculate since if we decide to use the overflow
3212 area we basically have to start over. So for these we build up a
3213 list of just the inside margin glyphs and manipulate it to
3214 determine the needed info. */
3216 glyph_block_dynarr *ib;
3217 int avail_in, avail_out;
3220 int used_in, used_out;
3223 used_in = used_out = 0;
3224 ib = Dynarr_new (glyph_block);
3225 while (elt < Dynarr_length (dl->right_glyphs))
3227 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3229 if (NILP (gb->extent))
3230 abort (); /* these should have been handled in add_glyph_rune */
3232 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3234 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3235 used_in += gb->width;
3236 Dynarr_add (ib, *gb);
3245 avail_in = dl->bounds.right_in - white_in_end;
3250 avail_out = dl->bounds.right_out - white_out_end;
3253 while (!done && marker < Dynarr_length (ib))
3255 int width = Dynarr_atp (ib, marker)->width;
3257 /* If everything now fits in the available inside margin
3258 space, we're done. */
3259 if (used_in <= avail_in)
3263 /* Otherwise see if we have room to move a glyph to the
3265 if (used_out + width <= avail_out)
3278 /* At this point we now know that everything from marker on goes in
3279 the inside margin and everything before it goes in the outside
3280 margin. The stuff going into the outside margin is guaranteed
3281 to fit, but we may have to trim some stuff from the inside. */
3283 in_in_start = dl->bounds.right_in;
3284 in_out_end = dl->bounds.right_in;
3285 in_out_cnt = in_in_cnt = 0;
3289 while (elt < Dynarr_length (dl->right_glyphs))
3291 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3293 if (NILP (gb->extent))
3294 abort (); /* these should have been handled in add_glyph_rune */
3296 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3298 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3303 in_out_end += width;
3308 else if (in_in_start - width >= white_in_end)
3311 in_in_start -= width;
3323 /* Determine how many outside margin glyphs we can display. They
3324 always start at the right outside margin and can only use the
3325 outside margin space. */
3326 out_start = dl->bounds.right_out;
3330 while (elt < Dynarr_length (dl->right_glyphs))
3332 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3334 if (NILP (gb->extent))
3335 abort (); /* these should have been handled in add_glyph_rune */
3337 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3339 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3341 if (out_start - width >= in_out_end)
3355 /* Now that we now where everything goes, we add the glyphs as runes
3356 to the appropriate display blocks. */
3357 if (out_cnt || in_out_cnt || white_out_cnt)
3359 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3360 /* #### See comments before odb->start_pos init in
3361 create_left_glyph_block */
3362 odb->start_pos = dl->bounds.right_in;
3363 odb->end_pos = dl->bounds.right_out;
3364 Dynarr_reset (odb->runes);
3369 if (in_in_cnt || white_in_cnt)
3371 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3372 idb->start_pos = dl->bounds.right_white;
3373 /* #### See comments before odb->start_pos init in
3374 create_left_glyph_block */
3375 idb->end_pos = dl->bounds.right_in;
3376 Dynarr_reset (idb->runes);
3381 /* First add the whitespace margin glyphs which are actually in the
3385 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3386 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3390 end_xpos = dl->bounds.right_white;
3392 /* Make sure that the area between the end of the whitespace glyphs
3393 and the inside margin glyphs is cleared. */
3394 if (in_in_cnt && (in_in_start - end_xpos))
3396 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3400 /* Next add the inside margin glyphs which are actually in the
3404 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3405 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3408 /* If we didn't add any inside margin glyphs then make sure the rest
3409 of the inside margin area gets cleared. */
3410 if (idb && (dl->bounds.right_in - end_xpos))
3412 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3416 /* Next add any whitespace glyphs in the outside margin. */
3419 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3420 GL_WHITESPACE, RIGHT_GLYPHS, window);
3423 end_xpos = dl->bounds.right_in;
3425 /* Next add any inside margin glyphs in the outside margin. */
3428 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3429 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3432 /* There may be space between any whitespace or inside margin glyphs
3433 in the outside margin and the actual outside margin glyphs. */
3434 if (odb && (out_start - end_xpos))
3436 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3440 /* Finally, add the outside margin glyphs. */
3443 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3444 RIGHT_GLYPHS, window);
3449 /***************************************************************************/
3451 /* modeline routines */
3453 /***************************************************************************/
3455 /* Ensure that the given display line DL accurately represents the
3456 modeline for the given window. */
3459 generate_modeline (struct window *w, struct display_line *dl, int type)
3461 struct buffer *b = XBUFFER (w->buffer);
3462 struct frame *f = XFRAME (w->frame);
3463 struct device *d = XDEVICE (f->device);
3465 /* Unlike display line and rune pointers, this one can't change underneath
3467 struct display_block *db = get_display_block_from_line (dl, TEXT);
3468 int max_pixpos, min_pixpos, ypos_adj;
3469 Lisp_Object font_inst;
3471 /* This will actually determine incorrect inside boundaries for the
3472 modeline since it ignores the margins. However being aware of this fact
3473 we never use those values anywhere so it doesn't matter. */
3474 dl->bounds = calculate_display_line_boundaries (w, 1);
3476 /* We are generating a modeline. */
3478 dl->cursor_elt = -1;
3480 /* Reset the runes on the modeline. */
3481 Dynarr_reset (db->runes);
3483 if (!WINDOW_HAS_MODELINE_P (w))
3487 /* If there is a horizontal scrollbar, don't add anything. */
3488 if (window_scrollbar_height (w))
3491 dl->ascent = DEVMETH (d, divider_height, ());
3493 /* The modeline is at the bottom of the gutters. */
3494 dl->ypos = WINDOW_BOTTOM (w);
3496 rb.findex = MODELINE_INDEX;
3497 rb.xpos = dl->bounds.left_out;
3498 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3501 rb.type = RUNE_HLINE;
3502 rb.object.hline.thickness = 1;
3503 rb.object.hline.yoffset = 0;
3504 rb.cursor_type = NO_CURSOR;
3506 if (!EQ (Qzero, w->modeline_shadow_thickness)
3509 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3511 dl->ypos -= shadow_thickness;
3512 rb.xpos += shadow_thickness;
3513 rb.width -= 2 * shadow_thickness;
3516 Dynarr_add (db->runes, rb);
3520 /* !!#### not right; needs to compute the max height of
3522 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3524 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3525 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3527 min_pixpos = dl->bounds.left_out;
3528 max_pixpos = dl->bounds.right_out;
3530 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3532 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3534 ypos_adj = shadow_thickness;
3535 min_pixpos += shadow_thickness;
3536 max_pixpos -= shadow_thickness;
3541 generate_formatted_string_db (b->modeline_format,
3542 b->generated_modeline_string, w, dl, db,
3543 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3545 /* The modeline is at the bottom of the gutters. We have to wait to
3546 set this until we've generated the modeline in order to account
3547 for any embedded faces. */
3548 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3552 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3553 struct window *w, struct display_line *dl,
3554 struct display_block *db, face_index findex,
3555 int min_pixpos, int max_pixpos, int type)
3557 struct frame *f = XFRAME (w->frame);
3558 struct device *d = XDEVICE (f->device);
3567 data.findex = findex;
3568 data.pixpos = min_pixpos;
3569 data.max_pixpos = max_pixpos;
3570 data.cursor_type = NO_CURSOR;
3571 data.last_charset = Qunbound;
3572 data.last_findex = DEFAULT_INDEX;
3573 data.result_str = result_str;
3574 data.is_modeline = 1;
3575 XSETWINDOW (data.window, w);
3577 Dynarr_reset (formatted_string_extent_dynarr);
3578 Dynarr_reset (formatted_string_extent_start_dynarr);
3579 Dynarr_reset (formatted_string_extent_end_dynarr);
3581 /* This recursively builds up the modeline. */
3582 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3583 max_pixpos - min_pixpos, findex, type);
3585 if (Dynarr_length (db->runes))
3588 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3589 c_pixpos = rb->xpos + rb->width;
3592 c_pixpos = min_pixpos;
3594 /* If we don't reach the right side of the window, add a blank rune
3595 to make up the difference. This usually only occurs if the
3596 modeline face is using a proportional width font or a fixed width
3597 font of a different size from the default face font. */
3599 if (c_pixpos < max_pixpos)
3601 data.pixpos = c_pixpos;
3602 data.blank_width = max_pixpos - data.pixpos;
3604 add_blank_rune (&data, NULL, 0);
3607 /* Now create the result string and frob the extents into it. */
3608 if (!NILP (result_str))
3613 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3615 detach_all_extents (result_str);
3616 resize_string (XSTRING (result_str), -1,
3617 data.bytepos - XSTRING_LENGTH (result_str));
3619 strdata = XSTRING_DATA (result_str);
3621 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3623 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3625 len += (set_charptr_emchar
3626 (strdata + len, Dynarr_atp (db->runes,
3627 elt)->object.chr.ch));
3631 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3634 Lisp_Object extent = Qnil;
3637 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3638 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3641 child = Fmake_extent (Qnil, Qnil, result_str);
3642 Fputhash (extent, child, buf->modeline_extent_table);
3644 Fset_extent_parent (child, extent);
3645 set_extent_endpoints
3647 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3648 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3655 add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
3656 Charcount pos, Charcount min_pos, Charcount max_pos)
3658 /* This function has been Mule-ized. */
3660 CONST Bufbyte *cur_pos = str;
3661 struct display_block *db = data->db;
3663 data->blank_width = space_width (XWINDOW (data->window));
3664 while (Dynarr_length (db->runes) < pos)
3665 add_blank_rune (data, NULL, 0);
3667 end = (Dynarr_length (db->runes) +
3668 bytecount_to_charcount (str, strlen ((CONST char *) str)));
3670 end = min (max_pos, end);
3672 while (pos < end && *cur_pos)
3674 CONST Bufbyte *old_cur_pos = cur_pos;
3677 data->ch = charptr_emchar (cur_pos);
3678 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3679 INC_CHARPTR (cur_pos);
3683 data->modeline_charpos++;
3684 data->bytepos += cur_pos - old_cur_pos;
3688 while (Dynarr_length (db->runes) < min_pos &&
3689 (data->pixpos + data->blank_width <= data->max_pixpos))
3690 add_blank_rune (data, NULL, 0);
3692 return Dynarr_length (db->runes);
3695 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3696 modeline extents. */
3698 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3699 Charcount pos, Charcount min_pos, Charcount max_pos)
3701 /* This function has been Mule-ized. */
3703 struct display_block *db = data->db;
3704 struct glyph_block gb;
3706 data->blank_width = space_width (XWINDOW (data->window));
3707 while (Dynarr_length (db->runes) < pos)
3708 add_blank_rune (data, NULL, 0);
3710 end = Dynarr_length (db->runes) + 1;
3712 end = min (max_pos, end);
3716 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3719 while (Dynarr_length (db->runes) < pos &&
3720 (data->pixpos + data->blank_width <= data->max_pixpos))
3721 add_blank_rune (data, NULL, 0);
3723 return Dynarr_length (db->runes);
3726 /* If max_pos is == -1, it is considered to be infinite. The same is
3727 true of max_pixsize. */
3728 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3729 if (Dynarr_length (data->db->runes)) \
3730 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3734 /* Note that this function does "positions" in terms of characters and
3735 not in terms of columns. This is necessary to make the formatting
3736 work correctly when proportional width fonts are used in the
3739 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3740 Charcount min_pos, Charcount max_pos,
3741 Lisp_Object elt, int depth, int max_pixsize,
3742 face_index findex, int type)
3744 /* This function has been Mule-ized. */
3745 /* #### The other losing things in this function are:
3747 -- C zero-terminated-string lossage.
3748 -- Non-printable characters should be converted into something
3749 appropriate (e.g. ^F) instead of blindly being printed anyway.
3760 /* A string. Add to the display line and check for %-constructs
3763 Bufbyte *this = XSTRING_DATA (elt);
3765 while ((pos < max_pos || max_pos == -1) && *this)
3767 Bufbyte *last = this;
3769 while (*this && *this != '%')
3774 /* The string is just a string. */
3776 bytecount_to_charcount (last, this - last) + pos;
3777 Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos));
3779 pos = add_string_to_fstring_db_runes (data, last, pos, pos,
3782 else /* *this == '%' */
3784 Charcount spec_width = 0;
3786 this++; /* skip over '%' */
3788 /* We can't allow -ve args due to the "%-" construct.
3789 * Argument specifies minwidth but not maxwidth
3790 * (maxwidth can be specified by
3791 * (<negative-number> . <stuff>) modeline elements)
3793 while (isdigit (*this))
3795 spec_width = spec_width * 10 + (*this - '0');
3802 pos = generate_fstring_runes (w, data, pos, spec_width,
3803 max_pos, Vglobal_mode_string,
3804 depth, max_pixsize, findex,
3807 else if (*this == '-')
3809 Charcount num_to_add;
3811 if (max_pixsize < 0)
3813 else if (max_pos != -1)
3814 num_to_add = max_pos - pos;
3820 SET_CURRENT_MODE_CHARS_PIXSIZE;
3823 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3826 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3830 while (num_to_add--)
3831 pos = add_string_to_fstring_db_runes
3832 (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
3834 else if (*this != 0)
3837 Emchar ch = charptr_emchar (this);
3838 decode_mode_spec (w, ch, type);
3840 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3841 pos = add_string_to_fstring_db_runes (data,str, pos, pos,
3845 /* NOT this++. There could be any sort of character at
3846 the current position. */
3850 if (max_pixsize > 0)
3853 SET_CURRENT_MODE_CHARS_PIXSIZE;
3855 if (cur_pixsize >= max_pixsize)
3860 else if (SYMBOLP (elt))
3862 /* A symbol: process the value of the symbol recursively
3863 as if it appeared here directly. */
3864 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3866 if (!UNBOUNDP (tem))
3868 /* If value is a string, output that string literally:
3869 don't check for % within it. */
3873 add_string_to_fstring_db_runes
3874 (data, XSTRING_DATA (tem), pos, min_pos, max_pos);
3876 /* Give up right away for nil or t. */
3877 else if (!EQ (tem, elt))
3884 else if (GENERIC_SPECIFIERP (elt))
3886 Lisp_Object window, tem;
3887 XSETWINDOW (window, w);
3888 tem = specifier_instance_no_quit (elt, Qunbound, window,
3889 ERROR_ME_NOT, 0, Qzero);
3890 if (!UNBOUNDP (tem))
3896 else if (CONSP (elt))
3898 /* A cons cell: four distinct cases.
3899 * If first element is a string or a cons, process all the elements
3900 * and effectively concatenate them.
3901 * If first element is a negative number, truncate displaying cdr to
3902 * at most that many characters. If positive, pad (with spaces)
3903 * to at least that many characters.
3904 * If first element is a symbol, process the cadr or caddr recursively
3905 * according to whether the symbol's value is non-nil or nil.
3906 * If first element is a face, process the cdr recursively
3907 * without altering the depth.
3909 Lisp_Object car, tem;
3917 tem = symbol_value_in_buffer (car, w->buffer);
3918 /* elt is now the cdr, and we know it is a cons cell.
3919 Use its car if CAR has a non-nil value. */
3920 if (!UNBOUNDP (tem))
3928 /* Symbol's value is nil (or symbol is unbound)
3929 * Get the cddr of the original list
3930 * and if possible find the caddr and use that.
3935 else if (!CONSP (elt))
3943 else if (INTP (car))
3945 Charcount lim = XINT (car);
3951 /* Negative int means reduce maximum width.
3952 * DO NOT change MIN_PIXPOS here!
3953 * (20 -10 . foo) should truncate foo to 10 col
3954 * and then pad to 20.
3957 max_pos = pos - lim;
3959 max_pos = min (max_pos, pos - lim);
3963 /* Padding specified. Don't let it be more than
3967 if (max_pos != -1 && lim > max_pos)
3969 /* If that's more padding than already wanted, queue it.
3970 * But don't reduce padding already specified even if
3971 * that is beyond the current truncation point.
3978 else if (STRINGP (car) || CONSP (car))
3981 /* LIMIT is to protect against circular lists. */
3982 while (CONSP (elt) && --limit > 0
3983 && (pos < max_pos || max_pos == -1))
3985 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
3987 max_pixsize, findex, type);
3991 else if (EXTENTP (car))
3993 struct extent *ext = XEXTENT (car);
3995 if (EXTENT_LIVE_P (ext))
3997 face_index old_findex = data->findex;
3999 Lisp_Object font_inst;
4000 face_index new_findex;
4001 Bytecount start = data->bytepos;
4003 face = extent_face (ext);
4006 /* #### needs to merge faces, sigh */
4007 /* #### needs to handle list of faces */
4008 new_findex = get_builtin_face_cache_index (w, face);
4009 /* !!#### not right; needs to compute the max height of
4011 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
4014 data->dl->ascent = max (data->dl->ascent,
4015 XFONT_INSTANCE (font_inst)->ascent);
4016 data->dl->descent = max (data->dl->descent,
4017 XFONT_INSTANCE (font_inst)->
4021 new_findex = old_findex;
4023 data->findex = new_findex;
4024 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4025 XCDR (elt), depth - 1,
4026 max_pixsize, new_findex, type);
4027 data->findex = old_findex;
4028 Dynarr_add (formatted_string_extent_dynarr, ext);
4029 Dynarr_add (formatted_string_extent_start_dynarr, start);
4030 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4034 else if (GLYPHP (elt))
4036 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos);
4042 add_string_to_fstring_db_runes
4043 (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos,
4049 add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos,
4056 /* The caller is responsible for freeing the returned string. */
4058 generate_formatted_string (struct window *w, Lisp_Object format_str,
4059 Lisp_Object result_str, face_index findex, int type)
4061 struct display_line *dl;
4062 struct display_block *db;
4065 dl = &formatted_string_display_line;
4066 db = get_display_block_from_line (dl, TEXT);
4067 Dynarr_reset (db->runes);
4069 generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
4072 Dynarr_reset (formatted_string_emchar_dynarr);
4073 while (elt < Dynarr_length (db->runes))
4075 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
4076 Dynarr_add (formatted_string_emchar_dynarr,
4077 Dynarr_atp (db->runes, elt)->object.chr.ch);
4082 convert_emchar_string_into_malloced_string
4083 ( Dynarr_atp (formatted_string_emchar_dynarr, 0),
4084 Dynarr_length (formatted_string_emchar_dynarr), 0);
4087 /* Update just the modeline. Assumes the desired display structs. If
4088 they do not have a modeline block, it does nothing. */
4090 regenerate_modeline (struct window *w)
4092 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4094 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4098 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4099 redisplay_update_line (w, 0, 0, 0);
4103 /* Make sure that modeline display line is present in the given
4104 display structs if the window has a modeline and update that
4105 line. Returns true if a modeline was needed. */
4107 ensure_modeline_generated (struct window *w, int type)
4111 /* minibuffer windows don't have modelines */
4112 if (MINI_WINDOW_P (w))
4114 /* windows which haven't had it turned off do */
4115 else if (WINDOW_HAS_MODELINE_P (w))
4117 /* windows which have it turned off don't have a divider if there is
4118 a horizontal scrollbar */
4119 else if (window_scrollbar_height (w))
4121 /* and in this case there is none */
4127 display_line_dynarr *dla;
4129 dla = window_display_lines (w, type);
4131 /* We don't care if there is a display line which is not
4132 currently a modeline because it is definitely going to become
4133 one if we have gotten to this point. */
4134 if (Dynarr_length (dla) == 0)
4136 if (Dynarr_largest (dla) > 0)
4138 struct display_line *mlp = Dynarr_atp (dla, 0);
4139 Dynarr_add (dla, *mlp);
4143 struct display_line modeline;
4145 Dynarr_add (dla, modeline);
4149 /* If we're adding a new place marker go ahead and generate the
4150 modeline so that it is available for use by
4151 window_modeline_height. */
4152 generate_modeline (w, Dynarr_atp (dla, 0), type);
4155 return need_modeline;
4158 /* #### Kludge or not a kludge. I tend towards the former. */
4160 real_current_modeline_height (struct window *w)
4162 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4163 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4165 if (ensure_modeline_generated (w, CMOTION_DISP))
4167 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4169 if (Dynarr_length (dla))
4171 if (Dynarr_atp (dla, 0)->modeline)
4172 return (Dynarr_atp (dla, 0)->ascent +
4173 Dynarr_atp (dla, 0)->descent);
4180 /***************************************************************************/
4182 /* window-regeneration routines */
4184 /***************************************************************************/
4186 /* For a given window and starting position in the buffer it contains,
4187 ensure that the TYPE display lines accurately represent the
4188 presentation of the window. We pass the buffer instead of getting
4189 it from the window since redisplay_window may have temporarily
4190 changed it to the echo area buffer. */
4193 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
4195 struct frame *f = XFRAME (w->frame);
4196 struct buffer *b = XBUFFER (w->buffer);
4197 int ypos = WINDOW_TEXT_TOP (w);
4198 int yend; /* set farther down */
4200 prop_block_dynarr *prop;
4201 layout_bounds bounds;
4202 display_line_dynarr *dla;
4205 /* The lines had better exist by this point. */
4206 if (!(dla = window_display_lines (w, type)))
4209 w->max_line_len = 0;
4211 /* Normally these get updated in redisplay_window but it is possible
4212 for this function to get called from some other points where that
4213 update may not have occurred. This acts as a safety check. */
4214 if (!Dynarr_length (w->face_cachels))
4215 reset_face_cachels (w);
4216 if (!Dynarr_length (w->glyph_cachels))
4217 reset_glyph_cachels (w);
4219 Fset_marker (w->start[type], make_int (start_pos), w->buffer);
4220 Fset_marker (w->pointm[type], make_int (point), w->buffer);
4221 w->last_point_x[type] = -1;
4222 w->last_point_y[type] = -1;
4224 /* Make sure a modeline is in the structs if needed. */
4225 need_modeline = ensure_modeline_generated (w, type);
4227 /* Wait until here to set this so that the structs have a modeline
4228 generated in the case where one didn't exist. */
4229 yend = WINDOW_TEXT_BOTTOM (w);
4231 bounds = calculate_display_line_boundaries (w, 0);
4233 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
4234 if (MINI_WINDOW_P (w)
4235 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
4236 && !echo_area_active (f)
4237 && start_pos == BUF_BEGV (b))
4239 struct prop_block pb;
4241 prop = Dynarr_new (prop_block);
4243 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
4244 pb.type = PROP_MINIBUF_PROMPT;
4245 pb.data.p_string.str = XSTRING_DATA(string);
4246 pb.data.p_string.len = XSTRING_LENGTH(string);
4247 Dynarr_add (prop, pb);
4254 struct display_line dl;
4255 struct display_line *dlp;
4258 if (Dynarr_length (dla) < Dynarr_largest (dla))
4260 dlp = Dynarr_atp (dla, Dynarr_length (dla));
4270 dlp->bounds = bounds;
4272 start_pos = generate_display_line (w, dlp, 1, start_pos,
4273 w->hscroll, &prop, type);
4274 dlp->ypos = ypos + dlp->ascent;
4275 ypos = dlp->ypos + dlp->descent;
4279 int visible_height = dlp->ascent + dlp->descent;
4281 dlp->clip = (ypos - yend);
4282 visible_height -= dlp->clip;
4284 if (visible_height < VERTICAL_CLIP (w, 1))
4287 free_display_line (dlp);
4294 if (dlp->cursor_elt != -1)
4296 /* #### This check is steaming crap. Have to get things
4297 fixed so when create_text_block hits EOB, we're done,
4299 if (w->last_point_x[type] == -1)
4301 w->last_point_x[type] = dlp->cursor_elt;
4302 w->last_point_y[type] = Dynarr_length (dla);
4306 /* #### This means that we've added a cursor at EOB
4307 twice. Yuck oh yuck. */
4308 struct display_block *db =
4309 get_display_block_from_line (dlp, TEXT);
4311 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
4312 dlp->cursor_elt = -1;
4316 if (dlp->num_chars > w->max_line_len)
4317 w->max_line_len = dlp->num_chars;
4319 Dynarr_add (dla, *dlp);
4321 /* #### This isn't right, but it is close enough for now. */
4322 w->window_end_pos[type] = start_pos;
4324 /* #### This type of check needs to be done down in the
4325 generate_display_line call. */
4326 if (start_pos > BUF_ZV (b))
4333 /* #### More not quite right, but close enough. */
4334 /* #### Ben sez: apparently window_end_pos[] is measured
4335 as the number of characters between the window end and the
4336 end of the buffer? This seems rather weirdo. What's
4337 the justification for this? */
4338 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
4342 /* We know that this is the right thing to use because we put it
4343 there when we first started working in this function. */
4344 generate_modeline (w, Dynarr_atp (dla, 0), type);
4348 #define REGEN_INC_FIND_START_END \
4350 /* Determine start and end of lines. */ \
4351 if (!Dynarr_length (cdla)) \
4355 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
4359 else if (!Dynarr_atp (cdla, 0)->modeline \
4360 && !Dynarr_atp (ddla, 0)->modeline) \
4365 abort (); /* structs differ */ \
4367 dla_end = Dynarr_length (cdla) - 1; \
4370 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
4371 + Dynarr_atp (cdla, dla_start)->offset); \
4372 /* If this isn't true, then startp has changed and we need to do a \
4374 if (startp != start_pos) \
4377 /* Point is outside the visible region so give up. */ \
4378 if (pointm < start_pos) \
4383 /* This attempts to incrementally update the display structures. It
4384 returns a boolean indicating success or failure. This function is
4385 very similar to regenerate_window_incrementally and is in fact only
4386 called from that function. However, because of the nature of the
4387 changes it deals with it sometimes makes different assumptions
4388 which can lead to success which are much more difficult to make
4389 when dealing with buffer changes. */
4392 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
4394 Charcount beg_unchanged,
4395 Charcount end_unchanged)
4397 struct buffer *b = XBUFFER (w->buffer);
4398 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
4399 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
4403 int first_line, last_line;
4405 /* Don't define this in the loop where it is used because we
4406 definitely want its value to survive between passes. */
4407 prop_block_dynarr *prop = NULL;
4409 /* If we don't have any buffer change recorded but the modiff flag has
4410 been incremented, then fail. I'm not sure of the exact circumstances
4411 under which this can happen, but I believe that it is probably a
4412 reasonable happening. */
4413 if (!point_visible (w, pointm, CURRENT_DISP)
4414 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
4417 /* If the cursor is moved we attempt to update it. If we succeed we
4418 go ahead and proceed with the optimization attempt. */
4419 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
4420 || pointm != marker_position (w->last_point[CURRENT_DISP]))
4422 struct frame *f = XFRAME (w->frame);
4423 struct device *d = XDEVICE (f->device);
4424 struct frame *sel_f = device_selected_frame (d);
4427 if (w->last_point_x[CURRENT_DISP] != -1
4428 && w->last_point_y[CURRENT_DISP] != -1)
4431 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
4433 /* Always regenerate the modeline in case it is
4434 displaying the current line or column. */
4435 regenerate_modeline (w);
4439 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
4441 if (f->modeline_changed)
4442 regenerate_modeline (w);
4450 if (beg_unchanged == -1 && end_unchanged == -1)
4453 /* assert: There are no buffer modifications or they are all below the
4454 visible region. We assume that regenerate_window_incrementally has
4455 not called us unless this is true. */
4457 REGEN_INC_FIND_START_END;
4459 /* If the changed are starts before the visible area, give up. */
4460 if (beg_unchanged < startp)
4463 /* Find what display line the extent changes first affect. */
4465 while (line <= dla_end)
4467 struct display_line *dl = Dynarr_atp (cdla, line);
4468 Bufpos lstart = dl->bufpos + dl->offset;
4469 Bufpos lend = dl->end_bufpos + dl->offset;
4471 if (beg_unchanged >= lstart && beg_unchanged <= lend)
4477 /* If the changes are below the visible area then if point hasn't
4478 moved return success otherwise fail in order to be safe. */
4481 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
4482 && pointm == marker_position (w->last_point[CURRENT_DISP]))
4488 /* At this point we know what line the changes first affect. We now
4489 begin redrawing lines as long as we are still in the affected
4490 region and the line's size and positioning don't change.
4491 Otherwise we fail. If we fail we will have altered the desired
4492 structs which could lead to an assertion failure. However, if we
4493 fail the next thing that is going to happen is a full regen so we
4494 will actually end up being safe. */
4495 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
4496 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
4497 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
4498 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
4500 first_line = last_line = line;
4501 while (line <= dla_end)
4503 Bufpos old_start, old_end, new_start;
4504 struct display_line *cdl = Dynarr_atp (cdla, line);
4505 struct display_line *ddl = Dynarr_atp (ddla, line);
4506 struct display_block *db;
4509 assert (cdl->bufpos == ddl->bufpos);
4510 assert (cdl->end_bufpos == ddl->end_bufpos);
4511 assert (cdl->offset == ddl->offset);
4513 db = get_display_block_from_line (ddl, TEXT);
4514 initial_size = Dynarr_length (db->runes);
4515 old_start = ddl->bufpos + ddl->offset;
4516 old_end = ddl->end_bufpos + ddl->offset;
4518 /* If this is the first line being updated and it used
4519 propagation data, fail. Otherwise we'll be okay because
4520 we'll have the necessary propagation data. */
4521 if (line == first_line && ddl->used_prop_data)
4524 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
4525 w->hscroll, &prop, DESIRED_DISP);
4528 /* #### If there is propagated stuff the fail. We could
4529 probably actually deal with this if the line had propagated
4530 information when originally created by a full
4538 /* If any line position parameters have changed or a
4539 cursor has disappeared or disappeared, fail. */
4540 db = get_display_block_from_line (ddl, TEXT);
4541 if (cdl->ypos != ddl->ypos
4542 || cdl->ascent != ddl->ascent
4543 || cdl->descent != ddl->descent
4544 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
4545 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
4546 || old_start != ddl->bufpos
4547 || old_end != ddl->end_bufpos
4548 || initial_size != Dynarr_length (db->runes))
4553 if (ddl->cursor_elt != -1)
4555 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
4556 w->last_point_y[DESIRED_DISP] = line;
4561 /* If the extent changes end on the line we just updated then
4562 we're done. Otherwise go on to the next line. */
4563 if (end_unchanged <= ddl->end_bufpos)
4569 redisplay_update_line (w, first_line, last_line, 1);
4573 /* Attempt to update the display data structures based on knowledge of
4574 the changed region in the buffer. Returns a boolean indicating
4575 success or failure. If this function returns a failure then a
4576 regenerate_window _must_ be performed next in order to maintain
4577 invariants located here. */
4580 regenerate_window_incrementally (struct window *w, Bufpos startp,
4583 struct buffer *b = XBUFFER (w->buffer);
4584 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
4585 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
4586 Charcount beg_unchanged, end_unchanged;
4587 Charcount extent_beg_unchanged, extent_end_unchanged;
4593 /* If this function is called, the current and desired structures
4594 had better be identical. If they are not, then that is a bug. */
4595 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
4597 /* We don't handle minibuffer windows yet. The minibuffer prompt
4599 if (MINI_WINDOW_P (w))
4602 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
4603 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
4605 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
4607 /* If nothing has changed in the buffer, then make sure point is ok
4609 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
4610 return regenerate_window_extents_only_changed (w, startp, pointm,
4611 extent_beg_unchanged,
4612 extent_end_unchanged);
4614 /* We can't deal with deleted newlines. */
4615 if (BUF_NEWLINE_WAS_DELETED (b))
4618 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
4619 end_unchanged = (BUF_END_UNCHANGED (b) == -1
4621 : BUF_Z (b) - BUF_END_UNCHANGED (b));
4623 REGEN_INC_FIND_START_END;
4625 /* If the changed area starts before the visible area, give up. */
4626 if (beg_unchanged < startp)
4629 /* Find what display line the buffer changes first affect. */
4631 while (line <= dla_end)
4633 struct display_line *dl = Dynarr_atp (cdla, line);
4634 Bufpos lstart = dl->bufpos + dl->offset;
4635 Bufpos lend = dl->end_bufpos + dl->offset;
4637 if (beg_unchanged >= lstart && beg_unchanged <= lend)
4643 /* If the changes are below the visible area then if point hasn't
4644 moved return success otherwise fail in order to be safe. */
4646 return regenerate_window_extents_only_changed (w, startp, pointm,
4647 extent_beg_unchanged,
4648 extent_end_unchanged);
4650 /* At this point we know what line the changes first affect. We
4651 now redraw that line. If the changes are contained within it
4652 we are going to succeed and can update just that one line.
4653 Otherwise we fail. If we fail we will have altered the desired
4654 structs which could lead to an assertion failure. However, if
4655 we fail the next thing that is going to happen is a full regen
4656 so we will actually end up being safe. */
4659 prop_block_dynarr *prop = NULL;
4660 struct display_line *cdl = Dynarr_atp (cdla, line);
4661 struct display_line *ddl = Dynarr_atp (ddla, line);
4663 assert (cdl->bufpos == ddl->bufpos);
4664 assert (cdl->end_bufpos == ddl->end_bufpos);
4665 assert (cdl->offset == ddl->offset);
4667 /* If the last rune is already a continuation glyph, fail.
4668 #### We should be able to handle this better. */
4670 struct display_block *db = get_display_block_from_line (ddl, TEXT);
4671 if (Dynarr_length (db->runes))
4674 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4676 if (rb->type == RUNE_DGLYPH
4677 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
4682 /* If the line was generated using propagation data, fail. */
4683 if (ddl->used_prop_data)
4686 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
4687 w->hscroll, &prop, DESIRED_DISP);
4690 /* If there is propagated stuff then it is pretty much a
4691 guarantee that more than just the one line is affected. */
4698 /* If the last rune is now a continuation glyph, fail. */
4700 struct display_block *db = get_display_block_from_line (ddl, TEXT);
4701 if (Dynarr_length (db->runes))
4704 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4706 if (rb->type == RUNE_DGLYPH
4707 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
4712 /* If any line position parameters have changed or a
4713 cursor has disappeared or disappeared, fail. */
4714 if (cdl->ypos != ddl->ypos
4715 || cdl->ascent != ddl->ascent
4716 || cdl->descent != ddl->descent
4717 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
4718 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
4723 /* If the changed area also ends on this line, then we may be in
4724 business. Update everything and return success. */
4725 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
4727 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
4728 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
4729 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
4731 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
4734 if (ddl->cursor_elt != -1)
4736 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
4737 w->last_point_y[DESIRED_DISP] = line;
4740 redisplay_update_line (w, line, line, 1);
4741 regenerate_modeline (w);
4743 /* #### For now we just flush the cache until this has been
4744 tested. After that is done, this should correct the
4746 Dynarr_reset (w->line_start_cache);
4748 /* Adjust the extent changed boundaries to remove any
4749 overlap with the buffer changes since we've just
4750 successfully updated that area. */
4751 if (extent_beg_unchanged != -1
4752 && extent_beg_unchanged >= beg_unchanged
4753 && extent_beg_unchanged < end_unchanged)
4754 extent_beg_unchanged = end_unchanged;
4756 if (extent_end_unchanged != -1
4757 && extent_end_unchanged >= beg_unchanged
4758 && extent_end_unchanged < end_unchanged)
4759 extent_end_unchanged = beg_unchanged - 1;
4761 if (extent_end_unchanged <= extent_beg_unchanged)
4762 extent_beg_unchanged = extent_end_unchanged = -1;
4764 /* This could lead to odd results if it fails, but since the
4765 buffer changes update succeeded this probably will to.
4766 We already know that the extent changes start at or after
4767 the line because we checked before entering the loop. */
4768 if (extent_beg_unchanged != -1
4769 && extent_end_unchanged != -1
4770 && ((extent_beg_unchanged < ddl->bufpos)
4771 || (extent_end_unchanged > ddl->end_bufpos)))
4772 return regenerate_window_extents_only_changed (w, startp, pointm,
4773 extent_beg_unchanged,
4774 extent_end_unchanged);
4784 /* Given a window and a point, update the given display lines such
4785 that point is displayed in the middle of the window.
4786 Return the window's new start position. */
4789 regenerate_window_point_center (struct window *w, Bufpos point, int type)
4793 /* We need to make sure that the modeline is generated so that the
4794 window height can be calculated correctly. */
4795 ensure_modeline_generated (w, type);
4797 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
4798 regenerate_window (w, startp, point, type);
4799 Fset_marker (w->start[type], make_int (startp), w->buffer);
4804 /* Given a window and a set of display lines, return a boolean
4805 indicating whether the given point is contained within. */
4808 point_visible (struct window *w, Bufpos point, int type)
4810 struct buffer *b = XBUFFER (w->buffer);
4811 display_line_dynarr *dla = window_display_lines (w, type);
4814 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
4819 if (Dynarr_length (dla) > first_line)
4822 struct display_line *dl = Dynarr_atp (dla, first_line);
4825 end = BUF_Z (b) - w->window_end_pos[type] - 1;
4827 if (point >= start && point <= end)
4829 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
4831 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
4833 if (point >= (dl->bufpos + dl->offset)
4834 && point <= (dl->end_bufpos + dl->offset))
4849 /* Return pixel position the middle of the window, not including the
4850 modeline and any potential horizontal scrollbar. */
4853 window_half_pixpos (struct window *w)
4855 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
4858 /* Return the display line which is currently in the middle of the
4859 window W for display lines TYPE. */
4862 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
4864 display_line_dynarr *dla;
4867 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
4869 if (type == CMOTION_DISP)
4870 regenerate_window (w, start, point, type);
4872 dla = window_display_lines (w, type);
4873 half = window_half_pixpos (w);
4875 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
4877 struct display_line *dl = Dynarr_atp (dla, elt);
4878 int line_bot = dl->ypos + dl->descent;
4880 if (line_bot > half)
4884 /* We may not have a line at the middle if the end of the buffer is
4889 /* Return a value for point that would place it at the beginning of
4890 the line which is in the middle of the window. */
4893 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
4895 /* line_at_center will regenerate the display structures, if necessary. */
4896 int line = line_at_center (w, type, start, point);
4899 return BUF_ZV (XBUFFER (w->buffer));
4902 display_line_dynarr *dla = window_display_lines (w, type);
4903 struct display_line *dl = Dynarr_atp (dla, line);
4909 /* For a given window, ensure that the current visual representation
4913 redisplay_window (Lisp_Object window, int skip_selected)
4915 struct window *w = XWINDOW (window);
4916 struct frame *f = XFRAME (w->frame);
4917 struct device *d = XDEVICE (f->device);
4918 Lisp_Object old_buffer = w->buffer;
4919 Lisp_Object the_buffer = w->buffer;
4921 int echo_active = 0;
4926 int selected_in_its_frame;
4927 int selected_globally;
4928 int skip_output = 0;
4929 int truncation_changed;
4930 int inactive_minibuffer =
4931 (MINI_WINDOW_P (w) &&
4932 (f != device_selected_frame (d)) &&
4933 !is_surrogate_for_selected_frame (f));
4935 /* #### In the new world this function actually does a bunch of
4936 optimizations such as buffer-based scrolling, but none of that is
4939 /* If this is a combination window, do its children; that's all.
4940 The selected window is always a leaf so we don't check for
4941 skip_selected here. */
4942 if (!NILP (w->vchild))
4944 redisplay_windows (w->vchild, skip_selected);
4947 if (!NILP (w->hchild))
4949 redisplay_windows (w->hchild, skip_selected);
4953 /* Is this window the selected window on its frame? */
4954 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
4956 selected_in_its_frame &&
4957 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
4958 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
4959 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
4960 if (skip_selected && selected_in_its_frame)
4963 /* It is possible that the window is not fully initialized yet. */
4964 if (NILP (w->buffer))
4967 if (MINI_WINDOW_P (w) && echo_area_active (f))
4969 w->buffer = the_buffer = Vecho_area_buffer;
4973 b = XBUFFER (w->buffer);
4977 old_pointm = selected_globally
4979 : marker_position (w->pointm[CURRENT_DISP]);
4984 if (selected_globally)
4986 pointm = BUF_PT (b);
4990 pointm = marker_position (w->pointm[CURRENT_DISP]);
4992 if (pointm < BUF_BEGV (b))
4993 pointm = BUF_BEGV (b);
4994 else if (pointm > BUF_ZV (b))
4995 pointm = BUF_ZV (b);
4998 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
5000 /* If the buffer has changed we have to invalid all of our face
5002 if ((!echo_active && b != window_display_buffer (w))
5003 || !Dynarr_length (w->face_cachels)
5004 || f->faces_changed)
5005 reset_face_cachels (w);
5007 mark_face_cachels_as_not_updated (w);
5009 /* Ditto the glyph cache elements. */
5010 if ((!echo_active && b != window_display_buffer (w))
5011 || !Dynarr_length (w->glyph_cachels)
5012 || f->glyphs_changed)
5013 reset_glyph_cachels (w);
5015 mark_glyph_cachels_as_not_updated (w);
5017 /* If the marker's buffer is not the window's buffer, then we need
5018 to find a new starting position. */
5019 if (!MINI_WINDOW_P (w)
5020 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5022 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5024 goto regeneration_done;
5029 old_startp = marker_position (w->start[CURRENT_DISP]);
5034 startp = marker_position (w->start[CURRENT_DISP]);
5035 if (startp < BUF_BEGV (b))
5036 startp = BUF_BEGV (b);
5037 else if (startp > BUF_ZV (b))
5038 startp = BUF_ZV (b);
5040 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5042 truncation_changed = (find_window_mirror (w)->truncate_win !=
5043 window_truncation_on (w));
5045 /* If w->force_start is set, then some function set w->start and we
5046 should display from there and change point, if necessary, to
5047 ensure that it is visible. */
5048 if (w->force_start || inactive_minibuffer)
5051 w->last_modified[DESIRED_DISP] = Qzero;
5052 w->last_facechange[DESIRED_DISP] = Qzero;
5054 regenerate_window (w, startp, pointm, DESIRED_DISP);
5056 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5058 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5060 if (selected_globally)
5061 BUF_SET_PT (b, pointm);
5063 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5066 /* #### BUFU amounts of overkill just to get the cursor
5067 location marked properly. FIX ME FIX ME FIX ME */
5068 regenerate_window (w, startp, pointm, DESIRED_DISP);
5071 goto regeneration_done;
5074 /* If nothing has changed since the last redisplay, then we just
5075 need to make sure that point is still visible. */
5076 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5077 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
5079 /* This check is to make sure we restore the minibuffer after a
5080 temporary change to the echo area. */
5081 && !(MINI_WINDOW_P (w) && f->buffers_changed)
5082 && !f->frame_changed
5083 && !truncation_changed
5084 /* check whether start is really at the begining of a line GE */
5085 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
5088 /* Check if the cursor has actually moved. */
5089 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5090 && pointm == marker_position (w->last_point[CURRENT_DISP])
5091 && selected_globally
5092 && !w->windows_changed
5094 && !f->extents_changed
5095 && !f->faces_changed
5096 && !f->glyphs_changed
5097 && !f->subwindows_changed
5098 && !f->point_changed
5099 && !f->windows_structure_changed)
5101 /* If not, we're done. */
5102 if (f->modeline_changed)
5103 regenerate_modeline (w);
5106 goto regeneration_done;
5110 /* If the new point is visible in the redisplay structures,
5111 then let the output update routines handle it, otherwise
5112 do things the hard way. */
5113 if (!w->windows_changed
5115 && !f->extents_changed
5116 && !f->faces_changed
5117 && !f->glyphs_changed
5118 && !f->subwindows_changed
5119 && !f->windows_structure_changed)
5121 if (point_visible (w, pointm, CURRENT_DISP)
5122 && w->last_point_x[CURRENT_DISP] != -1
5123 && w->last_point_y[CURRENT_DISP] != -1)
5125 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
5127 /* Always regenerate in case it is displaying
5128 the current line or column. */
5129 regenerate_modeline (w);
5132 goto regeneration_done;
5135 else if (!selected_in_its_frame && !f->point_changed)
5137 if (f->modeline_changed)
5138 regenerate_modeline (w);
5141 goto regeneration_done;
5145 /* If we weren't able to take the shortcut method, then use
5146 the brute force method. */
5147 regenerate_window (w, startp, pointm, DESIRED_DISP);
5149 if (point_visible (w, pointm, DESIRED_DISP))
5150 goto regeneration_done;
5154 /* Check if the starting point is no longer at the beginning of a
5155 line, in which case find a new starting point. We also recenter
5156 if our start position is equal to point-max. Otherwise we'll end
5157 up with a blank window. */
5158 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
5159 && !(startp == BUF_BEGV (b)
5160 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
5161 || (pointm == startp &&
5162 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
5163 startp < marker_position (w->last_start[CURRENT_DISP]))
5164 || (startp == BUF_ZV (b)))
5166 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5168 goto regeneration_done;
5170 /* See if we can update the data structures locally based on
5171 knowledge of what changed in the buffer. */
5172 else if (!w->windows_changed
5174 && !f->faces_changed
5175 && !f->glyphs_changed
5176 && !f->subwindows_changed
5177 && !f->windows_structure_changed
5178 && !f->frame_changed
5179 && !truncation_changed
5181 && regenerate_window_incrementally (w, startp, pointm))
5183 if (f->modeline_changed
5184 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
5185 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
5186 regenerate_modeline (w);
5189 goto regeneration_done;
5191 /* #### This is where a check for structure based scrolling would go. */
5192 /* If all else fails, try just regenerating and see what happens. */
5195 regenerate_window (w, startp, pointm, DESIRED_DISP);
5197 if (point_visible (w, pointm, DESIRED_DISP))
5198 goto regeneration_done;
5201 /* We still haven't gotten the window regenerated with point
5202 visible. Next we try scrolling a little and see if point comes
5203 back onto the screen. */
5204 if (scroll_step > 0)
5206 int scrolled = scroll_conservatively;
5207 for (; scrolled >= 0; scrolled -= scroll_step)
5209 startp = vmotion (w, startp,
5210 (pointm < startp) ? -scroll_step : scroll_step, 0);
5211 regenerate_window (w, startp, pointm, DESIRED_DISP);
5213 if (point_visible (w, pointm, DESIRED_DISP))
5214 goto regeneration_done;
5218 /* We still haven't managed to get the screen drawn with point on
5219 the screen, so just center it and be done with it. */
5220 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5225 /* If the window's frame is changed then reset the current display
5226 lines in order to force a full repaint. */
5227 if (f->frame_changed)
5229 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
5234 /* Must do this before calling redisplay_output_window because it
5235 sets some markers on the window. */
5238 w->buffer = old_buffer;
5239 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
5240 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
5243 /* These also have to be set before calling redisplay_output_window
5244 since it sets the CURRENT_DISP values based on them. */
5245 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5246 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5247 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5248 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5252 Bufpos start = marker_position (w->start[DESIRED_DISP]);
5253 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
5255 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
5257 update_line_start_cache (w, start, end, pointm, 1);
5258 redisplay_output_window (w);
5260 * If we just displayed the echo area, the line start cache is
5261 * no longer valid, because the minibuffer window is associated
5262 * with the window now.
5265 w->line_cache_last_updated = make_int (-1);
5268 /* #### This should be dependent on face changes and will need to be
5269 somewhere else once tty updates occur on a per-frame basis. */
5270 mark_face_cachels_as_clean (w);
5272 w->windows_changed = 0;
5275 /* Call buffer_reset_changes for all buffers present in any window
5276 currently visible in all frames on all devices. #### There has to
5277 be a better way to do this. */
5280 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
5282 buffer_reset_changes (XBUFFER (w->buffer));
5287 reset_buffer_changes (void)
5289 Lisp_Object frmcons, devcons, concons;
5291 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
5293 struct frame *f = XFRAME (XCAR (frmcons));
5295 if (FRAME_REPAINT_P (f))
5296 map_windows (f, reset_buffer_changes_mapfun, 0);
5300 /* Ensure that all windows underneath the given window in the window
5301 hierarchy are correctly displayed. */
5304 redisplay_windows (Lisp_Object window, int skip_selected)
5306 for (; !NILP (window) ; window = XWINDOW (window)->next)
5308 redisplay_window (window, skip_selected);
5313 call_redisplay_end_triggers (struct window *w, void *closure)
5315 Bufpos lrpos = w->last_redisplay_pos;
5316 w->last_redisplay_pos = 0;
5317 if (!NILP (w->buffer)
5318 && !NILP (w->redisplay_end_trigger)
5323 if (MARKERP (w->redisplay_end_trigger)
5324 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
5325 pos = marker_position (w->redisplay_end_trigger);
5326 else if (INTP (w->redisplay_end_trigger))
5327 pos = XINT (w->redisplay_end_trigger);
5330 w->redisplay_end_trigger = Qnil;
5337 XSETWINDOW (window, w);
5338 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
5339 Qredisplay_end_trigger_functions,
5341 w->redisplay_end_trigger);
5342 w->redisplay_end_trigger = Qnil;
5349 /* Ensure that all windows on the given frame are correctly displayed. */
5352 redisplay_frame (struct frame *f, int preemption_check)
5354 struct device *d = XDEVICE (f->device);
5356 if (preemption_check)
5358 /* The preemption check itself takes a lot of time,
5359 so normally don't do it here. We do it if called
5360 from Lisp, though (`redisplay-frame'). */
5363 REDISPLAY_PREEMPTION_CHECK;
5368 /* Before we put a hold on frame size changes, attempt to process
5369 any which are already pending. */
5370 if (f->size_change_pending)
5371 change_frame_size (f, f->new_height, f->new_width, 0);
5373 /* If frame size might need to be changed, due to changed size
5374 of toolbars, scrollbars etc, change it now */
5375 if (f->size_slipped)
5377 adjust_frame_size (f);
5378 assert (!f->size_slipped);
5381 /* The menubar, toolbar, and icon updates must be done before
5382 hold_frame_size_changes is called and we are officially
5383 'in_display'. They may eval lisp code which may call Fsignal.
5384 If in_display is set Fsignal will abort. */
5386 #ifdef HAVE_MENUBARS
5387 /* Update the menubar. It is done first since it could change
5388 the menubar's visibility. This way we avoid having flashing
5389 caused by an Expose event generated by the visibility change
5391 update_frame_menubars (f);
5392 #endif /* HAVE_MENUBARS */
5393 /* widgets are similar to menus in that they can call lisp to
5394 determine activation etc. Therefore update them before we get
5395 into redisplay. This is primarily for connected widgets such as
5397 update_frame_subwindows (f);
5398 #ifdef HAVE_TOOLBARS
5399 /* Update the toolbars. */
5400 update_frame_toolbars (f);
5401 #endif /* HAVE_TOOLBARS */
5403 hold_frame_size_changes ();
5405 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
5406 /* Within this section, we are defenseless and assume that the
5407 following cannot happen:
5409 1) garbage collection
5410 2) Lisp code evaluation
5411 3) frame size changes
5413 We ensure (3) by calling hold_frame_size_changes(), which
5414 will cause any pending frame size changes to get put on hold
5415 till after the end of the critical section. (1) follows
5416 automatically if (2) is met. #### Unfortunately, there are
5417 some places where Lisp code can be called within this section.
5418 We need to remove them.
5420 If Fsignal() is called during this critical section, we
5423 If garbage collection is called during this critical section,
5424 we simply return. #### We should abort instead.
5426 #### If a frame-size change does occur we should probably
5427 actually be preempting redisplay. */
5429 /* If we clear the frame we have to force its contents to be redrawn. */
5431 f->frame_changed = 1;
5433 /* Erase the frame before outputting its contents. */
5436 DEVMETH (d, clear_frame, (f));
5439 /* invalidate the subwindow cache. we are going to reuse the glyphs
5440 flag here to cause subwindows to get instantiated. This is
5441 because subwindows changed is less strict - dealing with things
5442 like the clicked state of button. */
5443 if (!Dynarr_length (f->subwindow_cachels)
5444 || f->glyphs_changed
5445 || f->frame_changed)
5446 reset_subwindow_cachels (f);
5448 mark_subwindow_cachels_as_not_updated (f);
5450 /* Do the selected window first. */
5451 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
5453 /* Then do the rest. */
5454 redisplay_windows (f->root_window, 1);
5456 /* We now call the output_end routine for tty frames. We delay
5457 doing so in order to avoid cursor flicker. So much for 100%
5459 if (FRAME_TTY_P (f))
5460 DEVMETH (d, output_end, (d));
5462 update_frame_title (f);
5464 f->buffers_changed = 0;
5465 f->clip_changed = 0;
5466 f->extents_changed = 0;
5467 f->faces_changed = 0;
5468 f->frame_changed = 0;
5469 f->glyphs_changed = 0;
5470 f->subwindows_changed = 0;
5471 f->icon_changed = 0;
5472 f->menubar_changed = 0;
5473 f->modeline_changed = 0;
5474 f->point_changed = 0;
5475 f->toolbar_changed = 0;
5476 f->windows_changed = 0;
5477 f->windows_structure_changed = 0;
5478 f->window_face_cache_reset = 0;
5479 f->echo_area_garbaged = 0;
5483 if (!f->size_change_pending)
5484 f->size_changed = 0;
5486 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
5488 /* Allow frame size changes to occur again.
5490 #### what happens if changes to other frames happen? */
5491 unhold_one_frame_size_changes (f);
5493 map_windows (f, call_redisplay_end_triggers, 0);
5497 /* Ensure that all frames on the given device are correctly displayed. */
5500 redisplay_device (struct device *d)
5502 Lisp_Object frame, frmcons;
5504 int size_change_failed = 0;
5507 if (DEVICE_STREAM_P (d)) /* nothing to do */
5510 /* It is possible that redisplay has been called before the
5511 device is fully initialized. If so then continue with the
5513 if (NILP (DEVICE_SELECTED_FRAME (d)))
5516 REDISPLAY_PREEMPTION_CHECK;
5520 /* Always do the selected frame first. */
5521 frame = DEVICE_SELECTED_FRAME (d);
5525 if (f->icon_changed || f->windows_changed)
5526 update_frame_icon (f);
5528 if (FRAME_REPAINT_P (f))
5530 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
5531 f->faces_changed || f->frame_changed || f->menubar_changed ||
5532 f->modeline_changed || f->point_changed || f->size_changed ||
5533 f->toolbar_changed || f->windows_changed || f->size_slipped ||
5534 f->windows_structure_changed || f->glyphs_changed || f->subwindows_changed)
5536 preempted = redisplay_frame (f, 0);
5542 /* If the frame redisplay did not get preempted, then this flag
5543 should have gotten set to 0. It might be possible for that
5544 not to happen if a size change event were to occur at an odd
5545 time. To make sure we don't miss anything we simply don't
5546 reset the top level flags until the condition ends up being
5547 in the right state. */
5548 if (f->size_changed)
5549 size_change_failed = 1;
5552 DEVICE_FRAME_LOOP (frmcons, d)
5554 f = XFRAME (XCAR (frmcons));
5556 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
5559 if (f->icon_changed || f->windows_changed)
5560 update_frame_icon (f);
5562 if (FRAME_REPAINT_P (f))
5564 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
5565 f->faces_changed || f->frame_changed || f->menubar_changed ||
5566 f->modeline_changed || f->point_changed || f->size_changed ||
5567 f->toolbar_changed || f->windows_changed ||
5568 f->windows_structure_changed ||
5569 f->glyphs_changed || f->subwindows_changed)
5571 preempted = redisplay_frame (f, 0);
5577 if (f->size_change_pending)
5578 size_change_failed = 1;
5582 /* If we get here then we redisplayed all of our frames without
5583 getting preempted so mark ourselves as clean. */
5584 d->buffers_changed = 0;
5585 d->clip_changed = 0;
5586 d->extents_changed = 0;
5587 d->faces_changed = 0;
5588 d->frame_changed = 0;
5589 d->glyphs_changed = 0;
5590 d->subwindows_changed = 0;
5591 d->icon_changed = 0;
5592 d->menubar_changed = 0;
5593 d->modeline_changed = 0;
5594 d->point_changed = 0;
5595 d->toolbar_changed = 0;
5596 d->windows_changed = 0;
5597 d->windows_structure_changed = 0;
5599 if (!size_change_failed)
5600 d->size_changed = 0;
5606 restore_profiling_redisplay_flag (Lisp_Object val)
5608 profiling_redisplay_flag = XINT (val);
5612 /* Ensure that all windows on all frames on all devices are displaying
5613 the current contents of their respective buffers. */
5616 redisplay_without_hooks (void)
5618 Lisp_Object devcons, concons;
5619 int size_change_failed = 0;
5620 int count = specpdl_depth ();
5622 if (profiling_active)
5624 record_unwind_protect (restore_profiling_redisplay_flag,
5625 make_int (profiling_redisplay_flag));
5626 profiling_redisplay_flag = 1;
5629 if (asynch_device_change_pending)
5630 handle_asynch_device_change ();
5632 if (!buffers_changed && !clip_changed && !extents_changed &&
5633 !faces_changed && !frame_changed && !icon_changed &&
5634 !menubar_changed && !modeline_changed && !point_changed &&
5635 !size_changed && !toolbar_changed && !windows_changed &&
5636 !glyphs_changed && !subwindows_changed &&
5637 !windows_structure_changed && !disable_preemption &&
5638 preemption_count < max_preempts)
5641 DEVICE_LOOP_NO_BREAK (devcons, concons)
5643 struct device *d = XDEVICE (XCAR (devcons));
5646 if (d->buffers_changed || d->clip_changed || d->extents_changed ||
5647 d->faces_changed || d->frame_changed || d->icon_changed ||
5648 d->menubar_changed || d->modeline_changed || d->point_changed ||
5649 d->size_changed || d->toolbar_changed || d->windows_changed ||
5650 d->windows_structure_changed ||
5651 d->glyphs_changed || d->subwindows_changed)
5653 preempted = redisplay_device (d);
5658 RESET_CHANGED_SET_FLAGS;
5662 /* See comment in redisplay_device. */
5663 if (d->size_changed)
5664 size_change_failed = 1;
5667 preemption_count = 0;
5669 /* Mark redisplay as accurate */
5670 buffers_changed = 0;
5672 extents_changed = 0;
5675 subwindows_changed = 0;
5677 menubar_changed = 0;
5678 modeline_changed = 0;
5680 toolbar_changed = 0;
5681 windows_changed = 0;
5682 windows_structure_changed = 0;
5683 RESET_CHANGED_SET_FLAGS;
5687 mark_all_faces_as_clean ();
5691 if (!size_change_failed)
5694 reset_buffer_changes ();
5697 unbind_to (count, Qnil);
5703 if (last_display_warning_tick != display_warning_tick &&
5704 !inhibit_warning_display)
5706 /* If an error occurs during this function, oh well.
5707 If we report another warning, we could get stuck in an
5708 infinite loop reporting warnings. */
5709 call0_trapping_errors (0, Qdisplay_warning_buffer);
5710 last_display_warning_tick = display_warning_tick;
5712 /* The run_hook_trapping_errors functions are smart enough not
5713 to do any evalling if the hook function is empty, so there
5714 should not be any significant time loss. All places in the
5715 C code that call redisplay() are prepared to handle GCing,
5716 so we should be OK. */
5717 #ifndef INHIBIT_REDISPLAY_HOOKS
5718 run_hook_trapping_errors ("Error in pre-redisplay-hook",
5719 Qpre_redisplay_hook);
5720 #endif /* INHIBIT_REDISPLAY_HOOKS */
5722 redisplay_without_hooks ();
5724 #ifndef INHIBIT_REDISPLAY_HOOKS
5725 run_hook_trapping_errors ("Error in post-redisplay-hook",
5726 Qpost_redisplay_hook);
5727 #endif /* INHIBIT_REDISPLAY_HOOKS */
5731 static char window_line_number_buf[32];
5733 /* Efficiently determine the window line number, and return a pointer
5734 to its printed representation. Do this regardless of whether
5735 line-number-mode is on. The first line in the buffer is counted as
5736 1. If narrowing is in effect, the lines are counted from the
5737 beginning of the visible portion of the buffer. */
5739 window_line_number (struct window *w, int type)
5741 struct device *d = XDEVICE (XFRAME (w->frame)->device);
5742 struct buffer *b = XBUFFER (w->buffer);
5743 /* Be careful in the order of these tests. The first clause will
5744 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
5745 This can occur when the frame title is computed really early */
5747 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
5748 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
5749 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5750 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
5752 : marker_position (w->pointm[type]));
5755 line = buffer_line_number (b, pos, 1);
5757 long_to_string (window_line_number_buf, line + 1);
5759 return window_line_number_buf;
5763 /* Given a character representing an object in a modeline
5764 specification, return a string (stored into the global array
5765 `mode_spec_bufbyte_string') with the information that object
5768 This function is largely unchanged from previous versions of the
5771 Warning! This code is also used for frame titles and can be called
5772 very early in the device/frame update process! JV
5776 decode_mode_spec (struct window *w, Emchar spec, int type)
5778 Lisp_Object obj = Qnil;
5779 CONST char *str = NULL;
5780 struct buffer *b = XBUFFER (w->buffer);
5782 Dynarr_reset (mode_spec_bufbyte_string);
5786 /* print buffer name */
5791 /* print visited file name */
5796 /* print the current column */
5799 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
5801 : marker_position (w->pointm[type]);
5802 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
5805 long_to_string (buf, col);
5807 Dynarr_add_many (mode_spec_bufbyte_string,
5808 (CONST Bufbyte *) buf, strlen (buf));
5810 goto decode_mode_spec_done;
5812 /* print the file coding system */
5816 Lisp_Object codesys = b->buffer_file_coding_system;
5817 /* Be very careful here not to get an error. */
5818 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
5820 codesys = Ffind_coding_system (codesys);
5821 if (CODING_SYSTEMP (codesys))
5822 obj = XCODING_SYSTEM_MNEMONIC (codesys);
5825 #endif /* FILE_CODING */
5828 /* print the current line number */
5830 str = window_line_number (w, type);
5833 /* print value of mode-name (obsolete) */
5838 /* print hyphen and frame number, if != 1 */
5842 struct frame *f = XFRAME (w->frame);
5843 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
5845 /* Naughty, naughty */
5846 char * writable_str = alloca_array (char, 10);
5847 sprintf (writable_str, "-%d", f->order_count);
5851 #endif /* HAVE_TTY */
5854 /* print Narrow if appropriate */
5856 if (BUF_BEGV (b) > BUF_BEG (b)
5857 || BUF_ZV (b) < BUF_Z (b))
5861 /* print %, * or hyphen, if buffer is read-only, modified or neither */
5863 str = (!NILP (b->read_only)
5865 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5870 /* print * or hyphen -- XEmacs change to allow a buffer to be
5871 read-only but still indicate whether it is modified. */
5873 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5875 : (!NILP (b->read_only)
5880 /* #### defined in 19.29 decode_mode_spec, but not in
5881 modeline-format doc string. */
5882 /* This differs from %* in that it ignores read-only-ness. */
5884 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5889 /* print process status */
5891 obj = Fget_buffer_process (w->buffer);
5893 str = GETTEXT ("no process");
5895 obj = Fsymbol_name (Fprocess_status (obj));
5898 /* Print name of selected frame. */
5900 obj = XFRAME (w->frame)->name;
5903 /* indicate TEXT or BINARY */
5905 /* #### NT does not use this any more. Now what? */
5909 /* print percent of buffer above top of window, or Top, Bot or All */
5912 Bufpos pos = marker_position (w->start[type]);
5913 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5915 /* This had better be while the desired lines are being done. */
5916 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
5918 if (pos <= BUF_BEGV (b))
5923 else if (pos <= BUF_BEGV (b))
5927 /* This hard limit is ok since the string it will hold has a
5928 fixed maximum length of 3. But just to be safe... */
5931 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
5933 /* We can't normally display a 3-digit number, so get us a
5934 2-digit number that is close. */
5938 sprintf (buf, "%2d%%", total);
5939 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5942 goto decode_mode_spec_done;
5947 /* print percent of buffer above bottom of window, perhaps plus
5948 Top, or print Bottom or All */
5951 Bufpos toppos = marker_position (w->start[type]);
5952 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
5953 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5955 /* botpos is only accurate as of the last redisplay, so we can
5956 only treat it as a hint. In particular, after erase-buffer,
5957 botpos may be negative. */
5958 if (botpos < toppos)
5961 if (botpos >= BUF_ZV (b))
5963 if (toppos <= BUF_BEGV (b))
5970 /* This hard limit is ok since the string it will hold has a
5971 fixed maximum length of around 6. But just to be safe... */
5974 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
5976 /* We can't normally display a 3-digit number, so get us a
5977 2-digit number that is close. */
5981 if (toppos <= BUF_BEGV (b))
5982 sprintf (buf, "Top%2d%%", total);
5984 sprintf (buf, "%2d%%", total);
5986 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5989 goto decode_mode_spec_done;
5999 /* print one [ for each recursive editing level. */
6004 if (command_loop_level > 5)
6010 for (i = 0; i < command_loop_level; i++)
6011 Dynarr_add (mode_spec_bufbyte_string, '[');
6013 goto decode_mode_spec_done;
6016 /* print one ] for each recursive editing level. */
6021 if (command_loop_level > 5)
6027 for (i = 0; i < command_loop_level; i++)
6028 Dynarr_add (mode_spec_bufbyte_string, ']');
6030 goto decode_mode_spec_done;
6033 /* print infinitely many dashes -- handle at top level now */
6040 Dynarr_add_many (mode_spec_bufbyte_string,
6042 XSTRING_LENGTH (obj));
6044 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6046 decode_mode_spec_done:
6047 Dynarr_add (mode_spec_bufbyte_string, '\0');
6050 /* Given a display line, free all of its data structures. */
6053 free_display_line (struct display_line *dl)
6057 if (dl->display_blocks)
6059 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6061 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6063 Dynarr_free (db->runes);
6066 Dynarr_free (dl->display_blocks);
6067 dl->display_blocks = NULL;
6070 if (dl->left_glyphs)
6072 Dynarr_free (dl->left_glyphs);
6073 dl->left_glyphs = NULL;
6076 if (dl->right_glyphs)
6078 Dynarr_free (dl->right_glyphs);
6079 dl->right_glyphs = NULL;
6084 /* Given an array of display lines, free them and all data structures
6085 contained within them. */
6088 free_display_lines (display_line_dynarr *dla)
6092 for (line = 0; line < Dynarr_largest (dla); line++)
6094 free_display_line (Dynarr_atp (dla, line));
6100 /* Call internal free routine for each set of display lines. */
6103 free_display_structs (struct window_mirror *mir)
6105 if (mir->current_display_lines)
6107 free_display_lines (mir->current_display_lines);
6108 mir->current_display_lines = 0;
6111 if (mir->desired_display_lines)
6113 free_display_lines (mir->desired_display_lines);
6114 mir->desired_display_lines = 0;
6120 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object))
6124 glyph_block *gb = Dynarr_atp (gba, 0);
6125 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
6127 for (; gb < gb_last; gb++)
6129 if (!NILP (gb->glyph))
6130 markobj (gb->glyph);
6131 if (!NILP (gb->extent))
6132 markobj (gb->extent);
6138 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object))
6140 display_line *dl = Dynarr_atp (dla, 0);
6141 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
6143 for (; dl < dl_last; dl++)
6145 display_block_dynarr *dba = dl->display_blocks;
6146 display_block *db = Dynarr_atp (dba, 0);
6147 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
6149 for (; db < db_last; db++)
6151 rune_dynarr *ra = db->runes;
6152 rune *r = Dynarr_atp (ra, 0);
6153 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
6155 for (; r < r_last; r++)
6157 if (r->type == RUNE_DGLYPH)
6159 if (!NILP (r->object.dglyph.glyph))
6160 markobj (r->object.dglyph.glyph);
6161 if (!NILP (r->object.dglyph.extent))
6162 markobj (r->object.dglyph.extent);
6167 mark_glyph_block_dynarr (dl->left_glyphs, markobj);
6168 mark_glyph_block_dynarr (dl->right_glyphs, markobj);
6173 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object))
6175 mark_redisplay_structs (mir->current_display_lines, markobj);
6176 mark_redisplay_structs (mir->desired_display_lines, markobj);
6179 mark_window_mirror (mir->next, markobj);
6182 mark_window_mirror (mir->hchild, markobj);
6183 else if (mir->vchild)
6184 mark_window_mirror (mir->vchild, markobj);
6188 mark_redisplay (void (*markobj)(Lisp_Object))
6190 Lisp_Object frmcons, devcons, concons;
6192 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6194 struct frame *f = XFRAME (XCAR (frmcons));
6195 update_frame_window_mirror (f);
6196 mark_window_mirror (f->root_mirror, markobj);
6200 /*****************************************************************************
6201 Line Start Cache Description and Rationale
6203 The traditional scrolling code in Emacs breaks in a variable height world.
6204 It depends on the key assumption that the number of lines that can be
6205 displayed at any given time is fixed. This led to a complete separation
6206 of the scrolling code from the redisplay code. In order to fully support
6207 variable height lines, the scrolling code must actually be tightly
6208 integrated with redisplay. Only redisplay can determine how many lines
6209 will be displayed on a screen for any given starting point.
6211 What is ideally wanted is a complete list of the starting buffer position
6212 for every possible display line of a buffer along with the height of that
6213 display line. Maintaining such a full list would be very expensive. We
6214 settle for having it include information for all areas which we happen to
6215 generate anyhow (i.e. the region currently being displayed) and for those
6216 areas we need to work with.
6218 In order to ensure that the cache accurately represents what redisplay
6219 would actually show, it is necessary to invalidate it in many situations.
6220 If the buffer changes, the starting positions may no longer be correct.
6221 If a face or an extent has changed then the line heights may have altered.
6222 These events happen frequently enough that the cache can end up being
6223 constantly disabled. With this potentially constant invalidation when is
6224 the cache ever useful?
6226 Even if the cache is invalidated before every single usage, it is
6227 necessary. Scrolling often requires knowledge about display lines which
6228 are actually above or below the visible region. The cache provides a
6229 convenient light-weight method of storing this information for multiple
6230 display regions. This knowledge is necessary for the scrolling code to
6231 always obey the First Golden Rule of Redisplay.
6233 If the cache already contains all of the information that the scrolling
6234 routines happen to need so that it doesn't have to go generate it, then we
6235 are able to obey the Third Golden Rule of Redisplay. The first thing we
6236 do to help out the cache is to always add the displayed region. This
6237 region had to be generated anyway, so the cache ends up getting the
6238 information basically for free. In those cases where a user is simply
6239 scrolling around viewing a buffer there is a high probability that this is
6240 sufficient to always provide the needed information. The second thing we
6241 can do is be smart about invalidating the cache.
6243 TODO -- Be smart about invalidating the cache. Potential places:
6245 + Insertions at end-of-line which don't cause line-wraps do not alter the
6246 starting positions of any display lines. These types of buffer
6247 modifications should not invalidate the cache. This is actually a large
6248 optimization for redisplay speed as well.
6250 + Buffer modifications frequently only affect the display of lines at and
6251 below where they occur. In these situations we should only invalidate
6252 the part of the cache starting at where the modification occurs.
6254 In case you're wondering, the Second Golden Rule of Redisplay is not
6256 ****************************************************************************/
6258 /* This will get used quite a bit so we don't want to be constantly
6259 allocating and freeing it. */
6260 line_start_cache_dynarr *internal_cache;
6262 /* Makes internal_cache represent the TYPE display structs and only
6263 the TYPE display structs. */
6266 update_internal_cache_list (struct window *w, int type)
6269 display_line_dynarr *dla = window_display_lines (w, type);
6271 Dynarr_reset (internal_cache);
6272 for (line = 0; line < Dynarr_length (dla); line++)
6274 struct display_line *dl = Dynarr_atp (dla, line);
6280 struct line_start_cache lsc;
6282 lsc.start = dl->bufpos;
6283 lsc.end = dl->end_bufpos;
6284 lsc.height = dl->ascent + dl->descent;
6286 Dynarr_add (internal_cache, lsc);
6291 /* Reset the line cache if necessary. This should be run at the
6292 beginning of any function which access the cache. */
6295 validate_line_start_cache (struct window *w)
6297 struct buffer *b = XBUFFER (w->buffer);
6298 struct frame *f = XFRAME (w->frame);
6300 if (!w->line_cache_validation_override)
6302 /* f->extents_changed used to be in here because extent face and
6303 size changes can cause text shifting. However, the extent
6304 covering the region is constantly having its face set and
6305 priority altered by the mouse code. This means that the line
6306 start cache is constantly being invalidated. This is bad
6307 since the mouse code also triggers heavy usage of the cache.
6308 Since it is an unlikely that f->extents being changed
6309 indicates that the cache really needs to be updated and if it
6310 does redisplay will catch it pretty quickly we no longer
6311 invalidate the cache if it is set. This greatly speeds up
6312 dragging out regions with the mouse. */
6313 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
6317 Dynarr_reset (w->line_start_cache);
6322 /* Return the very first buffer position contained in the given
6323 window's cache, or -1 if the cache is empty. Assumes that the
6327 line_start_cache_start (struct window *w)
6329 line_start_cache_dynarr *cache = w->line_start_cache;
6331 if (!Dynarr_length (cache))
6334 return Dynarr_atp (cache, 0)->start;
6337 /* Return the very last buffer position contained in the given
6338 window's cache, or -1 if the cache is empty. Assumes that the
6342 line_start_cache_end (struct window *w)
6344 line_start_cache_dynarr *cache = w->line_start_cache;
6346 if (!Dynarr_length (cache))
6349 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
6352 /* Return the index of the line POINT is contained within in window
6353 W's line start cache. It will enlarge the cache or move the cache
6354 window in order to have POINT be present in the cache. MIN_PAST is
6355 a guarantee of the number of entries in the cache present on either
6356 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
6357 then it will be treated as 0, but the cache window will not be
6358 allowed to shift. Returns -1 if POINT cannot be found in the cache
6362 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
6364 struct buffer *b = XBUFFER (w->buffer);
6365 line_start_cache_dynarr *cache = w->line_start_cache;
6366 unsigned int top, bottom, pos;
6368 validate_line_start_cache (w);
6369 w->line_cache_validation_override++;
6371 /* Let functions pass in negative values, but we still treat -1
6373 /* #### bogosity alert */
6374 if (min_past < 0 && min_past != -1)
6375 min_past = -min_past;
6377 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
6378 || line_start_cache_end (w) < point)
6381 int win_char_height = window_char_height (w, 1);
6383 /* Occasionally we get here with a 0 height
6384 window. find_next_newline_no_quit will abort if we pass it a
6385 count of 0 so handle that case. */
6386 if (!win_char_height)
6387 win_char_height = 1;
6389 if (!Dynarr_length (cache))
6391 Bufpos from = find_next_newline_no_quit (b, point, -1);
6392 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
6394 update_line_start_cache (w, from, to, point, 0);
6396 if (!Dynarr_length (cache))
6398 w->line_cache_validation_override--;
6403 assert (Dynarr_length (cache));
6406 while (line_start_cache_start (w) > point
6407 && (loop < cache_adjustment || min_past == -1))
6411 from = line_start_cache_start (w);
6412 if (from <= BUF_BEGV (b))
6415 from = find_next_newline_no_quit (b, from, -win_char_height);
6416 to = line_start_cache_end (w);
6418 update_line_start_cache (w, from, to, point, 0);
6422 if (line_start_cache_start (w) > point)
6426 from = find_next_newline_no_quit (b, point, -1);
6427 if (from >= BUF_ZV (b))
6429 to = find_next_newline_no_quit (b, from, -win_char_height);
6434 to = find_next_newline_no_quit (b, from, win_char_height);
6436 update_line_start_cache (w, from, to, point, 0);
6440 while (line_start_cache_end (w) < point
6441 && (loop < cache_adjustment || min_past == -1))
6445 to = line_start_cache_end (w);
6446 if (to >= BUF_ZV (b))
6449 from = line_start_cache_end (w);
6450 to = find_next_newline_no_quit (b, from, win_char_height);
6452 update_line_start_cache (w, from, to, point, 0);
6456 if (line_start_cache_end (w) < point)
6460 from = find_next_newline_no_quit (b, point, -1);
6461 if (from >= BUF_ZV (b))
6463 to = find_next_newline_no_quit (b, from, -win_char_height);
6468 to = find_next_newline_no_quit (b, from, win_char_height);
6470 update_line_start_cache (w, from, to, point, 0);
6474 assert (Dynarr_length (cache));
6479 /* This could happen if the buffer is narrowed. */
6480 if (line_start_cache_start (w) > point
6481 || line_start_cache_end (w) < point)
6483 w->line_cache_validation_override--;
6489 top = Dynarr_length (cache) - 1;
6494 unsigned int new_pos;
6497 pos = (bottom + top + 1) >> 1;
6498 start = Dynarr_atp (cache, pos)->start;
6499 end = Dynarr_atp (cache, pos)->end;
6501 if (point >= start && point <= end)
6503 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
6506 find_next_newline_no_quit (b, line_start_cache_start (w),
6508 Bufpos to = line_start_cache_end (w);
6510 update_line_start_cache (w, from, to, point, 0);
6511 goto find_point_loop;
6513 else if ((Dynarr_length (cache) - pos - 1) < min_past
6514 && line_start_cache_end (w) < BUF_ZV (b))
6516 Bufpos from = line_start_cache_end (w);
6517 Bufpos to = find_next_newline_no_quit (b, from,
6522 update_line_start_cache (w, from, to, point, 0);
6523 goto find_point_loop;
6527 w->line_cache_validation_override--;
6531 else if (point > end)
6533 else if (point < start)
6538 new_pos = (bottom + top + 1) >> 1;
6541 w->line_cache_validation_override--;
6547 /* Return a boolean indicating if POINT would be visible in window W
6548 if display of the window was to begin at STARTP. */
6551 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
6553 struct buffer *b = XBUFFER (w->buffer);
6555 int bottom = WINDOW_TEXT_HEIGHT (w);
6558 /* If point is before the intended start it obviously can't be visible. */
6562 /* If point or start are not in the accessible buffer range, then
6564 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
6565 || point < BUF_BEGV (b) || point > BUF_ZV (b))
6568 validate_line_start_cache (w);
6569 w->line_cache_validation_override++;
6571 start_elt = point_in_line_start_cache (w, startp, 0);
6572 if (start_elt == -1)
6574 w->line_cache_validation_override--;
6578 assert (line_start_cache_start (w) <= startp
6579 && line_start_cache_end (w) >= startp);
6585 /* Expand the cache if necessary. */
6586 if (start_elt == Dynarr_length (w->line_start_cache))
6589 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
6591 start_elt = point_in_line_start_cache (w, old_startp,
6592 window_char_height (w, 0));
6594 /* We've already actually processed old_startp, so increment
6598 /* If this happens we didn't add any extra elements. Bummer. */
6599 if (start_elt == Dynarr_length (w->line_start_cache))
6601 w->line_cache_validation_override--;
6606 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
6608 if (pixpos + height > bottom)
6610 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6612 w->line_cache_validation_override--;
6618 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
6620 w->line_cache_validation_override--;
6628 /* For the given window W, if display starts at STARTP, what will be
6629 the buffer position at the beginning or end of the last line
6630 displayed. The end of the last line is also know as the window end
6633 #### With a little work this could probably be reworked as just a
6634 call to start_with_line_at_pixpos. */
6637 start_end_of_last_line (struct window *w, Bufpos startp, int end)
6639 struct buffer *b = XBUFFER (w->buffer);
6640 line_start_cache_dynarr *cache = w->line_start_cache;
6642 int bottom = WINDOW_TEXT_HEIGHT (w);
6646 validate_line_start_cache (w);
6647 w->line_cache_validation_override++;
6649 if (startp < BUF_BEGV (b))
6650 startp = BUF_BEGV (b);
6651 else if (startp > BUF_ZV (b))
6652 startp = BUF_ZV (b);
6655 start_elt = point_in_line_start_cache (w, cur_start, 0);
6656 if (start_elt == -1)
6657 abort (); /* this had better never happen */
6661 int height = Dynarr_atp (cache, start_elt)->height;
6663 cur_start = Dynarr_atp (cache, start_elt)->start;
6665 if (pixpos + height > bottom)
6667 /* Adjust for any possible clip. */
6668 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6673 w->line_cache_validation_override--;
6677 return BUF_BEGV (b);
6681 w->line_cache_validation_override--;
6683 return Dynarr_atp (cache, start_elt)->end;
6685 return Dynarr_atp (cache, start_elt)->start;
6691 if (start_elt == Dynarr_length (cache))
6693 Bufpos from = line_start_cache_end (w);
6694 int win_char_height = window_char_height (w, 0);
6695 Bufpos to = find_next_newline_no_quit (b, from,
6700 /* We've hit the end of the bottom so that's what it is. */
6701 if (from >= BUF_ZV (b))
6703 w->line_cache_validation_override--;
6707 update_line_start_cache (w, from, to, BUF_PT (b), 0);
6709 /* Updating the cache invalidates any current indexes. */
6710 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
6715 /* For the given window W, if display starts at STARTP, what will be
6716 the buffer position at the beginning of the last line displayed. */
6719 start_of_last_line (struct window *w, Bufpos startp)
6721 return start_end_of_last_line (w, startp, 0);
6724 /* For the given window W, if display starts at STARTP, what will be
6725 the buffer position at the end of the last line displayed. This is
6726 also know as the window end position. */
6729 end_of_last_line (struct window *w, Bufpos startp)
6731 return start_end_of_last_line (w, startp, 1);
6734 /* For window W, what does the starting position have to be so that
6735 the line containing POINT will cover pixel position PIXPOS. */
6738 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
6740 struct buffer *b = XBUFFER (w->buffer);
6742 Bufpos cur_pos, prev_pos = point;
6743 int point_line_height;
6744 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
6746 validate_line_start_cache (w);
6747 w->line_cache_validation_override++;
6749 cur_elt = point_in_line_start_cache (w, point, 0);
6750 /* #### See comment in update_line_start_cache about big minibuffers. */
6753 w->line_cache_validation_override--;
6757 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
6761 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6763 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6765 /* Do not take into account the value of vertical_clip here.
6766 That is the responsibility of the calling functions. */
6769 w->line_cache_validation_override--;
6770 if (-pixheight > point_line_height)
6771 /* We can't make the target line cover pixpos, so put it
6772 above pixpos. That way it will at least be visible. */
6782 int win_char_height;
6784 if (cur_pos <= BUF_BEGV (b))
6786 w->line_cache_validation_override--;
6787 return BUF_BEGV (b);
6790 win_char_height = window_char_height (w, 0);
6791 if (!win_char_height)
6792 win_char_height = 1;
6794 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
6795 to = line_start_cache_end (w);
6796 update_line_start_cache (w, from, to, point, 0);
6798 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
6799 assert (cur_elt >= 0);
6805 /* For window W, what does the starting position have to be so that
6806 the line containing point is on display line LINE. If LINE is
6807 positive it is considered to be the number of lines from the top of
6808 the window (0 is the top line). If it is negative the number is
6809 considered to be the number of lines from the bottom (-1 is the
6813 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
6815 validate_line_start_cache (w);
6816 w->line_cache_validation_override++;
6820 int cur_elt = point_in_line_start_cache (w, point, line);
6822 if (cur_elt - line < 0)
6823 cur_elt = 0; /* Hit the top */
6827 w->line_cache_validation_override--;
6828 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
6832 /* The calculated value of pixpos is correct for the bottom line
6833 or what we want when line is -1. Therefore we subtract one
6834 because we have already handled one line. */
6835 int new_line = -line - 1;
6836 int cur_elt = point_in_line_start_cache (w, point, new_line);
6837 int pixpos = WINDOW_TEXT_BOTTOM (w);
6838 Bufpos retval, search_point;
6840 /* If scroll_on_clipped_lines is false, the last "visible" line of
6841 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
6842 If s_o_c_l is true, then we don't want to count a clipped
6843 line, so back up from the bottom by the height of the line
6844 containing point. */
6845 if (scroll_on_clipped_lines)
6846 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6850 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
6852 /* Hit the bottom of the buffer. */
6854 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
6858 XSETWINDOW (window, w);
6859 default_face_height_and_width (window, &defheight, 0);
6861 cur_elt = Dynarr_length (w->line_start_cache) - 1;
6863 pixpos -= (adjustment * defheight);
6864 if (pixpos < WINDOW_TEXT_TOP (w))
6865 pixpos = WINDOW_TEXT_TOP (w);
6868 cur_elt = cur_elt + new_line;
6870 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6872 retval = start_with_line_at_pixpos (w, search_point, pixpos);
6873 w->line_cache_validation_override--;
6878 /* This is used to speed up vertical scrolling by caching the known
6879 buffer starting positions for display lines. This allows the
6880 scrolling routines to avoid costly calls to regenerate_window. If
6881 NO_REGEN is true then it will only add the values in the DESIRED
6882 display structs which are in the given range.
6884 Note also that the FROM/TO values are minimums. It is possible
6885 that this function will actually add information outside of the
6886 lines containing those positions. This can't hurt but it could
6889 #### We currently force the cache to have only 1 contiguous region.
6890 It might help to make the cache a dynarr of caches so that we can
6891 cover more areas. This might, however, turn out to be a lot of
6892 overhead for too little gain. */
6895 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
6896 Bufpos point, int no_regen)
6898 struct buffer *b = XBUFFER (w->buffer);
6899 line_start_cache_dynarr *cache = w->line_start_cache;
6900 Bufpos low_bound, high_bound;
6902 validate_line_start_cache (w);
6903 w->line_cache_validation_override++;
6904 updating_line_start_cache = 1;
6906 if (from < BUF_BEGV (b))
6907 from = BUF_BEGV (b);
6908 if (to > BUF_ZV (b))
6913 updating_line_start_cache = 0;
6914 w->line_cache_validation_override--;
6918 if (Dynarr_length (cache))
6920 low_bound = line_start_cache_start (w);
6921 high_bound = line_start_cache_end (w);
6923 /* Check to see if the desired range is already in the cache. */
6924 if (from >= low_bound && to <= high_bound)
6926 updating_line_start_cache = 0;
6927 w->line_cache_validation_override--;
6931 /* Check to make sure that the desired range is adjacent to the
6932 current cache. If not, invalidate the cache. */
6933 if (to < low_bound || from > high_bound)
6935 Dynarr_reset (cache);
6936 low_bound = high_bound = -1;
6941 low_bound = high_bound = -1;
6944 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
6946 /* This could be integrated into the next two sections, but it is easier
6947 to follow what's going on by having it separate. */
6952 update_internal_cache_list (w, DESIRED_DISP);
6953 if (!Dynarr_length (internal_cache))
6955 updating_line_start_cache = 0;
6956 w->line_cache_validation_override--;
6960 start = Dynarr_atp (internal_cache, 0)->start;
6962 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
6964 /* We aren't allowed to generate additional information to fill in
6965 gaps, so if the DESIRED structs don't overlap the cache, reset the
6967 if (Dynarr_length (cache))
6969 if (end < low_bound || start > high_bound)
6970 Dynarr_reset (cache);
6972 /* #### What should really happen if what we are doing is
6973 extending a line (the last line)? */
6974 if (Dynarr_length (cache) == 1
6975 && Dynarr_length (internal_cache) == 1)
6976 Dynarr_reset (cache);
6979 if (!Dynarr_length (cache))
6981 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
6982 Dynarr_length (internal_cache));
6983 updating_line_start_cache = 0;
6984 w->line_cache_validation_override--;
6988 /* An extra check just in case the calling function didn't pass in
6989 the bounds of the DESIRED structs in the first place. */
6990 if (start >= low_bound && end <= high_bound)
6992 updating_line_start_cache = 0;
6993 w->line_cache_validation_override--;
6997 /* At this point we know that the internal cache partially overlaps
6999 if (start < low_bound)
7001 int ic_elt = Dynarr_length (internal_cache) - 1;
7004 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7012 Dynarr_reset (cache);
7013 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7014 Dynarr_length (internal_cache));
7015 updating_line_start_cache = 0;
7016 w->line_cache_validation_override--;
7020 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7024 if (end > high_bound)
7028 while (ic_elt < Dynarr_length (internal_cache))
7030 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7036 if (!(ic_elt < Dynarr_length (internal_cache)))
7038 Dynarr_reset (cache);
7039 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7040 Dynarr_length (internal_cache));
7041 updating_line_start_cache = 0;
7042 w->line_cache_validation_override--;
7046 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7047 Dynarr_length (internal_cache) - ic_elt);
7050 updating_line_start_cache = 0;
7051 w->line_cache_validation_override--;
7055 if (!Dynarr_length (cache) || from < low_bound)
7057 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7059 int old_lb = low_bound;
7061 while (startp < old_lb || low_bound == -1)
7066 regenerate_window (w, startp, point, CMOTION_DISP);
7067 update_internal_cache_list (w, CMOTION_DISP);
7069 /* If this assert is triggered then regenerate_window failed
7070 to layout a single line. That is not supposed to be
7071 possible because we impose a minimum height on the buffer
7072 and override vertical clip when we are in here. */
7073 /* #### Ah, but it is because the window may temporarily
7074 exist but not have any lines at all if the minibuffer is
7075 real big. Look into that situation better. */
7076 if (!Dynarr_length (internal_cache))
7078 if (old_lb == -1 && low_bound == -1)
7080 updating_line_start_cache = 0;
7081 w->line_cache_validation_override--;
7085 assert (Dynarr_length (internal_cache));
7087 assert (startp == Dynarr_atp (internal_cache, 0)->start);
7089 ic_elt = Dynarr_length (internal_cache) - 1;
7090 if (low_bound != -1)
7094 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
7100 assert (ic_elt >= 0);
7102 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
7105 * Handle invisible text properly:
7106 * If the last line we're inserting has the same end as the
7107 * line before which it will be added, merge the two lines.
7109 if (Dynarr_length (cache) &&
7110 Dynarr_atp (internal_cache, ic_elt)->end ==
7111 Dynarr_atp (cache, marker)->end)
7113 Dynarr_atp (cache, marker)->start
7114 = Dynarr_atp (internal_cache, ic_elt)->start;
7115 Dynarr_atp (cache, marker)->height
7116 = Dynarr_atp (internal_cache, ic_elt)->height;
7120 if (ic_elt >= 0) /* we still have lines to add.. */
7122 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
7123 ic_elt + 1, marker);
7124 marker += (ic_elt + 1);
7127 if (startp < low_bound || low_bound == -1)
7129 startp = new_startp;
7130 if (startp > BUF_ZV (b))
7132 updating_line_start_cache = 0;
7133 w->line_cache_validation_override--;
7139 assert (Dynarr_length (cache));
7140 assert (from >= low_bound);
7142 /* Readjust the high_bound to account for any changes made while
7143 correcting the low_bound. */
7144 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7146 if (to > high_bound)
7148 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
7152 regenerate_window (w, startp, point, CMOTION_DISP);
7153 update_internal_cache_list (w, CMOTION_DISP);
7155 /* See comment above about regenerate_window failing. */
7156 assert (Dynarr_length (internal_cache));
7158 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7159 Dynarr_length (internal_cache));
7160 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7161 startp = high_bound + 1;
7163 while (to > high_bound);
7166 updating_line_start_cache = 0;
7167 w->line_cache_validation_override--;
7168 assert (to <= high_bound);
7172 /* Given x and y coordinates in characters, relative to a window,
7173 return the pixel location corresponding to those coordinates. The
7174 pixel location returned is the center of the given character
7175 position. The pixel values are generated relative to the window,
7178 The modeline is considered to be part of the window. */
7181 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
7182 int *pix_x, int *pix_y)
7184 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
7185 int num_disp_lines, modeline;
7187 int defheight, defwidth;
7189 XSETWINDOW (window, w);
7190 default_face_height_and_width (window, &defheight, &defwidth);
7192 /* If we get a bogus value indicating somewhere above or to the left of
7193 the window, use the first window line or character position
7200 num_disp_lines = Dynarr_length (dla);
7204 if (Dynarr_atp (dla, 0)->modeline)
7211 /* First check if the y position intersects the display lines. */
7212 if (char_y < num_disp_lines)
7214 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
7215 struct display_block *db = get_display_block_from_line (dl, TEXT);
7217 *pix_y = (dl->ypos - dl->ascent +
7218 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
7220 if (char_x < Dynarr_length (db->runes))
7222 struct rune *rb = Dynarr_atp (db->runes, char_x);
7224 *pix_x = rb->xpos + (rb->width >> 1);
7228 int last_rune = Dynarr_length (db->runes) - 1;
7229 struct rune *rb = Dynarr_atp (db->runes, last_rune);
7231 char_x -= last_rune;
7233 *pix_x = rb->xpos + rb->width;
7234 *pix_x += ((char_x - 1) * defwidth);
7235 *pix_x += (defwidth >> 1);
7240 /* It didn't intersect, so extrapolate. #### For now, we include the
7241 modeline in this since we don't have true character positions in
7244 if (!Dynarr_length (w->face_cachels))
7245 reset_face_cachels (w);
7247 char_y -= num_disp_lines;
7249 if (Dynarr_length (dla))
7251 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
7252 *pix_y = dl->ypos + dl->descent - dl->clip;
7255 *pix_y = WINDOW_TEXT_TOP (w);
7257 *pix_y += (char_y * defheight);
7258 *pix_y += (defheight >> 1);
7260 *pix_x = WINDOW_TEXT_LEFT (w);
7261 /* Don't adjust by one because this is still the unadjusted value. */
7262 *pix_x += (char_x * defwidth);
7263 *pix_x += (defwidth >> 1);
7266 if (*pix_x > w->pixel_left + w->pixel_width)
7267 *pix_x = w->pixel_left + w->pixel_width;
7268 if (*pix_y > w->pixel_top + w->pixel_height)
7269 *pix_y = w->pixel_top + w->pixel_height;
7271 *pix_x -= w->pixel_left;
7272 *pix_y -= w->pixel_top;
7275 /* Given a display line and a position, determine if there is a glyph
7276 there and return information about it if there is. */
7279 get_position_object (struct display_line *dl, Lisp_Object *obj1,
7280 Lisp_Object *obj2, int x_coord, int *low_x_coord,
7283 struct display_block *db;
7286 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
7288 /* We use get_next_display_block to get the actual display block
7289 that would be displayed at x_coord. */
7291 if (block == NO_BLOCK)
7294 db = Dynarr_atp (dl->display_blocks, block);
7296 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
7298 struct rune *rb = Dynarr_atp (db->runes, elt);
7300 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
7302 if (rb->type == RUNE_DGLYPH)
7304 *obj1 = rb->object.dglyph.glyph;
7305 *obj2 = rb->object.dglyph.extent;
7314 *low_x_coord = rb->xpos;
7316 *high_x_coord = rb->xpos + rb->width;
7323 #define UPDATE_CACHE_RETURN \
7325 d->pixel_to_glyph_cache.valid = 1; \
7326 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
7327 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
7328 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
7329 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
7330 d->pixel_to_glyph_cache.frame = f; \
7331 d->pixel_to_glyph_cache.col = *col; \
7332 d->pixel_to_glyph_cache.row = *row; \
7333 d->pixel_to_glyph_cache.obj_x = *obj_x; \
7334 d->pixel_to_glyph_cache.obj_y = *obj_y; \
7335 d->pixel_to_glyph_cache.w = *w; \
7336 d->pixel_to_glyph_cache.bufpos = *bufpos; \
7337 d->pixel_to_glyph_cache.closest = *closest; \
7338 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
7339 d->pixel_to_glyph_cache.obj1 = *obj1; \
7340 d->pixel_to_glyph_cache.obj2 = *obj2; \
7341 d->pixel_to_glyph_cache.retval = position; \
7342 RETURN_SANS_WARNINGS position; \
7345 /* Given x and y coordinates in pixels relative to a frame, return
7346 information about what is located under those coordinates.
7348 The return value will be one of:
7350 OVER_TOOLBAR: over one of the 4 frame toolbars
7351 OVER_MODELINE: over a modeline
7352 OVER_BORDER: over an internal border
7353 OVER_NOTHING: over the text area, but not over text
7354 OVER_OUTSIDE: outside of the frame border
7355 OVER_TEXT: over text in the text area
7361 -- nil if the coordinates are not over a glyph or a toolbar button.
7365 -- an extent, if the coordinates are over a glyph in the text area
7368 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
7369 equivalent coordinates relative to the upper-left corner of the glyph.
7371 If the coordinates are over a character, OBJ_X and OBJ_Y give the
7372 equivalent coordinates relative to the upper-left corner of the character.
7374 Otherwise, OBJ_X and OBJ_Y are undefined.
7378 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
7379 int *col, int *row, int *obj_x, int *obj_y,
7380 struct window **w, Bufpos *bufpos,
7381 Bufpos *closest, Charcount *modeline_closest,
7382 Lisp_Object *obj1, Lisp_Object *obj2)
7385 struct pixel_to_glyph_translation_cache *cache;
7387 int frm_left, frm_right, frm_top, frm_bottom;
7388 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
7389 int position = OVER_NOTHING;
7390 int device_check_failed = 0;
7391 display_line_dynarr *dla;
7393 /* This is a safety valve in case this got called with a frame in
7394 the middle of being deleted. */
7395 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
7397 device_check_failed = 1;
7398 d = NULL, cache = NULL; /* Warning suppression */
7402 d = XDEVICE (f->device);
7403 cache = &d->pixel_to_glyph_cache;
7406 if (!device_check_failed
7408 && cache->frame == f
7409 && cache->low_x_coord <= x_coord
7410 && cache->high_x_coord > x_coord
7411 && cache->low_y_coord <= y_coord
7412 && cache->high_y_coord > y_coord)
7416 *obj_x = cache->obj_x;
7417 *obj_y = cache->obj_y;
7419 *bufpos = cache->bufpos;
7420 *closest = cache->closest;
7421 *modeline_closest = cache->modeline_closest;
7422 *obj1 = cache->obj1;
7423 *obj2 = cache->obj2;
7425 return cache->retval;
7436 *modeline_closest = -1;
7440 low_x_coord = x_coord;
7441 high_x_coord = x_coord + 1;
7442 low_y_coord = y_coord;
7443 high_y_coord = y_coord + 1;
7446 if (device_check_failed)
7447 return OVER_NOTHING;
7449 frm_left = FRAME_LEFT_BORDER_END (f);
7450 frm_right = FRAME_RIGHT_BORDER_START (f);
7451 frm_top = FRAME_TOP_BORDER_END (f);
7452 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
7454 /* Check if the mouse is outside of the text area actually used by
7456 if (y_coord < frm_top)
7458 if (y_coord >= FRAME_TOP_BORDER_START (f))
7460 low_y_coord = FRAME_TOP_BORDER_START (f);
7461 high_y_coord = frm_top;
7462 position = OVER_BORDER;
7464 else if (y_coord >= 0)
7467 high_y_coord = FRAME_TOP_BORDER_START (f);
7468 position = OVER_TOOLBAR;
7472 low_y_coord = y_coord;
7474 position = OVER_OUTSIDE;
7477 else if (y_coord >= frm_bottom)
7479 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
7481 low_y_coord = frm_bottom;
7482 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
7483 position = OVER_BORDER;
7485 else if (y_coord < FRAME_PIXHEIGHT (f))
7487 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
7488 high_y_coord = FRAME_PIXHEIGHT (f);
7489 position = OVER_TOOLBAR;
7493 low_y_coord = FRAME_PIXHEIGHT (f);
7494 high_y_coord = y_coord;
7495 position = OVER_OUTSIDE;
7499 if (position != OVER_TOOLBAR && position != OVER_BORDER)
7501 if (x_coord < frm_left)
7503 if (x_coord >= FRAME_LEFT_BORDER_START (f))
7505 low_x_coord = FRAME_LEFT_BORDER_START (f);
7506 high_x_coord = frm_left;
7507 position = OVER_BORDER;
7509 else if (x_coord >= 0)
7512 high_x_coord = FRAME_LEFT_BORDER_START (f);
7513 position = OVER_TOOLBAR;
7517 low_x_coord = x_coord;
7519 position = OVER_OUTSIDE;
7522 else if (x_coord >= frm_right)
7524 if (x_coord < FRAME_RIGHT_BORDER_END (f))
7526 low_x_coord = frm_right;
7527 high_x_coord = FRAME_RIGHT_BORDER_END (f);
7528 position = OVER_BORDER;
7530 else if (x_coord < FRAME_PIXWIDTH (f))
7532 low_x_coord = FRAME_RIGHT_BORDER_END (f);
7533 high_x_coord = FRAME_PIXWIDTH (f);
7534 position = OVER_TOOLBAR;
7538 low_x_coord = FRAME_PIXWIDTH (f);
7539 high_x_coord = x_coord;
7540 position = OVER_OUTSIDE;
7545 #ifdef HAVE_TOOLBARS
7546 if (position == OVER_TOOLBAR)
7548 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
7551 UPDATE_CACHE_RETURN;
7553 #endif /* HAVE_TOOLBARS */
7555 /* We still have to return the window the pointer is next to and its
7556 relative y position even if it is outside the x boundary. */
7557 if (x_coord < frm_left)
7559 else if (x_coord > frm_right)
7560 x_coord = frm_right;
7562 /* Same in reverse. */
7563 if (y_coord < frm_top)
7565 else if (y_coord > frm_bottom)
7566 y_coord = frm_bottom;
7568 /* Find what window the given coordinates are actually in. */
7569 window = f->root_window;
7570 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
7572 /* If we didn't find a window, we're done. */
7575 UPDATE_CACHE_RETURN;
7577 else if (position != OVER_NOTHING)
7580 *modeline_closest = -1;
7582 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
7585 UPDATE_CACHE_RETURN;
7589 /* Check if the window is a minibuffer but isn't active. */
7590 if (MINI_WINDOW_P (*w) && !minibuf_level)
7592 /* Must reset the window value since some callers will ignore
7593 the return value if it is set. */
7595 UPDATE_CACHE_RETURN;
7598 /* See if the point is over window vertical divider */
7599 if (window_needs_vertical_divider (*w))
7601 int div_x_high = WINDOW_RIGHT (*w);
7602 int div_x_low = div_x_high - window_divider_width (*w);
7603 int div_y_high = WINDOW_BOTTOM (*w);
7604 int div_y_low = WINDOW_TOP (*w);
7606 if (div_x_low < x_coord && x_coord <= div_x_high &&
7607 div_y_low < y_coord && y_coord <= div_y_high)
7609 low_x_coord = div_x_low;
7610 high_x_coord = div_x_high;
7611 low_y_coord = div_y_low;
7612 high_y_coord = div_y_high;
7613 position = OVER_V_DIVIDER;
7614 UPDATE_CACHE_RETURN;
7618 dla = window_display_lines (*w, CURRENT_DISP);
7620 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
7622 int really_over_nothing = 0;
7623 struct display_line *dl = Dynarr_atp (dla, *row);
7625 if ((int) (dl->ypos - dl->ascent) <= y_coord
7626 && y_coord <= (int) (dl->ypos + dl->descent))
7628 int check_margin_glyphs = 0;
7629 struct display_block *db = get_display_block_from_line (dl, TEXT);
7630 struct rune *rb = 0;
7632 if (x_coord < dl->bounds.left_white
7633 || x_coord >= dl->bounds.right_white)
7634 check_margin_glyphs = 1;
7636 low_y_coord = dl->ypos - dl->ascent;
7637 high_y_coord = dl->ypos + dl->descent + 1;
7639 if (position == OVER_BORDER
7640 || position == OVER_OUTSIDE
7641 || check_margin_glyphs)
7643 int x_check, left_bound;
7645 if (check_margin_glyphs)
7648 left_bound = dl->bounds.left_white;
7652 x_check = high_x_coord;
7653 left_bound = frm_left;
7656 if (Dynarr_length (db->runes))
7658 if (x_check <= left_bound)
7661 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
7663 *closest = Dynarr_atp (db->runes, 0)->bufpos;
7669 Dynarr_atp (db->runes,
7670 Dynarr_length (db->runes) - 1)->bufpos;
7673 Dynarr_atp (db->runes,
7674 Dynarr_length (db->runes) - 1)->bufpos;
7678 *modeline_closest += dl->offset;
7680 *closest += dl->offset;
7684 /* #### What should be here. */
7686 *modeline_closest = 0;
7691 if (check_margin_glyphs)
7693 if (x_coord < dl->bounds.left_in
7694 || x_coord >= dl->bounds.right_in)
7696 /* If we are over the outside margins then we
7697 know the loop over the text block isn't going
7698 to accomplish anything. So we go ahead and
7699 set what information we can right here and
7702 *obj_y = y_coord - (dl->ypos - dl->ascent);
7703 get_position_object (dl, obj1, obj2, x_coord,
7704 &low_x_coord, &high_x_coord);
7706 UPDATE_CACHE_RETURN;
7710 UPDATE_CACHE_RETURN;
7713 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
7715 int past_end = (*col == Dynarr_length (db->runes));
7718 rb = Dynarr_atp (db->runes, *col);
7721 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
7726 rb = Dynarr_atp (db->runes, *col);
7729 *bufpos = rb->bufpos + dl->offset;
7730 low_x_coord = rb->xpos;
7731 high_x_coord = rb->xpos + rb->width;
7733 if (rb->type == RUNE_DGLYPH)
7737 /* Find the first character after the glyph. */
7738 while (elt < Dynarr_length (db->runes))
7740 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
7744 (Dynarr_atp (db->runes, elt)->bufpos +
7748 (Dynarr_atp (db->runes, elt)->bufpos +
7756 /* In this case we failed to find a non-glyph
7757 character so we return the last position
7758 displayed on the line. */
7759 if (elt == Dynarr_length (db->runes))
7762 *modeline_closest = dl->end_bufpos + dl->offset;
7764 *closest = dl->end_bufpos + dl->offset;
7765 really_over_nothing = 1;
7771 *modeline_closest = rb->bufpos + dl->offset;
7773 *closest = rb->bufpos + dl->offset;
7778 *row = window_displayed_height (*w);
7780 if (position == OVER_NOTHING)
7781 position = OVER_MODELINE;
7783 if (rb->type == RUNE_DGLYPH)
7785 *obj1 = rb->object.dglyph.glyph;
7786 *obj2 = rb->object.dglyph.extent;
7788 else if (rb->type == RUNE_CHAR)
7799 UPDATE_CACHE_RETURN;
7802 || (rb->type == RUNE_CHAR
7803 && rb->object.chr.ch == '\n'))
7806 /* At this point we may have glyphs in the right
7808 if (check_margin_glyphs)
7809 get_position_object (dl, obj1, obj2, x_coord,
7810 &low_x_coord, &high_x_coord);
7811 UPDATE_CACHE_RETURN;
7816 if (rb->type == RUNE_DGLYPH)
7818 *obj1 = rb->object.dglyph.glyph;
7819 *obj2 = rb->object.dglyph.extent;
7821 else if (rb->type == RUNE_CHAR)
7832 *obj_x = x_coord - rb->xpos;
7833 *obj_y = y_coord - (dl->ypos - dl->ascent);
7835 /* At this point we may have glyphs in the left
7837 if (check_margin_glyphs)
7838 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
7840 if (position == OVER_NOTHING && !really_over_nothing)
7841 position = OVER_TEXT;
7843 UPDATE_CACHE_RETURN;
7850 *row = Dynarr_length (dla) - 1;
7851 if (FRAME_WIN_P (f))
7853 int bot_elt = Dynarr_length (dla) - 1;
7857 struct display_line *dl = Dynarr_atp (dla, bot_elt);
7858 int adj_area = y_coord - (dl->ypos + dl->descent);
7862 XSETWINDOW (lwin, *w);
7863 default_face_height_and_width (lwin, 0, &defheight);
7865 *row += (adj_area / defheight);
7869 /* #### This should be checked out some more to determine what
7870 should really be going on. */
7871 if (!MARKERP ((*w)->start[CURRENT_DISP]))
7874 *closest = end_of_last_line (*w,
7875 marker_position ((*w)->start[CURRENT_DISP]));
7877 UPDATE_CACHE_RETURN;
7879 #undef UPDATE_CACHE_RETURN
7882 /***************************************************************************/
7884 /* Lisp functions */
7886 /***************************************************************************/
7888 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
7889 Ensure that all minibuffers are correctly showing the echo area.
7893 Lisp_Object devcons, concons;
7895 DEVICE_LOOP_NO_BREAK (devcons, concons)
7897 struct device *d = XDEVICE (XCAR (devcons));
7898 Lisp_Object frmcons;
7900 DEVICE_FRAME_LOOP (frmcons, d)
7902 struct frame *f = XFRAME (XCAR (frmcons));
7904 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
7906 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
7908 * If the frame size has changed, there may be random
7909 * chud on the screen left from previous messages
7910 * because redisplay_frame hasn't been called yet.
7911 * Clear the screen to get rid of the potential mess.
7913 if (f->echo_area_garbaged)
7915 DEVMETH (d, clear_frame, (f));
7916 f->echo_area_garbaged = 0;
7918 redisplay_window (window, 0);
7919 call_redisplay_end_triggers (XWINDOW (window), 0);
7923 /* We now call the output_end routine for tty frames. We delay
7924 doing so in order to avoid cursor flicker. So much for 100%
7926 if (DEVICE_TTY_P (d))
7927 DEVMETH (d, output_end, (d));
7934 restore_disable_preemption_value (Lisp_Object value)
7936 disable_preemption = XINT (value);
7940 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
7941 Clear frame FRAME and output again what is supposed to appear on it.
7942 FRAME defaults to the selected frame if omitted.
7943 Normally, redisplay is preempted as normal if input arrives. However,
7944 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7945 input and is guaranteed to proceed to completion.
7947 (frame, no_preempt))
7949 struct frame *f = decode_frame (frame);
7950 int count = specpdl_depth ();
7952 if (!NILP (no_preempt))
7954 record_unwind_protect (restore_disable_preemption_value,
7955 make_int (disable_preemption));
7956 disable_preemption++;
7960 redisplay_frame (f, 1);
7962 return unbind_to (count, Qnil);
7965 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
7966 Ensure that FRAME's contents are correctly displayed.
7967 This differs from `redraw-frame' in that it only redraws what needs to
7968 be updated, as opposed to unconditionally clearing and redrawing
7970 FRAME defaults to the selected frame if omitted.
7971 Normally, redisplay is preempted as normal if input arrives. However,
7972 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7973 input and is guaranteed to proceed to completion.
7975 (frame, no_preempt))
7977 struct frame *f = decode_frame (frame);
7978 int count = specpdl_depth ();
7980 if (!NILP (no_preempt))
7982 record_unwind_protect (restore_disable_preemption_value,
7983 make_int (disable_preemption));
7984 disable_preemption++;
7987 redisplay_frame (f, 1);
7989 return unbind_to (count, Qnil);
7992 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
7993 Clear device DEVICE and output again what is supposed to appear on it.
7994 DEVICE defaults to the selected device if omitted.
7995 Normally, redisplay is preempted as normal if input arrives. However,
7996 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7997 input and is guaranteed to proceed to completion.
7999 (device, no_preempt))
8001 struct device *d = decode_device (device);
8002 Lisp_Object frmcons;
8003 int count = specpdl_depth ();
8005 if (!NILP (no_preempt))
8007 record_unwind_protect (restore_disable_preemption_value,
8008 make_int (disable_preemption));
8009 disable_preemption++;
8012 DEVICE_FRAME_LOOP (frmcons, d)
8014 XFRAME (XCAR (frmcons))->clear = 1;
8016 redisplay_device (d);
8018 return unbind_to (count, Qnil);
8021 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8022 Ensure that DEVICE's contents are correctly displayed.
8023 This differs from `redraw-device' in that it only redraws what needs to
8024 be updated, as opposed to unconditionally clearing and redrawing
8026 DEVICE defaults to the selected device if omitted.
8027 Normally, redisplay is preempted as normal if input arrives. However,
8028 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8029 input and is guaranteed to proceed to completion.
8031 (device, no_preempt))
8033 struct device *d = decode_device (device);
8034 int count = specpdl_depth ();
8036 if (!NILP (no_preempt))
8038 record_unwind_protect (restore_disable_preemption_value,
8039 make_int (disable_preemption));
8040 disable_preemption++;
8043 redisplay_device (d);
8045 return unbind_to (count, Qnil);
8048 /* Big lie. Big lie. This will force all modelines to be updated
8049 regardless if the all flag is set or not. It remains in existence
8050 solely for backwards compatibility. */
8051 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8052 Force the modeline of the current buffer to be redisplayed.
8053 With optional non-nil ALL, force redisplay of all modelines.
8057 MARK_MODELINE_CHANGED;
8061 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8062 Force an immediate update of the cursor on FRAME.
8063 FRAME defaults to the selected frame if omitted.
8067 redisplay_redraw_cursor (decode_frame (frame), 1);
8072 /***************************************************************************/
8074 /* Lisp-variable change triggers */
8076 /***************************************************************************/
8079 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
8082 /* Nothing to be done? */
8086 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
8087 Lisp_Object in_object, int flags)
8089 /* #### clip_changed should really be renamed something like
8090 global_redisplay_change. */
8096 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8099 if (WINDOWP (locale))
8101 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
8103 else if (FRAMEP (locale))
8105 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
8107 else if (DEVICEP (locale))
8109 Lisp_Object frmcons;
8110 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
8111 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8113 else if (CONSOLEP (locale))
8115 Lisp_Object frmcons, devcons;
8116 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
8117 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8119 else /* global or buffer */
8121 Lisp_Object frmcons, devcons, concons;
8122 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
8123 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8128 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
8131 if (XFRAME (w->frame)->init_finished)
8132 Fforce_cursor_redisplay (w->frame);
8135 #ifdef MEMORY_USAGE_STATS
8138 /***************************************************************************/
8140 /* memory usage computation */
8142 /***************************************************************************/
8145 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
8147 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8151 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
8152 struct overhead_stats *ovstats)
8159 total = Dynarr_memory_usage (dyn, ovstats);
8160 for (i = 0; i < Dynarr_largest (dyn); i++)
8161 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
8167 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
8168 struct overhead_stats *ovstats)
8170 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8174 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
8175 struct overhead_stats *ovstats)
8182 total = Dynarr_memory_usage (dyn, ovstats);
8183 for (i = 0; i < Dynarr_largest (dyn); i++)
8185 struct display_line *dl = &Dynarr_at (dyn, i);
8186 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
8187 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
8188 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
8195 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
8196 struct overhead_stats *ovstats)
8198 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8201 #endif /* MEMORY_USAGE_STATS */
8204 /***************************************************************************/
8206 /* initialization */
8208 /***************************************************************************/
8211 init_redisplay (void)
8213 disable_preemption = 0;
8214 preemption_count = 0;
8215 max_preempts = INIT_MAX_PREEMPTS;
8219 cmotion_display_lines = Dynarr_new (display_line);
8220 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
8221 formatted_string_emchar_dynarr = Dynarr_new (Emchar);
8222 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
8223 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
8224 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
8225 internal_cache = Dynarr_new (line_start_cache);
8226 xzero (formatted_string_display_line);
8229 /* window system is nil when in -batch mode */
8230 if (!initialized || noninteractive)
8233 /* If the user wants to use a window system, we shouldn't bother
8234 initializing the terminal. This is especially important when the
8235 terminal is so dumb that emacs gives up before and doesn't bother
8236 using the window system.
8238 If the DISPLAY environment variable is set, try to use X, and die
8239 with an error message if that doesn't work. */
8241 #ifdef HAVE_X_WINDOWS
8242 if (!strcmp (display_use, "x"))
8244 /* Some stuff checks this way early. */
8245 Vwindow_system = Qx;
8246 Vinitial_window_system = Qx;
8249 #endif /* HAVE_X_WINDOWS */
8251 #ifdef HAVE_MS_WINDOWS
8252 if (!strcmp (display_use, "mswindows"))
8254 /* Some stuff checks this way early. */
8255 Vwindow_system = Qmswindows;
8256 Vinitial_window_system = Qmswindows;
8259 #endif /* HAVE_MS_WINDOWS */
8262 /* If no window system has been specified, try to use the terminal. */
8265 stderr_out ("XEmacs: standard input is not a tty\n");
8269 /* Look at the TERM variable */
8270 if (!getenv ("TERM"))
8272 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
8276 Vinitial_window_system = Qtty;
8278 #else /* not HAVE_TTY */
8279 /* No DISPLAY specified, and no TTY support. */
8280 stderr_out ("XEmacs: Cannot open display.\n\
8281 Please set the environmental variable DISPLAY to an appropriate value.\n");
8288 syms_of_redisplay (void)
8290 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
8291 #ifndef INHIBIT_REDISPLAY_HOOKS
8292 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
8293 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
8294 #endif /* INHIBIT_REDISPLAY_HOOKS */
8295 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
8296 defsymbol (&Qbar_cursor, "bar-cursor");
8297 defsymbol (&Qwindow_scroll_functions, "window-scroll-functions");
8298 defsymbol (&Qredisplay_end_trigger_functions,
8299 "redisplay-end-trigger-functions");
8301 DEFSUBR (Fredisplay_echo_area);
8302 DEFSUBR (Fredraw_frame);
8303 DEFSUBR (Fredisplay_frame);
8304 DEFSUBR (Fredraw_device);
8305 DEFSUBR (Fredisplay_device);
8306 DEFSUBR (Fredraw_modeline);
8307 DEFSUBR (Fforce_cursor_redisplay);
8311 vars_of_redisplay (void)
8314 staticpro (&last_arrow_position);
8315 staticpro (&last_arrow_string);
8316 last_arrow_position = Qnil;
8317 last_arrow_string = Qnil;
8320 updating_line_start_cache = 0;
8322 /* #### Probably temporary */
8323 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
8324 \(Temporary) Setting this will impact the performance of the internal
8327 cache_adjustment = 2;
8329 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
8330 Minimum pixel height for clipped bottom display line.
8331 A clipped line shorter than this won't be displayed.
8333 redisplay_variable_changed);
8336 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
8337 Minimum visible area for clipped glyphs at right boundary.
8338 Clipped glyphs shorter than this won't be displayed.
8339 Only pixmap glyph instances are currently allowed to be clipped.
8341 redisplay_variable_changed);
8342 horizontal_clip = 5;
8344 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
8345 String displayed by modeline-format's "%m" specification.
8347 Vglobal_mode_string = Qnil;
8349 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
8350 Marker for where to display an arrow on top of the buffer text.
8351 This must be the beginning of a line in order to work.
8352 See also `overlay-arrow-string'.
8354 redisplay_variable_changed);
8355 Voverlay_arrow_position = Qnil;
8357 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
8358 String to display as an arrow. See also `overlay-arrow-position'.
8360 redisplay_variable_changed);
8361 Voverlay_arrow_string = Qnil;
8363 DEFVAR_INT ("scroll-step", &scroll_step /*
8364 *The number of lines to try scrolling a window by when point moves out.
8365 If that fails to bring point back on frame, point is centered instead.
8366 If this is zero, point is always centered after it moves off screen.
8370 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
8371 *Scroll up to this many lines, to bring point back on screen.
8373 scroll_conservatively = 0;
8375 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
8376 &truncate_partial_width_windows /*
8377 *Non-nil means truncate lines in all windows less than full frame wide.
8379 redisplay_variable_changed);
8380 truncate_partial_width_windows = 1;
8382 DEFVAR_BOOL ("visible-bell", &visible_bell /*
8383 *Non-nil means try to flash the frame to represent a bell.
8387 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
8388 *Non-nil means no need to redraw entire frame after suspending.
8389 A non-nil value is useful if the terminal can automatically preserve
8390 Emacs's frame display when you reenter Emacs.
8391 It is up to you to set this variable if your terminal can do that.
8393 no_redraw_on_reenter = 0;
8395 DEFVAR_LISP ("window-system", &Vwindow_system /*
8396 A symbol naming the window-system under which Emacs is running,
8397 such as `x', or nil if emacs is running on an ordinary terminal.
8399 Do not use this variable, except for GNU Emacs compatibility, as it
8400 gives wrong values in a multi-device environment. Use `console-type'
8403 Vwindow_system = Qnil;
8405 /* #### Temporary shit until window-system is eliminated. */
8406 DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /*
8409 Vinitial_window_system = Qnil;
8411 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
8412 Non-nil means put cursor in minibuffer, at end of any message there.
8414 cursor_in_echo_area = 0;
8416 /* #### Shouldn't this be generalized as follows:
8418 if nil, use block cursor.
8419 if a number, use a bar cursor of that width.
8420 Otherwise, use a 1-pixel bar cursor.
8422 #### Or better yet, this variable should be trashed entirely
8423 (use a Lisp-magic variable to maintain compatibility)
8424 and a specifier `cursor-shape' added, which allows a block
8425 cursor, a bar cursor, a flashing block or bar cursor,
8426 maybe a caret cursor, etc. */
8428 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
8429 Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
8433 #ifndef INHIBIT_REDISPLAY_HOOKS
8434 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
8435 Function or functions to run before every redisplay.
8436 Functions on this hook must be careful to avoid signalling errors!
8438 Vpre_redisplay_hook = Qnil;
8440 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
8441 Function or functions to run after every redisplay.
8442 Functions on this hook must be careful to avoid signalling errors!
8444 Vpost_redisplay_hook = Qnil;
8445 #endif /* INHIBIT_REDISPLAY_HOOKS */
8447 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
8448 Bump this to tell the C code to call `display-warning-buffer'
8449 at next redisplay. You should not normally change this; the function
8450 `display-warning' automatically does this at appropriate times.
8452 display_warning_tick = 0;
8454 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
8455 Non-nil means inhibit display of warning messages.
8456 You should *bind* this, not set it. Any pending warning messages
8457 will be displayed when the binding no longer applies.
8459 /* reset to 0 by startup.el after the splash screen has displayed.
8460 This way, the warnings don't obliterate the splash screen. */
8461 inhibit_warning_display = 1;
8463 DEFVAR_LISP ("window-size-change-functions",
8464 &Vwindow_size_change_functions /*
8465 Not currently implemented.
8466 Functions called before redisplay, if window sizes have changed.
8467 The value should be a list of functions that take one argument.
8468 Just before redisplay, for each frame, if any of its windows have changed
8469 size since the last redisplay, or have been split or deleted,
8470 all the functions in the list are called, with the frame as argument.
8472 Vwindow_size_change_functions = Qnil;
8474 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
8475 Not currently implemented.
8476 Functions to call before redisplaying a window with scrolling.
8477 Each function is called with two arguments, the window
8478 and its new display-start position. Note that the value of `window-end'
8479 is not valid when these functions are called.
8481 Vwindow_scroll_functions = Qnil;
8483 DEFVAR_LISP ("redisplay-end-trigger-functions",
8484 &Vredisplay_end_trigger_functions /*
8485 See `set-window-redisplay-end-trigger'.
8487 Vredisplay_end_trigger_functions = Qnil;
8489 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
8490 *Non-nil means column display number starts at 1.
8492 column_number_start_at_one = 0;
8496 specifier_vars_of_redisplay (void)
8498 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
8499 *Width of left margin.
8500 This is a specifier; use `set-specifier' to change it.
8502 Vleft_margin_width = Fmake_specifier (Qnatnum);
8503 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
8504 set_specifier_caching (Vleft_margin_width,
8505 slot_offset (struct window, left_margin_width),
8506 some_window_value_changed,
8507 slot_offset (struct frame, left_margin_width),
8508 margin_width_changed_in_frame);
8510 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
8511 *Width of right margin.
8512 This is a specifier; use `set-specifier' to change it.
8514 Vright_margin_width = Fmake_specifier (Qnatnum);
8515 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
8516 set_specifier_caching (Vright_margin_width,
8517 slot_offset (struct window, right_margin_width),
8518 some_window_value_changed,
8519 slot_offset (struct frame, right_margin_width),
8520 margin_width_changed_in_frame);
8522 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
8523 *Minimum ascent height of lines.
8524 This is a specifier; use `set-specifier' to change it.
8526 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
8527 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
8528 set_specifier_caching (Vminimum_line_ascent,
8529 slot_offset (struct window, minimum_line_ascent),
8530 some_window_value_changed,
8533 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
8534 *Minimum descent height of lines.
8535 This is a specifier; use `set-specifier' to change it.
8537 Vminimum_line_descent = Fmake_specifier (Qnatnum);
8538 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
8539 set_specifier_caching (Vminimum_line_descent,
8540 slot_offset (struct window, minimum_line_descent),
8541 some_window_value_changed,
8544 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
8545 *Non-nil means use the left outside margin as extra whitespace when
8546 displaying 'whitespace or 'inside-margin glyphs.
8547 This is a specifier; use `set-specifier' to change it.
8549 Vuse_left_overflow = Fmake_specifier (Qboolean);
8550 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
8551 set_specifier_caching (Vuse_left_overflow,
8552 slot_offset (struct window, use_left_overflow),
8553 some_window_value_changed,
8556 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
8557 *Non-nil means use the right outside margin as extra whitespace when
8558 displaying 'whitespace or 'inside-margin glyphs.
8559 This is a specifier; use `set-specifier' to change it.
8561 Vuse_right_overflow = Fmake_specifier (Qboolean);
8562 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
8563 set_specifier_caching (Vuse_right_overflow,
8564 slot_offset (struct window, use_right_overflow),
8565 some_window_value_changed,
8568 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
8569 *Non-nil means the text cursor is visible (this is usually the case).
8570 This is a specifier; use `set-specifier' to change it.
8572 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
8573 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
8574 set_specifier_caching (Vtext_cursor_visible_p,
8575 slot_offset (struct window, text_cursor_visible_p),
8576 text_cursor_visible_p_changed,