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);
5256 /* Don't pollute the cache if not sure if we are correct */
5257 if (w->start_at_line_beg)
5258 update_line_start_cache (w, start, end, pointm, 1);
5259 redisplay_output_window (w);
5261 * If we just displayed the echo area, the line start cache is
5262 * no longer valid, because the minibuffer window is associated
5263 * with the window now.
5266 w->line_cache_last_updated = make_int (-1);
5269 /* #### This should be dependent on face changes and will need to be
5270 somewhere else once tty updates occur on a per-frame basis. */
5271 mark_face_cachels_as_clean (w);
5273 w->windows_changed = 0;
5276 /* Call buffer_reset_changes for all buffers present in any window
5277 currently visible in all frames on all devices. #### There has to
5278 be a better way to do this. */
5281 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
5283 buffer_reset_changes (XBUFFER (w->buffer));
5288 reset_buffer_changes (void)
5290 Lisp_Object frmcons, devcons, concons;
5292 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
5294 struct frame *f = XFRAME (XCAR (frmcons));
5296 if (FRAME_REPAINT_P (f))
5297 map_windows (f, reset_buffer_changes_mapfun, 0);
5301 /* Ensure that all windows underneath the given window in the window
5302 hierarchy are correctly displayed. */
5305 redisplay_windows (Lisp_Object window, int skip_selected)
5307 for (; !NILP (window) ; window = XWINDOW (window)->next)
5309 redisplay_window (window, skip_selected);
5314 call_redisplay_end_triggers (struct window *w, void *closure)
5316 Bufpos lrpos = w->last_redisplay_pos;
5317 w->last_redisplay_pos = 0;
5318 if (!NILP (w->buffer)
5319 && !NILP (w->redisplay_end_trigger)
5324 if (MARKERP (w->redisplay_end_trigger)
5325 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
5326 pos = marker_position (w->redisplay_end_trigger);
5327 else if (INTP (w->redisplay_end_trigger))
5328 pos = XINT (w->redisplay_end_trigger);
5331 w->redisplay_end_trigger = Qnil;
5338 XSETWINDOW (window, w);
5339 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
5340 Qredisplay_end_trigger_functions,
5342 w->redisplay_end_trigger);
5343 w->redisplay_end_trigger = Qnil;
5350 /* Ensure that all windows on the given frame are correctly displayed. */
5353 redisplay_frame (struct frame *f, int preemption_check)
5355 struct device *d = XDEVICE (f->device);
5357 if (preemption_check)
5359 /* The preemption check itself takes a lot of time,
5360 so normally don't do it here. We do it if called
5361 from Lisp, though (`redisplay-frame'). */
5364 REDISPLAY_PREEMPTION_CHECK;
5369 /* Before we put a hold on frame size changes, attempt to process
5370 any which are already pending. */
5371 if (f->size_change_pending)
5372 change_frame_size (f, f->new_height, f->new_width, 0);
5374 /* If frame size might need to be changed, due to changed size
5375 of toolbars, scrollbars etc, change it now */
5376 if (f->size_slipped)
5378 adjust_frame_size (f);
5379 assert (!f->size_slipped);
5382 /* The menubar, toolbar, and icon updates must be done before
5383 hold_frame_size_changes is called and we are officially
5384 'in_display'. They may eval lisp code which may call Fsignal.
5385 If in_display is set Fsignal will abort. */
5387 #ifdef HAVE_MENUBARS
5388 /* Update the menubar. It is done first since it could change
5389 the menubar's visibility. This way we avoid having flashing
5390 caused by an Expose event generated by the visibility change
5392 update_frame_menubars (f);
5393 #endif /* HAVE_MENUBARS */
5394 /* widgets are similar to menus in that they can call lisp to
5395 determine activation etc. Therefore update them before we get
5396 into redisplay. This is primarily for connected widgets such as
5398 update_frame_subwindows (f);
5399 #ifdef HAVE_TOOLBARS
5400 /* Update the toolbars. */
5401 update_frame_toolbars (f);
5402 #endif /* HAVE_TOOLBARS */
5404 hold_frame_size_changes ();
5406 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
5407 /* Within this section, we are defenseless and assume that the
5408 following cannot happen:
5410 1) garbage collection
5411 2) Lisp code evaluation
5412 3) frame size changes
5414 We ensure (3) by calling hold_frame_size_changes(), which
5415 will cause any pending frame size changes to get put on hold
5416 till after the end of the critical section. (1) follows
5417 automatically if (2) is met. #### Unfortunately, there are
5418 some places where Lisp code can be called within this section.
5419 We need to remove them.
5421 If Fsignal() is called during this critical section, we
5424 If garbage collection is called during this critical section,
5425 we simply return. #### We should abort instead.
5427 #### If a frame-size change does occur we should probably
5428 actually be preempting redisplay. */
5430 /* If we clear the frame we have to force its contents to be redrawn. */
5432 f->frame_changed = 1;
5434 /* Erase the frame before outputting its contents. */
5437 DEVMETH (d, clear_frame, (f));
5440 /* invalidate the subwindow cache. we are going to reuse the glyphs
5441 flag here to cause subwindows to get instantiated. This is
5442 because subwindows changed is less strict - dealing with things
5443 like the clicked state of button. */
5444 if (!Dynarr_length (f->subwindow_cachels)
5445 || f->glyphs_changed
5446 || f->frame_changed)
5447 reset_subwindow_cachels (f);
5449 mark_subwindow_cachels_as_not_updated (f);
5451 /* Do the selected window first. */
5452 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
5454 /* Then do the rest. */
5455 redisplay_windows (f->root_window, 1);
5457 /* We now call the output_end routine for tty frames. We delay
5458 doing so in order to avoid cursor flicker. So much for 100%
5460 if (FRAME_TTY_P (f))
5461 DEVMETH (d, output_end, (d));
5463 update_frame_title (f);
5465 f->buffers_changed = 0;
5466 f->clip_changed = 0;
5467 f->extents_changed = 0;
5468 f->faces_changed = 0;
5469 f->frame_changed = 0;
5470 f->glyphs_changed = 0;
5471 f->subwindows_changed = 0;
5472 f->icon_changed = 0;
5473 f->menubar_changed = 0;
5474 f->modeline_changed = 0;
5475 f->point_changed = 0;
5476 f->toolbar_changed = 0;
5477 f->windows_changed = 0;
5478 f->windows_structure_changed = 0;
5479 f->window_face_cache_reset = 0;
5480 f->echo_area_garbaged = 0;
5484 if (!f->size_change_pending)
5485 f->size_changed = 0;
5487 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
5489 /* Allow frame size changes to occur again.
5491 #### what happens if changes to other frames happen? */
5492 unhold_one_frame_size_changes (f);
5494 map_windows (f, call_redisplay_end_triggers, 0);
5498 /* Ensure that all frames on the given device are correctly displayed. */
5501 redisplay_device (struct device *d)
5503 Lisp_Object frame, frmcons;
5505 int size_change_failed = 0;
5508 if (DEVICE_STREAM_P (d)) /* nothing to do */
5511 /* It is possible that redisplay has been called before the
5512 device is fully initialized. If so then continue with the
5514 if (NILP (DEVICE_SELECTED_FRAME (d)))
5517 REDISPLAY_PREEMPTION_CHECK;
5521 /* Always do the selected frame first. */
5522 frame = DEVICE_SELECTED_FRAME (d);
5526 if (f->icon_changed || f->windows_changed)
5527 update_frame_icon (f);
5529 if (FRAME_REPAINT_P (f))
5531 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
5532 f->faces_changed || f->frame_changed || f->menubar_changed ||
5533 f->modeline_changed || f->point_changed || f->size_changed ||
5534 f->toolbar_changed || f->windows_changed || f->size_slipped ||
5535 f->windows_structure_changed || f->glyphs_changed || f->subwindows_changed)
5537 preempted = redisplay_frame (f, 0);
5543 /* If the frame redisplay did not get preempted, then this flag
5544 should have gotten set to 0. It might be possible for that
5545 not to happen if a size change event were to occur at an odd
5546 time. To make sure we don't miss anything we simply don't
5547 reset the top level flags until the condition ends up being
5548 in the right state. */
5549 if (f->size_changed)
5550 size_change_failed = 1;
5553 DEVICE_FRAME_LOOP (frmcons, d)
5555 f = XFRAME (XCAR (frmcons));
5557 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
5560 if (f->icon_changed || f->windows_changed)
5561 update_frame_icon (f);
5563 if (FRAME_REPAINT_P (f))
5565 if (f->buffers_changed || f->clip_changed || f->extents_changed ||
5566 f->faces_changed || f->frame_changed || f->menubar_changed ||
5567 f->modeline_changed || f->point_changed || f->size_changed ||
5568 f->toolbar_changed || f->windows_changed ||
5569 f->windows_structure_changed ||
5570 f->glyphs_changed || f->subwindows_changed)
5572 preempted = redisplay_frame (f, 0);
5578 if (f->size_change_pending)
5579 size_change_failed = 1;
5583 /* If we get here then we redisplayed all of our frames without
5584 getting preempted so mark ourselves as clean. */
5585 d->buffers_changed = 0;
5586 d->clip_changed = 0;
5587 d->extents_changed = 0;
5588 d->faces_changed = 0;
5589 d->frame_changed = 0;
5590 d->glyphs_changed = 0;
5591 d->subwindows_changed = 0;
5592 d->icon_changed = 0;
5593 d->menubar_changed = 0;
5594 d->modeline_changed = 0;
5595 d->point_changed = 0;
5596 d->toolbar_changed = 0;
5597 d->windows_changed = 0;
5598 d->windows_structure_changed = 0;
5600 if (!size_change_failed)
5601 d->size_changed = 0;
5607 restore_profiling_redisplay_flag (Lisp_Object val)
5609 profiling_redisplay_flag = XINT (val);
5613 /* Ensure that all windows on all frames on all devices are displaying
5614 the current contents of their respective buffers. */
5617 redisplay_without_hooks (void)
5619 Lisp_Object devcons, concons;
5620 int size_change_failed = 0;
5621 int count = specpdl_depth ();
5623 if (profiling_active)
5625 record_unwind_protect (restore_profiling_redisplay_flag,
5626 make_int (profiling_redisplay_flag));
5627 profiling_redisplay_flag = 1;
5630 if (asynch_device_change_pending)
5631 handle_asynch_device_change ();
5633 if (!buffers_changed && !clip_changed && !extents_changed &&
5634 !faces_changed && !frame_changed && !icon_changed &&
5635 !menubar_changed && !modeline_changed && !point_changed &&
5636 !size_changed && !toolbar_changed && !windows_changed &&
5637 !glyphs_changed && !subwindows_changed &&
5638 !windows_structure_changed && !disable_preemption &&
5639 preemption_count < max_preempts)
5642 DEVICE_LOOP_NO_BREAK (devcons, concons)
5644 struct device *d = XDEVICE (XCAR (devcons));
5647 if (d->buffers_changed || d->clip_changed || d->extents_changed ||
5648 d->faces_changed || d->frame_changed || d->icon_changed ||
5649 d->menubar_changed || d->modeline_changed || d->point_changed ||
5650 d->size_changed || d->toolbar_changed || d->windows_changed ||
5651 d->windows_structure_changed ||
5652 d->glyphs_changed || d->subwindows_changed)
5654 preempted = redisplay_device (d);
5659 RESET_CHANGED_SET_FLAGS;
5663 /* See comment in redisplay_device. */
5664 if (d->size_changed)
5665 size_change_failed = 1;
5668 preemption_count = 0;
5670 /* Mark redisplay as accurate */
5671 buffers_changed = 0;
5673 extents_changed = 0;
5676 subwindows_changed = 0;
5678 menubar_changed = 0;
5679 modeline_changed = 0;
5681 toolbar_changed = 0;
5682 windows_changed = 0;
5683 windows_structure_changed = 0;
5684 RESET_CHANGED_SET_FLAGS;
5688 mark_all_faces_as_clean ();
5692 if (!size_change_failed)
5695 reset_buffer_changes ();
5698 unbind_to (count, Qnil);
5704 if (last_display_warning_tick != display_warning_tick &&
5705 !inhibit_warning_display)
5707 /* If an error occurs during this function, oh well.
5708 If we report another warning, we could get stuck in an
5709 infinite loop reporting warnings. */
5710 call0_trapping_errors (0, Qdisplay_warning_buffer);
5711 last_display_warning_tick = display_warning_tick;
5713 /* The run_hook_trapping_errors functions are smart enough not
5714 to do any evalling if the hook function is empty, so there
5715 should not be any significant time loss. All places in the
5716 C code that call redisplay() are prepared to handle GCing,
5717 so we should be OK. */
5718 #ifndef INHIBIT_REDISPLAY_HOOKS
5719 run_hook_trapping_errors ("Error in pre-redisplay-hook",
5720 Qpre_redisplay_hook);
5721 #endif /* INHIBIT_REDISPLAY_HOOKS */
5723 redisplay_without_hooks ();
5725 #ifndef INHIBIT_REDISPLAY_HOOKS
5726 run_hook_trapping_errors ("Error in post-redisplay-hook",
5727 Qpost_redisplay_hook);
5728 #endif /* INHIBIT_REDISPLAY_HOOKS */
5732 static char window_line_number_buf[32];
5734 /* Efficiently determine the window line number, and return a pointer
5735 to its printed representation. Do this regardless of whether
5736 line-number-mode is on. The first line in the buffer is counted as
5737 1. If narrowing is in effect, the lines are counted from the
5738 beginning of the visible portion of the buffer. */
5740 window_line_number (struct window *w, int type)
5742 struct device *d = XDEVICE (XFRAME (w->frame)->device);
5743 struct buffer *b = XBUFFER (w->buffer);
5744 /* Be careful in the order of these tests. The first clause will
5745 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
5746 This can occur when the frame title is computed really early */
5748 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
5749 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
5750 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5751 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
5753 : marker_position (w->pointm[type]));
5756 line = buffer_line_number (b, pos, 1);
5758 long_to_string (window_line_number_buf, line + 1);
5760 return window_line_number_buf;
5764 /* Given a character representing an object in a modeline
5765 specification, return a string (stored into the global array
5766 `mode_spec_bufbyte_string') with the information that object
5769 This function is largely unchanged from previous versions of the
5772 Warning! This code is also used for frame titles and can be called
5773 very early in the device/frame update process! JV
5777 decode_mode_spec (struct window *w, Emchar spec, int type)
5779 Lisp_Object obj = Qnil;
5780 CONST char *str = NULL;
5781 struct buffer *b = XBUFFER (w->buffer);
5783 Dynarr_reset (mode_spec_bufbyte_string);
5787 /* print buffer name */
5792 /* print visited file name */
5797 /* print the current column */
5800 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
5802 : marker_position (w->pointm[type]);
5803 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
5806 long_to_string (buf, col);
5808 Dynarr_add_many (mode_spec_bufbyte_string,
5809 (CONST Bufbyte *) buf, strlen (buf));
5811 goto decode_mode_spec_done;
5813 /* print the file coding system */
5817 Lisp_Object codesys = b->buffer_file_coding_system;
5818 /* Be very careful here not to get an error. */
5819 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
5821 codesys = Ffind_coding_system (codesys);
5822 if (CODING_SYSTEMP (codesys))
5823 obj = XCODING_SYSTEM_MNEMONIC (codesys);
5826 #endif /* FILE_CODING */
5829 /* print the current line number */
5831 str = window_line_number (w, type);
5834 /* print value of mode-name (obsolete) */
5839 /* print hyphen and frame number, if != 1 */
5843 struct frame *f = XFRAME (w->frame);
5844 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
5846 /* Naughty, naughty */
5847 char * writable_str = alloca_array (char, 10);
5848 sprintf (writable_str, "-%d", f->order_count);
5852 #endif /* HAVE_TTY */
5855 /* print Narrow if appropriate */
5857 if (BUF_BEGV (b) > BUF_BEG (b)
5858 || BUF_ZV (b) < BUF_Z (b))
5862 /* print %, * or hyphen, if buffer is read-only, modified or neither */
5864 str = (!NILP (b->read_only)
5866 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5871 /* print * or hyphen -- XEmacs change to allow a buffer to be
5872 read-only but still indicate whether it is modified. */
5874 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5876 : (!NILP (b->read_only)
5881 /* #### defined in 19.29 decode_mode_spec, but not in
5882 modeline-format doc string. */
5883 /* This differs from %* in that it ignores read-only-ness. */
5885 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5890 /* print process status */
5892 obj = Fget_buffer_process (w->buffer);
5894 str = GETTEXT ("no process");
5896 obj = Fsymbol_name (Fprocess_status (obj));
5899 /* Print name of selected frame. */
5901 obj = XFRAME (w->frame)->name;
5904 /* indicate TEXT or BINARY */
5906 /* #### NT does not use this any more. Now what? */
5910 /* print percent of buffer above top of window, or Top, Bot or All */
5913 Bufpos pos = marker_position (w->start[type]);
5914 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5916 /* This had better be while the desired lines are being done. */
5917 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
5919 if (pos <= BUF_BEGV (b))
5924 else if (pos <= BUF_BEGV (b))
5928 /* This hard limit is ok since the string it will hold has a
5929 fixed maximum length of 3. But just to be safe... */
5932 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
5934 /* We can't normally display a 3-digit number, so get us a
5935 2-digit number that is close. */
5939 sprintf (buf, "%2d%%", total);
5940 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5943 goto decode_mode_spec_done;
5948 /* print percent of buffer above bottom of window, perhaps plus
5949 Top, or print Bottom or All */
5952 Bufpos toppos = marker_position (w->start[type]);
5953 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
5954 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5956 /* botpos is only accurate as of the last redisplay, so we can
5957 only treat it as a hint. In particular, after erase-buffer,
5958 botpos may be negative. */
5959 if (botpos < toppos)
5962 if (botpos >= BUF_ZV (b))
5964 if (toppos <= BUF_BEGV (b))
5971 /* This hard limit is ok since the string it will hold has a
5972 fixed maximum length of around 6. But just to be safe... */
5975 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
5977 /* We can't normally display a 3-digit number, so get us a
5978 2-digit number that is close. */
5982 if (toppos <= BUF_BEGV (b))
5983 sprintf (buf, "Top%2d%%", total);
5985 sprintf (buf, "%2d%%", total);
5987 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5990 goto decode_mode_spec_done;
6000 /* print one [ for each recursive editing level. */
6005 if (command_loop_level > 5)
6011 for (i = 0; i < command_loop_level; i++)
6012 Dynarr_add (mode_spec_bufbyte_string, '[');
6014 goto decode_mode_spec_done;
6017 /* print one ] for each recursive editing level. */
6022 if (command_loop_level > 5)
6028 for (i = 0; i < command_loop_level; i++)
6029 Dynarr_add (mode_spec_bufbyte_string, ']');
6031 goto decode_mode_spec_done;
6034 /* print infinitely many dashes -- handle at top level now */
6041 Dynarr_add_many (mode_spec_bufbyte_string,
6043 XSTRING_LENGTH (obj));
6045 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6047 decode_mode_spec_done:
6048 Dynarr_add (mode_spec_bufbyte_string, '\0');
6051 /* Given a display line, free all of its data structures. */
6054 free_display_line (struct display_line *dl)
6058 if (dl->display_blocks)
6060 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6062 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6064 Dynarr_free (db->runes);
6067 Dynarr_free (dl->display_blocks);
6068 dl->display_blocks = NULL;
6071 if (dl->left_glyphs)
6073 Dynarr_free (dl->left_glyphs);
6074 dl->left_glyphs = NULL;
6077 if (dl->right_glyphs)
6079 Dynarr_free (dl->right_glyphs);
6080 dl->right_glyphs = NULL;
6085 /* Given an array of display lines, free them and all data structures
6086 contained within them. */
6089 free_display_lines (display_line_dynarr *dla)
6093 for (line = 0; line < Dynarr_largest (dla); line++)
6095 free_display_line (Dynarr_atp (dla, line));
6101 /* Call internal free routine for each set of display lines. */
6104 free_display_structs (struct window_mirror *mir)
6106 if (mir->current_display_lines)
6108 free_display_lines (mir->current_display_lines);
6109 mir->current_display_lines = 0;
6112 if (mir->desired_display_lines)
6114 free_display_lines (mir->desired_display_lines);
6115 mir->desired_display_lines = 0;
6121 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object))
6125 glyph_block *gb = Dynarr_atp (gba, 0);
6126 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
6128 for (; gb < gb_last; gb++)
6130 if (!NILP (gb->glyph))
6131 markobj (gb->glyph);
6132 if (!NILP (gb->extent))
6133 markobj (gb->extent);
6139 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object))
6141 display_line *dl = Dynarr_atp (dla, 0);
6142 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
6144 for (; dl < dl_last; dl++)
6146 display_block_dynarr *dba = dl->display_blocks;
6147 display_block *db = Dynarr_atp (dba, 0);
6148 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
6150 for (; db < db_last; db++)
6152 rune_dynarr *ra = db->runes;
6153 rune *r = Dynarr_atp (ra, 0);
6154 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
6156 for (; r < r_last; r++)
6158 if (r->type == RUNE_DGLYPH)
6160 if (!NILP (r->object.dglyph.glyph))
6161 markobj (r->object.dglyph.glyph);
6162 if (!NILP (r->object.dglyph.extent))
6163 markobj (r->object.dglyph.extent);
6168 mark_glyph_block_dynarr (dl->left_glyphs, markobj);
6169 mark_glyph_block_dynarr (dl->right_glyphs, markobj);
6174 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object))
6176 mark_redisplay_structs (mir->current_display_lines, markobj);
6177 mark_redisplay_structs (mir->desired_display_lines, markobj);
6180 mark_window_mirror (mir->next, markobj);
6183 mark_window_mirror (mir->hchild, markobj);
6184 else if (mir->vchild)
6185 mark_window_mirror (mir->vchild, markobj);
6189 mark_redisplay (void (*markobj)(Lisp_Object))
6191 Lisp_Object frmcons, devcons, concons;
6193 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6195 struct frame *f = XFRAME (XCAR (frmcons));
6196 update_frame_window_mirror (f);
6197 mark_window_mirror (f->root_mirror, markobj);
6201 /*****************************************************************************
6202 Line Start Cache Description and Rationale
6204 The traditional scrolling code in Emacs breaks in a variable height world.
6205 It depends on the key assumption that the number of lines that can be
6206 displayed at any given time is fixed. This led to a complete separation
6207 of the scrolling code from the redisplay code. In order to fully support
6208 variable height lines, the scrolling code must actually be tightly
6209 integrated with redisplay. Only redisplay can determine how many lines
6210 will be displayed on a screen for any given starting point.
6212 What is ideally wanted is a complete list of the starting buffer position
6213 for every possible display line of a buffer along with the height of that
6214 display line. Maintaining such a full list would be very expensive. We
6215 settle for having it include information for all areas which we happen to
6216 generate anyhow (i.e. the region currently being displayed) and for those
6217 areas we need to work with.
6219 In order to ensure that the cache accurately represents what redisplay
6220 would actually show, it is necessary to invalidate it in many situations.
6221 If the buffer changes, the starting positions may no longer be correct.
6222 If a face or an extent has changed then the line heights may have altered.
6223 These events happen frequently enough that the cache can end up being
6224 constantly disabled. With this potentially constant invalidation when is
6225 the cache ever useful?
6227 Even if the cache is invalidated before every single usage, it is
6228 necessary. Scrolling often requires knowledge about display lines which
6229 are actually above or below the visible region. The cache provides a
6230 convenient light-weight method of storing this information for multiple
6231 display regions. This knowledge is necessary for the scrolling code to
6232 always obey the First Golden Rule of Redisplay.
6234 If the cache already contains all of the information that the scrolling
6235 routines happen to need so that it doesn't have to go generate it, then we
6236 are able to obey the Third Golden Rule of Redisplay. The first thing we
6237 do to help out the cache is to always add the displayed region. This
6238 region had to be generated anyway, so the cache ends up getting the
6239 information basically for free. In those cases where a user is simply
6240 scrolling around viewing a buffer there is a high probability that this is
6241 sufficient to always provide the needed information. The second thing we
6242 can do is be smart about invalidating the cache.
6244 TODO -- Be smart about invalidating the cache. Potential places:
6246 + Insertions at end-of-line which don't cause line-wraps do not alter the
6247 starting positions of any display lines. These types of buffer
6248 modifications should not invalidate the cache. This is actually a large
6249 optimization for redisplay speed as well.
6251 + Buffer modifications frequently only affect the display of lines at and
6252 below where they occur. In these situations we should only invalidate
6253 the part of the cache starting at where the modification occurs.
6255 In case you're wondering, the Second Golden Rule of Redisplay is not
6257 ****************************************************************************/
6259 /* This will get used quite a bit so we don't want to be constantly
6260 allocating and freeing it. */
6261 line_start_cache_dynarr *internal_cache;
6263 /* Makes internal_cache represent the TYPE display structs and only
6264 the TYPE display structs. */
6267 update_internal_cache_list (struct window *w, int type)
6270 display_line_dynarr *dla = window_display_lines (w, type);
6272 Dynarr_reset (internal_cache);
6273 for (line = 0; line < Dynarr_length (dla); line++)
6275 struct display_line *dl = Dynarr_atp (dla, line);
6281 struct line_start_cache lsc;
6283 lsc.start = dl->bufpos;
6284 lsc.end = dl->end_bufpos;
6285 lsc.height = dl->ascent + dl->descent;
6287 Dynarr_add (internal_cache, lsc);
6292 /* Reset the line cache if necessary. This should be run at the
6293 beginning of any function which access the cache. */
6296 validate_line_start_cache (struct window *w)
6298 struct buffer *b = XBUFFER (w->buffer);
6299 struct frame *f = XFRAME (w->frame);
6301 if (!w->line_cache_validation_override)
6303 /* f->extents_changed used to be in here because extent face and
6304 size changes can cause text shifting. However, the extent
6305 covering the region is constantly having its face set and
6306 priority altered by the mouse code. This means that the line
6307 start cache is constantly being invalidated. This is bad
6308 since the mouse code also triggers heavy usage of the cache.
6309 Since it is an unlikely that f->extents being changed
6310 indicates that the cache really needs to be updated and if it
6311 does redisplay will catch it pretty quickly we no longer
6312 invalidate the cache if it is set. This greatly speeds up
6313 dragging out regions with the mouse. */
6314 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
6318 Dynarr_reset (w->line_start_cache);
6323 /* Return the very first buffer position contained in the given
6324 window's cache, or -1 if the cache is empty. Assumes that the
6328 line_start_cache_start (struct window *w)
6330 line_start_cache_dynarr *cache = w->line_start_cache;
6332 if (!Dynarr_length (cache))
6335 return Dynarr_atp (cache, 0)->start;
6338 /* Return the very last buffer position contained in the given
6339 window's cache, or -1 if the cache is empty. Assumes that the
6343 line_start_cache_end (struct window *w)
6345 line_start_cache_dynarr *cache = w->line_start_cache;
6347 if (!Dynarr_length (cache))
6350 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
6353 /* Return the index of the line POINT is contained within in window
6354 W's line start cache. It will enlarge the cache or move the cache
6355 window in order to have POINT be present in the cache. MIN_PAST is
6356 a guarantee of the number of entries in the cache present on either
6357 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
6358 then it will be treated as 0, but the cache window will not be
6359 allowed to shift. Returns -1 if POINT cannot be found in the cache
6363 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
6365 struct buffer *b = XBUFFER (w->buffer);
6366 line_start_cache_dynarr *cache = w->line_start_cache;
6367 unsigned int top, bottom, pos;
6369 validate_line_start_cache (w);
6370 w->line_cache_validation_override++;
6372 /* Let functions pass in negative values, but we still treat -1
6374 /* #### bogosity alert */
6375 if (min_past < 0 && min_past != -1)
6376 min_past = -min_past;
6378 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
6379 || line_start_cache_end (w) < point)
6382 int win_char_height = window_char_height (w, 1);
6384 /* Occasionally we get here with a 0 height
6385 window. find_next_newline_no_quit will abort if we pass it a
6386 count of 0 so handle that case. */
6387 if (!win_char_height)
6388 win_char_height = 1;
6390 if (!Dynarr_length (cache))
6392 Bufpos from = find_next_newline_no_quit (b, point, -1);
6393 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
6395 update_line_start_cache (w, from, to, point, 0);
6397 if (!Dynarr_length (cache))
6399 w->line_cache_validation_override--;
6404 assert (Dynarr_length (cache));
6407 while (line_start_cache_start (w) > point
6408 && (loop < cache_adjustment || min_past == -1))
6412 from = line_start_cache_start (w);
6413 if (from <= BUF_BEGV (b))
6416 from = find_next_newline_no_quit (b, from, -win_char_height);
6417 to = line_start_cache_end (w);
6419 update_line_start_cache (w, from, to, point, 0);
6423 if (line_start_cache_start (w) > point)
6427 from = find_next_newline_no_quit (b, point, -1);
6428 if (from >= BUF_ZV (b))
6430 to = find_next_newline_no_quit (b, from, -win_char_height);
6435 to = find_next_newline_no_quit (b, from, win_char_height);
6437 update_line_start_cache (w, from, to, point, 0);
6441 while (line_start_cache_end (w) < point
6442 && (loop < cache_adjustment || min_past == -1))
6446 to = line_start_cache_end (w);
6447 if (to >= BUF_ZV (b))
6450 from = line_start_cache_end (w);
6451 to = find_next_newline_no_quit (b, from, win_char_height);
6453 update_line_start_cache (w, from, to, point, 0);
6457 if (line_start_cache_end (w) < point)
6461 from = find_next_newline_no_quit (b, point, -1);
6462 if (from >= BUF_ZV (b))
6464 to = find_next_newline_no_quit (b, from, -win_char_height);
6469 to = find_next_newline_no_quit (b, from, win_char_height);
6471 update_line_start_cache (w, from, to, point, 0);
6475 assert (Dynarr_length (cache));
6480 /* This could happen if the buffer is narrowed. */
6481 if (line_start_cache_start (w) > point
6482 || line_start_cache_end (w) < point)
6484 w->line_cache_validation_override--;
6490 top = Dynarr_length (cache) - 1;
6495 unsigned int new_pos;
6498 pos = (bottom + top + 1) >> 1;
6499 start = Dynarr_atp (cache, pos)->start;
6500 end = Dynarr_atp (cache, pos)->end;
6502 if (point >= start && point <= end)
6504 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
6507 find_next_newline_no_quit (b, line_start_cache_start (w),
6509 Bufpos to = line_start_cache_end (w);
6511 update_line_start_cache (w, from, to, point, 0);
6512 goto find_point_loop;
6514 else if ((Dynarr_length (cache) - pos - 1) < min_past
6515 && line_start_cache_end (w) < BUF_ZV (b))
6517 Bufpos from = line_start_cache_end (w);
6518 Bufpos to = find_next_newline_no_quit (b, from,
6523 update_line_start_cache (w, from, to, point, 0);
6524 goto find_point_loop;
6528 w->line_cache_validation_override--;
6532 else if (point > end)
6534 else if (point < start)
6539 new_pos = (bottom + top + 1) >> 1;
6542 w->line_cache_validation_override--;
6548 /* Return a boolean indicating if POINT would be visible in window W
6549 if display of the window was to begin at STARTP. */
6552 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
6554 struct buffer *b = XBUFFER (w->buffer);
6556 int bottom = WINDOW_TEXT_HEIGHT (w);
6559 /* If point is before the intended start it obviously can't be visible. */
6563 /* If point or start are not in the accessible buffer range, then
6565 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
6566 || point < BUF_BEGV (b) || point > BUF_ZV (b))
6569 validate_line_start_cache (w);
6570 w->line_cache_validation_override++;
6572 start_elt = point_in_line_start_cache (w, startp, 0);
6573 if (start_elt == -1)
6575 w->line_cache_validation_override--;
6579 assert (line_start_cache_start (w) <= startp
6580 && line_start_cache_end (w) >= startp);
6586 /* Expand the cache if necessary. */
6587 if (start_elt == Dynarr_length (w->line_start_cache))
6590 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
6592 start_elt = point_in_line_start_cache (w, old_startp,
6593 window_char_height (w, 0));
6595 /* We've already actually processed old_startp, so increment
6599 /* If this happens we didn't add any extra elements. Bummer. */
6600 if (start_elt == Dynarr_length (w->line_start_cache))
6602 w->line_cache_validation_override--;
6607 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
6609 if (pixpos + height > bottom)
6611 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6613 w->line_cache_validation_override--;
6619 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
6621 w->line_cache_validation_override--;
6629 /* For the given window W, if display starts at STARTP, what will be
6630 the buffer position at the beginning or end of the last line
6631 displayed. The end of the last line is also know as the window end
6634 #### With a little work this could probably be reworked as just a
6635 call to start_with_line_at_pixpos. */
6638 start_end_of_last_line (struct window *w, Bufpos startp, int end)
6640 struct buffer *b = XBUFFER (w->buffer);
6641 line_start_cache_dynarr *cache = w->line_start_cache;
6643 int bottom = WINDOW_TEXT_HEIGHT (w);
6647 validate_line_start_cache (w);
6648 w->line_cache_validation_override++;
6650 if (startp < BUF_BEGV (b))
6651 startp = BUF_BEGV (b);
6652 else if (startp > BUF_ZV (b))
6653 startp = BUF_ZV (b);
6656 start_elt = point_in_line_start_cache (w, cur_start, 0);
6657 if (start_elt == -1)
6658 abort (); /* this had better never happen */
6662 int height = Dynarr_atp (cache, start_elt)->height;
6664 cur_start = Dynarr_atp (cache, start_elt)->start;
6666 if (pixpos + height > bottom)
6668 /* Adjust for any possible clip. */
6669 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6674 w->line_cache_validation_override--;
6678 return BUF_BEGV (b);
6682 w->line_cache_validation_override--;
6684 return Dynarr_atp (cache, start_elt)->end;
6686 return Dynarr_atp (cache, start_elt)->start;
6692 if (start_elt == Dynarr_length (cache))
6694 Bufpos from = line_start_cache_end (w);
6695 int win_char_height = window_char_height (w, 0);
6696 Bufpos to = find_next_newline_no_quit (b, from,
6701 /* We've hit the end of the bottom so that's what it is. */
6702 if (from >= BUF_ZV (b))
6704 w->line_cache_validation_override--;
6708 update_line_start_cache (w, from, to, BUF_PT (b), 0);
6710 /* Updating the cache invalidates any current indexes. */
6711 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
6716 /* For the given window W, if display starts at STARTP, what will be
6717 the buffer position at the beginning of the last line displayed. */
6720 start_of_last_line (struct window *w, Bufpos startp)
6722 return start_end_of_last_line (w, startp, 0);
6725 /* For the given window W, if display starts at STARTP, what will be
6726 the buffer position at the end of the last line displayed. This is
6727 also know as the window end position. */
6730 end_of_last_line (struct window *w, Bufpos startp)
6732 return start_end_of_last_line (w, startp, 1);
6735 /* For window W, what does the starting position have to be so that
6736 the line containing POINT will cover pixel position PIXPOS. */
6739 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
6741 struct buffer *b = XBUFFER (w->buffer);
6743 Bufpos cur_pos, prev_pos = point;
6744 int point_line_height;
6745 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
6747 validate_line_start_cache (w);
6748 w->line_cache_validation_override++;
6750 cur_elt = point_in_line_start_cache (w, point, 0);
6751 /* #### See comment in update_line_start_cache about big minibuffers. */
6754 w->line_cache_validation_override--;
6758 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
6762 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6764 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6766 /* Do not take into account the value of vertical_clip here.
6767 That is the responsibility of the calling functions. */
6770 w->line_cache_validation_override--;
6771 if (-pixheight > point_line_height)
6772 /* We can't make the target line cover pixpos, so put it
6773 above pixpos. That way it will at least be visible. */
6783 int win_char_height;
6785 if (cur_pos <= BUF_BEGV (b))
6787 w->line_cache_validation_override--;
6788 return BUF_BEGV (b);
6791 win_char_height = window_char_height (w, 0);
6792 if (!win_char_height)
6793 win_char_height = 1;
6795 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
6796 to = line_start_cache_end (w);
6797 update_line_start_cache (w, from, to, point, 0);
6799 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
6800 assert (cur_elt >= 0);
6806 /* For window W, what does the starting position have to be so that
6807 the line containing point is on display line LINE. If LINE is
6808 positive it is considered to be the number of lines from the top of
6809 the window (0 is the top line). If it is negative the number is
6810 considered to be the number of lines from the bottom (-1 is the
6814 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
6816 validate_line_start_cache (w);
6817 w->line_cache_validation_override++;
6821 int cur_elt = point_in_line_start_cache (w, point, line);
6823 if (cur_elt - line < 0)
6824 cur_elt = 0; /* Hit the top */
6828 w->line_cache_validation_override--;
6829 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
6833 /* The calculated value of pixpos is correct for the bottom line
6834 or what we want when line is -1. Therefore we subtract one
6835 because we have already handled one line. */
6836 int new_line = -line - 1;
6837 int cur_elt = point_in_line_start_cache (w, point, new_line);
6838 int pixpos = WINDOW_TEXT_BOTTOM (w);
6839 Bufpos retval, search_point;
6841 /* If scroll_on_clipped_lines is false, the last "visible" line of
6842 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
6843 If s_o_c_l is true, then we don't want to count a clipped
6844 line, so back up from the bottom by the height of the line
6845 containing point. */
6846 if (scroll_on_clipped_lines)
6847 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6851 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
6853 /* Hit the bottom of the buffer. */
6855 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
6859 XSETWINDOW (window, w);
6860 default_face_height_and_width (window, &defheight, 0);
6862 cur_elt = Dynarr_length (w->line_start_cache) - 1;
6864 pixpos -= (adjustment * defheight);
6865 if (pixpos < WINDOW_TEXT_TOP (w))
6866 pixpos = WINDOW_TEXT_TOP (w);
6869 cur_elt = cur_elt + new_line;
6871 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6873 retval = start_with_line_at_pixpos (w, search_point, pixpos);
6874 w->line_cache_validation_override--;
6879 /* This is used to speed up vertical scrolling by caching the known
6880 buffer starting positions for display lines. This allows the
6881 scrolling routines to avoid costly calls to regenerate_window. If
6882 NO_REGEN is true then it will only add the values in the DESIRED
6883 display structs which are in the given range.
6885 Note also that the FROM/TO values are minimums. It is possible
6886 that this function will actually add information outside of the
6887 lines containing those positions. This can't hurt but it could
6890 #### We currently force the cache to have only 1 contiguous region.
6891 It might help to make the cache a dynarr of caches so that we can
6892 cover more areas. This might, however, turn out to be a lot of
6893 overhead for too little gain. */
6896 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
6897 Bufpos point, int no_regen)
6899 struct buffer *b = XBUFFER (w->buffer);
6900 line_start_cache_dynarr *cache = w->line_start_cache;
6901 Bufpos low_bound, high_bound;
6903 validate_line_start_cache (w);
6904 w->line_cache_validation_override++;
6905 updating_line_start_cache = 1;
6907 if (from < BUF_BEGV (b))
6908 from = BUF_BEGV (b);
6909 if (to > BUF_ZV (b))
6914 updating_line_start_cache = 0;
6915 w->line_cache_validation_override--;
6919 if (Dynarr_length (cache))
6921 low_bound = line_start_cache_start (w);
6922 high_bound = line_start_cache_end (w);
6924 /* Check to see if the desired range is already in the cache. */
6925 if (from >= low_bound && to <= high_bound)
6927 updating_line_start_cache = 0;
6928 w->line_cache_validation_override--;
6932 /* Check to make sure that the desired range is adjacent to the
6933 current cache. If not, invalidate the cache. */
6934 if (to < low_bound || from > high_bound)
6936 Dynarr_reset (cache);
6937 low_bound = high_bound = -1;
6942 low_bound = high_bound = -1;
6945 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
6947 /* This could be integrated into the next two sections, but it is easier
6948 to follow what's going on by having it separate. */
6953 update_internal_cache_list (w, DESIRED_DISP);
6954 if (!Dynarr_length (internal_cache))
6956 updating_line_start_cache = 0;
6957 w->line_cache_validation_override--;
6961 start = Dynarr_atp (internal_cache, 0)->start;
6963 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
6965 /* We aren't allowed to generate additional information to fill in
6966 gaps, so if the DESIRED structs don't overlap the cache, reset the
6968 if (Dynarr_length (cache))
6970 if (end < low_bound || start > high_bound)
6971 Dynarr_reset (cache);
6973 /* #### What should really happen if what we are doing is
6974 extending a line (the last line)? */
6975 if (Dynarr_length (cache) == 1
6976 && Dynarr_length (internal_cache) == 1)
6977 Dynarr_reset (cache);
6980 if (!Dynarr_length (cache))
6982 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
6983 Dynarr_length (internal_cache));
6984 updating_line_start_cache = 0;
6985 w->line_cache_validation_override--;
6989 /* An extra check just in case the calling function didn't pass in
6990 the bounds of the DESIRED structs in the first place. */
6991 if (start >= low_bound && end <= high_bound)
6993 updating_line_start_cache = 0;
6994 w->line_cache_validation_override--;
6998 /* At this point we know that the internal cache partially overlaps
7000 if (start < low_bound)
7002 int ic_elt = Dynarr_length (internal_cache) - 1;
7005 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7013 Dynarr_reset (cache);
7014 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7015 Dynarr_length (internal_cache));
7016 updating_line_start_cache = 0;
7017 w->line_cache_validation_override--;
7021 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7025 if (end > high_bound)
7029 while (ic_elt < Dynarr_length (internal_cache))
7031 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7037 if (!(ic_elt < Dynarr_length (internal_cache)))
7039 Dynarr_reset (cache);
7040 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7041 Dynarr_length (internal_cache));
7042 updating_line_start_cache = 0;
7043 w->line_cache_validation_override--;
7047 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7048 Dynarr_length (internal_cache) - ic_elt);
7051 updating_line_start_cache = 0;
7052 w->line_cache_validation_override--;
7056 if (!Dynarr_length (cache) || from < low_bound)
7058 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7060 int old_lb = low_bound;
7062 while (startp < old_lb || low_bound == -1)
7067 regenerate_window (w, startp, point, CMOTION_DISP);
7068 update_internal_cache_list (w, CMOTION_DISP);
7070 /* If this assert is triggered then regenerate_window failed
7071 to layout a single line. That is not supposed to be
7072 possible because we impose a minimum height on the buffer
7073 and override vertical clip when we are in here. */
7074 /* #### Ah, but it is because the window may temporarily
7075 exist but not have any lines at all if the minibuffer is
7076 real big. Look into that situation better. */
7077 if (!Dynarr_length (internal_cache))
7079 if (old_lb == -1 && low_bound == -1)
7081 updating_line_start_cache = 0;
7082 w->line_cache_validation_override--;
7086 assert (Dynarr_length (internal_cache));
7088 assert (startp == Dynarr_atp (internal_cache, 0)->start);
7090 ic_elt = Dynarr_length (internal_cache) - 1;
7091 if (low_bound != -1)
7095 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
7101 assert (ic_elt >= 0);
7103 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
7106 * Handle invisible text properly:
7107 * If the last line we're inserting has the same end as the
7108 * line before which it will be added, merge the two lines.
7110 if (Dynarr_length (cache) &&
7111 Dynarr_atp (internal_cache, ic_elt)->end ==
7112 Dynarr_atp (cache, marker)->end)
7114 Dynarr_atp (cache, marker)->start
7115 = Dynarr_atp (internal_cache, ic_elt)->start;
7116 Dynarr_atp (cache, marker)->height
7117 = Dynarr_atp (internal_cache, ic_elt)->height;
7121 if (ic_elt >= 0) /* we still have lines to add.. */
7123 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
7124 ic_elt + 1, marker);
7125 marker += (ic_elt + 1);
7128 if (startp < low_bound || low_bound == -1)
7130 startp = new_startp;
7131 if (startp > BUF_ZV (b))
7133 updating_line_start_cache = 0;
7134 w->line_cache_validation_override--;
7140 assert (Dynarr_length (cache));
7141 assert (from >= low_bound);
7143 /* Readjust the high_bound to account for any changes made while
7144 correcting the low_bound. */
7145 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7147 if (to > high_bound)
7149 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
7153 regenerate_window (w, startp, point, CMOTION_DISP);
7154 update_internal_cache_list (w, CMOTION_DISP);
7156 /* See comment above about regenerate_window failing. */
7157 assert (Dynarr_length (internal_cache));
7159 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7160 Dynarr_length (internal_cache));
7161 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7162 startp = high_bound + 1;
7164 while (to > high_bound);
7167 updating_line_start_cache = 0;
7168 w->line_cache_validation_override--;
7169 assert (to <= high_bound);
7173 /* Given x and y coordinates in characters, relative to a window,
7174 return the pixel location corresponding to those coordinates. The
7175 pixel location returned is the center of the given character
7176 position. The pixel values are generated relative to the window,
7179 The modeline is considered to be part of the window. */
7182 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
7183 int *pix_x, int *pix_y)
7185 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
7186 int num_disp_lines, modeline;
7188 int defheight, defwidth;
7190 XSETWINDOW (window, w);
7191 default_face_height_and_width (window, &defheight, &defwidth);
7193 /* If we get a bogus value indicating somewhere above or to the left of
7194 the window, use the first window line or character position
7201 num_disp_lines = Dynarr_length (dla);
7205 if (Dynarr_atp (dla, 0)->modeline)
7212 /* First check if the y position intersects the display lines. */
7213 if (char_y < num_disp_lines)
7215 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
7216 struct display_block *db = get_display_block_from_line (dl, TEXT);
7218 *pix_y = (dl->ypos - dl->ascent +
7219 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
7221 if (char_x < Dynarr_length (db->runes))
7223 struct rune *rb = Dynarr_atp (db->runes, char_x);
7225 *pix_x = rb->xpos + (rb->width >> 1);
7229 int last_rune = Dynarr_length (db->runes) - 1;
7230 struct rune *rb = Dynarr_atp (db->runes, last_rune);
7232 char_x -= last_rune;
7234 *pix_x = rb->xpos + rb->width;
7235 *pix_x += ((char_x - 1) * defwidth);
7236 *pix_x += (defwidth >> 1);
7241 /* It didn't intersect, so extrapolate. #### For now, we include the
7242 modeline in this since we don't have true character positions in
7245 if (!Dynarr_length (w->face_cachels))
7246 reset_face_cachels (w);
7248 char_y -= num_disp_lines;
7250 if (Dynarr_length (dla))
7252 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
7253 *pix_y = dl->ypos + dl->descent - dl->clip;
7256 *pix_y = WINDOW_TEXT_TOP (w);
7258 *pix_y += (char_y * defheight);
7259 *pix_y += (defheight >> 1);
7261 *pix_x = WINDOW_TEXT_LEFT (w);
7262 /* Don't adjust by one because this is still the unadjusted value. */
7263 *pix_x += (char_x * defwidth);
7264 *pix_x += (defwidth >> 1);
7267 if (*pix_x > w->pixel_left + w->pixel_width)
7268 *pix_x = w->pixel_left + w->pixel_width;
7269 if (*pix_y > w->pixel_top + w->pixel_height)
7270 *pix_y = w->pixel_top + w->pixel_height;
7272 *pix_x -= w->pixel_left;
7273 *pix_y -= w->pixel_top;
7276 /* Given a display line and a position, determine if there is a glyph
7277 there and return information about it if there is. */
7280 get_position_object (struct display_line *dl, Lisp_Object *obj1,
7281 Lisp_Object *obj2, int x_coord, int *low_x_coord,
7284 struct display_block *db;
7287 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
7289 /* We use get_next_display_block to get the actual display block
7290 that would be displayed at x_coord. */
7292 if (block == NO_BLOCK)
7295 db = Dynarr_atp (dl->display_blocks, block);
7297 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
7299 struct rune *rb = Dynarr_atp (db->runes, elt);
7301 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
7303 if (rb->type == RUNE_DGLYPH)
7305 *obj1 = rb->object.dglyph.glyph;
7306 *obj2 = rb->object.dglyph.extent;
7315 *low_x_coord = rb->xpos;
7317 *high_x_coord = rb->xpos + rb->width;
7324 #define UPDATE_CACHE_RETURN \
7326 d->pixel_to_glyph_cache.valid = 1; \
7327 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
7328 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
7329 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
7330 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
7331 d->pixel_to_glyph_cache.frame = f; \
7332 d->pixel_to_glyph_cache.col = *col; \
7333 d->pixel_to_glyph_cache.row = *row; \
7334 d->pixel_to_glyph_cache.obj_x = *obj_x; \
7335 d->pixel_to_glyph_cache.obj_y = *obj_y; \
7336 d->pixel_to_glyph_cache.w = *w; \
7337 d->pixel_to_glyph_cache.bufpos = *bufpos; \
7338 d->pixel_to_glyph_cache.closest = *closest; \
7339 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
7340 d->pixel_to_glyph_cache.obj1 = *obj1; \
7341 d->pixel_to_glyph_cache.obj2 = *obj2; \
7342 d->pixel_to_glyph_cache.retval = position; \
7343 RETURN_SANS_WARNINGS position; \
7346 /* Given x and y coordinates in pixels relative to a frame, return
7347 information about what is located under those coordinates.
7349 The return value will be one of:
7351 OVER_TOOLBAR: over one of the 4 frame toolbars
7352 OVER_MODELINE: over a modeline
7353 OVER_BORDER: over an internal border
7354 OVER_NOTHING: over the text area, but not over text
7355 OVER_OUTSIDE: outside of the frame border
7356 OVER_TEXT: over text in the text area
7362 -- nil if the coordinates are not over a glyph or a toolbar button.
7366 -- an extent, if the coordinates are over a glyph in the text area
7369 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
7370 equivalent coordinates relative to the upper-left corner of the glyph.
7372 If the coordinates are over a character, OBJ_X and OBJ_Y give the
7373 equivalent coordinates relative to the upper-left corner of the character.
7375 Otherwise, OBJ_X and OBJ_Y are undefined.
7379 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
7380 int *col, int *row, int *obj_x, int *obj_y,
7381 struct window **w, Bufpos *bufpos,
7382 Bufpos *closest, Charcount *modeline_closest,
7383 Lisp_Object *obj1, Lisp_Object *obj2)
7386 struct pixel_to_glyph_translation_cache *cache;
7388 int frm_left, frm_right, frm_top, frm_bottom;
7389 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
7390 int position = OVER_NOTHING;
7391 int device_check_failed = 0;
7392 display_line_dynarr *dla;
7394 /* This is a safety valve in case this got called with a frame in
7395 the middle of being deleted. */
7396 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
7398 device_check_failed = 1;
7399 d = NULL, cache = NULL; /* Warning suppression */
7403 d = XDEVICE (f->device);
7404 cache = &d->pixel_to_glyph_cache;
7407 if (!device_check_failed
7409 && cache->frame == f
7410 && cache->low_x_coord <= x_coord
7411 && cache->high_x_coord > x_coord
7412 && cache->low_y_coord <= y_coord
7413 && cache->high_y_coord > y_coord)
7417 *obj_x = cache->obj_x;
7418 *obj_y = cache->obj_y;
7420 *bufpos = cache->bufpos;
7421 *closest = cache->closest;
7422 *modeline_closest = cache->modeline_closest;
7423 *obj1 = cache->obj1;
7424 *obj2 = cache->obj2;
7426 return cache->retval;
7437 *modeline_closest = -1;
7441 low_x_coord = x_coord;
7442 high_x_coord = x_coord + 1;
7443 low_y_coord = y_coord;
7444 high_y_coord = y_coord + 1;
7447 if (device_check_failed)
7448 return OVER_NOTHING;
7450 frm_left = FRAME_LEFT_BORDER_END (f);
7451 frm_right = FRAME_RIGHT_BORDER_START (f);
7452 frm_top = FRAME_TOP_BORDER_END (f);
7453 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
7455 /* Check if the mouse is outside of the text area actually used by
7457 if (y_coord < frm_top)
7459 if (y_coord >= FRAME_TOP_BORDER_START (f))
7461 low_y_coord = FRAME_TOP_BORDER_START (f);
7462 high_y_coord = frm_top;
7463 position = OVER_BORDER;
7465 else if (y_coord >= 0)
7468 high_y_coord = FRAME_TOP_BORDER_START (f);
7469 position = OVER_TOOLBAR;
7473 low_y_coord = y_coord;
7475 position = OVER_OUTSIDE;
7478 else if (y_coord >= frm_bottom)
7480 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
7482 low_y_coord = frm_bottom;
7483 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
7484 position = OVER_BORDER;
7486 else if (y_coord < FRAME_PIXHEIGHT (f))
7488 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
7489 high_y_coord = FRAME_PIXHEIGHT (f);
7490 position = OVER_TOOLBAR;
7494 low_y_coord = FRAME_PIXHEIGHT (f);
7495 high_y_coord = y_coord;
7496 position = OVER_OUTSIDE;
7500 if (position != OVER_TOOLBAR && position != OVER_BORDER)
7502 if (x_coord < frm_left)
7504 if (x_coord >= FRAME_LEFT_BORDER_START (f))
7506 low_x_coord = FRAME_LEFT_BORDER_START (f);
7507 high_x_coord = frm_left;
7508 position = OVER_BORDER;
7510 else if (x_coord >= 0)
7513 high_x_coord = FRAME_LEFT_BORDER_START (f);
7514 position = OVER_TOOLBAR;
7518 low_x_coord = x_coord;
7520 position = OVER_OUTSIDE;
7523 else if (x_coord >= frm_right)
7525 if (x_coord < FRAME_RIGHT_BORDER_END (f))
7527 low_x_coord = frm_right;
7528 high_x_coord = FRAME_RIGHT_BORDER_END (f);
7529 position = OVER_BORDER;
7531 else if (x_coord < FRAME_PIXWIDTH (f))
7533 low_x_coord = FRAME_RIGHT_BORDER_END (f);
7534 high_x_coord = FRAME_PIXWIDTH (f);
7535 position = OVER_TOOLBAR;
7539 low_x_coord = FRAME_PIXWIDTH (f);
7540 high_x_coord = x_coord;
7541 position = OVER_OUTSIDE;
7546 #ifdef HAVE_TOOLBARS
7547 if (position == OVER_TOOLBAR)
7549 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
7552 UPDATE_CACHE_RETURN;
7554 #endif /* HAVE_TOOLBARS */
7556 /* We still have to return the window the pointer is next to and its
7557 relative y position even if it is outside the x boundary. */
7558 if (x_coord < frm_left)
7560 else if (x_coord > frm_right)
7561 x_coord = frm_right;
7563 /* Same in reverse. */
7564 if (y_coord < frm_top)
7566 else if (y_coord > frm_bottom)
7567 y_coord = frm_bottom;
7569 /* Find what window the given coordinates are actually in. */
7570 window = f->root_window;
7571 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
7573 /* If we didn't find a window, we're done. */
7576 UPDATE_CACHE_RETURN;
7578 else if (position != OVER_NOTHING)
7581 *modeline_closest = -1;
7583 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
7586 UPDATE_CACHE_RETURN;
7590 /* Check if the window is a minibuffer but isn't active. */
7591 if (MINI_WINDOW_P (*w) && !minibuf_level)
7593 /* Must reset the window value since some callers will ignore
7594 the return value if it is set. */
7596 UPDATE_CACHE_RETURN;
7599 /* See if the point is over window vertical divider */
7600 if (window_needs_vertical_divider (*w))
7602 int div_x_high = WINDOW_RIGHT (*w);
7603 int div_x_low = div_x_high - window_divider_width (*w);
7604 int div_y_high = WINDOW_BOTTOM (*w);
7605 int div_y_low = WINDOW_TOP (*w);
7607 if (div_x_low < x_coord && x_coord <= div_x_high &&
7608 div_y_low < y_coord && y_coord <= div_y_high)
7610 low_x_coord = div_x_low;
7611 high_x_coord = div_x_high;
7612 low_y_coord = div_y_low;
7613 high_y_coord = div_y_high;
7614 position = OVER_V_DIVIDER;
7615 UPDATE_CACHE_RETURN;
7619 dla = window_display_lines (*w, CURRENT_DISP);
7621 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
7623 int really_over_nothing = 0;
7624 struct display_line *dl = Dynarr_atp (dla, *row);
7626 if ((int) (dl->ypos - dl->ascent) <= y_coord
7627 && y_coord <= (int) (dl->ypos + dl->descent))
7629 int check_margin_glyphs = 0;
7630 struct display_block *db = get_display_block_from_line (dl, TEXT);
7631 struct rune *rb = 0;
7633 if (x_coord < dl->bounds.left_white
7634 || x_coord >= dl->bounds.right_white)
7635 check_margin_glyphs = 1;
7637 low_y_coord = dl->ypos - dl->ascent;
7638 high_y_coord = dl->ypos + dl->descent + 1;
7640 if (position == OVER_BORDER
7641 || position == OVER_OUTSIDE
7642 || check_margin_glyphs)
7644 int x_check, left_bound;
7646 if (check_margin_glyphs)
7649 left_bound = dl->bounds.left_white;
7653 x_check = high_x_coord;
7654 left_bound = frm_left;
7657 if (Dynarr_length (db->runes))
7659 if (x_check <= left_bound)
7662 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
7664 *closest = Dynarr_atp (db->runes, 0)->bufpos;
7670 Dynarr_atp (db->runes,
7671 Dynarr_length (db->runes) - 1)->bufpos;
7674 Dynarr_atp (db->runes,
7675 Dynarr_length (db->runes) - 1)->bufpos;
7679 *modeline_closest += dl->offset;
7681 *closest += dl->offset;
7685 /* #### What should be here. */
7687 *modeline_closest = 0;
7692 if (check_margin_glyphs)
7694 if (x_coord < dl->bounds.left_in
7695 || x_coord >= dl->bounds.right_in)
7697 /* If we are over the outside margins then we
7698 know the loop over the text block isn't going
7699 to accomplish anything. So we go ahead and
7700 set what information we can right here and
7703 *obj_y = y_coord - (dl->ypos - dl->ascent);
7704 get_position_object (dl, obj1, obj2, x_coord,
7705 &low_x_coord, &high_x_coord);
7707 UPDATE_CACHE_RETURN;
7711 UPDATE_CACHE_RETURN;
7714 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
7716 int past_end = (*col == Dynarr_length (db->runes));
7719 rb = Dynarr_atp (db->runes, *col);
7722 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
7727 rb = Dynarr_atp (db->runes, *col);
7730 *bufpos = rb->bufpos + dl->offset;
7731 low_x_coord = rb->xpos;
7732 high_x_coord = rb->xpos + rb->width;
7734 if (rb->type == RUNE_DGLYPH)
7738 /* Find the first character after the glyph. */
7739 while (elt < Dynarr_length (db->runes))
7741 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
7745 (Dynarr_atp (db->runes, elt)->bufpos +
7749 (Dynarr_atp (db->runes, elt)->bufpos +
7757 /* In this case we failed to find a non-glyph
7758 character so we return the last position
7759 displayed on the line. */
7760 if (elt == Dynarr_length (db->runes))
7763 *modeline_closest = dl->end_bufpos + dl->offset;
7765 *closest = dl->end_bufpos + dl->offset;
7766 really_over_nothing = 1;
7772 *modeline_closest = rb->bufpos + dl->offset;
7774 *closest = rb->bufpos + dl->offset;
7779 *row = window_displayed_height (*w);
7781 if (position == OVER_NOTHING)
7782 position = OVER_MODELINE;
7784 if (rb->type == RUNE_DGLYPH)
7786 *obj1 = rb->object.dglyph.glyph;
7787 *obj2 = rb->object.dglyph.extent;
7789 else if (rb->type == RUNE_CHAR)
7800 UPDATE_CACHE_RETURN;
7803 || (rb->type == RUNE_CHAR
7804 && rb->object.chr.ch == '\n'))
7807 /* At this point we may have glyphs in the right
7809 if (check_margin_glyphs)
7810 get_position_object (dl, obj1, obj2, x_coord,
7811 &low_x_coord, &high_x_coord);
7812 UPDATE_CACHE_RETURN;
7817 if (rb->type == RUNE_DGLYPH)
7819 *obj1 = rb->object.dglyph.glyph;
7820 *obj2 = rb->object.dglyph.extent;
7822 else if (rb->type == RUNE_CHAR)
7833 *obj_x = x_coord - rb->xpos;
7834 *obj_y = y_coord - (dl->ypos - dl->ascent);
7836 /* At this point we may have glyphs in the left
7838 if (check_margin_glyphs)
7839 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
7841 if (position == OVER_NOTHING && !really_over_nothing)
7842 position = OVER_TEXT;
7844 UPDATE_CACHE_RETURN;
7851 *row = Dynarr_length (dla) - 1;
7852 if (FRAME_WIN_P (f))
7854 int bot_elt = Dynarr_length (dla) - 1;
7858 struct display_line *dl = Dynarr_atp (dla, bot_elt);
7859 int adj_area = y_coord - (dl->ypos + dl->descent);
7863 XSETWINDOW (lwin, *w);
7864 default_face_height_and_width (lwin, 0, &defheight);
7866 *row += (adj_area / defheight);
7870 /* #### This should be checked out some more to determine what
7871 should really be going on. */
7872 if (!MARKERP ((*w)->start[CURRENT_DISP]))
7875 *closest = end_of_last_line (*w,
7876 marker_position ((*w)->start[CURRENT_DISP]));
7878 UPDATE_CACHE_RETURN;
7880 #undef UPDATE_CACHE_RETURN
7883 /***************************************************************************/
7885 /* Lisp functions */
7887 /***************************************************************************/
7889 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
7890 Ensure that all minibuffers are correctly showing the echo area.
7894 Lisp_Object devcons, concons;
7896 DEVICE_LOOP_NO_BREAK (devcons, concons)
7898 struct device *d = XDEVICE (XCAR (devcons));
7899 Lisp_Object frmcons;
7901 DEVICE_FRAME_LOOP (frmcons, d)
7903 struct frame *f = XFRAME (XCAR (frmcons));
7905 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
7907 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
7909 * If the frame size has changed, there may be random
7910 * chud on the screen left from previous messages
7911 * because redisplay_frame hasn't been called yet.
7912 * Clear the screen to get rid of the potential mess.
7914 if (f->echo_area_garbaged)
7916 DEVMETH (d, clear_frame, (f));
7917 f->echo_area_garbaged = 0;
7919 redisplay_window (window, 0);
7920 call_redisplay_end_triggers (XWINDOW (window), 0);
7924 /* We now call the output_end routine for tty frames. We delay
7925 doing so in order to avoid cursor flicker. So much for 100%
7927 if (DEVICE_TTY_P (d))
7928 DEVMETH (d, output_end, (d));
7935 restore_disable_preemption_value (Lisp_Object value)
7937 disable_preemption = XINT (value);
7941 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
7942 Clear frame FRAME and output again what is supposed to appear on it.
7943 FRAME defaults to the selected frame if omitted.
7944 Normally, redisplay is preempted as normal if input arrives. However,
7945 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7946 input and is guaranteed to proceed to completion.
7948 (frame, no_preempt))
7950 struct frame *f = decode_frame (frame);
7951 int count = specpdl_depth ();
7953 if (!NILP (no_preempt))
7955 record_unwind_protect (restore_disable_preemption_value,
7956 make_int (disable_preemption));
7957 disable_preemption++;
7961 redisplay_frame (f, 1);
7963 return unbind_to (count, Qnil);
7966 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
7967 Ensure that FRAME's contents are correctly displayed.
7968 This differs from `redraw-frame' in that it only redraws what needs to
7969 be updated, as opposed to unconditionally clearing and redrawing
7971 FRAME defaults to the selected frame if omitted.
7972 Normally, redisplay is preempted as normal if input arrives. However,
7973 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7974 input and is guaranteed to proceed to completion.
7976 (frame, no_preempt))
7978 struct frame *f = decode_frame (frame);
7979 int count = specpdl_depth ();
7981 if (!NILP (no_preempt))
7983 record_unwind_protect (restore_disable_preemption_value,
7984 make_int (disable_preemption));
7985 disable_preemption++;
7988 redisplay_frame (f, 1);
7990 return unbind_to (count, Qnil);
7993 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
7994 Clear device DEVICE and output again what is supposed to appear on it.
7995 DEVICE defaults to the selected device if omitted.
7996 Normally, redisplay is preempted as normal if input arrives. However,
7997 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7998 input and is guaranteed to proceed to completion.
8000 (device, no_preempt))
8002 struct device *d = decode_device (device);
8003 Lisp_Object frmcons;
8004 int count = specpdl_depth ();
8006 if (!NILP (no_preempt))
8008 record_unwind_protect (restore_disable_preemption_value,
8009 make_int (disable_preemption));
8010 disable_preemption++;
8013 DEVICE_FRAME_LOOP (frmcons, d)
8015 XFRAME (XCAR (frmcons))->clear = 1;
8017 redisplay_device (d);
8019 return unbind_to (count, Qnil);
8022 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8023 Ensure that DEVICE's contents are correctly displayed.
8024 This differs from `redraw-device' in that it only redraws what needs to
8025 be updated, as opposed to unconditionally clearing and redrawing
8027 DEVICE defaults to the selected device if omitted.
8028 Normally, redisplay is preempted as normal if input arrives. However,
8029 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8030 input and is guaranteed to proceed to completion.
8032 (device, no_preempt))
8034 struct device *d = decode_device (device);
8035 int count = specpdl_depth ();
8037 if (!NILP (no_preempt))
8039 record_unwind_protect (restore_disable_preemption_value,
8040 make_int (disable_preemption));
8041 disable_preemption++;
8044 redisplay_device (d);
8046 return unbind_to (count, Qnil);
8049 /* Big lie. Big lie. This will force all modelines to be updated
8050 regardless if the all flag is set or not. It remains in existence
8051 solely for backwards compatibility. */
8052 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8053 Force the modeline of the current buffer to be redisplayed.
8054 With optional non-nil ALL, force redisplay of all modelines.
8058 MARK_MODELINE_CHANGED;
8062 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8063 Force an immediate update of the cursor on FRAME.
8064 FRAME defaults to the selected frame if omitted.
8068 redisplay_redraw_cursor (decode_frame (frame), 1);
8073 /***************************************************************************/
8075 /* Lisp-variable change triggers */
8077 /***************************************************************************/
8080 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
8083 /* Nothing to be done? */
8087 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
8088 Lisp_Object in_object, int flags)
8090 /* #### clip_changed should really be renamed something like
8091 global_redisplay_change. */
8097 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8100 if (WINDOWP (locale))
8102 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
8104 else if (FRAMEP (locale))
8106 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
8108 else if (DEVICEP (locale))
8110 Lisp_Object frmcons;
8111 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
8112 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8114 else if (CONSOLEP (locale))
8116 Lisp_Object frmcons, devcons;
8117 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
8118 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8120 else /* global or buffer */
8122 Lisp_Object frmcons, devcons, concons;
8123 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
8124 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8129 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
8132 if (XFRAME (w->frame)->init_finished)
8133 Fforce_cursor_redisplay (w->frame);
8136 #ifdef MEMORY_USAGE_STATS
8139 /***************************************************************************/
8141 /* memory usage computation */
8143 /***************************************************************************/
8146 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
8148 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8152 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
8153 struct overhead_stats *ovstats)
8160 total = Dynarr_memory_usage (dyn, ovstats);
8161 for (i = 0; i < Dynarr_largest (dyn); i++)
8162 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
8168 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
8169 struct overhead_stats *ovstats)
8171 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8175 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
8176 struct overhead_stats *ovstats)
8183 total = Dynarr_memory_usage (dyn, ovstats);
8184 for (i = 0; i < Dynarr_largest (dyn); i++)
8186 struct display_line *dl = &Dynarr_at (dyn, i);
8187 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
8188 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
8189 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
8196 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
8197 struct overhead_stats *ovstats)
8199 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8202 #endif /* MEMORY_USAGE_STATS */
8205 /***************************************************************************/
8207 /* initialization */
8209 /***************************************************************************/
8212 init_redisplay (void)
8214 disable_preemption = 0;
8215 preemption_count = 0;
8216 max_preempts = INIT_MAX_PREEMPTS;
8220 cmotion_display_lines = Dynarr_new (display_line);
8221 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
8222 formatted_string_emchar_dynarr = Dynarr_new (Emchar);
8223 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
8224 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
8225 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
8226 internal_cache = Dynarr_new (line_start_cache);
8227 xzero (formatted_string_display_line);
8230 /* window system is nil when in -batch mode */
8231 if (!initialized || noninteractive)
8234 /* If the user wants to use a window system, we shouldn't bother
8235 initializing the terminal. This is especially important when the
8236 terminal is so dumb that emacs gives up before and doesn't bother
8237 using the window system.
8239 If the DISPLAY environment variable is set, try to use X, and die
8240 with an error message if that doesn't work. */
8242 #ifdef HAVE_X_WINDOWS
8243 if (!strcmp (display_use, "x"))
8245 /* Some stuff checks this way early. */
8246 Vwindow_system = Qx;
8247 Vinitial_window_system = Qx;
8250 #endif /* HAVE_X_WINDOWS */
8252 #ifdef HAVE_MS_WINDOWS
8253 if (!strcmp (display_use, "mswindows"))
8255 /* Some stuff checks this way early. */
8256 Vwindow_system = Qmswindows;
8257 Vinitial_window_system = Qmswindows;
8260 #endif /* HAVE_MS_WINDOWS */
8263 /* If no window system has been specified, try to use the terminal. */
8266 stderr_out ("XEmacs: standard input is not a tty\n");
8270 /* Look at the TERM variable */
8271 if (!getenv ("TERM"))
8273 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
8277 Vinitial_window_system = Qtty;
8279 #else /* not HAVE_TTY */
8280 /* No DISPLAY specified, and no TTY support. */
8281 stderr_out ("XEmacs: Cannot open display.\n\
8282 Please set the environmental variable DISPLAY to an appropriate value.\n");
8289 syms_of_redisplay (void)
8291 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
8292 #ifndef INHIBIT_REDISPLAY_HOOKS
8293 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
8294 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
8295 #endif /* INHIBIT_REDISPLAY_HOOKS */
8296 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
8297 defsymbol (&Qbar_cursor, "bar-cursor");
8298 defsymbol (&Qwindow_scroll_functions, "window-scroll-functions");
8299 defsymbol (&Qredisplay_end_trigger_functions,
8300 "redisplay-end-trigger-functions");
8302 DEFSUBR (Fredisplay_echo_area);
8303 DEFSUBR (Fredraw_frame);
8304 DEFSUBR (Fredisplay_frame);
8305 DEFSUBR (Fredraw_device);
8306 DEFSUBR (Fredisplay_device);
8307 DEFSUBR (Fredraw_modeline);
8308 DEFSUBR (Fforce_cursor_redisplay);
8312 vars_of_redisplay (void)
8315 staticpro (&last_arrow_position);
8316 staticpro (&last_arrow_string);
8317 last_arrow_position = Qnil;
8318 last_arrow_string = Qnil;
8321 updating_line_start_cache = 0;
8323 /* #### Probably temporary */
8324 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
8325 \(Temporary) Setting this will impact the performance of the internal
8328 cache_adjustment = 2;
8330 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
8331 Minimum pixel height for clipped bottom display line.
8332 A clipped line shorter than this won't be displayed.
8334 redisplay_variable_changed);
8337 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
8338 Minimum visible area for clipped glyphs at right boundary.
8339 Clipped glyphs shorter than this won't be displayed.
8340 Only pixmap glyph instances are currently allowed to be clipped.
8342 redisplay_variable_changed);
8343 horizontal_clip = 5;
8345 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
8346 String displayed by modeline-format's "%m" specification.
8348 Vglobal_mode_string = Qnil;
8350 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
8351 Marker for where to display an arrow on top of the buffer text.
8352 This must be the beginning of a line in order to work.
8353 See also `overlay-arrow-string'.
8355 redisplay_variable_changed);
8356 Voverlay_arrow_position = Qnil;
8358 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
8359 String to display as an arrow. See also `overlay-arrow-position'.
8361 redisplay_variable_changed);
8362 Voverlay_arrow_string = Qnil;
8364 DEFVAR_INT ("scroll-step", &scroll_step /*
8365 *The number of lines to try scrolling a window by when point moves out.
8366 If that fails to bring point back on frame, point is centered instead.
8367 If this is zero, point is always centered after it moves off screen.
8371 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
8372 *Scroll up to this many lines, to bring point back on screen.
8374 scroll_conservatively = 0;
8376 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
8377 &truncate_partial_width_windows /*
8378 *Non-nil means truncate lines in all windows less than full frame wide.
8380 redisplay_variable_changed);
8381 truncate_partial_width_windows = 1;
8383 DEFVAR_BOOL ("visible-bell", &visible_bell /*
8384 *Non-nil means try to flash the frame to represent a bell.
8388 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
8389 *Non-nil means no need to redraw entire frame after suspending.
8390 A non-nil value is useful if the terminal can automatically preserve
8391 Emacs's frame display when you reenter Emacs.
8392 It is up to you to set this variable if your terminal can do that.
8394 no_redraw_on_reenter = 0;
8396 DEFVAR_LISP ("window-system", &Vwindow_system /*
8397 A symbol naming the window-system under which Emacs is running,
8398 such as `x', or nil if emacs is running on an ordinary terminal.
8400 Do not use this variable, except for GNU Emacs compatibility, as it
8401 gives wrong values in a multi-device environment. Use `console-type'
8404 Vwindow_system = Qnil;
8406 /* #### Temporary shit until window-system is eliminated. */
8407 DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /*
8410 Vinitial_window_system = Qnil;
8412 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
8413 Non-nil means put cursor in minibuffer, at end of any message there.
8415 cursor_in_echo_area = 0;
8417 /* #### Shouldn't this be generalized as follows:
8419 if nil, use block cursor.
8420 if a number, use a bar cursor of that width.
8421 Otherwise, use a 1-pixel bar cursor.
8423 #### Or better yet, this variable should be trashed entirely
8424 (use a Lisp-magic variable to maintain compatibility)
8425 and a specifier `cursor-shape' added, which allows a block
8426 cursor, a bar cursor, a flashing block or bar cursor,
8427 maybe a caret cursor, etc. */
8429 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
8430 Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
8434 #ifndef INHIBIT_REDISPLAY_HOOKS
8435 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
8436 Function or functions to run before every redisplay.
8437 Functions on this hook must be careful to avoid signalling errors!
8439 Vpre_redisplay_hook = Qnil;
8441 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
8442 Function or functions to run after every redisplay.
8443 Functions on this hook must be careful to avoid signalling errors!
8445 Vpost_redisplay_hook = Qnil;
8446 #endif /* INHIBIT_REDISPLAY_HOOKS */
8448 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
8449 Bump this to tell the C code to call `display-warning-buffer'
8450 at next redisplay. You should not normally change this; the function
8451 `display-warning' automatically does this at appropriate times.
8453 display_warning_tick = 0;
8455 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
8456 Non-nil means inhibit display of warning messages.
8457 You should *bind* this, not set it. Any pending warning messages
8458 will be displayed when the binding no longer applies.
8460 /* reset to 0 by startup.el after the splash screen has displayed.
8461 This way, the warnings don't obliterate the splash screen. */
8462 inhibit_warning_display = 1;
8464 DEFVAR_LISP ("window-size-change-functions",
8465 &Vwindow_size_change_functions /*
8466 Not currently implemented.
8467 Functions called before redisplay, if window sizes have changed.
8468 The value should be a list of functions that take one argument.
8469 Just before redisplay, for each frame, if any of its windows have changed
8470 size since the last redisplay, or have been split or deleted,
8471 all the functions in the list are called, with the frame as argument.
8473 Vwindow_size_change_functions = Qnil;
8475 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
8476 Not currently implemented.
8477 Functions to call before redisplaying a window with scrolling.
8478 Each function is called with two arguments, the window
8479 and its new display-start position. Note that the value of `window-end'
8480 is not valid when these functions are called.
8482 Vwindow_scroll_functions = Qnil;
8484 DEFVAR_LISP ("redisplay-end-trigger-functions",
8485 &Vredisplay_end_trigger_functions /*
8486 See `set-window-redisplay-end-trigger'.
8488 Vredisplay_end_trigger_functions = Qnil;
8490 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
8491 *Non-nil means column display number starts at 1.
8493 column_number_start_at_one = 0;
8497 specifier_vars_of_redisplay (void)
8499 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
8500 *Width of left margin.
8501 This is a specifier; use `set-specifier' to change it.
8503 Vleft_margin_width = Fmake_specifier (Qnatnum);
8504 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
8505 set_specifier_caching (Vleft_margin_width,
8506 slot_offset (struct window, left_margin_width),
8507 some_window_value_changed,
8508 slot_offset (struct frame, left_margin_width),
8509 margin_width_changed_in_frame);
8511 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
8512 *Width of right margin.
8513 This is a specifier; use `set-specifier' to change it.
8515 Vright_margin_width = Fmake_specifier (Qnatnum);
8516 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
8517 set_specifier_caching (Vright_margin_width,
8518 slot_offset (struct window, right_margin_width),
8519 some_window_value_changed,
8520 slot_offset (struct frame, right_margin_width),
8521 margin_width_changed_in_frame);
8523 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
8524 *Minimum ascent height of lines.
8525 This is a specifier; use `set-specifier' to change it.
8527 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
8528 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
8529 set_specifier_caching (Vminimum_line_ascent,
8530 slot_offset (struct window, minimum_line_ascent),
8531 some_window_value_changed,
8534 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
8535 *Minimum descent height of lines.
8536 This is a specifier; use `set-specifier' to change it.
8538 Vminimum_line_descent = Fmake_specifier (Qnatnum);
8539 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
8540 set_specifier_caching (Vminimum_line_descent,
8541 slot_offset (struct window, minimum_line_descent),
8542 some_window_value_changed,
8545 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
8546 *Non-nil means use the left outside margin as extra whitespace when
8547 displaying 'whitespace or 'inside-margin glyphs.
8548 This is a specifier; use `set-specifier' to change it.
8550 Vuse_left_overflow = Fmake_specifier (Qboolean);
8551 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
8552 set_specifier_caching (Vuse_left_overflow,
8553 slot_offset (struct window, use_left_overflow),
8554 some_window_value_changed,
8557 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
8558 *Non-nil means use the right outside margin as extra whitespace when
8559 displaying 'whitespace or 'inside-margin glyphs.
8560 This is a specifier; use `set-specifier' to change it.
8562 Vuse_right_overflow = Fmake_specifier (Qboolean);
8563 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
8564 set_specifier_caching (Vuse_right_overflow,
8565 slot_offset (struct window, use_right_overflow),
8566 some_window_value_changed,
8569 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
8570 *Non-nil means the text cursor is visible (this is usually the case).
8571 This is a specifier; use `set-specifier' to change it.
8573 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
8574 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
8575 set_specifier_caching (Vtext_cursor_visible_p,
8576 slot_offset (struct window, text_cursor_visible_p),
8577 text_cursor_visible_p_changed,