1 /* Display generation from window structure and buffer text.
2 Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois.
3 Copyright (C) 1995 Free Software Foundation, Inc.
4 Copyright (C) 1995, 1996 Ben Wing.
5 Copyright (C) 1995 Sun Microsystems, Inc.
6 Copyright (C) 1996 Chuck Thompson.
8 This file is part of XEmacs.
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 /* Synched up with: Not in FSF. */
27 /* Author: Chuck Thompson */
29 /* Fixed up by Ben Wing for Mule */
31 /* This file has been Mule-ized. */
33 /*****************************************************************************
34 The Golden Rules of Redisplay
36 First: It Is Better To Be Correct Than Fast
37 Second: Thou Shalt Not Run Elisp From Within Redisplay
38 Third: It Is Better To Be Fast Than Not To Be
39 ****************************************************************************/
59 #include "redisplay.h"
62 #include "line-number.h"
64 #include "file-coding.h"
68 #include "console-tty.h"
70 #include <unistd.h> /* for isatty() */
74 /* Note: We have to be careful throughout this code to properly handle
75 and differentiate between Bufbytes and Emchars.
77 Since strings are generally composed of Bufbytes, I've taken the tack
78 that any contiguous set of Bufbytes is called a "string", while
79 any contiguous set of Emchars is called an "array". */
81 /* Return value to indicate a failure by an add_*_rune routine to add
82 a rune, but no propagation information needs to be returned. */
83 #define ADD_FAILED (prop_block_dynarr *) 1
85 #define BEGIN_GLYPHS 0
88 #define RIGHT_GLYPHS 3
90 /* Set the vertical clip to 0 if we are currently updating the line
91 start cache. Otherwise for buffers of line height 1 it may fail to
92 be able to work properly because regenerate_window will not layout
94 #define VERTICAL_CLIP(w, display) \
95 (updating_line_start_cache \
97 : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
101 /* The following structures are completely private to redisplay.c so
102 we put them here instead of in a header file, for modularity. */
104 /* NOTE: Bytinds not Bufpos's in this structure. */
106 typedef struct position_redisplay_data_type
108 /* This information is normally filled in by the create_*_block
109 routines and is used by the add_*_rune routines. */
111 /* if we are working with strings rather than buffers we need a
112 handle to the string */
115 struct display_block *db;
116 struct display_line *dl;
117 Emchar ch; /* Character that is to be added. This is
118 used to communicate this information to
119 add_emchar_rune(). */
120 Lisp_Object last_charset; /* The charset of the previous character.
121 Used to optimize some lookups -- we
122 only have to do some things when
123 the charset changes. */
124 face_index last_findex; /* The face index of the previous character.
125 Needed to ensure the validity of the
126 last_charset optimization. */
128 int last_char_width; /* The width of the previous character. */
129 int font_is_bogus; /* If true, it means we couldn't instantiate
130 the font for this charset, so we substitute
131 ~'s from the ASCII charset. */
136 int blank_width; /* Width of the blank that is to be added.
137 This is used to communicate this information
140 This is also used rather cheesily to
141 communicate the width of the eol-cursor-size
142 blank that exists at the end of the line.
143 add_emchar_rune() is called cheesily with
144 the non-printing char '\n', which is stuck
145 in the output routines with its width being
147 Bytind bi_cursor_bufpos;/* This stores the buffer position of the cursor. */
148 unsigned int cursor_type :3;
149 int cursor_x; /* rune block cursor is at */
150 int start_col; /* Number of character columns (each column has
151 a width of the default char width) that still
152 need to be skipped. This is used for horizontal
153 scrolling, where a certain number of columns
154 (those off the left side of the screen) need
155 to be skipped before anything is displayed. */
156 Bytind bi_start_col_enabled;
157 int start_col_xoffset; /* Number of pixels that still need to
158 be skipped. This is used for
159 horizontal scrolling of glyphs, where we want
160 to be able to scroll over part of the glyph. */
162 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
163 glyph differs from space_width (w).
164 0 if no hscroll glyph was used,
165 i.e. the window is not scrolled
166 horizontally. Used in tab
169 /* Information about the face the text should be displayed in and
170 any begin-glyphs and end-glyphs. */
171 struct extent_fragment *ef;
174 /* The height of a pixmap may either be predetermined if the user
175 has set a baseline value, or it may be dependent on whatever the
176 line ascent and descent values end up being, based just on font
177 information. In the first case we can immediately update the
178 values, thus their inclusion here. In the last case we cannot
179 determine the actual contribution to the line height until we
180 have finished laying out all text on the line. Thus we propagate
181 the max height of such pixmaps and do a final calculation after
182 all text has been added to the line. */
185 int max_pixmap_height;
187 Lisp_Object result_str; /* String where we put the result of
188 generating a formatted string in the modeline. */
189 int is_modeline; /* Non-zero if we're generating the modeline. */
190 Charcount modeline_charpos; /* Number of chars used in result_str so far;
191 corresponds to bytepos. */
192 Bytecount bytepos; /* Number of bytes used in result_str so far.
193 We don't actually copy the bytes into result_str
194 until the end because we don't know how big the
195 string is going to be until then. */
206 /* Data that should be propagated to the next line. Either a single
207 Emchar or a string of Bufbyte's.
209 The actual data that is propagated ends up as a Dynarr of these
212 #### It's unclean that both Emchars and Bufbytes are here.
215 typedef struct prop_block prop_block;
225 Bytecount len; /* length of the string. */
231 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
232 unsigned int cursor_type :3;
245 Dynarr_declare (prop_block);
249 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
250 Charcount pos, Charcount min_pos,
251 Charcount max_pos, Lisp_Object elt,
252 int depth, int max_pixsize,
253 face_index findex, int type,
255 Lisp_Object cur_ext);
256 static prop_block_dynarr *add_glyph_rune (pos_data *data,
257 struct glyph_block *gb,
258 int pos_type, int allow_cursor,
259 struct glyph_cachel *cachel);
260 static Bytind create_text_block (struct window *w, struct display_line *dl,
261 Bytind bi_start_pos, prop_block_dynarr **prop,
263 static int create_overlay_glyph_block (struct window *w,
264 struct display_line *dl);
265 static void create_left_glyph_block (struct window *w,
266 struct display_line *dl,
268 static void create_right_glyph_block (struct window *w,
269 struct display_line *dl);
270 static void redisplay_windows (Lisp_Object window, int skip_selected);
271 static void decode_mode_spec (struct window *w, Emchar spec, int type);
272 static void free_display_line (struct display_line *dl);
273 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
274 Bufpos point, int no_regen);
275 static int point_visible (struct window *w, Bufpos point, int type);
277 /* This used to be 10 but 30 seems to give much better performance. */
278 #define INIT_MAX_PREEMPTS 30
279 static int max_preempts;
281 #define REDISPLAY_PREEMPTION_CHECK \
284 (!disable_preemption && \
285 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
286 (!INTERACTIVE || detect_input_pending ()))))
289 * Redisplay global variables.
292 /* We need a third set of display structures for the cursor motion
293 routines. We used to just give each window a third set. However,
294 we always fully regenerate the structures when needed so there
295 isn't any reason we need more than a single set. */
296 display_line_dynarr *cmotion_display_lines;
298 /* We store the extents that we need to generate in a Dynarr and then
299 frob them all on at the end of generating the string. We do it
300 this way rather than adding them as we generate the string because
301 we don't store the text into the resulting string until we're done
302 (to avoid having to resize the string multiple times), and we don't
303 want to go around adding extents to a string when the extents might
304 stretch off the end of the string. */
305 static EXTENT_dynarr *formatted_string_extent_dynarr;
306 static Bytecount_dynarr *formatted_string_extent_start_dynarr;
307 static Bytecount_dynarr *formatted_string_extent_end_dynarr;
310 /* #### probably temporary */
311 int cache_adjustment;
313 /* This holds a string representing the text corresponding to a single
315 static Bufbyte_dynarr *mode_spec_bufbyte_string;
317 int in_display; /* 1 if in redisplay. */
319 int disable_preemption; /* Used for debugging redisplay and for
322 /* We only allow max_preempts preemptions before we force a redisplay. */
323 static int preemption_count;
325 /* Minimum pixel height of clipped bottom display line. */
328 /* Minimum visible pixel width of clipped glyphs at right margin. */
331 /* Set if currently inside update_line_start_cache. */
332 static int updating_line_start_cache;
334 /* Nonzero means reading single-character input with prompt
335 so put cursor on minibuffer after the prompt. */
336 int cursor_in_echo_area;
337 Lisp_Object Qcursor_in_echo_area;
339 /* Nonzero means truncate lines in all windows less wide than the frame */
340 int truncate_partial_width_windows;
342 /* non-nil if a buffer has changed since the last time redisplay completed */
344 int buffers_changed_set;
346 /* non-nil if hscroll has changed somewhere or a buffer has been
347 narrowed or widened */
349 int clip_changed_set;
351 /* non-nil if any extent has changed since the last time redisplay completed */
353 int extents_changed_set;
355 /* non-nil if any face has changed since the last time redisplay completed */
358 /* Nonzero means some frames have been marked as garbaged */
361 /* non-zero if any of the builtin display glyphs (continuation,
362 hscroll, control-arrow, etc) is in need of updating
365 int glyphs_changed_set;
367 /* non-zero if any displayed subwindow is in need of updating
369 int subwindows_changed;
370 int subwindows_changed_set;
372 /* non-zero if any displayed subwindow is in need of updating
374 int subwindows_state_changed;
375 int subwindows_state_changed_set;
377 /* This variable is 1 if the icon has to be updated.
378 It is set to 1 when `frame-icon-glyph' changes. */
380 int icon_changed_set;
382 /* This variable is 1 if the menubar widget has to be updated.
383 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
386 int menubar_changed_set;
388 /* true iff we should redraw the modelines on the next redisplay */
389 int modeline_changed;
390 int modeline_changed_set;
392 /* non-nil if point has changed in some buffer since the last time
393 redisplay completed */
395 int point_changed_set;
397 /* non-nil if some frame has changed its size */
400 /* non-nil if some device has signaled that it wants to change size */
401 int asynch_device_change_pending;
403 /* non-nil if any toolbar has changed */
405 int toolbar_changed_set;
407 /* non-nil if any gutter has changed */
409 int gutter_changed_set;
411 /* non-nil if any window has changed since the last time redisplay completed */
414 /* non-nil if any frame's window structure has changed since the last
415 time redisplay completed */
416 int windows_structure_changed;
418 /* If non-nil, use vertical bar cursor. */
419 Lisp_Object Vbar_cursor;
420 Lisp_Object Qbar_cursor;
422 int visible_bell; /* If true and the terminal will support it
423 then the frame will flash instead of
424 beeping when an error occurs */
426 /* Nonzero means no need to redraw the entire frame on resuming
427 a suspended Emacs. This is useful on terminals with multiple pages,
428 where one page is used for Emacs and another for all else. */
429 int no_redraw_on_reenter;
431 Lisp_Object Vwindow_system; /* nil or a symbol naming the window system
432 under which emacs is running
433 ('x is the only current possibility) */
434 Lisp_Object Vinitial_window_system;
436 Lisp_Object Vglobal_mode_string;
438 /* The number of lines scroll a window by when point leaves the window; if
439 it is <=0 then point is centered in the window */
442 /* Scroll up to this many lines, to bring point back on screen. */
443 int scroll_conservatively;
445 /* Marker for where to display an arrow on top of the buffer text. */
446 Lisp_Object Voverlay_arrow_position;
447 /* String to display for the arrow. */
448 Lisp_Object Voverlay_arrow_string;
450 Lisp_Object Vwindow_size_change_functions;
451 Lisp_Object Vwindow_scroll_functions;
452 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
454 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
456 #ifndef INHIBIT_REDISPLAY_HOOKS
457 /* #### Chuck says: I think this needs more thought.
458 Think about this for 19.14. */
459 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
460 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
461 #endif /* INHIBIT_REDISPLAY_HOOKS */
463 static int last_display_warning_tick, display_warning_tick;
464 Lisp_Object Qdisplay_warning_buffer;
465 int inhibit_warning_display;
467 Lisp_Object Vleft_margin_width, Vright_margin_width;
468 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
469 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
470 Lisp_Object Vtext_cursor_visible_p;
472 int column_number_start_at_one;
474 #define WINDOW_SCROLLED(w) \
475 (w->hscroll > 0 || w->left_xoffset)
478 /***************************************************************************/
480 /* low-level interfaces onto device routines */
482 /***************************************************************************/
485 redisplay_text_width_emchar_string (struct window *w, int findex,
486 Emchar *str, Charcount len)
488 Charset_ID charsets[NUM_LEADING_BYTES];
491 find_charsets_in_emchar_string (charsets, str, len);
492 XSETWINDOW (window, w);
493 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
495 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))),
496 text_width, (XFRAME (WINDOW_FRAME (w)),
497 WINDOW_FACE_CACHEL (w, findex), str, len));
500 static Emchar_dynarr *rtw_emchar_dynarr;
503 redisplay_text_width_string (struct window *w, int findex,
504 Bufbyte *nonreloc, Lisp_Object reloc,
505 Bytecount offset, Bytecount len)
507 if (!rtw_emchar_dynarr)
508 rtw_emchar_dynarr = Dynarr_new (Emchar);
509 Dynarr_reset (rtw_emchar_dynarr);
511 fixup_internal_substring (nonreloc, reloc, offset, &len);
513 nonreloc = XSTRING_DATA (reloc);
514 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
515 return redisplay_text_width_emchar_string
516 (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
517 Dynarr_length (rtw_emchar_dynarr));
521 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face,
522 Bufbyte *nonreloc, Lisp_Object reloc,
523 Bytecount offset, Bytecount len)
525 Charset_ID charsets[NUM_LEADING_BYTES];
527 struct face_cachel cachel;
529 if (!rtw_emchar_dynarr)
530 rtw_emchar_dynarr = Dynarr_new (Emchar);
531 Dynarr_reset (rtw_emchar_dynarr);
533 fixup_internal_substring (nonreloc, reloc, offset, &len);
535 nonreloc = XSTRING_DATA (reloc);
536 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
537 find_charsets_in_bufbyte_string (charsets, nonreloc, len);
538 reset_face_cachel (&cachel);
540 XSETFRAME (frame, f);
541 ensure_face_cachel_complete (&cachel, frame, charsets);
542 return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
543 text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
544 Dynarr_length (rtw_emchar_dynarr)));
547 /* Return the display block from DL of the given TYPE. A display line
548 can have only one display block of each possible type. If DL does
549 not have a block of type TYPE, one will be created and added to DL. */
551 struct display_block *
552 get_display_block_from_line (struct display_line *dl, enum display_type type)
555 struct display_block db;
557 /* Check if this display line already has a block of the desired type and
559 if (dl->display_blocks)
561 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++)
563 if (Dynarr_at (dl->display_blocks, elt).type == type)
564 return Dynarr_atp (dl->display_blocks, elt);
567 /* There isn't an active block of the desired type, but there
568 might still be allocated blocks we need to reuse. */
569 if (elt < Dynarr_largest (dl->display_blocks))
571 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
573 /* 'add' the block to the list */
574 Dynarr_increment (dl->display_blocks);
576 /* initialize and return */
583 /* This line doesn't have any display blocks, so initialize the display
585 dl->display_blocks = Dynarr_new (display_block);
588 /* The line doesn't have a block of the desired type so go ahead and create
589 one and add it to the line. */
592 db.runes = Dynarr_new (rune);
593 Dynarr_add (dl->display_blocks, db);
595 /* Return the newly added display block. */
596 elt = Dynarr_length (dl->display_blocks) - 1;
598 return Dynarr_atp (dl->display_blocks, elt);
602 tab_char_width (struct window *w)
604 struct buffer *b = XBUFFER (w->buffer);
605 int char_tab_width = XINT (b->tab_width);
607 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8;
609 return char_tab_width;
613 space_width (struct window *w)
615 /* While tabs are traditional composed of spaces, for variable-width
616 fonts the space character tends to give too narrow a value. So
617 we use 'n' instead. Except that we don't. We use the default
618 character width for the default face. If this is actually
619 defined by the font then it is probably the best thing to
620 actually use. If it isn't, we have assumed it is 'n' and have
621 already calculated its width. Thus we can avoid a call to
622 XTextWidth on X frames by just querying the default width. */
623 return XFONT_INSTANCE
624 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width;
628 tab_pix_width (struct window *w)
630 return space_width (w) * tab_char_width (w);
633 /* Given a pixel position in a window, return the pixel location of
634 the next tabstop. Tabs are calculated from the left window edge in
635 terms of spaces displayed in the default face. Formerly the space
636 width was determined using the currently active face. That method
637 leads to tabstops which do not line up. */
640 next_tab_position (struct window *w, int start_pixpos, int left_pixpos)
642 int n_pos = left_pixpos;
643 int pix_tab_width = tab_pix_width (w);
645 /* Adjust n_pos for any hscrolling which has happened. */
646 if (WINDOW_SCROLLED (w))
647 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset;
649 while (n_pos <= start_pixpos)
650 n_pos += pix_tab_width;
655 /* For the given window, calculate the outside and margin boundaries for a
656 display line. The whitespace boundaries must be calculated by the text
660 calculate_display_line_boundaries (struct window *w, int modeline)
662 layout_bounds bounds;
664 /* Set the outermost boundaries which are the boundaries of the
665 window itself minus the gutters (and minus the scrollbars if this
666 is for the modeline). */
669 bounds.left_out = WINDOW_TEXT_LEFT (w);
670 bounds.right_out = WINDOW_TEXT_RIGHT (w);
674 bounds.left_out = WINDOW_MODELINE_LEFT (w);
675 bounds.right_out = WINDOW_MODELINE_RIGHT (w);
678 /* The inner boundaries mark where the glyph margins are located. */
679 bounds.left_in = bounds.left_out + window_left_margin_width (w);
680 bounds.right_in = bounds.right_out - window_right_margin_width (w);
682 /* We cannot fully calculate the whitespace boundaries as they
683 depend on the contents of the line being displayed. */
684 bounds.left_white = bounds.left_in;
685 bounds.right_white = bounds.right_in;
690 /* Given a display line and a starting position, ensure that the
691 contents of the display line accurately represent the visual
692 representation of the buffer contents starting from the given
693 position when displayed in the given window. The display line ends
694 when the contents of the line reach the right boundary of the given
698 generate_display_line (struct window *w, struct display_line *dl, int bounds,
699 Bufpos start_pos, prop_block_dynarr **prop,
704 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
706 /* If our caller hasn't already set the boundaries, then do so now. */
708 dl->bounds = calculate_display_line_boundaries (w, 0);
710 /* Reset what this line is using. */
711 if (dl->display_blocks)
712 Dynarr_reset (dl->display_blocks);
715 Dynarr_free (dl->left_glyphs);
718 if (dl->right_glyphs)
720 Dynarr_free (dl->right_glyphs);
721 dl->right_glyphs = 0;
724 /* We aren't generating a modeline at the moment. */
727 /* Create a display block for the text region of the line. */
729 /* #### urk urk urk!!! Chuck fix this shit! */
730 Bytind hacked_up_bytind =
731 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
733 if (hacked_up_bytind > BI_BUF_ZV (b))
734 ret_bufpos = BUF_ZV (b) + 1;
736 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
738 dl->bufpos = start_pos;
739 if (dl->end_bufpos < dl->bufpos)
740 dl->end_bufpos = dl->bufpos;
742 if (MARKERP (Voverlay_arrow_position)
743 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
744 && start_pos == marker_position (Voverlay_arrow_position)
745 && (STRINGP (Voverlay_arrow_string)
746 || GLYPHP (Voverlay_arrow_string)))
748 overlay_width = create_overlay_glyph_block (w, dl);
753 /* If there are left glyphs associated with any character in the
754 text block, then create a display block to handle them. */
755 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
756 create_left_glyph_block (w, dl, overlay_width);
758 /* If there are right glyphs associated with any character in the
759 text block, then create a display block to handle them. */
760 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
761 create_right_glyph_block (w, dl);
763 /* In the future additional types of display blocks may be generated
766 w->last_redisplay_pos = ret_bufpos;
771 /* Adds an hscroll glyph to a display block. If this is called, then
772 the block had better be empty.
774 Yes, there are multiple places where this function is called but
775 that is the way it has to be. Each calling function has to deal
776 with bi_start_col_enabled a little differently depending on the
777 object being worked with. */
779 static prop_block_dynarr *
780 add_hscroll_rune (pos_data *data)
782 struct glyph_block gb;
783 prop_block_dynarr *retval;
784 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
785 unsigned int old_cursor_type = data->cursor_type;
786 Bytind bi_old_bufpos = data->bi_bufpos;
788 if (data->cursor_type == CURSOR_ON
789 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
790 && data->bi_cursor_bufpos <= data->bi_bufpos)
792 data->bi_cursor_bufpos = data->bi_start_col_enabled;
796 data->cursor_type = NO_CURSOR;
799 data->bi_endpos = data->bi_bufpos;
800 data->bi_bufpos = data->bi_start_col_enabled;
803 gb.glyph = Vhscroll_glyph;
805 int oldpixpos = data->pixpos;
806 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
807 GLYPH_CACHEL (XWINDOW (data->window),
808 HSCROLL_GLYPH_INDEX));
809 data->hscroll_glyph_width_adjust =
810 data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
813 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
814 data->cursor_type = old_cursor_type;
815 data->bi_bufpos = bi_old_bufpos;
817 data->bi_start_col_enabled = 0;
821 /* Adds a character rune to a display block. If there is not enough
822 room to fit the rune on the display block (as determined by the
823 MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
825 static prop_block_dynarr *
826 add_emchar_rune (pos_data *data)
828 struct rune rb, *crb;
839 if (data->bi_start_col_enabled)
841 return add_hscroll_rune (data);
844 if (data->ch == '\n')
846 data->font_is_bogus = 0;
847 /* Cheesy end-of-line pseudo-character. */
848 width = data->blank_width;
852 Lisp_Object charset = CHAR_CHARSET (data->ch);
853 if (!EQ (charset, data->last_charset) ||
854 data->findex != data->last_findex)
856 /* OK, we need to do things the hard way. */
857 struct window *w = XWINDOW (data->window);
858 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
859 Lisp_Object font_instance =
860 ensure_face_cachel_contains_charset (cachel, data->window,
862 struct Lisp_Font_Instance *fi;
864 if (EQ (font_instance, Vthe_null_font_instance))
866 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
867 data->font_is_bogus = 1;
870 data->font_is_bogus = 0;
872 fi = XFONT_INSTANCE (font_instance);
873 if (!fi->proportional_p)
874 /* sweetness and light. */
875 data->last_char_width = fi->width;
877 data->last_char_width = -1;
878 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
879 data->new_descent = max (data->new_descent, (int) fi->descent);
880 data->last_charset = charset;
881 data->last_findex = data->findex;
884 width = data->last_char_width;
887 /* bummer. Proportional fonts. */
888 width = redisplay_text_width_emchar_string (XWINDOW (data->window),
894 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
899 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
901 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
910 crb->findex = data->findex;
911 crb->xpos = data->pixpos;
915 if (NILP (data->string))
917 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
921 bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
923 else if (data->is_modeline)
924 crb->bufpos = data->modeline_charpos;
926 /* fuckme if this shouldn't be an abort. */
927 /* abort (); fuckme harder, this abort gets tripped quite often,
928 in propagation and whatnot. #### fixme */
930 crb->type = RUNE_CHAR;
931 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
934 if (data->cursor_type == CURSOR_ON)
936 if (data->bi_bufpos == data->bi_cursor_bufpos)
938 crb->cursor_type = CURSOR_ON;
939 data->cursor_x = Dynarr_length (data->db->runes);
942 crb->cursor_type = CURSOR_OFF;
944 else if (data->cursor_type == NEXT_CURSOR)
946 crb->cursor_type = CURSOR_ON;
947 data->cursor_x = Dynarr_length (data->db->runes);
948 data->cursor_type = NO_CURSOR;
950 else if (data->cursor_type == IGNORE_CURSOR)
951 crb->cursor_type = IGNORE_CURSOR;
953 crb->cursor_type = CURSOR_OFF;
956 Dynarr_add (data->db->runes, *crb);
958 Dynarr_increment (data->db->runes);
960 data->pixpos += width;
965 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
966 for each character in the string. Propagate any left-over data
967 unless NO_PROP is non-zero. */
969 static prop_block_dynarr *
970 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
971 Bytecount c_length, int no_prop)
973 Bufbyte *pos, *end = c_string + c_length;
974 prop_block_dynarr *prop;
976 /* #### This function is too simplistic. It needs to do the same
977 sort of character interpretation (display-table lookup,
978 ctl-arrow checking), etc. that create_text_block() does.
979 The functionality to do this in that routine needs to be
982 for (pos = c_string; pos < end;)
984 data->ch = charptr_emchar (pos);
986 prop = add_emchar_rune (data);
994 struct prop_block pb;
995 Bytecount len = end - pos;
996 prop = Dynarr_new (prop_block);
998 pb.type = PROP_STRING;
999 pb.data.p_string.str = xnew_array (Bufbyte, len);
1000 strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
1001 pb.data.p_string.len = len;
1003 Dynarr_add (prop, pb);
1008 assert (pos <= end);
1014 /* Add a single rune of the specified width. The area covered by this
1015 rune will be displayed in the foreground color of the associated
1018 static prop_block_dynarr *
1019 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1023 /* If data->start_col is not 0 then this call to add_blank_rune must have
1024 been to add it as a tab. */
1025 if (data->start_col)
1027 /* assert (w != NULL) */
1028 prop_block_dynarr *retval;
1030 /* If we have still not fully scrolled horizontally, subtract
1031 the width of this tab and return. */
1032 if (char_tab_width < data->start_col)
1034 data->start_col -= char_tab_width;
1037 else if (char_tab_width == data->start_col)
1038 data->blank_width = 0;
1041 int spcwid = space_width (w);
1043 if (spcwid >= data->blank_width)
1044 data->blank_width = 0;
1046 data->blank_width -= spcwid;
1049 data->start_col = 0;
1050 retval = add_hscroll_rune (data);
1052 /* Could be caused by the handling of the hscroll rune. */
1053 if (retval != NULL || !data->blank_width)
1057 /* Blank runes are always calculated to fit. */
1058 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1060 rb.findex = data->findex;
1061 rb.xpos = data->pixpos;
1062 rb.width = data->blank_width;
1063 if (data->bi_bufpos)
1065 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1068 /* #### and this is really correct too? */
1071 rb.type = RUNE_BLANK;
1073 if (data->cursor_type == CURSOR_ON)
1075 if (data->bi_bufpos == data->bi_cursor_bufpos)
1077 rb.cursor_type = CURSOR_ON;
1078 data->cursor_x = Dynarr_length (data->db->runes);
1081 rb.cursor_type = CURSOR_OFF;
1083 else if (data->cursor_type == NEXT_CURSOR)
1085 rb.cursor_type = CURSOR_ON;
1086 data->cursor_x = Dynarr_length (data->db->runes);
1087 data->cursor_type = NO_CURSOR;
1090 rb.cursor_type = CURSOR_OFF;
1092 Dynarr_add (data->db->runes, rb);
1093 data->pixpos += data->blank_width;
1098 /* Add runes representing a character in octal. */
1100 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1102 if (add_failed || (add_failed = add_emchar_rune (data))) \
1104 struct prop_block pb; \
1106 prop = Dynarr_new (prop_block); \
1108 pb.type = PROP_CHAR; \
1109 pb.data.p_char.ch = data->ch; \
1110 pb.data.p_char.cursor_type = data->cursor_type; \
1111 Dynarr_add (prop, pb); \
1115 static prop_block_dynarr *
1116 add_octal_runes (pos_data *data)
1118 prop_block_dynarr *prop, *add_failed;
1119 Emchar orig_char = data->ch;
1120 unsigned int orig_cursor_type = data->cursor_type;
1126 if (data->start_col)
1129 if (!data->start_col)
1131 if (data->bi_start_col_enabled)
1133 add_failed = add_hscroll_rune (data);
1137 struct glyph_block gb;
1138 struct window *w = XWINDOW (data->window);
1141 gb.glyph = Voctal_escape_glyph;
1143 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1144 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1148 /* We only propagate information if the glyph was partially
1153 data->cursor_type = IGNORE_CURSOR;
1155 if (data->ch >= 0x100)
1157 /* If the character is an extended Mule character, it could have
1158 up to 19 bits. For the moment, we treat it as a seven-digit
1159 octal number. This is not that pretty, but whatever. */
1160 data->ch = (7 & (orig_char >> 18)) + '0';
1161 ADD_NEXT_OCTAL_RUNE_CHAR;
1163 data->ch = (7 & (orig_char >> 15)) + '0';
1164 ADD_NEXT_OCTAL_RUNE_CHAR;
1166 data->ch = (7 & (orig_char >> 12)) + '0';
1167 ADD_NEXT_OCTAL_RUNE_CHAR;
1169 data->ch = (7 & (orig_char >> 9)) + '0';
1170 ADD_NEXT_OCTAL_RUNE_CHAR;
1173 data->ch = (7 & (orig_char >> 6)) + '0';
1174 ADD_NEXT_OCTAL_RUNE_CHAR;
1176 data->ch = (7 & (orig_char >> 3)) + '0';
1177 ADD_NEXT_OCTAL_RUNE_CHAR;
1179 data->ch = (7 & orig_char) + '0';
1180 ADD_NEXT_OCTAL_RUNE_CHAR;
1182 data->cursor_type = orig_cursor_type;
1186 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1188 /* Add runes representing a control character to a display block. */
1190 static prop_block_dynarr *
1191 add_control_char_runes (pos_data *data, struct buffer *b)
1193 if (!NILP (b->ctl_arrow))
1195 prop_block_dynarr *prop;
1196 Emchar orig_char = data->ch;
1197 unsigned int old_cursor_type = data->cursor_type;
1202 if (data->start_col)
1205 if (!data->start_col)
1207 if (data->bi_start_col_enabled)
1209 prop_block_dynarr *retval;
1211 retval = add_hscroll_rune (data);
1217 struct glyph_block gb;
1218 struct window *w = XWINDOW (data->window);
1221 gb.glyph = Vcontrol_arrow_glyph;
1223 /* We only propagate information if the glyph was partially
1225 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1226 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1231 if (orig_char == 0177)
1234 data->ch = orig_char ^ 0100;
1235 data->cursor_type = IGNORE_CURSOR;
1237 if (add_emchar_rune (data))
1239 struct prop_block pb;
1241 prop = Dynarr_new (prop_block);
1243 pb.type = PROP_CHAR;
1244 pb.data.p_char.ch = data->ch;
1245 pb.data.p_char.cursor_type = data->cursor_type;
1246 Dynarr_add (prop, pb);
1249 data->cursor_type = old_cursor_type;
1254 return add_octal_runes (data);
1258 static prop_block_dynarr *
1259 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
1261 prop_block_dynarr *prop = NULL;
1263 if (STRINGP (entry))
1265 prop = add_bufbyte_string_runes (data,
1266 XSTRING_DATA (entry),
1267 XSTRING_LENGTH (entry),
1270 else if (GLYPHP (entry))
1272 if (data->start_col)
1275 if (!data->start_col && data->bi_start_col_enabled)
1277 prop = add_hscroll_rune (data);
1281 struct glyph_block gb;
1285 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1288 else if (CHAR_OR_CHAR_INTP (entry))
1290 data->ch = XCHAR_OR_CHAR_INT (entry);
1291 prop = add_emchar_rune (data);
1293 else if (CONSP (entry))
1295 if (EQ (XCAR (entry), Qformat)
1296 && CONSP (XCDR (entry))
1297 && STRINGP (XCAR (XCDR (entry))))
1299 Lisp_Object format = XCAR (XCDR (entry));
1300 Bytind len = XSTRING_LENGTH (format);
1301 Bufbyte *src = XSTRING_DATA (format), *end = src + len;
1302 Bufbyte *result = alloca_array (Bufbyte, len);
1303 Bufbyte *dst = result;
1307 Emchar c = charptr_emchar (src);
1309 if (c != '%' || src == end)
1310 dst += set_charptr_emchar (dst, c);
1313 c = charptr_emchar (src);
1318 dst += long_to_string_base ((char *)dst, data->ch, 16);
1321 dst += set_charptr_emchar (dst, '%');
1326 prop = add_bufbyte_string_runes (data, result, dst - result, 0);
1330 /* Else blow it off because someone added a bad entry and we don't
1331 have any safe way of signaling an error. */
1335 /* Given a display table entry, call the appropriate functions to
1336 display each element of the entry. */
1338 static prop_block_dynarr *
1339 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1341 prop_block_dynarr *prop = NULL;
1342 if (VECTORP (entry))
1344 struct Lisp_Vector *de = XVECTOR (entry);
1345 EMACS_INT len = vector_length (de);
1348 for (elt = 0; elt < len; elt++)
1350 if (NILP (vector_data (de)[elt]))
1353 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
1354 /* Else blow it off because someone added a bad entry and we
1355 don't have any safe way of signaling an error. Hey, this
1356 comment sounds familiar. */
1358 /* #### Still need to add any remaining elements to the
1359 propagation information. */
1365 prop = add_disp_table_entry_runes_1 (data, entry);
1369 /* Add runes which were propagated from the previous line. */
1371 static prop_block_dynarr *
1372 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1374 /* #### Remember to handle start_col parameter of data when the rest of
1375 this is finished. */
1376 /* #### Chuck -- I've redone this function a bit. It looked like the
1377 case of not all the propagation blocks being added was not handled
1379 /* #### Chuck -- I also think the double indirection of PROP is kind
1380 of bogus. A cleaner solution is just to check for
1381 Dynarr_length (prop) > 0. */
1382 /* #### This function also doesn't even pay attention to ADD_FAILED!
1383 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1386 prop_block_dynarr *add_failed;
1387 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1388 unsigned int old_cursor_type = data->cursor_type;
1390 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1392 struct prop_block *pb = Dynarr_atp (*prop, elt);
1397 data->ch = pb->data.p_char.ch;
1398 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1399 data->cursor_type = pb->data.p_char.cursor_type;
1400 add_failed = add_emchar_rune (data);
1403 goto oops_no_more_space;
1406 if (pb->data.p_string.str)
1407 xfree (pb->data.p_string.str);
1408 /* #### bogus bogus -- this doesn't do anything!
1409 Should probably call add_bufbyte_string_runes(),
1410 once that function is fixed. */
1412 case PROP_MINIBUF_PROMPT:
1414 face_index old_findex = data->findex;
1415 Bytind bi_old_bufpos = data->bi_bufpos;
1417 data->findex = DEFAULT_INDEX;
1418 data->bi_bufpos = 0;
1419 data->cursor_type = NO_CURSOR;
1421 while (pb->data.p_string.len > 0)
1423 data->ch = charptr_emchar (pb->data.p_string.str);
1424 add_failed = add_emchar_rune (data);
1428 data->findex = old_findex;
1429 data->bi_bufpos = bi_old_bufpos;
1430 goto oops_no_more_space;
1434 /* Complicated equivalent of ptr++, len-- */
1435 Bufbyte *oldpos = pb->data.p_string.str;
1436 INC_CHARPTR (pb->data.p_string.str);
1437 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1441 data->findex = old_findex;
1442 /* ##### FIXME FIXME FIXME -- Upon successful return from
1443 this function, data->bi_bufpos is automatically incremented.
1444 However, we don't want that to happen if we were adding
1445 the minibuffer prompt. */
1447 struct buffer *buf =
1448 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1449 /* #### Chuck fix this shit or I'm gonna scream! */
1450 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1451 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1453 /* #### is this correct? Does anyone know?
1454 Does anyone care? Is this a cheesy hack or what? */
1455 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1461 /* #### I think it's unnecessary and misleading to preserve
1462 the blank_width, as it implies that the value carries
1463 over from one rune to the next, which is wrong. */
1464 int old_width = data->blank_width;
1465 face_index old_findex = data->findex;
1467 data->findex = pb->data.p_blank.findex;
1468 data->blank_width = pb->data.p_blank.width;
1469 data->bi_cursor_bufpos = 0;
1470 data->cursor_type = IGNORE_CURSOR;
1472 if (data->pixpos + data->blank_width > data->max_pixpos)
1473 data->blank_width = data->max_pixpos - data->pixpos;
1475 /* We pass a bogus value of char_tab_width. It shouldn't
1476 matter because unless something is really screwed up
1477 this call won't cause that arg to be used. */
1478 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1480 /* This can happen in the case where we have a tab which
1481 is wider than the window. */
1482 if (data->blank_width != pb->data.p_blank.width)
1484 pb->data.p_blank.width -= data->blank_width;
1485 add_failed = ADD_FAILED;
1488 data->findex = old_findex;
1489 data->blank_width = old_width;
1492 goto oops_no_more_space;
1502 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1503 data->cursor_type = old_cursor_type;
1504 if (elt < Dynarr_length (*prop))
1506 Dynarr_delete_many (*prop, 0, elt);
1511 Dynarr_free (*prop);
1516 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1517 the display block, but add all other types to the appropriate list
1518 of the display line. They will be added later by different
1521 static prop_block_dynarr *
1522 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1523 int allow_cursor, struct glyph_cachel *cachel)
1525 struct window *w = XWINDOW (data->window);
1527 /* A nil extent indicates a special glyph (ex. truncator). */
1528 if (NILP (gb->extent)
1529 || (pos_type == BEGIN_GLYPHS &&
1530 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1531 || (pos_type == END_GLYPHS &&
1532 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
1537 int ascent, descent;
1538 Lisp_Object baseline;
1542 width = cachel->width;
1544 width = glyph_width (gb->glyph, data->window);
1549 if (data->start_col || data->start_col_xoffset)
1551 prop_block_dynarr *retval;
1552 int glyph_char_width = width / space_width (w);
1554 /* If we still have not fully scrolled horizontally after
1555 taking into account the width of the glyph, subtract its
1556 width and return. */
1557 if (glyph_char_width < data->start_col)
1559 data->start_col -= glyph_char_width;
1562 else if (glyph_char_width == data->start_col)
1566 xoffset = space_width (w) * data->start_col;
1569 /* #### Can this happen? */
1574 data->start_col = 0;
1575 retval = add_hscroll_rune (data);
1577 /* Could be caused by the handling of the hscroll rune. */
1578 if (retval != NULL || !width)
1584 if (data->pixpos + width > data->max_pixpos)
1586 /* If this is the first object we are attempting to add to
1587 the line then we ignore the horizontal_clip threshold.
1588 Otherwise we will loop until the bottom of the window
1589 continually failing to add this glyph because it is wider
1590 than the window. We could alternatively just completely
1591 ignore the glyph and proceed from there but I think that
1592 this is a better solution. */
1593 if (Dynarr_length (data->db->runes)
1594 && data->max_pixpos - data->pixpos < horizontal_clip)
1597 width = data->max_pixpos - data->pixpos;
1602 ascent = cachel->ascent;
1603 descent = cachel->descent;
1607 ascent = glyph_ascent (gb->glyph, data->window);
1608 descent = glyph_descent (gb->glyph, data->window);
1611 baseline = glyph_baseline (gb->glyph, data->window);
1613 if (glyph_contrib_p (gb->glyph, data->window))
1615 /* A pixmap that has not had a baseline explicitly set. Its
1616 contribution will be determined later. */
1617 if (NILP (baseline))
1619 int height = ascent + descent;
1620 data->max_pixmap_height = max (data->max_pixmap_height, height);
1623 /* A string so determine contribution normally. */
1624 else if (EQ (baseline, Qt))
1626 data->new_ascent = max (data->new_ascent, ascent);
1627 data->new_descent = max (data->new_descent, descent);
1630 /* A pixmap with an explicitly set baseline. We determine the
1631 contribution here. */
1632 else if (INTP (baseline))
1634 int height = ascent + descent;
1635 int pix_ascent, pix_descent;
1637 pix_ascent = height * XINT (baseline) / 100;
1638 pix_descent = height - pix_ascent;
1640 data->new_ascent = max (data->new_ascent, pix_ascent);
1641 data->new_descent = max (data->new_descent, pix_descent);
1644 /* Otherwise something is screwed up. */
1649 face = glyph_face (gb->glyph, data->window);
1651 rb.findex = data->findex;
1653 rb.findex = get_builtin_face_cache_index (w, face);
1655 rb.xpos = data->pixpos;
1657 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1658 if (data->bi_endpos)
1659 /* #### is this necessary at all? */
1660 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1664 rb.type = RUNE_DGLYPH;
1665 /* #### Ben sez: this is way bogus if the glyph is a string.
1666 You should not make the output routines have to cope with
1667 this. The string could contain Mule characters, or non-
1668 printable characters, or characters to be passed through
1669 the display table, or non-character objects (when this gets
1670 implemented), etc. Instead, this routine here should parse
1671 the string into a series of runes. */
1672 rb.object.dglyph.glyph = gb->glyph;
1673 rb.object.dglyph.extent = gb->extent;
1674 rb.object.dglyph.xoffset = xoffset;
1678 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1681 if (data->cursor_type == CURSOR_ON)
1683 if (data->bi_bufpos == data->bi_cursor_bufpos)
1685 rb.cursor_type = CURSOR_ON;
1686 data->cursor_x = Dynarr_length (data->db->runes);
1689 rb.cursor_type = CURSOR_OFF;
1691 else if (data->cursor_type == NEXT_CURSOR)
1693 rb.cursor_type = CURSOR_ON;
1694 data->cursor_x = Dynarr_length (data->db->runes);
1695 data->cursor_type = NO_CURSOR;
1697 else if (data->cursor_type == IGNORE_CURSOR)
1698 rb.cursor_type = IGNORE_CURSOR;
1699 else if (data->cursor_type == NO_CURSOR)
1700 rb.cursor_type = NO_CURSOR;
1702 rb.cursor_type = CURSOR_OFF;
1705 rb.cursor_type = CURSOR_OFF;
1707 Dynarr_add (data->db->runes, rb);
1708 data->pixpos += width;
1714 if (!NILP (glyph_face (gb->glyph, data->window)))
1716 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1719 gb->findex = data->findex;
1721 if (pos_type == BEGIN_GLYPHS)
1723 if (!data->dl->left_glyphs)
1724 data->dl->left_glyphs = Dynarr_new (glyph_block);
1725 Dynarr_add (data->dl->left_glyphs, *gb);
1728 else if (pos_type == END_GLYPHS)
1730 if (!data->dl->right_glyphs)
1731 data->dl->right_glyphs = Dynarr_new (glyph_block);
1732 Dynarr_add (data->dl->right_glyphs, *gb);
1736 abort (); /* there are no unknown types */
1739 return NULL; /* shut up compiler */
1742 /* Add all glyphs at position POS_TYPE that are contained in the given
1745 static prop_block_dynarr *
1746 add_glyph_runes (pos_data *data, int pos_type)
1748 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1749 why didn't you just modify add_glyph_rune in the first place? */
1751 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1752 ? data->ef->begin_glyphs
1753 : data->ef->end_glyphs);
1754 prop_block_dynarr *prop;
1756 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1758 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1763 /* #### Add some propagation information. */
1768 Dynarr_reset (glyph_arr);
1773 /* Given a position for a buffer in a window, ensure that the given
1774 display line DL accurately represents the text on a line starting
1775 at the given position.
1777 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1778 You must do appropriate conversion. */
1781 create_text_block (struct window *w, struct display_line *dl,
1782 Bytind bi_start_pos, prop_block_dynarr **prop,
1785 struct frame *f = XFRAME (w->frame);
1786 struct buffer *b = XBUFFER (w->buffer);
1787 struct device *d = XDEVICE (f->device);
1791 /* Don't display anything in the minibuffer if this window is not on
1792 a selected frame. We consider all other windows to be active
1793 minibuffers as it simplifies the coding. */
1794 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1795 (f == device_selected_frame (d)) ||
1796 is_surrogate_for_selected_frame (f));
1798 int truncate_win = window_truncation_on (w);
1799 int end_glyph_width;
1801 /* If the buffer's value of selective_display is an integer then
1802 only lines that start with less than selective_display columns of
1803 space will be displayed. If selective_display is t then all text
1804 after a ^M is invisible. */
1805 int selective = (INTP (b->selective_display)
1806 ? XINT (b->selective_display)
1807 : (!NILP (b->selective_display) ? -1 : 0));
1809 /* The variable ctl-arrow allows the user to specify what characters
1810 can actually be displayed and which octal should be used for.
1811 #### This variable should probably have some rethought done to
1814 #### It would also be really nice if you could specify that
1815 the characters come out in hex instead of in octal. Mule
1816 does that by adding a ctl-hexa variable similar to ctl-arrow,
1817 but that's bogus -- we need a more general solution. I
1818 think you need to extend the concept of display tables
1819 into a more general conversion mechanism. Ideally you
1820 could specify a Lisp function that converts characters,
1821 but this violates the Second Golden Rule and besides would
1822 make things way way way way slow.
1824 So instead, we extend the display-table concept, which was
1825 historically limited to 256-byte vectors, to one of the
1828 a) A 256-entry vector, for backward compatibility;
1829 b) char-table, mapping characters to values;
1830 c) range-table, mapping ranges of characters to values;
1831 d) a list of the above.
1833 The (d) option allows you to specify multiple display tables
1834 instead of just one. Each display table can specify conversions
1835 for some characters and leave others unchanged. The way the
1836 character gets displayed is determined by the first display table
1837 with a binding for that character. This way, you could call a
1838 function `enable-hex-display' that adds a hex display-table to
1839 the list of display tables for the current buffer.
1841 #### ...not yet implemented... Also, we extend the concept of
1842 "mapping" to include a printf-like spec. Thus you can make all
1843 extended characters show up as hex with a display table like
1846 #s(range-table data ((256 524288) (format "%x")))
1848 Since more than one display table is possible, you have
1849 great flexibility in mapping ranges of characters. */
1850 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1851 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1852 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1855 Lisp_Object face_dt, window_dt;
1857 /* The text display block for this display line. */
1858 struct display_block *db = get_display_block_from_line (dl, TEXT);
1860 /* The first time through the main loop we need to force the glyph
1861 data to be updated. */
1864 /* Apparently the new extent_fragment_update returns an end position
1865 equal to the position passed in if there are no more runs to be
1867 int no_more_frags = 0;
1869 Lisp_Object synch_minibuffers_value =
1870 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1872 dl->used_prop_data = 0;
1876 data.ef = extent_fragment_new (w->buffer, f);
1878 /* These values are used by all of the rune addition routines. We add
1879 them to this structure for ease of passing. */
1881 XSETWINDOW (data.window, w);
1886 data.bi_bufpos = bi_start_pos;
1887 data.pixpos = dl->bounds.left_in;
1888 data.last_charset = Qunbound;
1889 data.last_findex = DEFAULT_INDEX;
1890 data.result_str = Qnil;
1892 /* Set the right boundary adjusting it to take into account any end
1893 glyph. Save the width of the end glyph for later use. */
1894 data.max_pixpos = dl->bounds.right_in;
1896 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1898 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1899 data.max_pixpos -= end_glyph_width;
1901 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1903 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1904 data.cursor_type = CURSOR_ON;
1906 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1907 data.cursor_type = NO_CURSOR;
1908 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1909 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1910 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1911 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1913 data.bi_cursor_bufpos = BI_BUF_PT (b);
1914 data.cursor_type = CURSOR_ON;
1916 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1918 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1919 data.cursor_type = CURSOR_ON;
1922 data.cursor_type = NO_CURSOR;
1925 data.start_col = w->hscroll;
1926 data.start_col_xoffset = w->left_xoffset;
1927 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1928 data.hscroll_glyph_width_adjust = 0;
1930 /* We regenerate the line from the very beginning. */
1931 Dynarr_reset (db->runes);
1933 /* Why is this less than or equal and not just less than? If the
1934 starting position is already equal to the maximum we can't add
1935 anything else, right? Wrong. We might still have a newline to
1936 add. A newline can use the room allocated for an end glyph since
1937 if we add it we know we aren't going to be adding any end
1940 /* #### Chuck -- I think this condition should be while (1).
1941 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1942 and the begin-glyph ends exactly at the end of the window, the
1943 end-glyph and text might not be displayed. while (1) ensures
1944 that the loop terminates only when either (a) there is
1945 propagation data or (b) the end-of-line or end-of-buffer is hit.
1947 #### Also I think you need to ensure that the operation
1948 "add begin glyphs; add end glyphs; add text" is atomic and
1949 can't get interrupted in the middle. If you run off the end
1950 of the line during that operation, then you keep accumulating
1951 propagation data until you're done. Otherwise, if the (e.g.)
1952 there's a begin glyph at a particular position and attempting
1953 to display that glyph results in window-end being hit and
1954 propagation data being generated, then the character at that
1955 position won't be displayed.
1957 #### See also the comment after the end of this loop, below.
1959 while (data.pixpos <= data.max_pixpos
1960 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1962 /* #### This check probably should not be necessary. */
1963 if (data.bi_bufpos > BI_BUF_ZV (b))
1965 /* #### urk! More of this lossage! */
1970 /* If selective display was an integer and we aren't working on
1971 a continuation line then find the next line we are actually
1972 supposed to display. */
1974 && (data.bi_bufpos == BI_BUF_BEGV (b)
1975 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
1977 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
1980 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
1981 if (data.bi_bufpos >= BI_BUF_ZV (b))
1983 data.bi_bufpos = BI_BUF_ZV (b);
1989 /* Check for face changes. */
1990 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
1992 /* Now compute the face and begin/end-glyph information. */
1994 /* Remember that the extent-fragment routines deal in Bytind's. */
1995 extent_fragment_update (w, data.ef, data.bi_bufpos);
1997 get_display_tables (w, data.findex, &face_dt, &window_dt);
1999 if (data.bi_bufpos == data.ef->end)
2004 /* Determine what is next to be displayed. We first handle any
2005 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2006 display then we determine what to do based on the character at the
2007 current buffer position. */
2009 /* If the current position is covered by an invisible extent, do
2010 nothing (except maybe add some ellipses).
2012 #### The behavior of begin and end-glyphs at the edge of an
2013 invisible extent should be investigated further. This is
2014 fairly low priority though. */
2015 if (data.ef->invisible)
2017 /* #### Chuck, perhaps you could look at this code? I don't
2018 really know what I'm doing. */
2021 Dynarr_free (*prop);
2025 /* The extent fragment code only sets this when we should
2026 really display the ellipses. It makes sure the ellipses
2027 don't get displayed more than once in a row. */
2028 if (data.ef->invisible_ellipses)
2030 struct glyph_block gb;
2032 data.ef->invisible_ellipses_already_displayed = 1;
2033 data.ef->invisible_ellipses = 0;
2035 gb.glyph = Vinvisible_text_glyph;
2036 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2037 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2038 /* Perhaps they shouldn't propagate if the very next thing
2039 is to display a newline (for compatibility with
2040 selective-display-ellipses)? Maybe that's too
2046 /* If point is in an invisible region we place it on the
2047 next visible character. */
2048 if (data.cursor_type == CURSOR_ON
2049 && data.bi_bufpos == data.bi_cursor_bufpos)
2051 data.cursor_type = NEXT_CURSOR;
2054 /* #### What if we we're dealing with a display table? */
2058 if (data.bi_bufpos == BI_BUF_ZV (b))
2061 INC_BYTIND (b, data.bi_bufpos);
2064 /* If there is propagation data, then it represents the current
2065 buffer position being displayed. Add them and advance the
2066 position counter. This might also add the minibuffer
2070 dl->used_prop_data = 1;
2071 *prop = add_propagation_runes (prop, &data);
2074 goto done; /* gee, a really narrow window */
2075 else if (data.bi_bufpos == BI_BUF_ZV (b))
2077 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2078 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2079 data.bi_bufpos = BI_BUF_BEGV (b);
2081 INC_BYTIND (b, data.bi_bufpos);
2084 /* If there are end glyphs, add them to the line. These are
2085 the end glyphs for the previous run of text. We add them
2086 here rather than doing them at the end of handling the
2087 previous run so that glyphs at the beginning and end of
2088 a line are handled correctly. */
2089 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2091 *prop = add_glyph_runes (&data, END_GLYPHS);
2096 /* If there are begin glyphs, add them to the line. */
2097 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2099 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2104 /* If at end-of-buffer, we've already processed begin and
2105 end-glyphs at this point and there's no text to process,
2107 else if (data.bi_bufpos == BI_BUF_ZV (b))
2112 Lisp_Object entry = Qnil;
2113 /* Get the character at the current buffer position. */
2114 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2115 if (!NILP (face_dt) || !NILP (window_dt))
2116 entry = display_table_entry (data.ch, face_dt, window_dt);
2118 /* If there is a display table entry for it, hand it off to
2119 add_disp_table_entry_runes and let it worry about it. */
2120 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
2122 *prop = add_disp_table_entry_runes (&data, entry);
2128 /* Check if we have hit a newline character. If so, add a marker
2129 to the line and end this loop. */
2130 else if (data.ch == '\n')
2132 /* We aren't going to be adding an end glyph so give its
2133 space back in order to make sure that the cursor can
2135 data.max_pixpos += end_glyph_width;
2138 && (bi_spaces_at_point
2139 (b, next_bytind (b, data.bi_bufpos))
2142 if (!NILP (b->selective_display_ellipses))
2144 struct glyph_block gb;
2147 gb.glyph = Vinvisible_text_glyph;
2148 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2149 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2153 /* Cheesy, cheesy, cheesy. We mark the end of the
2154 line with a special "character rune" whose width
2155 is the EOL cursor width and whose character is
2156 the non-printing character '\n'. */
2157 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2158 *prop = add_emchar_rune (&data);
2161 /* We need to set data.bi_bufpos to the start of the
2162 next visible region in order to make this line
2163 appear to contain all of the invisible area.
2164 Otherwise, the line cache won't work
2166 INC_BYTIND (b, data.bi_bufpos);
2167 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2170 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2171 if (data.bi_bufpos >= BI_BUF_ZV (b))
2173 data.bi_bufpos = BI_BUF_ZV (b);
2177 if (BI_BUF_FETCH_CHAR
2178 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2179 DEC_BYTIND (b, data.bi_bufpos);
2183 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2184 *prop = add_emchar_rune (&data);
2190 /* If the current character is ^M, and selective display is
2191 enabled, then add the invisible-text-glyph if
2192 selective-display-ellipses is set. In any case, this
2194 else if (data.ch == (('M' & 037)) && selective == -1)
2196 Bytind bi_next_bufpos;
2198 /* Find the buffer position at the end of the line. */
2200 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2201 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2203 DEC_BYTIND (b, bi_next_bufpos);
2205 /* If the cursor is somewhere in the elided text make
2206 sure that the cursor gets drawn appropriately. */
2207 if (data.cursor_type == CURSOR_ON
2208 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2209 data.bi_cursor_bufpos < bi_next_bufpos))
2211 data.cursor_type = NEXT_CURSOR;
2214 /* We won't be adding a truncation or continuation glyph
2215 so give up the room allocated for them. */
2216 data.max_pixpos += end_glyph_width;
2218 if (!NILP (b->selective_display_ellipses))
2220 /* We don't propagate anything from the invisible
2221 text glyph if it fails to fit. This is
2223 struct glyph_block gb;
2226 gb.glyph = Vinvisible_text_glyph;
2227 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2228 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2231 /* Set the buffer position to the end of the line. We
2232 need to do this before potentially adding a newline
2233 so that the cursor flag will get set correctly (if
2235 data.bi_bufpos = bi_next_bufpos;
2237 if (NILP (b->selective_display_ellipses)
2238 || data.bi_cursor_bufpos == bi_next_bufpos)
2240 /* We have to at least add a newline character so
2241 that the cursor shows up properly. */
2243 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2244 data.findex = DEFAULT_INDEX;
2246 data.start_col_xoffset = 0;
2247 data.bi_start_col_enabled = 0;
2249 add_emchar_rune (&data);
2252 /* This had better be a newline but doing it this way
2253 we'll see obvious incorrect results if it isn't. No
2254 need to abort here. */
2255 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2260 /* If the current character is considered to be printable, then
2262 else if (data.ch >= printable_min)
2264 *prop = add_emchar_rune (&data);
2269 /* If the current character is a tab, determine the next tab
2270 starting position and add a blank rune which extends from the
2271 current pixel position to that starting position. */
2272 else if (data.ch == '\t')
2274 int tab_start_pixpos = data.pixpos;
2279 if (data.start_col > 1)
2280 tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
2281 + data.start_col_xoffset;
2284 next_tab_position (w, tab_start_pixpos,
2285 dl->bounds.left_in +
2286 data.hscroll_glyph_width_adjust);
2287 if (next_tab_start > data.max_pixpos)
2289 prop_width = next_tab_start - data.max_pixpos;
2290 next_tab_start = data.max_pixpos;
2292 data.blank_width = next_tab_start - data.pixpos;
2294 (next_tab_start - tab_start_pixpos) / space_width (w);
2296 *prop = add_blank_rune (&data, w, char_tab_width);
2298 /* add_blank_rune is only supposed to be called with
2299 sizes guaranteed to fit in the available space. */
2304 struct prop_block pb;
2305 *prop = Dynarr_new (prop_block);
2307 pb.type = PROP_BLANK;
2308 pb.data.p_blank.width = prop_width;
2309 pb.data.p_blank.findex = data.findex;
2310 Dynarr_add (*prop, pb);
2316 /* If character is a control character, pass it off to
2317 add_control_char_runes.
2319 The is_*() routines have undefined results on
2320 arguments outside of the range [-1, 255]. (This
2321 often bites people who carelessly use `char' instead
2322 of `unsigned char'.)
2324 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2326 *prop = add_control_char_runes (&data, b);
2332 /* If the character is above the ASCII range and we have not
2333 already handled it, then print it as an octal number. */
2334 else if (data.ch >= 0200)
2336 *prop = add_octal_runes (&data);
2342 /* Assume the current character is considered to be printable,
2343 then just add it. */
2346 *prop = add_emchar_rune (&data);
2351 INC_BYTIND (b, data.bi_bufpos);
2357 /* Determine the starting point of the next line if we did not hit the
2358 end of the buffer. */
2359 if (data.bi_bufpos < BI_BUF_ZV (b)
2360 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2362 /* #### This check is not correct. If the line terminated
2363 due to a begin-glyph or end-glyph hitting window-end, then
2364 data.ch will not point to the character at data.bi_bufpos. If
2365 you make the two changes mentioned at the top of this loop,
2366 you should be able to say '(if (*prop))'. That should also
2367 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2370 /* The common case is that the line ended because we hit a newline.
2371 In that case, the next character is just the next buffer
2373 if (data.ch == '\n')
2375 /* If data.start_col_enabled is still true, then the window is
2376 scrolled far enough so that nothing on this line is visible.
2377 We need to stick a truncation glyph at the beginning of the
2378 line in that case unless the line is completely blank. */
2379 if (data.bi_start_col_enabled)
2381 if (data.cursor_type == CURSOR_ON)
2383 if (data.bi_cursor_bufpos >= bi_start_pos
2384 && data.bi_cursor_bufpos <= data.bi_bufpos)
2385 data.bi_cursor_bufpos = data.bi_bufpos;
2387 data.findex = DEFAULT_INDEX;
2389 data.bi_start_col_enabled = 0;
2391 if (data.bi_bufpos != bi_start_pos)
2393 struct glyph_block gb;
2396 gb.glyph = Vhscroll_glyph;
2397 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2398 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2402 /* This duplicates code down below to add a newline to
2403 the end of an otherwise empty line.*/
2405 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2407 add_emchar_rune (&data);
2411 INC_BYTIND (b, data.bi_bufpos);
2414 /* Otherwise we have a buffer line which cannot fit on one display
2418 struct glyph_block gb;
2419 struct glyph_cachel *cachel;
2421 /* If the line is to be truncated then we actually have to look
2422 for the next newline. We also add the end-of-line glyph which
2423 we know will fit because we adjusted the right border before
2424 we starting laying out the line. */
2425 data.max_pixpos += end_glyph_width;
2426 data.findex = DEFAULT_INDEX;
2433 /* Now find the start of the next line. */
2434 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2436 /* If the cursor is past the truncation line then we
2437 make it appear on the truncation glyph. If we've hit
2438 the end of the buffer then we also make the cursor
2439 appear unless eob is immediately preceded by a
2440 newline. In that case the cursor should actually
2441 appear on the next line. */
2442 if (data.cursor_type == CURSOR_ON
2443 && data.bi_cursor_bufpos >= data.bi_bufpos
2444 && (data.bi_cursor_bufpos < bi_pos ||
2445 (bi_pos == BI_BUF_ZV (b)
2446 && (bi_pos == BI_BUF_BEGV (b)
2447 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2449 data.bi_cursor_bufpos = bi_pos;
2451 data.cursor_type = NO_CURSOR;
2453 data.bi_bufpos = bi_pos;
2454 gb.glyph = Vtruncation_glyph;
2455 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2459 /* The cursor can never be on the continuation glyph. */
2460 data.cursor_type = NO_CURSOR;
2462 /* data.bi_bufpos is already at the start of the next line. */
2464 gb.glyph = Vcontinuation_glyph;
2465 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2468 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
2470 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2471 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2472 /* #### Damn this losing shit. */
2476 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2477 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2479 /* We need to add a marker to the end of the line since there is no
2480 newline character in order for the cursor to get drawn. We label
2481 it as a newline so that it gets handled correctly by the
2482 whitespace routines below. */
2485 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2486 data.findex = DEFAULT_INDEX;
2488 data.start_col_xoffset = 0;
2489 data.bi_start_col_enabled = 0;
2491 data.max_pixpos += data.blank_width;
2492 add_emchar_rune (&data);
2493 data.max_pixpos -= data.blank_width;
2495 /* #### urk! Chuck, this shit is bad news. Going around
2496 manipulating invalid positions is guaranteed to result in
2497 trouble sooner or later. */
2498 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2501 /* Calculate left whitespace boundary. */
2505 /* Whitespace past a newline is considered right whitespace. */
2506 while (elt < Dynarr_length (db->runes))
2508 struct rune *rb = Dynarr_atp (db->runes, elt);
2510 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2511 || rb->type == RUNE_BLANK)
2513 dl->bounds.left_white += rb->width;
2517 elt = Dynarr_length (db->runes);
2521 /* Calculate right whitespace boundary. */
2523 int elt = Dynarr_length (db->runes) - 1;
2526 while (!done && elt >= 0)
2528 struct rune *rb = Dynarr_atp (db->runes, elt);
2530 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2531 && isspace (rb->object.chr.ch))
2532 && !rb->type == RUNE_BLANK)
2534 dl->bounds.right_white = rb->xpos + rb->width;
2542 /* The line is blank so everything is considered to be right
2545 dl->bounds.right_white = dl->bounds.left_in;
2548 /* Set the display blocks bounds. */
2549 db->start_pos = dl->bounds.left_in;
2550 if (Dynarr_length (db->runes))
2552 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2554 db->end_pos = rb->xpos + rb->width;
2557 db->end_pos = dl->bounds.right_white;
2559 /* update line height parameters */
2560 if (!data.new_ascent && !data.new_descent)
2562 /* We've got a blank line so initialize these values from the default
2564 default_face_font_info (data.window, &data.new_ascent,
2565 &data.new_descent, 0, 0, 0);
2568 if (data.max_pixmap_height)
2570 int height = data.new_ascent + data.new_descent;
2571 int pix_ascent, pix_descent;
2573 pix_descent = data.max_pixmap_height * data.new_descent / height;
2574 pix_ascent = data.max_pixmap_height - pix_descent;
2576 data.new_ascent = max (data.new_ascent, pix_ascent);
2577 data.new_descent = max (data.new_descent, pix_descent);
2580 dl->ascent = data.new_ascent;
2581 dl->descent = data.new_descent;
2584 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2586 if (dl->ascent < ascent)
2587 dl->ascent = ascent;
2590 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2592 if (dl->descent < descent)
2593 dl->descent = descent;
2596 dl->cursor_elt = data.cursor_x;
2597 /* #### lossage lossage lossage! Fix this shit! */
2598 if (data.bi_bufpos > BI_BUF_ZV (b))
2599 dl->end_bufpos = BUF_ZV (b);
2601 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2603 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2605 /* This doesn't correctly take into account tabs and control
2606 characters but if the window isn't being truncated then this
2607 value isn't going to end up being used anyhow. */
2608 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2610 /* #### handle horizontally scrolled line with text none of which
2611 was actually laid out. */
2613 /* #### handle any remainder of overlay arrow */
2615 if (*prop == ADD_FAILED)
2618 if (truncate_win && *prop)
2620 Dynarr_free (*prop);
2624 extent_fragment_delete (data.ef);
2626 /* #### If we started at EOB, then make sure we return a value past
2627 it so that regenerate_window will exit properly. This is bogus.
2628 The main loop should get fixed so that it isn't necessary to call
2629 this function if we are already at EOB. */
2631 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2632 return data.bi_bufpos + 1; /* Yuck! */
2634 return data.bi_bufpos;
2637 /* Display the overlay arrow at the beginning of the given line. */
2640 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2642 struct frame *f = XFRAME (w->frame);
2643 struct device *d = XDEVICE (f->device);
2646 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2647 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2653 XSETWINDOW (data.window, w);
2654 data.db = get_display_block_from_line (dl, OVERWRITE);
2656 data.pixpos = dl->bounds.left_in;
2657 data.max_pixpos = dl->bounds.right_in;
2658 data.cursor_type = NO_CURSOR;
2660 data.findex = DEFAULT_INDEX;
2661 data.last_charset = Qunbound;
2662 data.last_findex = DEFAULT_INDEX;
2663 data.result_str = Qnil;
2666 Dynarr_reset (data.db->runes);
2668 if (STRINGP (Voverlay_arrow_string))
2670 add_bufbyte_string_runes
2672 XSTRING_DATA (Voverlay_arrow_string),
2673 XSTRING_LENGTH (Voverlay_arrow_string),
2676 else if (GLYPHP (Voverlay_arrow_string))
2678 struct glyph_block gb;
2680 gb.glyph = Voverlay_arrow_string;
2682 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2685 if (data.max_pixmap_height)
2687 int height = data.new_ascent + data.new_descent;
2688 int pix_ascent, pix_descent;
2690 pix_descent = data.max_pixmap_height * data.new_descent / height;
2691 pix_ascent = data.max_pixmap_height - pix_descent;
2693 data.new_ascent = max (data.new_ascent, pix_ascent);
2694 data.new_descent = max (data.new_descent, pix_descent);
2697 dl->ascent = data.new_ascent;
2698 dl->descent = data.new_descent;
2700 data.db->start_pos = dl->bounds.left_in;
2701 data.db->end_pos = data.pixpos;
2703 return data.pixpos - dl->bounds.left_in;
2706 /* Add a type of glyph to a margin display block. */
2709 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2710 int count, enum glyph_layout layout, int side, Lisp_Object window)
2712 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2714 : dl->right_glyphs);
2719 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2720 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2723 elt = Dynarr_length (gbd) - 1;
2730 end = Dynarr_length (gbd);
2733 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2735 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2737 if (NILP (gb->extent))
2738 abort (); /* these should have been handled in add_glyph_rune */
2741 ((side == LEFT_GLYPHS &&
2742 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2743 || (side == RIGHT_GLYPHS &&
2744 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2748 rb.width = gb->width;
2749 rb.findex = gb->findex;
2753 rb.type = RUNE_DGLYPH;
2754 rb.object.dglyph.glyph = gb->glyph;
2755 rb.object.dglyph.extent = gb->extent;
2756 rb.object.dglyph.xoffset = 0;
2757 rb.cursor_type = CURSOR_OFF;
2759 Dynarr_add (db->runes, rb);
2764 if (glyph_contrib_p (gb->glyph, window))
2766 unsigned short ascent, descent;
2767 Lisp_Object baseline = glyph_baseline (gb->glyph, window);
2769 ascent = glyph_ascent (gb->glyph, window);
2770 descent = glyph_descent (gb->glyph, window);
2772 /* A pixmap that has not had a baseline explicitly set.
2773 We use the existing ascent / descent ratio of the
2775 if (NILP (baseline))
2777 int gheight = ascent + descent;
2778 int line_height = dl->ascent + dl->descent;
2779 int pix_ascent, pix_descent;
2781 pix_descent = (int) (gheight * dl->descent) / line_height;
2782 pix_ascent = gheight - pix_descent;
2784 dl->ascent = max ((int) dl->ascent, pix_ascent);
2785 dl->descent = max ((int) dl->descent, pix_descent);
2788 /* A string so determine contribution normally. */
2789 else if (EQ (baseline, Qt))
2791 dl->ascent = max (dl->ascent, ascent);
2792 dl->descent = max (dl->descent, descent);
2795 /* A pixmap with an explicitly set baseline. We determine the
2796 contribution here. */
2797 else if (INTP (baseline))
2799 int height = ascent + descent;
2800 int pix_ascent, pix_descent;
2802 pix_ascent = height * XINT (baseline) / 100;
2803 pix_descent = height - pix_ascent;
2805 dl->ascent = max ((int) dl->ascent, pix_ascent);
2806 dl->descent = max ((int) dl->descent, pix_descent);
2809 /* Otherwise something is screwed up. */
2815 (reverse ? elt-- : elt++);
2821 /* Add a blank to a margin display block. */
2824 add_margin_blank (struct display_line *dl, struct display_block *db,
2825 struct window *w, int xpos, int width, int side)
2829 rb.findex = (side == LEFT_GLYPHS
2830 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2831 : get_builtin_face_cache_index (w, Vright_margin_face));
2836 rb.type = RUNE_BLANK;
2837 rb.cursor_type = CURSOR_OFF;
2839 Dynarr_add (db->runes, rb);
2842 /* Display glyphs in the left outside margin, left inside margin and
2843 left whitespace area. */
2846 create_left_glyph_block (struct window *w, struct display_line *dl,
2851 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2853 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2854 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2855 int left_in_start = dl->bounds.left_in;
2856 int left_in_end = dl->bounds.left_in + overlay_width;
2858 struct display_block *odb, *idb;
2860 XSETWINDOW (window, w);
2862 /* We have to add the glyphs to the line in the order outside,
2863 inside, whitespace. However the precedence dictates that we
2864 determine how many will fit in the reverse order. */
2866 /* Determine how many whitespace glyphs we can display and where
2867 they should start. */
2868 white_in_start = dl->bounds.left_white;
2869 white_out_start = left_in_start;
2870 white_out_cnt = white_in_cnt = 0;
2873 while (elt < Dynarr_length (dl->left_glyphs))
2875 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2877 if (NILP (gb->extent))
2878 abort (); /* these should have been handled in add_glyph_rune */
2880 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2884 width = glyph_width (gb->glyph, window);
2886 if (white_in_start - width >= left_in_end)
2889 white_in_start -= width;
2893 else if (use_overflow
2894 && (white_out_start - width > dl->bounds.left_out))
2897 white_out_start -= width;
2908 /* Determine how many inside margin glyphs we can display and where
2909 they should start. The inside margin glyphs get whatever space
2910 is left after the whitespace glyphs have been displayed. These
2911 are tricky to calculate since if we decide to use the overflow
2912 area we basically have to start over. So for these we build up a
2913 list of just the inside margin glyphs and manipulate it to
2914 determine the needed info. */
2916 glyph_block_dynarr *ib;
2917 int avail_in, avail_out;
2920 int used_in, used_out;
2923 used_in = used_out = 0;
2924 ib = Dynarr_new (glyph_block);
2925 while (elt < Dynarr_length (dl->left_glyphs))
2927 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2929 if (NILP (gb->extent))
2930 abort (); /* these should have been handled in add_glyph_rune */
2932 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2935 gb->width = glyph_width (gb->glyph, window);
2936 used_in += gb->width;
2937 Dynarr_add (ib, *gb);
2947 avail_in = white_in_start - left_in_end;
2955 avail_out = white_out_start - dl->bounds.left_out;
2958 while (!done && marker < Dynarr_length (ib))
2960 int width = Dynarr_atp (ib, marker)->width;
2962 /* If everything now fits in the available inside margin
2963 space, we're done. */
2964 if (used_in <= avail_in)
2968 /* Otherwise see if we have room to move a glyph to the
2970 if (used_out + width <= avail_out)
2983 /* At this point we now know that everything from marker on goes in
2984 the inside margin and everything before it goes in the outside
2985 margin. The stuff going into the outside margin is guaranteed
2986 to fit, but we may have to trim some stuff from the inside. */
2988 in_in_end = left_in_end;
2989 in_out_start = white_out_start;
2990 in_out_cnt = in_in_cnt = 0;
2994 while (elt < Dynarr_length (dl->left_glyphs))
2996 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2998 if (NILP (gb->extent))
2999 abort (); /* these should have been handled in add_glyph_rune */
3001 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3004 int width = glyph_width (gb->glyph, window);
3009 in_out_start -= width;
3014 else if (in_in_end + width < white_in_start)
3029 /* Determine how many outside margin glyphs we can display. They
3030 always start at the left outside margin and can only use the
3031 outside margin space. */
3032 out_end = dl->bounds.left_out;
3036 while (elt < Dynarr_length (dl->left_glyphs))
3038 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3040 if (NILP (gb->extent))
3041 abort (); /* these should have been handled in add_glyph_rune */
3043 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3046 int width = glyph_width (gb->glyph, window);
3048 if (out_end + width <= in_out_start)
3062 /* Now that we know where everything goes, we add the glyphs as
3063 runes to the appropriate display blocks. */
3064 if (out_cnt || in_out_cnt || white_out_cnt)
3066 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3067 odb->start_pos = dl->bounds.left_out;
3068 /* #### We should stop adding a blank to account for the space
3069 between the end of the glyphs and the margin and instead set
3070 this accordingly. */
3071 odb->end_pos = dl->bounds.left_in;
3072 Dynarr_reset (odb->runes);
3077 if (in_in_cnt || white_in_cnt)
3079 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3080 idb->start_pos = dl->bounds.left_in;
3081 /* #### See above comment for odb->end_pos */
3082 idb->end_pos = dl->bounds.left_white;
3083 Dynarr_reset (idb->runes);
3088 /* First add the outside margin glyphs. */
3090 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3091 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3093 end_xpos = dl->bounds.left_out;
3095 /* There may be blank space between the outside margin glyphs and
3096 the inside margin glyphs. If so, add a blank. */
3097 if (in_out_cnt && (in_out_start - end_xpos))
3099 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3103 /* Next add the inside margin glyphs which are actually in the
3107 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3108 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3111 /* If we didn't add any inside margin glyphs to the outside margin,
3112 but are adding whitespace glyphs, then we need to add a blank
3114 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3116 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3120 /* Next add the whitespace margin glyphs which are actually in the
3124 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3125 GL_WHITESPACE, LEFT_GLYPHS, window);
3128 /* We take care of clearing between the end of the glyphs and the
3129 start of the inside margin for lines which have glyphs. */
3130 if (odb && (left_in_start - end_xpos))
3132 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3136 /* Next add the inside margin glyphs which are actually in the
3140 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3141 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3144 end_xpos = left_in_end;
3146 /* Make sure that the area between the end of the inside margin
3147 glyphs and the whitespace glyphs is cleared. */
3148 if (idb && (white_in_start - end_xpos > 0))
3150 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3154 /* Next add the whitespace margin glyphs which are actually in the
3158 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3159 LEFT_GLYPHS, window);
3162 /* Whitespace glyphs always end right next to the text block so
3163 there is nothing we have to make sure is cleared after them. */
3166 /* Display glyphs in the right outside margin, right inside margin and
3167 right whitespace area. */
3170 create_right_glyph_block (struct window *w, struct display_line *dl)
3174 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3176 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3177 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3179 struct display_block *odb, *idb;
3181 XSETWINDOW (window, w);
3183 /* We have to add the glyphs to the line in the order outside,
3184 inside, whitespace. However the precedence dictates that we
3185 determine how many will fit in the reverse order. */
3187 /* Determine how many whitespace glyphs we can display and where
3188 they should start. */
3189 white_in_end = dl->bounds.right_white;
3190 white_out_end = dl->bounds.right_in;
3191 white_out_cnt = white_in_cnt = 0;
3194 while (elt < Dynarr_length (dl->right_glyphs))
3196 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3198 if (NILP (gb->extent))
3199 abort (); /* these should have been handled in add_glyph_rune */
3201 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3203 int width = glyph_width (gb->glyph, window);
3205 if (white_in_end + width <= dl->bounds.right_in)
3208 white_in_end += width;
3212 else if (use_overflow
3213 && (white_out_end + width <= dl->bounds.right_out))
3216 white_out_end += width;
3227 /* Determine how many inside margin glyphs we can display and where
3228 they should start. The inside margin glyphs get whatever space
3229 is left after the whitespace glyphs have been displayed. These
3230 are tricky to calculate since if we decide to use the overflow
3231 area we basically have to start over. So for these we build up a
3232 list of just the inside margin glyphs and manipulate it to
3233 determine the needed info. */
3235 glyph_block_dynarr *ib;
3236 int avail_in, avail_out;
3239 int used_in, used_out;
3242 used_in = used_out = 0;
3243 ib = Dynarr_new (glyph_block);
3244 while (elt < Dynarr_length (dl->right_glyphs))
3246 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3248 if (NILP (gb->extent))
3249 abort (); /* these should have been handled in add_glyph_rune */
3251 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3253 gb->width = glyph_width (gb->glyph, window);
3254 used_in += gb->width;
3255 Dynarr_add (ib, *gb);
3264 avail_in = dl->bounds.right_in - white_in_end;
3269 avail_out = dl->bounds.right_out - white_out_end;
3272 while (!done && marker < Dynarr_length (ib))
3274 int width = Dynarr_atp (ib, marker)->width;
3276 /* If everything now fits in the available inside margin
3277 space, we're done. */
3278 if (used_in <= avail_in)
3282 /* Otherwise see if we have room to move a glyph to the
3284 if (used_out + width <= avail_out)
3297 /* At this point we now know that everything from marker on goes in
3298 the inside margin and everything before it goes in the outside
3299 margin. The stuff going into the outside margin is guaranteed
3300 to fit, but we may have to trim some stuff from the inside. */
3302 in_in_start = dl->bounds.right_in;
3303 in_out_end = dl->bounds.right_in;
3304 in_out_cnt = in_in_cnt = 0;
3308 while (elt < Dynarr_length (dl->right_glyphs))
3310 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3312 if (NILP (gb->extent))
3313 abort (); /* these should have been handled in add_glyph_rune */
3315 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3317 int width = glyph_width (gb->glyph, window);
3322 in_out_end += width;
3327 else if (in_in_start - width >= white_in_end)
3330 in_in_start -= width;
3342 /* Determine how many outside margin glyphs we can display. They
3343 always start at the right outside margin and can only use the
3344 outside margin space. */
3345 out_start = dl->bounds.right_out;
3349 while (elt < Dynarr_length (dl->right_glyphs))
3351 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3353 if (NILP (gb->extent))
3354 abort (); /* these should have been handled in add_glyph_rune */
3356 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3358 int width = glyph_width (gb->glyph, window);
3360 if (out_start - width >= in_out_end)
3374 /* Now that we now where everything goes, we add the glyphs as runes
3375 to the appropriate display blocks. */
3376 if (out_cnt || in_out_cnt || white_out_cnt)
3378 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3379 /* #### See comments before odb->start_pos init in
3380 create_left_glyph_block */
3381 odb->start_pos = dl->bounds.right_in;
3382 odb->end_pos = dl->bounds.right_out;
3383 Dynarr_reset (odb->runes);
3388 if (in_in_cnt || white_in_cnt)
3390 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3391 idb->start_pos = dl->bounds.right_white;
3392 /* #### See comments before odb->start_pos init in
3393 create_left_glyph_block */
3394 idb->end_pos = dl->bounds.right_in;
3395 Dynarr_reset (idb->runes);
3400 /* First add the whitespace margin glyphs which are actually in the
3404 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3405 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3409 end_xpos = dl->bounds.right_white;
3411 /* Make sure that the area between the end of the whitespace glyphs
3412 and the inside margin glyphs is cleared. */
3413 if (in_in_cnt && (in_in_start - end_xpos))
3415 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3419 /* Next add the inside margin glyphs which are actually in the
3423 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3424 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3427 /* If we didn't add any inside margin glyphs then make sure the rest
3428 of the inside margin area gets cleared. */
3429 if (idb && (dl->bounds.right_in - end_xpos))
3431 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3435 /* Next add any whitespace glyphs in the outside margin. */
3438 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3439 GL_WHITESPACE, RIGHT_GLYPHS, window);
3442 end_xpos = dl->bounds.right_in;
3444 /* Next add any inside margin glyphs in the outside margin. */
3447 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3448 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3451 /* There may be space between any whitespace or inside margin glyphs
3452 in the outside margin and the actual outside margin glyphs. */
3453 if (odb && (out_start - end_xpos))
3455 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3459 /* Finally, add the outside margin glyphs. */
3462 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3463 RIGHT_GLYPHS, window);
3468 /***************************************************************************/
3470 /* modeline routines */
3472 /***************************************************************************/
3474 /* This function is also used in frame.c by `generate_title_string' */
3476 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3477 struct window *w, struct display_line *dl,
3478 struct display_block *db, face_index findex,
3479 int min_pixpos, int max_pixpos, int type)
3481 struct frame *f = XFRAME (w->frame);
3482 struct device *d = XDEVICE (f->device);
3486 Charcount offset = 0;
3492 data.findex = findex;
3493 data.pixpos = min_pixpos;
3494 data.max_pixpos = max_pixpos;
3495 data.cursor_type = NO_CURSOR;
3496 data.last_charset = Qunbound;
3497 data.last_findex = DEFAULT_INDEX;
3498 data.result_str = result_str;
3499 data.is_modeline = 1;
3501 XSETWINDOW (data.window, w);
3503 Dynarr_reset (formatted_string_extent_dynarr);
3504 Dynarr_reset (formatted_string_extent_start_dynarr);
3505 Dynarr_reset (formatted_string_extent_end_dynarr);
3507 /* result_str is nil when we're building a frame or icon title. Otherwise,
3508 we're building a modeline, so the offset starts at the modeline
3509 horizontal scrolling ammount */
3510 if (! NILP (result_str))
3511 offset = w->modeline_hscroll;
3512 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3513 max_pixpos - min_pixpos, findex, type, &offset,
3516 if (Dynarr_length (db->runes))
3519 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3520 c_pixpos = rb->xpos + rb->width;
3523 c_pixpos = min_pixpos;
3525 /* If we don't reach the right side of the window, add a blank rune
3526 to make up the difference. This usually only occurs if the
3527 modeline face is using a proportional width font or a fixed width
3528 font of a different size from the default face font. */
3530 if (c_pixpos < max_pixpos)
3532 data.pixpos = c_pixpos;
3533 data.blank_width = max_pixpos - data.pixpos;
3535 add_blank_rune (&data, NULL, 0);
3538 /* Now create the result string and frob the extents into it. */
3539 if (!NILP (result_str))
3544 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3546 detach_all_extents (result_str);
3547 resize_string (XSTRING (result_str), -1,
3548 data.bytepos - XSTRING_LENGTH (result_str));
3550 strdata = XSTRING_DATA (result_str);
3552 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3554 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3556 len += (set_charptr_emchar
3557 (strdata + len, Dynarr_atp (db->runes,
3558 elt)->object.chr.ch));
3562 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3565 Lisp_Object extent = Qnil;
3568 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3569 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3572 child = Fmake_extent (Qnil, Qnil, result_str);
3573 Fputhash (extent, child, buf->modeline_extent_table);
3575 Fset_extent_parent (child, extent);
3576 set_extent_endpoints
3578 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3579 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3585 /* Ensure that the given display line DL accurately represents the
3586 modeline for the given window. */
3588 generate_modeline (struct window *w, struct display_line *dl, int type)
3590 struct buffer *b = XBUFFER (w->buffer);
3591 struct frame *f = XFRAME (w->frame);
3592 struct device *d = XDEVICE (f->device);
3594 /* Unlike display line and rune pointers, this one can't change underneath
3596 struct display_block *db = get_display_block_from_line (dl, TEXT);
3597 int max_pixpos, min_pixpos, ypos_adj;
3598 Lisp_Object font_inst;
3600 /* This will actually determine incorrect inside boundaries for the
3601 modeline since it ignores the margins. However being aware of this fact
3602 we never use those values anywhere so it doesn't matter. */
3603 dl->bounds = calculate_display_line_boundaries (w, 1);
3605 /* We are generating a modeline. */
3607 dl->cursor_elt = -1;
3609 /* Reset the runes on the modeline. */
3610 Dynarr_reset (db->runes);
3612 if (!WINDOW_HAS_MODELINE_P (w))
3616 /* If there is a horizontal scrollbar, don't add anything. */
3617 if (window_scrollbar_height (w))
3620 dl->ascent = DEVMETH (d, divider_height, ());
3622 /* The modeline is at the bottom of the gutters. */
3623 dl->ypos = WINDOW_BOTTOM (w);
3625 /* adjust for the bottom gutter */
3626 if (window_is_lowest (w))
3627 dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
3629 rb.findex = MODELINE_INDEX;
3630 rb.xpos = dl->bounds.left_out;
3631 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3634 rb.type = RUNE_HLINE;
3635 rb.object.hline.thickness = 1;
3636 rb.object.hline.yoffset = 0;
3637 rb.cursor_type = NO_CURSOR;
3639 if (!EQ (Qzero, w->modeline_shadow_thickness)
3642 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3644 dl->ypos -= shadow_thickness;
3645 rb.xpos += shadow_thickness;
3646 rb.width -= 2 * shadow_thickness;
3649 Dynarr_add (db->runes, rb);
3653 /* !!#### not right; needs to compute the max height of
3655 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3657 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3658 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3660 min_pixpos = dl->bounds.left_out;
3661 max_pixpos = dl->bounds.right_out;
3663 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3665 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3667 ypos_adj = shadow_thickness;
3668 min_pixpos += shadow_thickness;
3669 max_pixpos -= shadow_thickness;
3674 generate_formatted_string_db (b->modeline_format,
3675 b->generated_modeline_string, w, dl, db,
3676 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3678 /* The modeline is at the bottom of the gutters. We have to wait to
3679 set this until we've generated the modeline in order to account
3680 for any embedded faces. */
3681 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3682 /* adjust for the bottom gutter */
3683 if (window_is_lowest (w))
3684 dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
3688 add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
3689 Charcount pos, Charcount min_pos, Charcount max_pos)
3691 /* This function has been Mule-ized. */
3693 CONST Bufbyte *cur_pos = str;
3694 struct display_block *db = data->db;
3696 data->blank_width = space_width (XWINDOW (data->window));
3697 while (Dynarr_length (db->runes) < pos)
3698 add_blank_rune (data, NULL, 0);
3700 end = (Dynarr_length (db->runes) +
3701 bytecount_to_charcount (str, strlen ((CONST char *) str)));
3703 end = min (max_pos, end);
3705 while (pos < end && *cur_pos)
3707 CONST Bufbyte *old_cur_pos = cur_pos;
3710 data->ch = charptr_emchar (cur_pos);
3711 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3712 INC_CHARPTR (cur_pos);
3716 data->modeline_charpos++;
3717 data->bytepos += cur_pos - old_cur_pos;
3721 while (Dynarr_length (db->runes) < min_pos &&
3722 (data->pixpos + data->blank_width <= data->max_pixpos))
3723 add_blank_rune (data, NULL, 0);
3725 return Dynarr_length (db->runes);
3728 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3729 modeline extents. */
3731 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3732 Charcount pos, Charcount min_pos,
3733 Charcount max_pos, Lisp_Object extent)
3735 /* This function has been Mule-ized. */
3737 struct display_block *db = data->db;
3738 struct glyph_block gb;
3740 data->blank_width = space_width (XWINDOW (data->window));
3741 while (Dynarr_length (db->runes) < pos)
3742 add_blank_rune (data, NULL, 0);
3744 end = Dynarr_length (db->runes) + 1;
3746 end = min (max_pos, end);
3750 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3753 while (Dynarr_length (db->runes) < pos &&
3754 (data->pixpos + data->blank_width <= data->max_pixpos))
3755 add_blank_rune (data, NULL, 0);
3757 return Dynarr_length (db->runes);
3760 /* If max_pos is == -1, it is considered to be infinite. The same is
3761 true of max_pixsize. */
3762 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3763 if (Dynarr_length (data->db->runes)) \
3764 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3768 /* Note that this function does "positions" in terms of characters and
3769 not in terms of columns. This is necessary to make the formatting
3770 work correctly when proportional width fonts are used in the
3773 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3774 Charcount min_pos, Charcount max_pos,
3775 Lisp_Object elt, int depth, int max_pixsize,
3776 face_index findex, int type, Charcount *offset,
3777 Lisp_Object cur_ext)
3779 /* This function has been Mule-ized. */
3780 /* #### The other losing things in this function are:
3782 -- C zero-terminated-string lossage.
3783 -- Non-printable characters should be converted into something
3784 appropriate (e.g. ^F) instead of blindly being printed anyway.
3795 /* A string. Add to the display line and check for %-constructs
3798 Bufbyte *this = XSTRING_DATA (elt);
3800 while ((pos < max_pos || max_pos == -1) && *this)
3802 Bufbyte *last = this;
3804 while (*this && *this != '%')
3809 /* No %-construct */
3811 bytecount_to_charcount (last, this - last);
3813 if (size <= *offset)
3817 Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
3818 min (pos + size - *offset, max_pos));
3819 CONST Bufbyte *tmp_last = charptr_n_addr (last, *offset);
3821 pos = add_string_to_fstring_db_runes (data, tmp_last,
3826 else /* *this == '%' */
3828 Charcount spec_width = 0;
3830 this++; /* skip over '%' */
3832 /* We can't allow -ve args due to the "%-" construct.
3833 * Argument specifies minwidth but not maxwidth
3834 * (maxwidth can be specified by
3835 * (<negative-number> . <stuff>) modeline elements)
3837 while (isdigit (*this))
3839 spec_width = spec_width * 10 + (*this - '0');
3846 pos = generate_fstring_runes (w, data, pos, spec_width,
3847 max_pos, Vglobal_mode_string,
3848 depth, max_pixsize, findex,
3849 type, offset, cur_ext);
3851 else if (*this == '-')
3853 Charcount num_to_add;
3855 if (max_pixsize < 0)
3857 else if (max_pos != -1)
3858 num_to_add = max_pos - pos;
3864 SET_CURRENT_MODE_CHARS_PIXSIZE;
3867 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3870 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3874 while (num_to_add--)
3875 pos = add_string_to_fstring_db_runes
3876 (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
3878 else if (*this != 0)
3880 Emchar ch = charptr_emchar (this);
3884 decode_mode_spec (w, ch, type);
3886 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3887 size = bytecount_to_charcount
3888 /* Skip the null character added by `decode_mode_spec' */
3889 (str, Dynarr_length (mode_spec_bufbyte_string)) - 1;
3891 if (size <= *offset)
3895 CONST Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3897 /* ### NOTE: I don't understand why a tmp_max is not
3898 computed and used here as in the plain string case
3900 pos = add_string_to_fstring_db_runes (data, tmp_str,
3907 /* NOT this++. There could be any sort of character at
3908 the current position. */
3912 if (max_pixsize > 0)
3915 SET_CURRENT_MODE_CHARS_PIXSIZE;
3917 if (cur_pixsize >= max_pixsize)
3922 else if (SYMBOLP (elt))
3924 /* A symbol: process the value of the symbol recursively
3925 as if it appeared here directly. */
3926 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3928 if (!UNBOUNDP (tem))
3930 /* If value is a string, output that string literally:
3931 don't check for % within it. */
3934 Bufbyte *str = XSTRING_DATA (tem);
3935 Charcount size = XSTRING_CHAR_LENGTH (tem);
3937 if (size <= *offset)
3941 CONST Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3943 /* ### NOTE: I don't understand why a tmp_max is not
3944 computed and used here as in the plain string case
3946 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
3951 /* Give up right away for nil or t. */
3952 else if (!EQ (tem, elt))
3959 else if (GENERIC_SPECIFIERP (elt))
3961 Lisp_Object window, tem;
3962 XSETWINDOW (window, w);
3963 tem = specifier_instance_no_quit (elt, Qunbound, window,
3964 ERROR_ME_NOT, 0, Qzero);
3965 if (!UNBOUNDP (tem))
3971 else if (CONSP (elt))
3973 /* A cons cell: four distinct cases.
3974 * - If first element is a string or a cons, process all the elements
3975 * and effectively concatenate them.
3976 * - If first element is a negative number, truncate displaying cdr to
3977 * at most that many characters. If positive, pad (with spaces)
3978 * to at least that many characters.
3979 * - If first element is another symbol, process the cadr or caddr
3980 * recursively according to whether the symbol's value is non-nil or
3982 * - If first element is a face, process the cdr recursively
3983 * without altering the depth.
3986 Lisp_Object car, tem;
3995 tem = symbol_value_in_buffer (car, w->buffer);
3996 /* elt is now the cdr, and we know it is a cons cell.
3997 Use its car if CAR has a non-nil value. */
3998 if (!UNBOUNDP (tem))
4006 /* Symbol's value is nil (or symbol is unbound)
4007 * Get the cddr of the original list
4008 * and if possible find the caddr and use that.
4013 else if (!CONSP (elt))
4021 else if (INTP (car))
4023 Charcount lim = XINT (car);
4029 /* Negative int means reduce maximum width.
4030 * DO NOT change MIN_PIXPOS here!
4031 * (20 -10 . foo) should truncate foo to 10 col
4032 * and then pad to 20.
4035 max_pos = pos - lim;
4037 max_pos = min (max_pos, pos - lim);
4041 /* Padding specified. Don't let it be more than
4045 if (max_pos != -1 && lim > max_pos)
4047 /* If that's more padding than already wanted, queue it.
4048 * But don't reduce padding already specified even if
4049 * that is beyond the current truncation point.
4056 else if (STRINGP (car) || CONSP (car))
4060 /* LIMIT is to protect against circular lists. */
4061 while (CONSP (elt) && --limit > 0
4062 && (pos < max_pos || max_pos == -1))
4064 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4065 XCAR (elt), depth, max_pixsize,
4066 findex, type, offset, cur_ext);
4070 else if (EXTENTP (car))
4072 struct extent *ext = XEXTENT (car);
4074 if (EXTENT_LIVE_P (ext))
4076 face_index old_findex = data->findex;
4078 Lisp_Object font_inst;
4079 face_index new_findex;
4080 Bytecount start = data->bytepos;
4082 face = extent_face (ext);
4085 /* #### needs to merge faces, sigh */
4086 /* #### needs to handle list of faces */
4087 new_findex = get_builtin_face_cache_index (w, face);
4088 /* !!#### not right; needs to compute the max height of
4090 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
4093 data->dl->ascent = max (data->dl->ascent,
4094 XFONT_INSTANCE (font_inst)->ascent);
4095 data->dl->descent = max (data->dl->descent,
4096 XFONT_INSTANCE (font_inst)->
4100 new_findex = old_findex;
4102 data->findex = new_findex;
4103 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4104 XCDR (elt), depth - 1,
4105 max_pixsize, new_findex, type,
4107 data->findex = old_findex;
4108 Dynarr_add (formatted_string_extent_dynarr, ext);
4109 Dynarr_add (formatted_string_extent_start_dynarr, start);
4110 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4114 else if (GLYPHP (elt))
4116 /* Glyphs are considered as one character with respect to the modeline
4117 horizontal scrolling facility. -- dv */
4121 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos,
4128 char *str = GETTEXT ("*invalid*");
4129 Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */
4131 if (size <= *offset)
4135 CONST Bufbyte *tmp_str =
4136 charptr_n_addr ((CONST Bufbyte *) str, *offset);
4138 /* ### NOTE: I don't understand why a tmp_max is not computed and
4139 used here as in the plain string case above. -- dv */
4140 pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
4149 add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos,
4156 /* Update just the modeline. Assumes the desired display structs. If
4157 they do not have a modeline block, it does nothing. */
4159 regenerate_modeline (struct window *w)
4161 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4163 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4167 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4168 redisplay_update_line (w, 0, 0, 0);
4172 /* Make sure that modeline display line is present in the given
4173 display structs if the window has a modeline and update that
4174 line. Returns true if a modeline was needed. */
4176 ensure_modeline_generated (struct window *w, int type)
4180 /* minibuffer windows don't have modelines */
4181 if (MINI_WINDOW_P (w))
4183 /* windows which haven't had it turned off do */
4184 else if (WINDOW_HAS_MODELINE_P (w))
4186 /* windows which have it turned off don't have a divider if there is
4187 a horizontal scrollbar */
4188 else if (window_scrollbar_height (w))
4190 /* and in this case there is none */
4196 display_line_dynarr *dla;
4198 dla = window_display_lines (w, type);
4200 /* We don't care if there is a display line which is not
4201 currently a modeline because it is definitely going to become
4202 one if we have gotten to this point. */
4203 if (Dynarr_length (dla) == 0)
4205 if (Dynarr_largest (dla) > 0)
4207 struct display_line *mlp = Dynarr_atp (dla, 0);
4208 Dynarr_add (dla, *mlp);
4212 struct display_line modeline;
4214 Dynarr_add (dla, modeline);
4218 /* If we're adding a new place marker go ahead and generate the
4219 modeline so that it is available for use by
4220 window_modeline_height. */
4221 generate_modeline (w, Dynarr_atp (dla, 0), type);
4224 return need_modeline;
4227 /* #### Kludge or not a kludge. I tend towards the former. */
4229 real_current_modeline_height (struct window *w)
4231 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4232 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4234 if (ensure_modeline_generated (w, CMOTION_DISP))
4236 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4238 if (Dynarr_length (dla))
4240 if (Dynarr_atp (dla, 0)->modeline)
4241 return (Dynarr_atp (dla, 0)->ascent +
4242 Dynarr_atp (dla, 0)->descent);
4249 /***************************************************************************/
4251 /* displayable string routines */
4253 /***************************************************************************/
4255 /* Given a position for a string in a window, ensure that the given
4256 display line DL accurately represents the text on a line starting
4257 at the given position.
4259 Yes, this is duplicating the code of create_text_block, but it
4260 looked just too hard to change create_text_block to handle strings
4261 *and* buffers. We already make a distinction between the two
4262 elsewhere in the code so I think unifying them would require a
4263 complete MULE rewrite. Besides, the other distinction is that these
4264 functions cover text that the user *cannot edit* so we can remove
4265 everything to do with cursors, minibuffers etc. Eventually the
4266 modeline routines should be modified to use this code as it copes
4267 with many more types of display situation. */
4270 create_string_text_block (struct window *w, Lisp_Object disp_string,
4271 struct display_line *dl,
4273 prop_block_dynarr **prop,
4274 face_index default_face)
4276 struct frame *f = XFRAME (w->frame);
4277 /* Note that a lot of the buffer controlled stuff has been left in
4278 because you might well want to make use of it (selective display
4279 etc), its just the buffer text that we do not use. However, it
4280 seems to be possible for buffer to be nil sometimes so protect
4281 against this case. */
4282 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
4283 struct device *d = XDEVICE (f->device);
4284 struct Lisp_String* s = XSTRING (disp_string);
4286 /* we're working with these a lot so precalculate them */
4287 Bytecount slen = XSTRING_LENGTH (disp_string);
4288 Bytecount bi_string_zv = slen;
4289 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4293 int truncate_win = b ? window_truncation_on (w) : 0;
4294 int end_glyph_width = 0;
4296 /* we're going to ditch selective display for static text, its an
4297 FSF thing and invisble extents are the way to go
4298 here. Implementing it also relies on a number of buffer-specific
4299 functions that we don't have the luxury of being able to use
4302 /* The variable ctl-arrow allows the user to specify what characters
4303 can actually be displayed and which octal should be used for.
4304 #### This variable should probably have some rethought done to
4307 #### It would also be really nice if you could specify that
4308 the characters come out in hex instead of in octal. Mule
4309 does that by adding a ctl-hexa variable similar to ctl-arrow,
4310 but that's bogus -- we need a more general solution. I
4311 think you need to extend the concept of display tables
4312 into a more general conversion mechanism. Ideally you
4313 could specify a Lisp function that converts characters,
4314 but this violates the Second Golden Rule and besides would
4315 make things way way way way slow.
4317 So instead, we extend the display-table concept, which was
4318 historically limited to 256-byte vectors, to one of the
4321 a) A 256-entry vector, for backward compatibility;
4322 b) char-table, mapping characters to values;
4323 c) range-table, mapping ranges of characters to values;
4324 d) a list of the above.
4326 The (d) option allows you to specify multiple display tables
4327 instead of just one. Each display table can specify conversions
4328 for some characters and leave others unchanged. The way the
4329 character gets displayed is determined by the first display table
4330 with a binding for that character. This way, you could call a
4331 function `enable-hex-display' that adds a hex display-table to
4332 the list of display tables for the current buffer.
4334 #### ...not yet implemented... Also, we extend the concept of
4335 "mapping" to include a printf-like spec. Thus you can make all
4336 extended characters show up as hex with a display table like
4339 #s(range-table data ((256 524288) (format "%x")))
4341 Since more than one display table is possible, you have
4342 great flexibility in mapping ranges of characters. */
4343 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4344 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4345 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4346 ? 255 : 160)) : 255;
4348 Lisp_Object face_dt, window_dt;
4350 /* The text display block for this display line. */
4351 struct display_block *db = get_display_block_from_line (dl, TEXT);
4353 /* The first time through the main loop we need to force the glyph
4354 data to be updated. */
4357 /* Apparently the new extent_fragment_update returns an end position
4358 equal to the position passed in if there are no more runs to be
4360 int no_more_frags = 0;
4362 dl->used_prop_data = 0;
4365 /* set up faces to use for clearing areas, used by
4366 output_display_line */
4367 dl->default_findex = default_face;
4370 dl->left_margin_findex = default_face;
4371 dl->right_margin_findex = default_face;
4375 dl->left_margin_findex =
4376 get_builtin_face_cache_index (w, Vleft_margin_face);
4377 dl->right_margin_findex =
4378 get_builtin_face_cache_index (w, Vright_margin_face);
4382 data.ef = extent_fragment_new (disp_string, f);
4384 /* These values are used by all of the rune addition routines. We add
4385 them to this structure for ease of passing. */
4387 XSETWINDOW (data.window, w);
4391 data.bi_bufpos = bi_start_pos;
4392 data.pixpos = dl->bounds.left_in;
4393 data.last_charset = Qunbound;
4394 data.last_findex = default_face;
4395 data.result_str = Qnil;
4396 data.string = disp_string;
4398 /* Set the right boundary adjusting it to take into account any end
4399 glyph. Save the width of the end glyph for later use. */
4400 data.max_pixpos = dl->bounds.right_in;
4403 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
4405 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
4407 data.max_pixpos -= end_glyph_width;
4409 data.cursor_type = NO_CURSOR;
4413 /* I don't think we want this, string areas should not scroll with
4415 data.start_col = w->hscroll;
4416 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4418 data.bi_start_col_enabled = 0;
4419 data.hscroll_glyph_width_adjust = 0;
4421 /* We regenerate the line from the very beginning. */
4422 Dynarr_reset (db->runes);
4424 /* Why is this less than or equal and not just less than? If the
4425 starting position is already equal to the maximum we can't add
4426 anything else, right? Wrong. We might still have a newline to
4427 add. A newline can use the room allocated for an end glyph since
4428 if we add it we know we aren't going to be adding any end
4431 /* #### Chuck -- I think this condition should be while (1).
4432 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4433 and the begin-glyph ends exactly at the end of the window, the
4434 end-glyph and text might not be displayed. while (1) ensures
4435 that the loop terminates only when either (a) there is
4436 propagation data or (b) the end-of-line or end-of-buffer is hit.
4438 #### Also I think you need to ensure that the operation
4439 "add begin glyphs; add end glyphs; add text" is atomic and
4440 can't get interrupted in the middle. If you run off the end
4441 of the line during that operation, then you keep accumulating
4442 propagation data until you're done. Otherwise, if the (e.g.)
4443 there's a begin glyph at a particular position and attempting
4444 to display that glyph results in window-end being hit and
4445 propagation data being generated, then the character at that
4446 position won't be displayed.
4448 #### See also the comment after the end of this loop, below.
4450 while (data.pixpos <= data.max_pixpos)
4452 /* #### This check probably should not be necessary. */
4453 if (data.bi_bufpos > bi_string_zv)
4455 /* #### urk! More of this lossage! */
4460 /* Check for face changes. */
4461 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
4463 /* Now compute the face and begin/end-glyph information. */
4465 /* Remember that the extent-fragment routines deal in Bytind's. */
4466 extent_fragment_update (w, data.ef, data.bi_bufpos);
4467 /* This is somewhat cheesy but the alternative is to
4468 propagate default_face into extent_fragment_update. */
4469 if (data.findex == DEFAULT_INDEX)
4470 data.findex = default_face;
4472 get_display_tables (w, data.findex, &face_dt, &window_dt);
4474 if (data.bi_bufpos == data.ef->end)
4479 /* Determine what is next to be displayed. We first handle any
4480 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4481 display then we determine what to do based on the character at the
4482 current buffer position. */
4484 /* If the current position is covered by an invisible extent, do
4485 nothing (except maybe add some ellipses).
4487 #### The behavior of begin and end-glyphs at the edge of an
4488 invisible extent should be investigated further. This is
4489 fairly low priority though. */
4490 if (data.ef->invisible)
4492 /* #### Chuck, perhaps you could look at this code? I don't
4493 really know what I'm doing. */
4496 Dynarr_free (*prop);
4500 /* The extent fragment code only sets this when we should
4501 really display the ellipses. It makes sure the ellipses
4502 don't get displayed more than once in a row. */
4503 if (data.ef->invisible_ellipses)
4505 struct glyph_block gb;
4507 data.ef->invisible_ellipses_already_displayed = 1;
4508 data.ef->invisible_ellipses = 0;
4510 gb.glyph = Vinvisible_text_glyph;
4511 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
4512 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
4513 /* Perhaps they shouldn't propagate if the very next thing
4514 is to display a newline (for compatibility with
4515 selective-display-ellipses)? Maybe that's too
4521 /* #### What if we we're dealing with a display table? */
4525 if (data.bi_bufpos == bi_string_zv)
4528 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4531 /* If there is propagation data, then it represents the current
4532 buffer position being displayed. Add them and advance the
4533 position counter. This might also add the minibuffer
4537 dl->used_prop_data = 1;
4538 *prop = add_propagation_runes (prop, &data);
4541 goto done; /* gee, a really narrow window */
4542 else if (data.bi_bufpos == bi_string_zv)
4544 else if (data.bi_bufpos < 0)
4545 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4548 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4551 /* If there are end glyphs, add them to the line. These are
4552 the end glyphs for the previous run of text. We add them
4553 here rather than doing them at the end of handling the
4554 previous run so that glyphs at the beginning and end of
4555 a line are handled correctly. */
4556 else if (Dynarr_length (data.ef->end_glyphs) > 0)
4558 *prop = add_glyph_runes (&data, END_GLYPHS);
4563 /* If there are begin glyphs, add them to the line. */
4564 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
4566 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
4571 /* If at end-of-buffer, we've already processed begin and
4572 end-glyphs at this point and there's no text to process,
4574 else if (data.bi_bufpos == bi_string_zv)
4579 Lisp_Object entry = Qnil;
4580 /* Get the character at the current buffer position. */
4581 data.ch = string_char (s, data.bi_bufpos);
4582 if (!NILP (face_dt) || !NILP (window_dt))
4583 entry = display_table_entry (data.ch, face_dt, window_dt);
4585 /* If there is a display table entry for it, hand it off to
4586 add_disp_table_entry_runes and let it worry about it. */
4587 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
4589 *prop = add_disp_table_entry_runes (&data, entry);
4595 /* Check if we have hit a newline character. If so, add a marker
4596 to the line and end this loop. */
4597 else if (data.ch == '\n')
4599 /* We aren't going to be adding an end glyph so give its
4600 space back in order to make sure that the cursor can
4602 data.max_pixpos += end_glyph_width;
4606 /* If the current character is considered to be printable, then
4608 else if (data.ch >= printable_min)
4610 *prop = add_emchar_rune (&data);
4615 /* If the current character is a tab, determine the next tab
4616 starting position and add a blank rune which extends from the
4617 current pixel position to that starting position. */
4618 else if (data.ch == '\t')
4620 int tab_start_pixpos = data.pixpos;
4625 if (data.start_col > 1)
4626 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
4629 next_tab_position (w, tab_start_pixpos,
4630 dl->bounds.left_in +
4631 data.hscroll_glyph_width_adjust);
4632 if (next_tab_start > data.max_pixpos)
4634 prop_width = next_tab_start - data.max_pixpos;
4635 next_tab_start = data.max_pixpos;
4637 data.blank_width = next_tab_start - data.pixpos;
4639 (next_tab_start - tab_start_pixpos) / space_width (w);
4641 *prop = add_blank_rune (&data, w, char_tab_width);
4643 /* add_blank_rune is only supposed to be called with
4644 sizes guaranteed to fit in the available space. */
4649 struct prop_block pb;
4650 *prop = Dynarr_new (prop_block);
4652 pb.type = PROP_BLANK;
4653 pb.data.p_blank.width = prop_width;
4654 pb.data.p_blank.findex = data.findex;
4655 Dynarr_add (*prop, pb);
4661 /* If character is a control character, pass it off to
4662 add_control_char_runes.
4664 The is_*() routines have undefined results on
4665 arguments outside of the range [-1, 255]. (This
4666 often bites people who carelessly use `char' instead
4667 of `unsigned char'.)
4669 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
4671 *prop = add_control_char_runes (&data, b);
4677 /* If the character is above the ASCII range and we have not
4678 already handled it, then print it as an octal number. */
4679 else if (data.ch >= 0200)
4681 *prop = add_octal_runes (&data);
4687 /* Assume the current character is considered to be printable,
4688 then just add it. */
4691 *prop = add_emchar_rune (&data);
4696 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4702 /* Determine the starting point of the next line if we did not hit the
4703 end of the buffer. */
4704 if (data.bi_bufpos < bi_string_zv)
4706 /* #### This check is not correct. If the line terminated
4707 due to a begin-glyph or end-glyph hitting window-end, then
4708 data.ch will not point to the character at data.bi_bufpos. If
4709 you make the two changes mentioned at the top of this loop,
4710 you should be able to say '(if (*prop))'. That should also
4711 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4714 /* The common case is that the line ended because we hit a newline.
4715 In that case, the next character is just the next buffer
4717 if (data.ch == '\n')
4719 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4722 /* Otherwise we have a buffer line which cannot fit on one display
4726 struct glyph_block gb;
4727 struct glyph_cachel *cachel;
4729 /* If the line is to be truncated then we actually have to look
4730 for the next newline. We also add the end-of-line glyph which
4731 we know will fit because we adjusted the right border before
4732 we starting laying out the line. */
4733 data.max_pixpos += end_glyph_width;
4734 data.findex = default_face;
4741 /* Now find the start of the next line. */
4742 bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
4744 data.cursor_type = NO_CURSOR;
4745 data.bi_bufpos = bi_pos;
4746 gb.glyph = Vtruncation_glyph;
4747 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
4751 /* The cursor can never be on the continuation glyph. */
4752 data.cursor_type = NO_CURSOR;
4754 /* data.bi_bufpos is already at the start of the next line. */
4756 gb.glyph = Vcontinuation_glyph;
4757 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
4760 if (end_glyph_width)
4761 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
4763 if (truncate_win && data.bi_bufpos == bi_string_zv)
4765 CONST Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
4767 if (charptr_emchar (endb) != '\n')
4769 /* #### Damn this losing shit. */
4775 else if (data.bi_bufpos == bi_string_zv)
4777 /* create_text_block () adds a bogus \n marker here which screws
4778 up subwindow display. Since we never have a cursor in the
4779 gutter we can safely ignore it. */
4781 /* Calculate left whitespace boundary. */
4785 /* Whitespace past a newline is considered right whitespace. */
4786 while (elt < Dynarr_length (db->runes))
4788 struct rune *rb = Dynarr_atp (db->runes, elt);
4790 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4791 || rb->type == RUNE_BLANK)
4793 dl->bounds.left_white += rb->width;
4797 elt = Dynarr_length (db->runes);
4801 /* Calculate right whitespace boundary. */
4803 int elt = Dynarr_length (db->runes) - 1;
4806 while (!done && elt >= 0)
4808 struct rune *rb = Dynarr_atp (db->runes, elt);
4810 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4811 && isspace (rb->object.chr.ch))
4812 && !rb->type == RUNE_BLANK)
4814 dl->bounds.right_white = rb->xpos + rb->width;
4822 /* The line is blank so everything is considered to be right
4825 dl->bounds.right_white = dl->bounds.left_in;
4828 /* Set the display blocks bounds. */
4829 db->start_pos = dl->bounds.left_in;
4830 if (Dynarr_length (db->runes))
4832 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4834 db->end_pos = rb->xpos + rb->width;
4837 db->end_pos = dl->bounds.right_white;
4839 /* update line height parameters */
4840 if (!data.new_ascent && !data.new_descent)
4842 /* We've got a blank line so initialize these values from the default
4844 default_face_font_info (data.window, &data.new_ascent,
4845 &data.new_descent, 0, 0, 0);
4848 if (data.max_pixmap_height)
4850 int height = data.new_ascent + data.new_descent;
4851 int pix_ascent, pix_descent;
4853 pix_descent = data.max_pixmap_height * data.new_descent / height;
4854 pix_ascent = data.max_pixmap_height - pix_descent;
4856 data.new_ascent = max (data.new_ascent, pix_ascent);
4857 data.new_descent = max (data.new_descent, pix_descent);
4860 dl->ascent = data.new_ascent;
4861 dl->descent = data.new_descent;
4864 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
4866 if (dl->ascent < ascent)
4867 dl->ascent = ascent;
4870 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
4872 if (dl->descent < descent)
4873 dl->descent = descent;
4876 dl->cursor_elt = data.cursor_x;
4877 /* #### lossage lossage lossage! Fix this shit! */
4878 if (data.bi_bufpos > bi_string_zv)
4879 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4881 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4883 data.dl->num_chars =
4884 string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
4886 /* This doesn't correctly take into account tabs and control
4887 characters but if the window isn't being truncated then this
4888 value isn't going to end up being used anyhow. */
4889 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4891 /* #### handle horizontally scrolled line with text none of which
4892 was actually laid out. */
4894 /* #### handle any remainder of overlay arrow */
4896 if (*prop == ADD_FAILED)
4899 if (truncate_win && *prop)
4901 Dynarr_free (*prop);
4905 extent_fragment_delete (data.ef);
4907 /* #### If we started at EOB, then make sure we return a value past
4908 it so that regenerate_window will exit properly. This is bogus.
4909 The main loop should get fixed so that it isn't necessary to call
4910 this function if we are already at EOB. */
4912 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4913 return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
4915 return bytecount_to_charcount (string_data (s), data.bi_bufpos);
4918 /* Given a display line and a starting position, ensure that the
4919 contents of the display line accurately represent the visual
4920 representation of the buffer contents starting from the given
4921 position when displayed in the given window. The display line ends
4922 when the contents of the line reach the right boundary of the given
4925 This is very similar to generate_display_line but with the same
4926 limitations as create_string_text_block. I have taken the liberty
4927 of fixing the bytind stuff though.*/
4930 generate_string_display_line (struct window *w, Lisp_Object disp_string,
4931 struct display_line *dl,
4933 prop_block_dynarr **prop,
4934 face_index default_face)
4938 /* you must set bounds before calling this. */
4940 /* Reset what this line is using. */
4941 if (dl->display_blocks)
4942 Dynarr_reset (dl->display_blocks);
4943 if (dl->left_glyphs)
4945 Dynarr_free (dl->left_glyphs);
4946 dl->left_glyphs = 0;
4948 if (dl->right_glyphs)
4950 Dynarr_free (dl->right_glyphs);
4951 dl->right_glyphs = 0;
4954 /* We aren't generating a modeline at the moment. */
4957 /* Create a display block for the text region of the line. */
4958 ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
4959 prop, default_face);
4960 dl->bufpos = start_pos;
4961 if (dl->end_bufpos < dl->bufpos)
4962 dl->end_bufpos = dl->bufpos;
4964 /* If there are left glyphs associated with any character in the
4965 text block, then create a display block to handle them. */
4966 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
4967 create_left_glyph_block (w, dl, 0);
4969 /* If there are right glyphs associated with any character in the
4970 text block, then create a display block to handle them. */
4971 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
4972 create_right_glyph_block (w, dl);
4977 /* This is ripped off from regenerate_window. All we want to do is
4978 loop through elements in the string creating display lines until we
4979 have covered the provided area. Simple really. */
4981 generate_displayable_area (struct window *w, Lisp_Object disp_string,
4982 int xpos, int ypos, int width, int height,
4983 display_line_dynarr* dla,
4985 face_index default_face)
4987 int yend = ypos + height;
4990 prop_block_dynarr *prop = 0;
4991 layout_bounds bounds;
4995 /* if there's nothing to do then do nothing. code after this assumes
4996 there is something to do. */
4997 if (NILP (disp_string))
5000 s_zv = XSTRING_CHAR_LENGTH (disp_string);
5002 bounds.left_out = xpos;
5003 bounds.right_out = xpos + width;
5004 /* The inner boundaries mark where the glyph margins are located. */
5005 bounds.left_in = bounds.left_out + window_left_margin_width (w);
5006 bounds.right_in = bounds.right_out - window_right_margin_width (w);
5007 /* We cannot fully calculate the whitespace boundaries as they
5008 depend on the contents of the line being displayed. */
5009 bounds.left_white = bounds.left_in;
5010 bounds.right_white = bounds.right_in;
5014 struct display_line dl;
5015 struct display_line *dlp;
5019 if (Dynarr_length (dla) < Dynarr_largest (dla))
5021 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5032 dlp->bounds = bounds;
5034 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5035 &prop, default_face);
5036 /* we need to make sure that we continue along the line if there
5037 is more left to display otherwise we just end up redisplaying
5038 the same chunk over and over again. */
5039 if (next_pos == start_pos && next_pos < s_zv)
5042 start_pos = next_pos;
5044 dlp->ypos = ypos + dlp->ascent;
5045 ypos = dlp->ypos + dlp->descent;
5049 int visible_height = dlp->ascent + dlp->descent;
5051 dlp->clip = (ypos - yend);
5052 visible_height -= dlp->clip;
5054 if (visible_height < VERTICAL_CLIP (w, 1))
5057 free_display_line (dlp);
5064 Dynarr_add (dla, *dlp);
5066 /* #### This type of check needs to be done down in the
5067 generate_display_line call. */
5068 if (start_pos >= s_zv)
5077 /***************************************************************************/
5079 /* window-regeneration routines */
5081 /***************************************************************************/
5083 /* For a given window and starting position in the buffer it contains,
5084 ensure that the TYPE display lines accurately represent the
5085 presentation of the window. We pass the buffer instead of getting
5086 it from the window since redisplay_window may have temporarily
5087 changed it to the echo area buffer. */
5090 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
5092 struct frame *f = XFRAME (w->frame);
5093 struct buffer *b = XBUFFER (w->buffer);
5094 int ypos = WINDOW_TEXT_TOP (w);
5095 int yend; /* set farther down */
5096 int yclip = WINDOW_TEXT_TOP_CLIP (w);
5098 prop_block_dynarr *prop;
5099 layout_bounds bounds;
5100 display_line_dynarr *dla;
5103 /* The lines had better exist by this point. */
5104 if (!(dla = window_display_lines (w, type)))
5107 w->max_line_len = 0;
5109 /* Normally these get updated in redisplay_window but it is possible
5110 for this function to get called from some other points where that
5111 update may not have occurred. This acts as a safety check. */
5112 if (!Dynarr_length (w->face_cachels))
5113 reset_face_cachels (w);
5114 if (!Dynarr_length (w->glyph_cachels))
5115 reset_glyph_cachels (w);
5117 Fset_marker (w->start[type], make_int (start_pos), w->buffer);
5118 Fset_marker (w->pointm[type], make_int (point), w->buffer);
5119 w->last_point_x[type] = -1;
5120 w->last_point_y[type] = -1;
5122 /* Make sure a modeline is in the structs if needed. */
5123 need_modeline = ensure_modeline_generated (w, type);
5125 /* Wait until here to set this so that the structs have a modeline
5126 generated in the case where one didn't exist. */
5127 yend = WINDOW_TEXT_BOTTOM (w);
5129 bounds = calculate_display_line_boundaries (w, 0);
5131 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5132 if (MINI_WINDOW_P (w)
5133 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
5134 && !echo_area_active (f)
5135 && start_pos == BUF_BEGV (b))
5137 struct prop_block pb;
5139 prop = Dynarr_new (prop_block);
5141 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5142 pb.type = PROP_MINIBUF_PROMPT;
5143 pb.data.p_string.str = XSTRING_DATA(string);
5144 pb.data.p_string.len = XSTRING_LENGTH(string);
5145 Dynarr_add (prop, pb);
5152 struct display_line dl;
5153 struct display_line *dlp;
5156 if (Dynarr_length (dla) < Dynarr_largest (dla))
5158 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5169 dlp->bounds = bounds;
5171 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
5173 if (yclip > dlp->ascent)
5175 /* this should never happen, but if it does just display the
5180 dlp->ypos = (ypos + dlp->ascent) - yclip;
5181 ypos = dlp->ypos + dlp->descent;
5183 /* See if we've been asked to start midway through a line, for
5184 partial display line scrolling. */
5187 dlp->top_clip = yclip;
5195 int visible_height = dlp->ascent + dlp->descent;
5197 dlp->clip = (ypos - yend);
5198 /* Although this seems strange we could have a single very
5199 tall line visible for which we need to account for both
5200 the top clip and the bottom clip. */
5201 visible_height -= (dlp->clip + dlp->top_clip);
5203 if (visible_height < VERTICAL_CLIP (w, 1))
5206 free_display_line (dlp);
5213 if (dlp->cursor_elt != -1)
5215 /* #### This check is steaming crap. Have to get things
5216 fixed so when create_text_block hits EOB, we're done,
5218 if (w->last_point_x[type] == -1)
5220 w->last_point_x[type] = dlp->cursor_elt;
5221 w->last_point_y[type] = Dynarr_length (dla);
5225 /* #### This means that we've added a cursor at EOB
5226 twice. Yuck oh yuck. */
5227 struct display_block *db =
5228 get_display_block_from_line (dlp, TEXT);
5230 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
5231 dlp->cursor_elt = -1;
5235 if (dlp->num_chars > w->max_line_len)
5236 w->max_line_len = dlp->num_chars;
5238 Dynarr_add (dla, *dlp);
5240 /* #### This isn't right, but it is close enough for now. */
5241 w->window_end_pos[type] = start_pos;
5243 /* #### This type of check needs to be done down in the
5244 generate_display_line call. */
5245 if (start_pos > BUF_ZV (b))
5252 /* #### More not quite right, but close enough. */
5253 /* #### Ben sez: apparently window_end_pos[] is measured
5254 as the number of characters between the window end and the
5255 end of the buffer? This seems rather weirdo. What's
5256 the justification for this? */
5257 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
5261 /* We know that this is the right thing to use because we put it
5262 there when we first started working in this function. */
5263 generate_modeline (w, Dynarr_atp (dla, 0), type);
5267 #define REGEN_INC_FIND_START_END \
5269 /* Determine start and end of lines. */ \
5270 if (!Dynarr_length (cdla)) \
5274 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5278 else if (!Dynarr_atp (cdla, 0)->modeline \
5279 && !Dynarr_atp (ddla, 0)->modeline) \
5284 abort (); /* structs differ */ \
5286 dla_end = Dynarr_length (cdla) - 1; \
5289 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5290 + Dynarr_atp (cdla, dla_start)->offset); \
5291 /* If this isn't true, then startp has changed and we need to do a \
5293 if (startp != start_pos) \
5296 /* Point is outside the visible region so give up. */ \
5297 if (pointm < start_pos) \
5302 /* This attempts to incrementally update the display structures. It
5303 returns a boolean indicating success or failure. This function is
5304 very similar to regenerate_window_incrementally and is in fact only
5305 called from that function. However, because of the nature of the
5306 changes it deals with it sometimes makes different assumptions
5307 which can lead to success which are much more difficult to make
5308 when dealing with buffer changes. */
5311 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
5313 Charcount beg_unchanged,
5314 Charcount end_unchanged)
5316 struct buffer *b = XBUFFER (w->buffer);
5317 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5318 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5322 int first_line, last_line;
5324 /* Don't define this in the loop where it is used because we
5325 definitely want its value to survive between passes. */
5326 prop_block_dynarr *prop = NULL;
5328 /* If we don't have any buffer change recorded but the modiff flag has
5329 been incremented, then fail. I'm not sure of the exact circumstances
5330 under which this can happen, but I believe that it is probably a
5331 reasonable happening. */
5332 if (!point_visible (w, pointm, CURRENT_DISP)
5333 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
5336 /* If the cursor is moved we attempt to update it. If we succeed we
5337 go ahead and proceed with the optimization attempt. */
5338 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5339 || pointm != marker_position (w->last_point[CURRENT_DISP]))
5341 struct frame *f = XFRAME (w->frame);
5342 struct device *d = XDEVICE (f->device);
5343 struct frame *sel_f = device_selected_frame (d);
5346 if (w->last_point_x[CURRENT_DISP] != -1
5347 && w->last_point_y[CURRENT_DISP] != -1)
5350 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
5352 /* Always regenerate the modeline in case it is
5353 displaying the current line or column. */
5354 regenerate_modeline (w);
5358 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
5360 if (f->modeline_changed)
5361 regenerate_modeline (w);
5369 if (beg_unchanged == -1 && end_unchanged == -1)
5372 /* assert: There are no buffer modifications or they are all below the
5373 visible region. We assume that regenerate_window_incrementally has
5374 not called us unless this is true. */
5376 REGEN_INC_FIND_START_END;
5378 /* If the changed are starts before the visible area, give up. */
5379 if (beg_unchanged < startp)
5382 /* Find what display line the extent changes first affect. */
5384 while (line <= dla_end)
5386 struct display_line *dl = Dynarr_atp (cdla, line);
5387 Bufpos lstart = dl->bufpos + dl->offset;
5388 Bufpos lend = dl->end_bufpos + dl->offset;
5390 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5396 /* If the changes are below the visible area then if point hasn't
5397 moved return success otherwise fail in order to be safe. */
5400 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5401 && pointm == marker_position (w->last_point[CURRENT_DISP]))
5407 /* At this point we know what line the changes first affect. We now
5408 begin redrawing lines as long as we are still in the affected
5409 region and the line's size and positioning don't change.
5410 Otherwise we fail. If we fail we will have altered the desired
5411 structs which could lead to an assertion failure. However, if we
5412 fail the next thing that is going to happen is a full regen so we
5413 will actually end up being safe. */
5414 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5415 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5416 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5417 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5419 first_line = last_line = line;
5420 while (line <= dla_end)
5422 Bufpos old_start, old_end, new_start;
5423 struct display_line *cdl = Dynarr_atp (cdla, line);
5424 struct display_line *ddl = Dynarr_atp (ddla, line);
5425 struct display_block *db;
5428 assert (cdl->bufpos == ddl->bufpos);
5429 assert (cdl->end_bufpos == ddl->end_bufpos);
5430 assert (cdl->offset == ddl->offset);
5432 db = get_display_block_from_line (ddl, TEXT);
5433 initial_size = Dynarr_length (db->runes);
5434 old_start = ddl->bufpos + ddl->offset;
5435 old_end = ddl->end_bufpos + ddl->offset;
5437 /* If this is the first line being updated and it used
5438 propagation data, fail. Otherwise we'll be okay because
5439 we'll have the necessary propagation data. */
5440 if (line == first_line && ddl->used_prop_data)
5443 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5444 &prop, DESIRED_DISP);
5447 /* #### If there is propagated stuff the fail. We could
5448 probably actually deal with this if the line had propagated
5449 information when originally created by a full
5457 /* If any line position parameters have changed or a
5458 cursor has disappeared or disappeared, fail. */
5459 db = get_display_block_from_line (ddl, TEXT);
5460 if (cdl->ypos != ddl->ypos
5461 || cdl->ascent != ddl->ascent
5462 || cdl->descent != ddl->descent
5463 || cdl->top_clip != ddl->top_clip
5464 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5465 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5466 || old_start != ddl->bufpos
5467 || old_end != ddl->end_bufpos
5468 || initial_size != Dynarr_length (db->runes))
5473 if (ddl->cursor_elt != -1)
5475 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5476 w->last_point_y[DESIRED_DISP] = line;
5481 /* If the extent changes end on the line we just updated then
5482 we're done. Otherwise go on to the next line. */
5483 if (end_unchanged <= ddl->end_bufpos)
5489 redisplay_update_line (w, first_line, last_line, 1);
5493 /* Attempt to update the display data structures based on knowledge of
5494 the changed region in the buffer. Returns a boolean indicating
5495 success or failure. If this function returns a failure then a
5496 regenerate_window _must_ be performed next in order to maintain
5497 invariants located here. */
5500 regenerate_window_incrementally (struct window *w, Bufpos startp,
5503 struct buffer *b = XBUFFER (w->buffer);
5504 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5505 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5506 Charcount beg_unchanged, end_unchanged;
5507 Charcount extent_beg_unchanged, extent_end_unchanged;
5513 /* If this function is called, the current and desired structures
5514 had better be identical. If they are not, then that is a bug. */
5515 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
5517 /* We don't handle minibuffer windows yet. The minibuffer prompt
5519 if (MINI_WINDOW_P (w))
5522 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
5523 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
5525 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
5527 /* If nothing has changed in the buffer, then make sure point is ok
5529 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
5530 return regenerate_window_extents_only_changed (w, startp, pointm,
5531 extent_beg_unchanged,
5532 extent_end_unchanged);
5534 /* We can't deal with deleted newlines. */
5535 if (BUF_NEWLINE_WAS_DELETED (b))
5538 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
5539 end_unchanged = (BUF_END_UNCHANGED (b) == -1
5541 : BUF_Z (b) - BUF_END_UNCHANGED (b));
5543 REGEN_INC_FIND_START_END;
5545 /* If the changed area starts before the visible area, give up. */
5546 if (beg_unchanged < startp)
5549 /* Find what display line the buffer changes first affect. */
5551 while (line <= dla_end)
5553 struct display_line *dl = Dynarr_atp (cdla, line);
5554 Bufpos lstart = dl->bufpos + dl->offset;
5555 Bufpos lend = dl->end_bufpos + dl->offset;
5557 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5563 /* If the changes are below the visible area then if point hasn't
5564 moved return success otherwise fail in order to be safe. */
5566 return regenerate_window_extents_only_changed (w, startp, pointm,
5567 extent_beg_unchanged,
5568 extent_end_unchanged);
5570 /* At this point we know what line the changes first affect. We
5571 now redraw that line. If the changes are contained within it
5572 we are going to succeed and can update just that one line.
5573 Otherwise we fail. If we fail we will have altered the desired
5574 structs which could lead to an assertion failure. However, if
5575 we fail the next thing that is going to happen is a full regen
5576 so we will actually end up being safe. */
5579 prop_block_dynarr *prop = NULL;
5580 struct display_line *cdl = Dynarr_atp (cdla, line);
5581 struct display_line *ddl = Dynarr_atp (ddla, line);
5583 assert (cdl->bufpos == ddl->bufpos);
5584 assert (cdl->end_bufpos == ddl->end_bufpos);
5585 assert (cdl->offset == ddl->offset);
5587 /* If the last rune is already a continuation glyph, fail.
5588 #### We should be able to handle this better. */
5590 struct display_block *db = get_display_block_from_line (ddl, TEXT);
5591 if (Dynarr_length (db->runes))
5594 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
5596 if (rb->type == RUNE_DGLYPH
5597 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
5602 /* If the line was generated using propagation data, fail. */
5603 if (ddl->used_prop_data)
5606 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5607 &prop, DESIRED_DISP);
5610 /* If there is propagated stuff then it is pretty much a
5611 guarantee that more than just the one line is affected. */
5618 /* If the last rune is now a continuation glyph, fail. */
5620 struct display_block *db = get_display_block_from_line (ddl, TEXT);
5621 if (Dynarr_length (db->runes))
5624 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
5626 if (rb->type == RUNE_DGLYPH
5627 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
5632 /* If any line position parameters have changed or a
5633 cursor has disappeared or disappeared, fail. */
5634 if (cdl->ypos != ddl->ypos
5635 || cdl->ascent != ddl->ascent
5636 || cdl->descent != ddl->descent
5637 || cdl->top_clip != ddl->top_clip
5638 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5639 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
5644 /* If the changed area also ends on this line, then we may be in
5645 business. Update everything and return success. */
5646 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
5648 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5649 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5650 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
5652 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
5655 if (ddl->cursor_elt != -1)
5657 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5658 w->last_point_y[DESIRED_DISP] = line;
5661 redisplay_update_line (w, line, line, 1);
5662 regenerate_modeline (w);
5664 /* #### For now we just flush the cache until this has been
5665 tested. After that is done, this should correct the
5667 Dynarr_reset (w->line_start_cache);
5669 /* Adjust the extent changed boundaries to remove any
5670 overlap with the buffer changes since we've just
5671 successfully updated that area. */
5672 if (extent_beg_unchanged != -1
5673 && extent_beg_unchanged >= beg_unchanged
5674 && extent_beg_unchanged < end_unchanged)
5675 extent_beg_unchanged = end_unchanged;
5677 if (extent_end_unchanged != -1
5678 && extent_end_unchanged >= beg_unchanged
5679 && extent_end_unchanged < end_unchanged)
5680 extent_end_unchanged = beg_unchanged - 1;
5682 if (extent_end_unchanged <= extent_beg_unchanged)
5683 extent_beg_unchanged = extent_end_unchanged = -1;
5685 /* This could lead to odd results if it fails, but since the
5686 buffer changes update succeeded this probably will to.
5687 We already know that the extent changes start at or after
5688 the line because we checked before entering the loop. */
5689 if (extent_beg_unchanged != -1
5690 && extent_end_unchanged != -1
5691 && ((extent_beg_unchanged < ddl->bufpos)
5692 || (extent_end_unchanged > ddl->end_bufpos)))
5693 return regenerate_window_extents_only_changed (w, startp, pointm,
5694 extent_beg_unchanged,
5695 extent_end_unchanged);
5705 /* Given a window and a point, update the given display lines such
5706 that point is displayed in the middle of the window.
5707 Return the window's new start position. */
5710 regenerate_window_point_center (struct window *w, Bufpos point, int type)
5714 /* We need to make sure that the modeline is generated so that the
5715 window height can be calculated correctly. */
5716 ensure_modeline_generated (w, type);
5718 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
5719 regenerate_window (w, startp, point, type);
5720 Fset_marker (w->start[type], make_int (startp), w->buffer);
5725 /* Given a window and a set of display lines, return a boolean
5726 indicating whether the given point is contained within. */
5729 point_visible (struct window *w, Bufpos point, int type)
5731 struct buffer *b = XBUFFER (w->buffer);
5732 display_line_dynarr *dla = window_display_lines (w, type);
5735 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5740 if (Dynarr_length (dla) > first_line)
5743 struct display_line *dl = Dynarr_atp (dla, first_line);
5746 end = BUF_Z (b) - w->window_end_pos[type] - 1;
5748 if (point >= start && point <= end)
5750 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
5752 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
5754 if (point >= (dl->bufpos + dl->offset)
5755 && point <= (dl->end_bufpos + dl->offset))
5770 /* Return pixel position the middle of the window, not including the
5771 modeline and any potential horizontal scrollbar. */
5774 window_half_pixpos (struct window *w)
5776 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
5779 /* Return the display line which is currently in the middle of the
5780 window W for display lines TYPE. */
5783 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5785 display_line_dynarr *dla;
5788 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
5790 if (type == CMOTION_DISP)
5791 regenerate_window (w, start, point, type);
5793 dla = window_display_lines (w, type);
5794 half = window_half_pixpos (w);
5796 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
5798 struct display_line *dl = Dynarr_atp (dla, elt);
5799 int line_bot = dl->ypos + dl->descent;
5801 if (line_bot > half)
5805 /* We may not have a line at the middle if the end of the buffer is
5810 /* Return a value for point that would place it at the beginning of
5811 the line which is in the middle of the window. */
5814 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5816 /* line_at_center will regenerate the display structures, if necessary. */
5817 int line = line_at_center (w, type, start, point);
5820 return BUF_ZV (XBUFFER (w->buffer));
5823 display_line_dynarr *dla = window_display_lines (w, type);
5824 struct display_line *dl = Dynarr_atp (dla, line);
5830 /* For a given window, ensure that the current visual representation
5834 redisplay_window (Lisp_Object window, int skip_selected)
5836 struct window *w = XWINDOW (window);
5837 struct frame *f = XFRAME (w->frame);
5838 struct device *d = XDEVICE (f->device);
5839 Lisp_Object old_buffer = w->buffer;
5840 Lisp_Object the_buffer = w->buffer;
5842 int echo_active = 0;
5847 int selected_in_its_frame;
5848 int selected_globally;
5849 int skip_output = 0;
5850 int truncation_changed;
5851 int inactive_minibuffer =
5852 (MINI_WINDOW_P (w) &&
5853 (f != device_selected_frame (d)) &&
5854 !is_surrogate_for_selected_frame (f));
5856 /* #### In the new world this function actually does a bunch of
5857 optimizations such as buffer-based scrolling, but none of that is
5860 /* If this is a combination window, do its children; that's all.
5861 The selected window is always a leaf so we don't check for
5862 skip_selected here. */
5863 if (!NILP (w->vchild))
5865 redisplay_windows (w->vchild, skip_selected);
5868 if (!NILP (w->hchild))
5870 redisplay_windows (w->hchild, skip_selected);
5874 /* Is this window the selected window on its frame? */
5875 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
5877 selected_in_its_frame &&
5878 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5879 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
5880 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5881 if (skip_selected && selected_in_its_frame)
5884 /* It is possible that the window is not fully initialized yet. */
5885 if (NILP (w->buffer))
5888 if (MINI_WINDOW_P (w) && echo_area_active (f))
5890 w->buffer = the_buffer = Vecho_area_buffer;
5894 b = XBUFFER (w->buffer);
5898 old_pointm = selected_globally
5900 : marker_position (w->pointm[CURRENT_DISP]);
5905 if (selected_globally)
5907 pointm = BUF_PT (b);
5911 pointm = marker_position (w->pointm[CURRENT_DISP]);
5913 if (pointm < BUF_BEGV (b))
5914 pointm = BUF_BEGV (b);
5915 else if (pointm > BUF_ZV (b))
5916 pointm = BUF_ZV (b);
5919 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
5921 /* If the buffer has changed we have to invalidate all of our face
5923 if ((!echo_active && b != window_display_buffer (w))
5924 || !Dynarr_length (w->face_cachels)
5925 || f->faces_changed)
5926 reset_face_cachels (w);
5928 mark_face_cachels_as_not_updated (w);
5930 /* Ditto the glyph cache elements, although we do *not* invalidate
5931 the cache purely because glyphs have changed - this is now
5932 handled by the dirty flag.*/
5933 if ((!echo_active && b != window_display_buffer (w))
5934 || !Dynarr_length (w->glyph_cachels))
5935 reset_glyph_cachels (w);
5937 mark_glyph_cachels_as_not_updated (w);
5939 /* If the marker's buffer is not the window's buffer, then we need
5940 to find a new starting position. */
5941 if (!MINI_WINDOW_P (w)
5942 && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5944 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5946 goto regeneration_done;
5951 old_startp = marker_position (w->start[CURRENT_DISP]);
5956 startp = marker_position (w->start[CURRENT_DISP]);
5957 if (startp < BUF_BEGV (b))
5958 startp = BUF_BEGV (b);
5959 else if (startp > BUF_ZV (b))
5960 startp = BUF_ZV (b);
5962 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5964 truncation_changed = (find_window_mirror (w)->truncate_win !=
5965 window_truncation_on (w));
5967 /* If w->force_start is set, then some function set w->start and we
5968 should display from there and change point, if necessary, to
5969 ensure that it is visible. */
5970 if (w->force_start || inactive_minibuffer)
5973 w->last_modified[DESIRED_DISP] = Qzero;
5974 w->last_facechange[DESIRED_DISP] = Qzero;
5976 regenerate_window (w, startp, pointm, DESIRED_DISP);
5978 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5980 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5982 if (selected_globally)
5983 BUF_SET_PT (b, pointm);
5985 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5988 /* #### BUFU amounts of overkill just to get the cursor
5989 location marked properly. FIX ME FIX ME FIX ME */
5990 regenerate_window (w, startp, pointm, DESIRED_DISP);
5993 goto regeneration_done;
5996 /* If nothing has changed since the last redisplay, then we just
5997 need to make sure that point is still visible. */
5998 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5999 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
6001 /* This check is to make sure we restore the minibuffer after a
6002 temporary change to the echo area. */
6003 && !(MINI_WINDOW_P (w) && f->buffers_changed)
6004 && !f->frame_changed
6005 && !truncation_changed
6006 /* check whether start is really at the begining of a line GE */
6007 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
6010 /* Check if the cursor has actually moved. */
6011 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
6012 && pointm == marker_position (w->last_point[CURRENT_DISP])
6013 && selected_globally
6014 && !w->windows_changed
6016 && !f->extents_changed
6017 && !f->faces_changed
6018 && !f->glyphs_changed
6019 && !f->subwindows_changed
6020 && !f->subwindows_state_changed
6021 && !f->point_changed
6022 && !f->windows_structure_changed)
6024 /* If not, we're done. */
6025 if (f->modeline_changed)
6026 regenerate_modeline (w);
6029 goto regeneration_done;
6033 /* If the new point is visible in the redisplay structures,
6034 then let the output update routines handle it, otherwise
6035 do things the hard way. */
6036 if (!w->windows_changed
6038 && !f->extents_changed
6039 && !f->faces_changed
6040 && !f->glyphs_changed
6041 && !f->subwindows_changed
6042 && !f->subwindows_state_changed
6043 && !f->windows_structure_changed)
6045 if (point_visible (w, pointm, CURRENT_DISP)
6046 && w->last_point_x[CURRENT_DISP] != -1
6047 && w->last_point_y[CURRENT_DISP] != -1)
6049 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
6051 /* Always regenerate in case it is displaying
6052 the current line or column. */
6053 regenerate_modeline (w);
6056 goto regeneration_done;
6059 else if (!selected_in_its_frame && !f->point_changed)
6061 if (f->modeline_changed)
6062 regenerate_modeline (w);
6065 goto regeneration_done;
6069 /* If we weren't able to take the shortcut method, then use
6070 the brute force method. */
6071 regenerate_window (w, startp, pointm, DESIRED_DISP);
6073 if (point_visible (w, pointm, DESIRED_DISP))
6074 goto regeneration_done;
6078 /* Check if the starting point is no longer at the beginning of a
6079 line, in which case find a new starting point. We also recenter
6080 if our start position is equal to point-max. Otherwise we'll end
6081 up with a blank window. */
6082 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
6083 && !(startp == BUF_BEGV (b)
6084 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
6085 || (pointm == startp &&
6086 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
6087 startp < marker_position (w->last_start[CURRENT_DISP]))
6088 || (startp == BUF_ZV (b)))
6090 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6092 goto regeneration_done;
6094 /* See if we can update the data structures locally based on
6095 knowledge of what changed in the buffer. */
6096 else if (!w->windows_changed
6098 && !f->faces_changed
6099 && !f->glyphs_changed
6100 && !f->subwindows_changed
6101 && !f->subwindows_state_changed
6102 && !f->windows_structure_changed
6103 && !f->frame_changed
6104 && !truncation_changed
6106 && regenerate_window_incrementally (w, startp, pointm))
6108 if (f->modeline_changed
6109 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
6110 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
6111 regenerate_modeline (w);
6114 goto regeneration_done;
6116 /* #### This is where a check for structure based scrolling would go. */
6117 /* If all else fails, try just regenerating and see what happens. */
6120 regenerate_window (w, startp, pointm, DESIRED_DISP);
6122 if (point_visible (w, pointm, DESIRED_DISP))
6123 goto regeneration_done;
6126 /* We still haven't gotten the window regenerated with point
6127 visible. Next we try scrolling a little and see if point comes
6128 back onto the screen. */
6129 if (scroll_step > 0)
6131 int scrolled = scroll_conservatively;
6132 for (; scrolled >= 0; scrolled -= scroll_step)
6134 startp = vmotion (w, startp,
6135 (pointm < startp) ? -scroll_step : scroll_step, 0);
6136 regenerate_window (w, startp, pointm, DESIRED_DISP);
6138 if (point_visible (w, pointm, DESIRED_DISP))
6139 goto regeneration_done;
6143 /* We still haven't managed to get the screen drawn with point on
6144 the screen, so just center it and be done with it. */
6145 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6150 /* If the window's frame is changed then reset the current display
6151 lines in order to force a full repaint. */
6152 if (f->frame_changed)
6154 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
6159 /* Must do this before calling redisplay_output_window because it
6160 sets some markers on the window. */
6163 w->buffer = old_buffer;
6164 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
6165 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
6168 /* These also have to be set before calling redisplay_output_window
6169 since it sets the CURRENT_DISP values based on them. */
6170 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
6171 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
6172 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
6173 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
6177 Bufpos start = marker_position (w->start[DESIRED_DISP]);
6178 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
6180 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
6181 /* Don't pollute the cache if not sure if we are correct */
6182 if (w->start_at_line_beg)
6183 update_line_start_cache (w, start, end, pointm, 1);
6184 redisplay_output_window (w);
6186 * If we just displayed the echo area, the line start cache is
6187 * no longer valid, because the minibuffer window is associated
6188 * with the window now.
6191 w->line_cache_last_updated = make_int (-1);
6194 /* #### This should be dependent on face changes and will need to be
6195 somewhere else once tty updates occur on a per-frame basis. */
6196 mark_face_cachels_as_clean (w);
6198 /* The glyph cachels only get dirty if someone changed something.
6199 Since redisplay has now effectively ended we can reset the dirty
6200 flag since everything must be up-to-date. */
6202 mark_glyph_cachels_as_clean (w);
6204 w->windows_changed = 0;
6207 /* Call buffer_reset_changes for all buffers present in any window
6208 currently visible in all frames on all devices. #### There has to
6209 be a better way to do this. */
6212 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
6214 buffer_reset_changes (XBUFFER (w->buffer));
6219 reset_buffer_changes (void)
6221 Lisp_Object frmcons, devcons, concons;
6223 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6225 struct frame *f = XFRAME (XCAR (frmcons));
6227 if (FRAME_REPAINT_P (f))
6228 map_windows (f, reset_buffer_changes_mapfun, 0);
6232 /* Ensure that all windows underneath the given window in the window
6233 hierarchy are correctly displayed. */
6236 redisplay_windows (Lisp_Object window, int skip_selected)
6238 for (; !NILP (window) ; window = XWINDOW (window)->next)
6240 redisplay_window (window, skip_selected);
6245 call_redisplay_end_triggers (struct window *w, void *closure)
6247 Bufpos lrpos = w->last_redisplay_pos;
6248 w->last_redisplay_pos = 0;
6249 if (!NILP (w->buffer)
6250 && !NILP (w->redisplay_end_trigger)
6255 if (MARKERP (w->redisplay_end_trigger)
6256 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
6257 pos = marker_position (w->redisplay_end_trigger);
6258 else if (INTP (w->redisplay_end_trigger))
6259 pos = XINT (w->redisplay_end_trigger);
6262 w->redisplay_end_trigger = Qnil;
6269 XSETWINDOW (window, w);
6270 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
6271 Qredisplay_end_trigger_functions,
6273 w->redisplay_end_trigger);
6274 w->redisplay_end_trigger = Qnil;
6281 /* Ensure that all windows on the given frame are correctly displayed. */
6284 redisplay_frame (struct frame *f, int preemption_check)
6286 struct device *d = XDEVICE (f->device);
6288 if (preemption_check)
6290 /* The preemption check itself takes a lot of time,
6291 so normally don't do it here. We do it if called
6292 from Lisp, though (`redisplay-frame'). */
6295 REDISPLAY_PREEMPTION_CHECK;
6300 /* Before we put a hold on frame size changes, attempt to process
6301 any which are already pending. */
6302 if (f->size_change_pending)
6303 change_frame_size (f, f->new_height, f->new_width, 0);
6305 /* If frame size might need to be changed, due to changed size
6306 of toolbars, scrollbars etc, change it now */
6307 if (f->size_slipped)
6309 adjust_frame_size (f);
6310 assert (!f->size_slipped);
6313 /* The menubar, toolbar, and icon updates must be done before
6314 hold_frame_size_changes is called and we are officially
6315 'in_display'. They may eval lisp code which may call Fsignal.
6316 If in_display is set Fsignal will abort. */
6318 #ifdef HAVE_MENUBARS
6319 /* Update the menubar. It is done first since it could change
6320 the menubar's visibility. This way we avoid having flashing
6321 caused by an Expose event generated by the visibility change
6323 update_frame_menubars (f);
6324 #endif /* HAVE_MENUBARS */
6325 /* widgets are similar to menus in that they can call lisp to
6326 determine activation etc. Therefore update them before we get
6327 into redisplay. This is primarily for connected widgets such as
6329 update_frame_subwindows (f);
6330 #ifdef HAVE_TOOLBARS
6331 /* Update the toolbars. */
6332 update_frame_toolbars (f);
6333 #endif /* HAVE_TOOLBARS */
6335 /* If we clear the frame we have to force its contents to be redrawn. */
6337 f->frame_changed = 1;
6339 /* invalidate the subwindow cache. We use subwindows_changed here to
6340 cause subwindows to get instantiated. This is because
6341 subwindows_state_changed is less strict - dealing with things
6342 like the clicked state of button. We have to do this before
6343 redisplaying the gutters as subwindows get unmapped in the
6345 if (!Dynarr_length (f->subwindow_cachels)
6346 || f->subwindows_changed
6348 || f->frame_changed)
6350 reset_subwindow_cachels (f);
6351 /* we have to do this so the gutter gets regenerated. */
6352 reset_gutter_display_lines (f);
6355 mark_subwindow_cachels_as_not_updated (f);
6356 /* We can now update the gutters, safe in the knowledge that our
6357 efforts won't get undone. */
6358 update_frame_gutters (f);
6360 hold_frame_size_changes ();
6362 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6363 /* Within this section, we are defenseless and assume that the
6364 following cannot happen:
6366 1) garbage collection
6367 2) Lisp code evaluation
6368 3) frame size changes
6370 We ensure (3) by calling hold_frame_size_changes(), which
6371 will cause any pending frame size changes to get put on hold
6372 till after the end of the critical section. (1) follows
6373 automatically if (2) is met. #### Unfortunately, there are
6374 some places where Lisp code can be called within this section.
6375 We need to remove them.
6377 If Fsignal() is called during this critical section, we
6380 If garbage collection is called during this critical section,
6381 we simply return. #### We should abort instead.
6383 #### If a frame-size change does occur we should probably
6384 actually be preempting redisplay. */
6386 /* Erase the frame before outputting its contents. */
6389 DEVMETH (d, clear_frame, (f));
6392 /* Do the selected window first. */
6393 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
6395 /* Then do the rest. */
6396 redisplay_windows (f->root_window, 1);
6398 /* We now call the output_end routine for tty frames. We delay
6399 doing so in order to avoid cursor flicker. So much for 100%
6401 if (FRAME_TTY_P (f))
6402 DEVMETH (d, output_end, (d));
6404 update_frame_title (f);
6406 CLASS_RESET_CHANGED_FLAGS (f);
6407 f->window_face_cache_reset = 0;
6408 f->echo_area_garbaged = 0;
6411 if (!f->size_change_pending)
6412 f->size_changed = 0;
6414 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6416 /* Allow frame size changes to occur again.
6418 #### what happens if changes to other frames happen? */
6419 unhold_one_frame_size_changes (f);
6421 map_windows (f, call_redisplay_end_triggers, 0);
6425 /* Ensure that all frames on the given device are correctly displayed. */
6428 redisplay_device (struct device *d)
6430 Lisp_Object frame, frmcons;
6432 int size_change_failed = 0;
6435 if (DEVICE_STREAM_P (d)) /* nothing to do */
6438 /* It is possible that redisplay has been called before the
6439 device is fully initialized. If so then continue with the
6441 if (NILP (DEVICE_SELECTED_FRAME (d)))
6444 REDISPLAY_PREEMPTION_CHECK;
6448 /* Always do the selected frame first. */
6449 frame = DEVICE_SELECTED_FRAME (d);
6453 if (f->icon_changed || f->windows_changed)
6454 update_frame_icon (f);
6456 if (FRAME_REPAINT_P (f))
6458 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
6460 preempted = redisplay_frame (f, 0);
6466 /* If the frame redisplay did not get preempted, then this flag
6467 should have gotten set to 0. It might be possible for that
6468 not to happen if a size change event were to occur at an odd
6469 time. To make sure we don't miss anything we simply don't
6470 reset the top level flags until the condition ends up being
6471 in the right state. */
6472 if (f->size_changed)
6473 size_change_failed = 1;
6476 DEVICE_FRAME_LOOP (frmcons, d)
6478 f = XFRAME (XCAR (frmcons));
6480 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
6483 if (f->icon_changed || f->windows_changed)
6484 update_frame_icon (f);
6486 if (FRAME_REPAINT_P (f))
6488 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (f))
6490 preempted = redisplay_frame (f, 0);
6496 if (f->size_change_pending)
6497 size_change_failed = 1;
6501 /* If we get here then we redisplayed all of our frames without
6502 getting preempted so mark ourselves as clean. */
6503 CLASS_RESET_CHANGED_FLAGS (d);
6505 if (!size_change_failed)
6506 d->size_changed = 0;
6512 restore_profiling_redisplay_flag (Lisp_Object val)
6514 profiling_redisplay_flag = XINT (val);
6518 /* Ensure that all windows on all frames on all devices are displaying
6519 the current contents of their respective buffers. */
6522 redisplay_without_hooks (void)
6524 Lisp_Object devcons, concons;
6525 int size_change_failed = 0;
6526 int count = specpdl_depth ();
6528 if (profiling_active)
6530 record_unwind_protect (restore_profiling_redisplay_flag,
6531 make_int (profiling_redisplay_flag));
6532 profiling_redisplay_flag = 1;
6535 if (asynch_device_change_pending)
6536 handle_asynch_device_change ();
6538 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6539 !disable_preemption && preemption_count < max_preempts)
6542 DEVICE_LOOP_NO_BREAK (devcons, concons)
6544 struct device *d = XDEVICE (XCAR (devcons));
6547 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d))
6549 preempted = redisplay_device (d);
6554 RESET_CHANGED_SET_FLAGS;
6558 /* See comment in redisplay_device. */
6559 if (d->size_changed)
6560 size_change_failed = 1;
6563 preemption_count = 0;
6565 /* Mark redisplay as accurate */
6566 GLOBAL_RESET_CHANGED_FLAGS;
6567 RESET_CHANGED_SET_FLAGS;
6571 mark_all_faces_as_clean ();
6575 if (!size_change_failed)
6578 reset_buffer_changes ();
6581 unbind_to (count, Qnil);
6587 if (last_display_warning_tick != display_warning_tick &&
6588 !inhibit_warning_display)
6590 /* If an error occurs during this function, oh well.
6591 If we report another warning, we could get stuck in an
6592 infinite loop reporting warnings. */
6593 call0_trapping_errors (0, Qdisplay_warning_buffer);
6594 last_display_warning_tick = display_warning_tick;
6596 /* The run_hook_trapping_errors functions are smart enough not
6597 to do any evalling if the hook function is empty, so there
6598 should not be any significant time loss. All places in the
6599 C code that call redisplay() are prepared to handle GCing,
6600 so we should be OK. */
6601 #ifndef INHIBIT_REDISPLAY_HOOKS
6602 run_hook_trapping_errors ("Error in pre-redisplay-hook",
6603 Qpre_redisplay_hook);
6604 #endif /* INHIBIT_REDISPLAY_HOOKS */
6606 redisplay_without_hooks ();
6608 #ifndef INHIBIT_REDISPLAY_HOOKS
6609 run_hook_trapping_errors ("Error in post-redisplay-hook",
6610 Qpost_redisplay_hook);
6611 #endif /* INHIBIT_REDISPLAY_HOOKS */
6615 static char window_line_number_buf[32];
6617 /* Efficiently determine the window line number, and return a pointer
6618 to its printed representation. Do this regardless of whether
6619 line-number-mode is on. The first line in the buffer is counted as
6620 1. If narrowing is in effect, the lines are counted from the
6621 beginning of the visible portion of the buffer. */
6623 window_line_number (struct window *w, int type)
6625 struct device *d = XDEVICE (XFRAME (w->frame)->device);
6626 struct buffer *b = XBUFFER (w->buffer);
6627 /* Be careful in the order of these tests. The first clause will
6628 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6629 This can occur when the frame title is computed really early */
6631 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6632 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
6633 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6634 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
6636 : marker_position (w->pointm[type]));
6639 line = buffer_line_number (b, pos, 1);
6641 long_to_string (window_line_number_buf, line + 1);
6643 return window_line_number_buf;
6647 /* Given a character representing an object in a modeline
6648 specification, return a string (stored into the global array
6649 `mode_spec_bufbyte_string') with the information that object
6652 This function is largely unchanged from previous versions of the
6655 Warning! This code is also used for frame titles and can be called
6656 very early in the device/frame update process! JV
6660 decode_mode_spec (struct window *w, Emchar spec, int type)
6662 Lisp_Object obj = Qnil;
6663 CONST char *str = NULL;
6664 struct buffer *b = XBUFFER (w->buffer);
6666 Dynarr_reset (mode_spec_bufbyte_string);
6670 /* print buffer name */
6675 /* print visited file name */
6680 /* print the current column */
6683 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
6685 : marker_position (w->pointm[type]);
6686 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
6689 long_to_string (buf, col);
6691 Dynarr_add_many (mode_spec_bufbyte_string,
6692 (CONST Bufbyte *) buf, strlen (buf));
6694 goto decode_mode_spec_done;
6696 /* print the file coding system */
6700 Lisp_Object codesys = b->buffer_file_coding_system;
6701 /* Be very careful here not to get an error. */
6702 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
6704 codesys = Ffind_coding_system (codesys);
6705 if (CODING_SYSTEMP (codesys))
6706 obj = XCODING_SYSTEM_MNEMONIC (codesys);
6709 #endif /* FILE_CODING */
6712 /* print the current line number */
6714 str = window_line_number (w, type);
6717 /* print value of mode-name (obsolete) */
6722 /* print hyphen and frame number, if != 1 */
6726 struct frame *f = XFRAME (w->frame);
6727 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
6729 /* Naughty, naughty */
6730 char * writable_str = alloca_array (char, 10);
6731 sprintf (writable_str, "-%d", f->order_count);
6735 #endif /* HAVE_TTY */
6738 /* print Narrow if appropriate */
6740 if (BUF_BEGV (b) > BUF_BEG (b)
6741 || BUF_ZV (b) < BUF_Z (b))
6745 /* print %, * or hyphen, if buffer is read-only, modified or neither */
6747 str = (!NILP (b->read_only)
6749 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6754 /* print * or hyphen -- XEmacs change to allow a buffer to be
6755 read-only but still indicate whether it is modified. */
6757 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6759 : (!NILP (b->read_only)
6764 /* #### defined in 19.29 decode_mode_spec, but not in
6765 modeline-format doc string. */
6766 /* This differs from %* in that it ignores read-only-ness. */
6768 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6773 /* print process status */
6775 obj = Fget_buffer_process (w->buffer);
6777 str = GETTEXT ("no process");
6779 obj = Fsymbol_name (Fprocess_status (obj));
6782 /* Print name of selected frame. */
6784 obj = XFRAME (w->frame)->name;
6787 /* indicate TEXT or BINARY */
6789 /* #### NT does not use this any more. Now what? */
6793 /* print percent of buffer above top of window, or Top, Bot or All */
6796 Bufpos pos = marker_position (w->start[type]);
6798 /* This had better be while the desired lines are being done. */
6799 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
6801 if (pos <= BUF_BEGV (b))
6806 else if (pos <= BUF_BEGV (b))
6810 /* This hard limit is ok since the string it will hold has a
6811 fixed maximum length of 3. But just to be safe... */
6813 Charcount chars = pos - BUF_BEGV (b);
6814 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6816 /* Avoid overflow on big buffers */
6817 int percent = total > LONG_MAX/200 ?
6818 (chars + total/200) / (total / 100) :
6819 (chars * 100 + total/2) / total;
6821 /* We can't normally display a 3-digit number, so get us a
6822 2-digit number that is close. */
6826 sprintf (buf, "%d%%", percent);
6827 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6830 goto decode_mode_spec_done;
6835 /* print percent of buffer above bottom of window, perhaps plus
6836 Top, or print Bottom or All */
6839 Bufpos toppos = marker_position (w->start[type]);
6840 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
6842 /* botpos is only accurate as of the last redisplay, so we can
6843 only treat it as a hint. In particular, after erase-buffer,
6844 botpos may be negative. */
6845 if (botpos < toppos)
6848 if (botpos >= BUF_ZV (b))
6850 if (toppos <= BUF_BEGV (b))
6857 /* This hard limit is ok since the string it will hold has a
6858 fixed maximum length of around 6. But just to be safe... */
6860 Charcount chars = botpos - BUF_BEGV (b);
6861 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6863 /* Avoid overflow on big buffers */
6864 int percent = total > LONG_MAX/200 ?
6865 (chars + total/200) / (total / 100) :
6866 (chars * 100 + total/2) / max (total, 1);
6868 /* We can't normally display a 3-digit number, so get us a
6869 2-digit number that is close. */
6873 if (toppos <= BUF_BEGV (b))
6874 sprintf (buf, "Top%d%%", percent);
6876 sprintf (buf, "%d%%", percent);
6878 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6881 goto decode_mode_spec_done;
6891 /* print one [ for each recursive editing level. */
6896 if (command_loop_level > 5)
6902 for (i = 0; i < command_loop_level; i++)
6903 Dynarr_add (mode_spec_bufbyte_string, '[');
6905 goto decode_mode_spec_done;
6908 /* print one ] for each recursive editing level. */
6913 if (command_loop_level > 5)
6919 for (i = 0; i < command_loop_level; i++)
6920 Dynarr_add (mode_spec_bufbyte_string, ']');
6922 goto decode_mode_spec_done;
6925 /* print infinitely many dashes -- handle at top level now */
6932 Dynarr_add_many (mode_spec_bufbyte_string,
6934 XSTRING_LENGTH (obj));
6936 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6938 decode_mode_spec_done:
6939 Dynarr_add (mode_spec_bufbyte_string, '\0');
6942 /* Given a display line, free all of its data structures. */
6945 free_display_line (struct display_line *dl)
6949 if (dl->display_blocks)
6951 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6953 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6955 Dynarr_free (db->runes);
6958 Dynarr_free (dl->display_blocks);
6959 dl->display_blocks = NULL;
6962 if (dl->left_glyphs)
6964 Dynarr_free (dl->left_glyphs);
6965 dl->left_glyphs = NULL;
6968 if (dl->right_glyphs)
6970 Dynarr_free (dl->right_glyphs);
6971 dl->right_glyphs = NULL;
6976 /* Given an array of display lines, free them and all data structures
6977 contained within them. */
6980 free_display_lines (display_line_dynarr *dla)
6984 for (line = 0; line < Dynarr_largest (dla); line++)
6986 free_display_line (Dynarr_atp (dla, line));
6992 /* Call internal free routine for each set of display lines. */
6995 free_display_structs (struct window_mirror *mir)
6997 if (mir->current_display_lines)
6999 free_display_lines (mir->current_display_lines);
7000 mir->current_display_lines = 0;
7003 if (mir->desired_display_lines)
7005 free_display_lines (mir->desired_display_lines);
7006 mir->desired_display_lines = 0;
7012 mark_glyph_block_dynarr (glyph_block_dynarr *gba)
7016 glyph_block *gb = Dynarr_atp (gba, 0);
7017 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
7019 for (; gb < gb_last; gb++)
7021 if (!NILP (gb->glyph))
7022 mark_object (gb->glyph);
7023 if (!NILP (gb->extent))
7024 mark_object (gb->extent);
7030 mark_redisplay_structs (display_line_dynarr *dla)
7032 display_line *dl = Dynarr_atp (dla, 0);
7033 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
7035 for (; dl < dl_last; dl++)
7037 display_block_dynarr *dba = dl->display_blocks;
7038 display_block *db = Dynarr_atp (dba, 0);
7039 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
7041 for (; db < db_last; db++)
7043 rune_dynarr *ra = db->runes;
7044 rune *r = Dynarr_atp (ra, 0);
7045 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
7047 for (; r < r_last; r++)
7049 if (r->type == RUNE_DGLYPH)
7051 if (!NILP (r->object.dglyph.glyph))
7052 mark_object (r->object.dglyph.glyph);
7053 if (!NILP (r->object.dglyph.extent))
7054 mark_object (r->object.dglyph.extent);
7059 mark_glyph_block_dynarr (dl->left_glyphs);
7060 mark_glyph_block_dynarr (dl->right_glyphs);
7065 mark_window_mirror (struct window_mirror *mir)
7067 mark_redisplay_structs (mir->current_display_lines);
7068 mark_redisplay_structs (mir->desired_display_lines);
7071 mark_window_mirror (mir->next);
7074 mark_window_mirror (mir->hchild);
7075 else if (mir->vchild)
7076 mark_window_mirror (mir->vchild);
7080 mark_redisplay (void)
7082 Lisp_Object frmcons, devcons, concons;
7084 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
7086 struct frame *f = XFRAME (XCAR (frmcons));
7087 update_frame_window_mirror (f);
7088 mark_window_mirror (f->root_mirror);
7092 /*****************************************************************************
7093 Line Start Cache Description and Rationale
7095 The traditional scrolling code in Emacs breaks in a variable height world.
7096 It depends on the key assumption that the number of lines that can be
7097 displayed at any given time is fixed. This led to a complete separation
7098 of the scrolling code from the redisplay code. In order to fully support
7099 variable height lines, the scrolling code must actually be tightly
7100 integrated with redisplay. Only redisplay can determine how many lines
7101 will be displayed on a screen for any given starting point.
7103 What is ideally wanted is a complete list of the starting buffer position
7104 for every possible display line of a buffer along with the height of that
7105 display line. Maintaining such a full list would be very expensive. We
7106 settle for having it include information for all areas which we happen to
7107 generate anyhow (i.e. the region currently being displayed) and for those
7108 areas we need to work with.
7110 In order to ensure that the cache accurately represents what redisplay
7111 would actually show, it is necessary to invalidate it in many situations.
7112 If the buffer changes, the starting positions may no longer be correct.
7113 If a face or an extent has changed then the line heights may have altered.
7114 These events happen frequently enough that the cache can end up being
7115 constantly disabled. With this potentially constant invalidation when is
7116 the cache ever useful?
7118 Even if the cache is invalidated before every single usage, it is
7119 necessary. Scrolling often requires knowledge about display lines which
7120 are actually above or below the visible region. The cache provides a
7121 convenient light-weight method of storing this information for multiple
7122 display regions. This knowledge is necessary for the scrolling code to
7123 always obey the First Golden Rule of Redisplay.
7125 If the cache already contains all of the information that the scrolling
7126 routines happen to need so that it doesn't have to go generate it, then we
7127 are able to obey the Third Golden Rule of Redisplay. The first thing we
7128 do to help out the cache is to always add the displayed region. This
7129 region had to be generated anyway, so the cache ends up getting the
7130 information basically for free. In those cases where a user is simply
7131 scrolling around viewing a buffer there is a high probability that this is
7132 sufficient to always provide the needed information. The second thing we
7133 can do is be smart about invalidating the cache.
7135 TODO -- Be smart about invalidating the cache. Potential places:
7137 + Insertions at end-of-line which don't cause line-wraps do not alter the
7138 starting positions of any display lines. These types of buffer
7139 modifications should not invalidate the cache. This is actually a large
7140 optimization for redisplay speed as well.
7142 + Buffer modifications frequently only affect the display of lines at and
7143 below where they occur. In these situations we should only invalidate
7144 the part of the cache starting at where the modification occurs.
7146 In case you're wondering, the Second Golden Rule of Redisplay is not
7148 ****************************************************************************/
7150 /* This will get used quite a bit so we don't want to be constantly
7151 allocating and freeing it. */
7152 static line_start_cache_dynarr *internal_cache;
7154 /* Makes internal_cache represent the TYPE display structs and only
7155 the TYPE display structs. */
7158 update_internal_cache_list (struct window *w, int type)
7161 display_line_dynarr *dla = window_display_lines (w, type);
7163 Dynarr_reset (internal_cache);
7164 for (line = 0; line < Dynarr_length (dla); line++)
7166 struct display_line *dl = Dynarr_atp (dla, line);
7172 struct line_start_cache lsc;
7174 lsc.start = dl->bufpos;
7175 lsc.end = dl->end_bufpos;
7176 lsc.height = dl->ascent + dl->descent;
7178 Dynarr_add (internal_cache, lsc);
7183 /* Reset the line cache if necessary. This should be run at the
7184 beginning of any function which access the cache. */
7187 validate_line_start_cache (struct window *w)
7189 struct buffer *b = XBUFFER (w->buffer);
7190 struct frame *f = XFRAME (w->frame);
7192 if (!w->line_cache_validation_override)
7194 /* f->extents_changed used to be in here because extent face and
7195 size changes can cause text shifting. However, the extent
7196 covering the region is constantly having its face set and
7197 priority altered by the mouse code. This means that the line
7198 start cache is constantly being invalidated. This is bad
7199 since the mouse code also triggers heavy usage of the cache.
7200 Since it is an unlikely that f->extents being changed
7201 indicates that the cache really needs to be updated and if it
7202 does redisplay will catch it pretty quickly we no longer
7203 invalidate the cache if it is set. This greatly speeds up
7204 dragging out regions with the mouse. */
7205 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
7209 Dynarr_reset (w->line_start_cache);
7214 /* Return the very first buffer position contained in the given
7215 window's cache, or -1 if the cache is empty. Assumes that the
7219 line_start_cache_start (struct window *w)
7221 line_start_cache_dynarr *cache = w->line_start_cache;
7223 if (!Dynarr_length (cache))
7226 return Dynarr_atp (cache, 0)->start;
7229 /* Return the very last buffer position contained in the given
7230 window's cache, or -1 if the cache is empty. Assumes that the
7234 line_start_cache_end (struct window *w)
7236 line_start_cache_dynarr *cache = w->line_start_cache;
7238 if (!Dynarr_length (cache))
7241 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7244 /* Return the index of the line POINT is contained within in window
7245 W's line start cache. It will enlarge the cache or move the cache
7246 window in order to have POINT be present in the cache. MIN_PAST is
7247 a guarantee of the number of entries in the cache present on either
7248 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7249 then it will be treated as 0, but the cache window will not be
7250 allowed to shift. Returns -1 if POINT cannot be found in the cache
7254 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
7256 struct buffer *b = XBUFFER (w->buffer);
7257 line_start_cache_dynarr *cache = w->line_start_cache;
7258 unsigned int top, bottom, pos;
7260 validate_line_start_cache (w);
7261 w->line_cache_validation_override++;
7263 /* Let functions pass in negative values, but we still treat -1
7265 /* #### bogosity alert */
7266 if (min_past < 0 && min_past != -1)
7267 min_past = -min_past;
7269 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
7270 || line_start_cache_end (w) < point)
7273 int win_char_height = window_char_height (w, 1);
7275 /* Occasionally we get here with a 0 height
7276 window. find_next_newline_no_quit will abort if we pass it a
7277 count of 0 so handle that case. */
7278 if (!win_char_height)
7279 win_char_height = 1;
7281 if (!Dynarr_length (cache))
7283 Bufpos from = find_next_newline_no_quit (b, point, -1);
7284 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
7286 update_line_start_cache (w, from, to, point, 0);
7288 if (!Dynarr_length (cache))
7290 w->line_cache_validation_override--;
7295 assert (Dynarr_length (cache));
7298 while (line_start_cache_start (w) > point
7299 && (loop < cache_adjustment || min_past == -1))
7303 from = line_start_cache_start (w);
7304 if (from <= BUF_BEGV (b))
7307 from = find_next_newline_no_quit (b, from, -win_char_height);
7308 to = line_start_cache_end (w);
7310 update_line_start_cache (w, from, to, point, 0);
7314 if (line_start_cache_start (w) > point)
7318 from = find_next_newline_no_quit (b, point, -1);
7319 if (from >= BUF_ZV (b))
7321 to = find_next_newline_no_quit (b, from, -win_char_height);
7326 to = find_next_newline_no_quit (b, from, win_char_height);
7328 update_line_start_cache (w, from, to, point, 0);
7332 while (line_start_cache_end (w) < point
7333 && (loop < cache_adjustment || min_past == -1))
7337 to = line_start_cache_end (w);
7338 if (to >= BUF_ZV (b))
7341 from = line_start_cache_end (w);
7342 to = find_next_newline_no_quit (b, from, win_char_height);
7344 update_line_start_cache (w, from, to, point, 0);
7348 if (line_start_cache_end (w) < point)
7352 from = find_next_newline_no_quit (b, point, -1);
7353 if (from >= BUF_ZV (b))
7355 to = find_next_newline_no_quit (b, from, -win_char_height);
7360 to = find_next_newline_no_quit (b, from, win_char_height);
7362 update_line_start_cache (w, from, to, point, 0);
7366 assert (Dynarr_length (cache));
7371 /* This could happen if the buffer is narrowed. */
7372 if (line_start_cache_start (w) > point
7373 || line_start_cache_end (w) < point)
7375 w->line_cache_validation_override--;
7381 top = Dynarr_length (cache) - 1;
7386 unsigned int new_pos;
7389 pos = (bottom + top + 1) >> 1;
7390 start = Dynarr_atp (cache, pos)->start;
7391 end = Dynarr_atp (cache, pos)->end;
7393 if (point >= start && point <= end)
7395 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
7398 find_next_newline_no_quit (b, line_start_cache_start (w),
7400 Bufpos to = line_start_cache_end (w);
7402 update_line_start_cache (w, from, to, point, 0);
7403 goto find_point_loop;
7405 else if ((Dynarr_length (cache) - pos - 1) < min_past
7406 && line_start_cache_end (w) < BUF_ZV (b))
7408 Bufpos from = line_start_cache_end (w);
7409 Bufpos to = find_next_newline_no_quit (b, from,
7414 update_line_start_cache (w, from, to, point, 0);
7415 goto find_point_loop;
7419 w->line_cache_validation_override--;
7423 else if (point > end)
7425 else if (point < start)
7430 new_pos = (bottom + top + 1) >> 1;
7433 w->line_cache_validation_override--;
7439 /* Return a boolean indicating if POINT would be visible in window W
7440 if display of the window was to begin at STARTP. */
7443 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
7445 struct buffer *b = XBUFFER (w->buffer);
7446 int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
7447 int bottom = WINDOW_TEXT_HEIGHT (w);
7450 /* If point is before the intended start it obviously can't be visible. */
7454 /* If point or start are not in the accessible buffer range, then
7456 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
7457 || point < BUF_BEGV (b) || point > BUF_ZV (b))
7460 validate_line_start_cache (w);
7461 w->line_cache_validation_override++;
7463 start_elt = point_in_line_start_cache (w, startp, 0);
7464 if (start_elt == -1)
7466 w->line_cache_validation_override--;
7470 assert (line_start_cache_start (w) <= startp
7471 && line_start_cache_end (w) >= startp);
7477 /* Expand the cache if necessary. */
7478 if (start_elt == Dynarr_length (w->line_start_cache))
7481 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
7483 start_elt = point_in_line_start_cache (w, old_startp,
7484 window_char_height (w, 0));
7486 /* We've already actually processed old_startp, so increment
7490 /* If this happens we didn't add any extra elements. Bummer. */
7491 if (start_elt == Dynarr_length (w->line_start_cache))
7493 w->line_cache_validation_override--;
7498 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
7500 if (pixpos + height > bottom)
7502 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7504 w->line_cache_validation_override--;
7510 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
7512 w->line_cache_validation_override--;
7520 /* For the given window W, if display starts at STARTP, what will be
7521 the buffer position at the beginning or end of the last line
7522 displayed. The end of the last line is also know as the window end
7525 #### With a little work this could probably be reworked as just a
7526 call to start_with_line_at_pixpos. */
7529 start_end_of_last_line (struct window *w, Bufpos startp, int end)
7531 struct buffer *b = XBUFFER (w->buffer);
7532 line_start_cache_dynarr *cache = w->line_start_cache;
7534 int bottom = WINDOW_TEXT_HEIGHT (w);
7538 validate_line_start_cache (w);
7539 w->line_cache_validation_override++;
7541 if (startp < BUF_BEGV (b))
7542 startp = BUF_BEGV (b);
7543 else if (startp > BUF_ZV (b))
7544 startp = BUF_ZV (b);
7547 start_elt = point_in_line_start_cache (w, cur_start, 0);
7548 if (start_elt == -1)
7549 abort (); /* this had better never happen */
7553 int height = Dynarr_atp (cache, start_elt)->height;
7555 cur_start = Dynarr_atp (cache, start_elt)->start;
7557 if (pixpos + height > bottom)
7559 /* Adjust for any possible clip. */
7560 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7565 w->line_cache_validation_override--;
7569 return BUF_BEGV (b);
7573 w->line_cache_validation_override--;
7575 return Dynarr_atp (cache, start_elt)->end;
7577 return Dynarr_atp (cache, start_elt)->start;
7583 if (start_elt == Dynarr_length (cache))
7585 Bufpos from = line_start_cache_end (w);
7586 int win_char_height = window_char_height (w, 0);
7587 Bufpos to = find_next_newline_no_quit (b, from,
7592 /* We've hit the end of the bottom so that's what it is. */
7593 if (from >= BUF_ZV (b))
7595 w->line_cache_validation_override--;
7599 update_line_start_cache (w, from, to, BUF_PT (b), 0);
7601 /* Updating the cache invalidates any current indexes. */
7602 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
7607 /* For the given window W, if display starts at STARTP, what will be
7608 the buffer position at the beginning of the last line displayed. */
7611 start_of_last_line (struct window *w, Bufpos startp)
7613 return start_end_of_last_line (w, startp, 0);
7616 /* For the given window W, if display starts at STARTP, what will be
7617 the buffer position at the end of the last line displayed. This is
7618 also know as the window end position. */
7621 end_of_last_line (struct window *w, Bufpos startp)
7623 return start_end_of_last_line (w, startp, 1);
7626 /* For window W, what does the starting position have to be so that
7627 the line containing POINT will cover pixel position PIXPOS. */
7630 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
7632 struct buffer *b = XBUFFER (w->buffer);
7634 Bufpos cur_pos, prev_pos = point;
7635 int point_line_height;
7636 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
7638 validate_line_start_cache (w);
7639 w->line_cache_validation_override++;
7641 cur_elt = point_in_line_start_cache (w, point, 0);
7642 /* #### See comment in update_line_start_cache about big minibuffers. */
7645 w->line_cache_validation_override--;
7649 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
7653 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7655 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7657 /* Do not take into account the value of vertical_clip here.
7658 That is the responsibility of the calling functions. */
7661 w->line_cache_validation_override--;
7662 if (-pixheight > point_line_height)
7663 /* We can't make the target line cover pixpos, so put it
7664 above pixpos. That way it will at least be visible. */
7674 int win_char_height;
7676 if (cur_pos <= BUF_BEGV (b))
7678 w->line_cache_validation_override--;
7679 return BUF_BEGV (b);
7682 win_char_height = window_char_height (w, 0);
7683 if (!win_char_height)
7684 win_char_height = 1;
7686 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
7687 to = line_start_cache_end (w);
7688 update_line_start_cache (w, from, to, point, 0);
7690 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
7691 assert (cur_elt >= -1);
7692 /* This used to be cur_elt>=0 under the assumption that if
7693 point is in the top line and not at BUF_BEGV, then
7694 setting the window_start to a newline before the start of
7695 the first line will always cause scrolling.
7697 However in my (jv) opinion this is wrong. That new line
7698 can be hidden in various ways: invisible extents, an
7699 explicit window-start not at a newline character etc.
7700 The existence of those are indeed known to create crashes
7701 on that assert. So we have no option but to continue the
7702 search if we found point at the top of the line_start_cache
7704 cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
7710 /* For window W, what does the starting position have to be so that
7711 the line containing point is on display line LINE. If LINE is
7712 positive it is considered to be the number of lines from the top of
7713 the window (0 is the top line). If it is negative the number is
7714 considered to be the number of lines from the bottom (-1 is the
7718 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
7720 validate_line_start_cache (w);
7721 w->line_cache_validation_override++;
7725 int cur_elt = point_in_line_start_cache (w, point, line);
7727 if (cur_elt - line < 0)
7728 cur_elt = 0; /* Hit the top */
7732 w->line_cache_validation_override--;
7733 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
7737 /* The calculated value of pixpos is correct for the bottom line
7738 or what we want when line is -1. Therefore we subtract one
7739 because we have already handled one line. */
7740 int new_line = -line - 1;
7741 int cur_elt = point_in_line_start_cache (w, point, new_line);
7742 int pixpos = WINDOW_TEXT_BOTTOM (w);
7743 Bufpos retval, search_point;
7745 /* If scroll_on_clipped_lines is false, the last "visible" line of
7746 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7747 If s_o_c_l is true, then we don't want to count a clipped
7748 line, so back up from the bottom by the height of the line
7749 containing point. */
7750 if (scroll_on_clipped_lines)
7751 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7755 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
7757 /* Hit the bottom of the buffer. */
7759 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
7763 XSETWINDOW (window, w);
7764 default_face_height_and_width (window, &defheight, 0);
7766 cur_elt = Dynarr_length (w->line_start_cache) - 1;
7768 pixpos -= (adjustment * defheight);
7769 if (pixpos < WINDOW_TEXT_TOP (w))
7770 pixpos = WINDOW_TEXT_TOP (w);
7773 cur_elt = cur_elt + new_line;
7775 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7777 retval = start_with_line_at_pixpos (w, search_point, pixpos);
7778 w->line_cache_validation_override--;
7783 /* This is used to speed up vertical scrolling by caching the known
7784 buffer starting positions for display lines. This allows the
7785 scrolling routines to avoid costly calls to regenerate_window. If
7786 NO_REGEN is true then it will only add the values in the DESIRED
7787 display structs which are in the given range.
7789 Note also that the FROM/TO values are minimums. It is possible
7790 that this function will actually add information outside of the
7791 lines containing those positions. This can't hurt but it could
7794 #### We currently force the cache to have only 1 contiguous region.
7795 It might help to make the cache a dynarr of caches so that we can
7796 cover more areas. This might, however, turn out to be a lot of
7797 overhead for too little gain. */
7800 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
7801 Bufpos point, int no_regen)
7803 struct buffer *b = XBUFFER (w->buffer);
7804 line_start_cache_dynarr *cache = w->line_start_cache;
7805 Bufpos low_bound, high_bound;
7807 validate_line_start_cache (w);
7808 w->line_cache_validation_override++;
7809 updating_line_start_cache = 1;
7811 if (from < BUF_BEGV (b))
7812 from = BUF_BEGV (b);
7813 if (to > BUF_ZV (b))
7818 updating_line_start_cache = 0;
7819 w->line_cache_validation_override--;
7823 if (Dynarr_length (cache))
7825 low_bound = line_start_cache_start (w);
7826 high_bound = line_start_cache_end (w);
7828 /* Check to see if the desired range is already in the cache. */
7829 if (from >= low_bound && to <= high_bound)
7831 updating_line_start_cache = 0;
7832 w->line_cache_validation_override--;
7836 /* Check to make sure that the desired range is adjacent to the
7837 current cache. If not, invalidate the cache. */
7838 if (to < low_bound || from > high_bound)
7840 Dynarr_reset (cache);
7841 low_bound = high_bound = -1;
7846 low_bound = high_bound = -1;
7849 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
7851 /* This could be integrated into the next two sections, but it is easier
7852 to follow what's going on by having it separate. */
7857 update_internal_cache_list (w, DESIRED_DISP);
7858 if (!Dynarr_length (internal_cache))
7860 updating_line_start_cache = 0;
7861 w->line_cache_validation_override--;
7865 start = Dynarr_atp (internal_cache, 0)->start;
7867 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
7869 /* We aren't allowed to generate additional information to fill in
7870 gaps, so if the DESIRED structs don't overlap the cache, reset the
7872 if (Dynarr_length (cache))
7874 if (end < low_bound || start > high_bound)
7875 Dynarr_reset (cache);
7877 /* #### What should really happen if what we are doing is
7878 extending a line (the last line)? */
7879 if (Dynarr_length (cache) == 1
7880 && Dynarr_length (internal_cache) == 1)
7881 Dynarr_reset (cache);
7884 if (!Dynarr_length (cache))
7886 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7887 Dynarr_length (internal_cache));
7888 updating_line_start_cache = 0;
7889 w->line_cache_validation_override--;
7893 /* An extra check just in case the calling function didn't pass in
7894 the bounds of the DESIRED structs in the first place. */
7895 if (start >= low_bound && end <= high_bound)
7897 updating_line_start_cache = 0;
7898 w->line_cache_validation_override--;
7902 /* At this point we know that the internal cache partially overlaps
7904 if (start < low_bound)
7906 int ic_elt = Dynarr_length (internal_cache) - 1;
7909 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7917 Dynarr_reset (cache);
7918 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7919 Dynarr_length (internal_cache));
7920 updating_line_start_cache = 0;
7921 w->line_cache_validation_override--;
7925 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7929 if (end > high_bound)
7933 while (ic_elt < Dynarr_length (internal_cache))
7935 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7941 if (!(ic_elt < Dynarr_length (internal_cache)))
7943 Dynarr_reset (cache);
7944 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7945 Dynarr_length (internal_cache));
7946 updating_line_start_cache = 0;
7947 w->line_cache_validation_override--;
7951 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7952 Dynarr_length (internal_cache) - ic_elt);
7955 updating_line_start_cache = 0;
7956 w->line_cache_validation_override--;
7960 if (!Dynarr_length (cache) || from < low_bound)
7962 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7964 int old_lb = low_bound;
7966 while (startp < old_lb || low_bound == -1)
7971 regenerate_window (w, startp, point, CMOTION_DISP);
7972 update_internal_cache_list (w, CMOTION_DISP);
7974 /* If this assert is triggered then regenerate_window failed
7975 to layout a single line. That is not supposed to be
7976 possible because we impose a minimum height on the buffer
7977 and override vertical clip when we are in here. */
7978 /* #### Ah, but it is because the window may temporarily
7979 exist but not have any lines at all if the minibuffer is
7980 real big. Look into that situation better. */
7981 if (!Dynarr_length (internal_cache))
7983 if (old_lb == -1 && low_bound == -1)
7985 updating_line_start_cache = 0;
7986 w->line_cache_validation_override--;
7990 assert (Dynarr_length (internal_cache));
7992 assert (startp == Dynarr_atp (internal_cache, 0)->start);
7994 ic_elt = Dynarr_length (internal_cache) - 1;
7995 if (low_bound != -1)
7999 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
8005 assert (ic_elt >= 0);
8007 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
8010 * Handle invisible text properly:
8011 * If the last line we're inserting has the same end as the
8012 * line before which it will be added, merge the two lines.
8014 if (Dynarr_length (cache) &&
8015 Dynarr_atp (internal_cache, ic_elt)->end ==
8016 Dynarr_atp (cache, marker)->end)
8018 Dynarr_atp (cache, marker)->start
8019 = Dynarr_atp (internal_cache, ic_elt)->start;
8020 Dynarr_atp (cache, marker)->height
8021 = Dynarr_atp (internal_cache, ic_elt)->height;
8025 if (ic_elt >= 0) /* we still have lines to add.. */
8027 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
8028 ic_elt + 1, marker);
8029 marker += (ic_elt + 1);
8032 if (startp < low_bound || low_bound == -1)
8034 startp = new_startp;
8035 if (startp > BUF_ZV (b))
8037 updating_line_start_cache = 0;
8038 w->line_cache_validation_override--;
8044 assert (Dynarr_length (cache));
8045 assert (from >= low_bound);
8047 /* Readjust the high_bound to account for any changes made while
8048 correcting the low_bound. */
8049 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8051 if (to > high_bound)
8053 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
8057 regenerate_window (w, startp, point, CMOTION_DISP);
8058 update_internal_cache_list (w, CMOTION_DISP);
8060 /* See comment above about regenerate_window failing. */
8061 assert (Dynarr_length (internal_cache));
8063 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
8064 Dynarr_length (internal_cache));
8065 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8066 startp = high_bound + 1;
8068 while (to > high_bound);
8071 updating_line_start_cache = 0;
8072 w->line_cache_validation_override--;
8073 assert (to <= high_bound);
8077 /* Given x and y coordinates in characters, relative to a window,
8078 return the pixel location corresponding to those coordinates. The
8079 pixel location returned is the center of the given character
8080 position. The pixel values are generated relative to the window,
8083 The modeline is considered to be part of the window. */
8086 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
8087 int *pix_x, int *pix_y)
8089 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
8090 int num_disp_lines, modeline;
8092 int defheight, defwidth;
8094 XSETWINDOW (window, w);
8095 default_face_height_and_width (window, &defheight, &defwidth);
8097 /* If we get a bogus value indicating somewhere above or to the left of
8098 the window, use the first window line or character position
8105 num_disp_lines = Dynarr_length (dla);
8109 if (Dynarr_atp (dla, 0)->modeline)
8116 /* First check if the y position intersects the display lines. */
8117 if (char_y < num_disp_lines)
8119 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
8120 struct display_block *db = get_display_block_from_line (dl, TEXT);
8122 *pix_y = (dl->ypos - dl->ascent +
8123 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
8125 if (char_x < Dynarr_length (db->runes))
8127 struct rune *rb = Dynarr_atp (db->runes, char_x);
8129 *pix_x = rb->xpos + (rb->width >> 1);
8133 int last_rune = Dynarr_length (db->runes) - 1;
8134 struct rune *rb = Dynarr_atp (db->runes, last_rune);
8136 char_x -= last_rune;
8138 *pix_x = rb->xpos + rb->width;
8139 *pix_x += ((char_x - 1) * defwidth);
8140 *pix_x += (defwidth >> 1);
8145 /* It didn't intersect, so extrapolate. #### For now, we include the
8146 modeline in this since we don't have true character positions in
8149 if (!Dynarr_length (w->face_cachels))
8150 reset_face_cachels (w);
8152 char_y -= num_disp_lines;
8154 if (Dynarr_length (dla))
8156 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
8157 *pix_y = dl->ypos + dl->descent - dl->clip;
8160 *pix_y = WINDOW_TEXT_TOP (w);
8162 *pix_y += (char_y * defheight);
8163 *pix_y += (defheight >> 1);
8165 *pix_x = WINDOW_TEXT_LEFT (w);
8166 /* Don't adjust by one because this is still the unadjusted value. */
8167 *pix_x += (char_x * defwidth);
8168 *pix_x += (defwidth >> 1);
8171 if (*pix_x > w->pixel_left + w->pixel_width)
8172 *pix_x = w->pixel_left + w->pixel_width;
8173 if (*pix_y > w->pixel_top + w->pixel_height)
8174 *pix_y = w->pixel_top + w->pixel_height;
8176 *pix_x -= w->pixel_left;
8177 *pix_y -= w->pixel_top;
8180 /* Given a display line and a position, determine if there is a glyph
8181 there and return information about it if there is. */
8184 get_position_object (struct display_line *dl, Lisp_Object *obj1,
8185 Lisp_Object *obj2, int x_coord, int *low_x_coord,
8188 struct display_block *db;
8191 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
8193 /* We use get_next_display_block to get the actual display block
8194 that would be displayed at x_coord. */
8196 if (block == NO_BLOCK)
8199 db = Dynarr_atp (dl->display_blocks, block);
8201 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
8203 struct rune *rb = Dynarr_atp (db->runes, elt);
8205 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
8207 if (rb->type == RUNE_DGLYPH)
8209 *obj1 = rb->object.dglyph.glyph;
8210 *obj2 = rb->object.dglyph.extent;
8219 *low_x_coord = rb->xpos;
8221 *high_x_coord = rb->xpos + rb->width;
8228 #define UPDATE_CACHE_RETURN \
8230 d->pixel_to_glyph_cache.valid = 1; \
8231 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8232 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8233 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8234 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8235 d->pixel_to_glyph_cache.frame = f; \
8236 d->pixel_to_glyph_cache.col = *col; \
8237 d->pixel_to_glyph_cache.row = *row; \
8238 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8239 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8240 d->pixel_to_glyph_cache.w = *w; \
8241 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8242 d->pixel_to_glyph_cache.closest = *closest; \
8243 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8244 d->pixel_to_glyph_cache.obj1 = *obj1; \
8245 d->pixel_to_glyph_cache.obj2 = *obj2; \
8246 d->pixel_to_glyph_cache.retval = position; \
8247 RETURN_SANS_WARNINGS position; \
8250 /* Given x and y coordinates in pixels relative to a frame, return
8251 information about what is located under those coordinates.
8253 The return value will be one of:
8255 OVER_TOOLBAR: over one of the 4 frame toolbars
8256 OVER_MODELINE: over a modeline
8257 OVER_BORDER: over an internal border
8258 OVER_NOTHING: over the text area, but not over text
8259 OVER_OUTSIDE: outside of the frame border
8260 OVER_TEXT: over text in the text area
8266 -- nil if the coordinates are not over a glyph or a toolbar button.
8270 -- an extent, if the coordinates are over a glyph in the text area
8273 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8274 equivalent coordinates relative to the upper-left corner of the glyph.
8276 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8277 equivalent coordinates relative to the upper-left corner of the character.
8279 Otherwise, OBJ_X and OBJ_Y are undefined.
8283 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
8284 int *col, int *row, int *obj_x, int *obj_y,
8285 struct window **w, Bufpos *bufpos,
8286 Bufpos *closest, Charcount *modeline_closest,
8287 Lisp_Object *obj1, Lisp_Object *obj2)
8290 struct pixel_to_glyph_translation_cache *cache;
8292 int frm_left, frm_right, frm_top, frm_bottom;
8293 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8294 int position = OVER_NOTHING;
8295 int device_check_failed = 0;
8296 display_line_dynarr *dla;
8298 /* This is a safety valve in case this got called with a frame in
8299 the middle of being deleted. */
8300 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
8302 device_check_failed = 1;
8303 d = NULL, cache = NULL; /* Warning suppression */
8307 d = XDEVICE (f->device);
8308 cache = &d->pixel_to_glyph_cache;
8311 if (!device_check_failed
8313 && cache->frame == f
8314 && cache->low_x_coord <= x_coord
8315 && cache->high_x_coord > x_coord
8316 && cache->low_y_coord <= y_coord
8317 && cache->high_y_coord > y_coord)
8321 *obj_x = cache->obj_x;
8322 *obj_y = cache->obj_y;
8324 *bufpos = cache->bufpos;
8325 *closest = cache->closest;
8326 *modeline_closest = cache->modeline_closest;
8327 *obj1 = cache->obj1;
8328 *obj2 = cache->obj2;
8330 return cache->retval;
8341 *modeline_closest = -1;
8345 low_x_coord = x_coord;
8346 high_x_coord = x_coord + 1;
8347 low_y_coord = y_coord;
8348 high_y_coord = y_coord + 1;
8351 if (device_check_failed)
8352 return OVER_NOTHING;
8354 frm_left = FRAME_LEFT_BORDER_END (f);
8355 frm_right = FRAME_RIGHT_BORDER_START (f);
8356 frm_top = FRAME_TOP_BORDER_END (f);
8357 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
8359 /* Check if the mouse is outside of the text area actually used by
8361 if (y_coord < frm_top)
8363 if (y_coord >= FRAME_TOP_BORDER_START (f))
8365 low_y_coord = FRAME_TOP_BORDER_START (f);
8366 high_y_coord = frm_top;
8367 position = OVER_BORDER;
8369 else if (y_coord >= 0)
8372 high_y_coord = FRAME_TOP_BORDER_START (f);
8373 position = OVER_TOOLBAR;
8377 low_y_coord = y_coord;
8379 position = OVER_OUTSIDE;
8382 else if (y_coord >= frm_bottom)
8384 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
8386 low_y_coord = frm_bottom;
8387 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
8388 position = OVER_BORDER;
8390 else if (y_coord < FRAME_PIXHEIGHT (f))
8392 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
8393 high_y_coord = FRAME_PIXHEIGHT (f);
8394 position = OVER_TOOLBAR;
8398 low_y_coord = FRAME_PIXHEIGHT (f);
8399 high_y_coord = y_coord;
8400 position = OVER_OUTSIDE;
8404 if (position != OVER_TOOLBAR && position != OVER_BORDER)
8406 if (x_coord < frm_left)
8408 if (x_coord >= FRAME_LEFT_BORDER_START (f))
8410 low_x_coord = FRAME_LEFT_BORDER_START (f);
8411 high_x_coord = frm_left;
8412 position = OVER_BORDER;
8414 else if (x_coord >= 0)
8417 high_x_coord = FRAME_LEFT_BORDER_START (f);
8418 position = OVER_TOOLBAR;
8422 low_x_coord = x_coord;
8424 position = OVER_OUTSIDE;
8427 else if (x_coord >= frm_right)
8429 if (x_coord < FRAME_RIGHT_BORDER_END (f))
8431 low_x_coord = frm_right;
8432 high_x_coord = FRAME_RIGHT_BORDER_END (f);
8433 position = OVER_BORDER;
8435 else if (x_coord < FRAME_PIXWIDTH (f))
8437 low_x_coord = FRAME_RIGHT_BORDER_END (f);
8438 high_x_coord = FRAME_PIXWIDTH (f);
8439 position = OVER_TOOLBAR;
8443 low_x_coord = FRAME_PIXWIDTH (f);
8444 high_x_coord = x_coord;
8445 position = OVER_OUTSIDE;
8450 #ifdef HAVE_TOOLBARS
8451 if (position == OVER_TOOLBAR)
8453 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
8456 UPDATE_CACHE_RETURN;
8458 #endif /* HAVE_TOOLBARS */
8460 /* We still have to return the window the pointer is next to and its
8461 relative y position even if it is outside the x boundary. */
8462 if (x_coord < frm_left)
8464 else if (x_coord > frm_right)
8465 x_coord = frm_right;
8467 /* Same in reverse. */
8468 if (y_coord < frm_top)
8470 else if (y_coord > frm_bottom)
8471 y_coord = frm_bottom;
8473 /* Find what window the given coordinates are actually in. */
8474 window = f->root_window;
8475 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
8477 /* If we didn't find a window, we're done. */
8480 UPDATE_CACHE_RETURN;
8482 else if (position != OVER_NOTHING)
8485 *modeline_closest = -1;
8487 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
8490 UPDATE_CACHE_RETURN;
8494 /* Check if the window is a minibuffer but isn't active. */
8495 if (MINI_WINDOW_P (*w) && !minibuf_level)
8497 /* Must reset the window value since some callers will ignore
8498 the return value if it is set. */
8500 UPDATE_CACHE_RETURN;
8503 /* See if the point is over window vertical divider */
8504 if (window_needs_vertical_divider (*w))
8506 int div_x_high = WINDOW_RIGHT (*w);
8507 int div_x_low = div_x_high - window_divider_width (*w);
8508 int div_y_high = WINDOW_BOTTOM (*w);
8509 int div_y_low = WINDOW_TOP (*w);
8511 if (div_x_low < x_coord && x_coord <= div_x_high &&
8512 div_y_low < y_coord && y_coord <= div_y_high)
8514 low_x_coord = div_x_low;
8515 high_x_coord = div_x_high;
8516 low_y_coord = div_y_low;
8517 high_y_coord = div_y_high;
8518 position = OVER_V_DIVIDER;
8519 UPDATE_CACHE_RETURN;
8523 dla = window_display_lines (*w, CURRENT_DISP);
8525 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
8527 int really_over_nothing = 0;
8528 struct display_line *dl = Dynarr_atp (dla, *row);
8530 if ((int) (dl->ypos - dl->ascent) <= y_coord
8531 && y_coord <= (int) (dl->ypos + dl->descent))
8533 int check_margin_glyphs = 0;
8534 struct display_block *db = get_display_block_from_line (dl, TEXT);
8535 struct rune *rb = 0;
8537 if (x_coord < dl->bounds.left_white
8538 || x_coord >= dl->bounds.right_white)
8539 check_margin_glyphs = 1;
8541 low_y_coord = dl->ypos - dl->ascent;
8542 high_y_coord = dl->ypos + dl->descent + 1;
8544 if (position == OVER_BORDER
8545 || position == OVER_OUTSIDE
8546 || check_margin_glyphs)
8548 int x_check, left_bound;
8550 if (check_margin_glyphs)
8553 left_bound = dl->bounds.left_white;
8557 x_check = high_x_coord;
8558 left_bound = frm_left;
8561 if (Dynarr_length (db->runes))
8563 if (x_check <= left_bound)
8566 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
8568 *closest = Dynarr_atp (db->runes, 0)->bufpos;
8574 Dynarr_atp (db->runes,
8575 Dynarr_length (db->runes) - 1)->bufpos;
8578 Dynarr_atp (db->runes,
8579 Dynarr_length (db->runes) - 1)->bufpos;
8583 *modeline_closest += dl->offset;
8585 *closest += dl->offset;
8589 /* #### What should be here. */
8591 *modeline_closest = 0;
8596 if (check_margin_glyphs)
8598 if (x_coord < dl->bounds.left_in
8599 || x_coord >= dl->bounds.right_in)
8601 /* If we are over the outside margins then we
8602 know the loop over the text block isn't going
8603 to accomplish anything. So we go ahead and
8604 set what information we can right here and
8607 *obj_y = y_coord - (dl->ypos - dl->ascent);
8608 get_position_object (dl, obj1, obj2, x_coord,
8609 &low_x_coord, &high_x_coord);
8611 UPDATE_CACHE_RETURN;
8615 UPDATE_CACHE_RETURN;
8618 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
8620 int past_end = (*col == Dynarr_length (db->runes));
8623 rb = Dynarr_atp (db->runes, *col);
8626 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
8631 rb = Dynarr_atp (db->runes, *col);
8634 *bufpos = rb->bufpos + dl->offset;
8635 low_x_coord = rb->xpos;
8636 high_x_coord = rb->xpos + rb->width;
8638 if (rb->type == RUNE_DGLYPH)
8642 /* Find the first character after the glyph. */
8643 while (elt < Dynarr_length (db->runes))
8645 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
8649 (Dynarr_atp (db->runes, elt)->bufpos +
8653 (Dynarr_atp (db->runes, elt)->bufpos +
8661 /* In this case we failed to find a non-glyph
8662 character so we return the last position
8663 displayed on the line. */
8664 if (elt == Dynarr_length (db->runes))
8667 *modeline_closest = dl->end_bufpos + dl->offset;
8669 *closest = dl->end_bufpos + dl->offset;
8670 really_over_nothing = 1;
8676 *modeline_closest = rb->bufpos + dl->offset;
8678 *closest = rb->bufpos + dl->offset;
8683 *row = window_displayed_height (*w);
8685 if (position == OVER_NOTHING)
8686 position = OVER_MODELINE;
8688 if (rb->type == RUNE_DGLYPH)
8690 *obj1 = rb->object.dglyph.glyph;
8691 *obj2 = rb->object.dglyph.extent;
8693 else if (rb->type == RUNE_CHAR)
8704 UPDATE_CACHE_RETURN;
8707 || (rb->type == RUNE_CHAR
8708 && rb->object.chr.ch == '\n'))
8711 /* At this point we may have glyphs in the right
8713 if (check_margin_glyphs)
8714 get_position_object (dl, obj1, obj2, x_coord,
8715 &low_x_coord, &high_x_coord);
8716 UPDATE_CACHE_RETURN;
8721 if (rb->type == RUNE_DGLYPH)
8723 *obj1 = rb->object.dglyph.glyph;
8724 *obj2 = rb->object.dglyph.extent;
8726 else if (rb->type == RUNE_CHAR)
8737 *obj_x = x_coord - rb->xpos;
8738 *obj_y = y_coord - (dl->ypos - dl->ascent);
8740 /* At this point we may have glyphs in the left
8742 if (check_margin_glyphs)
8743 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
8745 if (position == OVER_NOTHING && !really_over_nothing)
8746 position = OVER_TEXT;
8748 UPDATE_CACHE_RETURN;
8755 *row = Dynarr_length (dla) - 1;
8756 if (FRAME_WIN_P (f))
8758 int bot_elt = Dynarr_length (dla) - 1;
8762 struct display_line *dl = Dynarr_atp (dla, bot_elt);
8763 int adj_area = y_coord - (dl->ypos + dl->descent);
8767 XSETWINDOW (lwin, *w);
8768 default_face_height_and_width (lwin, 0, &defheight);
8770 *row += (adj_area / defheight);
8774 /* #### This should be checked out some more to determine what
8775 should really be going on. */
8776 if (!MARKERP ((*w)->start[CURRENT_DISP]))
8779 *closest = end_of_last_line (*w,
8780 marker_position ((*w)->start[CURRENT_DISP]));
8782 UPDATE_CACHE_RETURN;
8784 #undef UPDATE_CACHE_RETURN
8787 /***************************************************************************/
8789 /* Lisp functions */
8791 /***************************************************************************/
8793 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8794 Ensure that all minibuffers are correctly showing the echo area.
8798 Lisp_Object devcons, concons;
8800 DEVICE_LOOP_NO_BREAK (devcons, concons)
8802 struct device *d = XDEVICE (XCAR (devcons));
8803 Lisp_Object frmcons;
8805 DEVICE_FRAME_LOOP (frmcons, d)
8807 struct frame *f = XFRAME (XCAR (frmcons));
8809 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
8811 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
8813 * If the frame size has changed, there may be random
8814 * chud on the screen left from previous messages
8815 * because redisplay_frame hasn't been called yet.
8816 * Clear the screen to get rid of the potential mess.
8818 if (f->echo_area_garbaged)
8820 DEVMETH (d, clear_frame, (f));
8821 f->echo_area_garbaged = 0;
8823 redisplay_window (window, 0);
8824 call_redisplay_end_triggers (XWINDOW (window), 0);
8828 /* We now call the output_end routine for tty frames. We delay
8829 doing so in order to avoid cursor flicker. So much for 100%
8831 if (DEVICE_TTY_P (d))
8832 DEVMETH (d, output_end, (d));
8839 restore_disable_preemption_value (Lisp_Object value)
8841 disable_preemption = XINT (value);
8845 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8846 Clear frame FRAME and output again what is supposed to appear on it.
8847 FRAME defaults to the selected frame if omitted.
8848 Normally, redisplay is preempted as normal if input arrives. However,
8849 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8850 input and is guaranteed to proceed to completion.
8852 (frame, no_preempt))
8854 struct frame *f = decode_frame (frame);
8855 int count = specpdl_depth ();
8857 if (!NILP (no_preempt))
8859 record_unwind_protect (restore_disable_preemption_value,
8860 make_int (disable_preemption));
8861 disable_preemption++;
8865 redisplay_frame (f, 1);
8867 return unbind_to (count, Qnil);
8870 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8871 Ensure that FRAME's contents are correctly displayed.
8872 This differs from `redraw-frame' in that it only redraws what needs to
8873 be updated, as opposed to unconditionally clearing and redrawing
8875 FRAME defaults to the selected frame if omitted.
8876 Normally, redisplay is preempted as normal if input arrives. However,
8877 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8878 input and is guaranteed to proceed to completion.
8880 (frame, no_preempt))
8882 struct frame *f = decode_frame (frame);
8883 int count = specpdl_depth ();
8885 if (!NILP (no_preempt))
8887 record_unwind_protect (restore_disable_preemption_value,
8888 make_int (disable_preemption));
8889 disable_preemption++;
8892 redisplay_frame (f, 1);
8894 return unbind_to (count, Qnil);
8897 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
8898 Clear device DEVICE and output again what is supposed to appear on it.
8899 DEVICE defaults to the selected device if omitted.
8900 Normally, redisplay is preempted as normal if input arrives. However,
8901 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8902 input and is guaranteed to proceed to completion.
8904 (device, no_preempt))
8906 struct device *d = decode_device (device);
8907 Lisp_Object frmcons;
8908 int count = specpdl_depth ();
8910 if (!NILP (no_preempt))
8912 record_unwind_protect (restore_disable_preemption_value,
8913 make_int (disable_preemption));
8914 disable_preemption++;
8917 DEVICE_FRAME_LOOP (frmcons, d)
8919 XFRAME (XCAR (frmcons))->clear = 1;
8921 redisplay_device (d);
8923 return unbind_to (count, Qnil);
8926 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8927 Ensure that DEVICE's contents are correctly displayed.
8928 This differs from `redraw-device' in that it only redraws what needs to
8929 be updated, as opposed to unconditionally clearing and redrawing
8931 DEVICE defaults to the selected device if omitted.
8932 Normally, redisplay is preempted as normal if input arrives. However,
8933 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8934 input and is guaranteed to proceed to completion.
8936 (device, no_preempt))
8938 struct device *d = decode_device (device);
8939 int count = specpdl_depth ();
8941 if (!NILP (no_preempt))
8943 record_unwind_protect (restore_disable_preemption_value,
8944 make_int (disable_preemption));
8945 disable_preemption++;
8948 redisplay_device (d);
8950 return unbind_to (count, Qnil);
8953 /* Big lie. Big lie. This will force all modelines to be updated
8954 regardless if the all flag is set or not. It remains in existence
8955 solely for backwards compatibility. */
8956 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8957 Force the modeline of the current buffer to be redisplayed.
8958 With optional non-nil ALL, force redisplay of all modelines.
8962 MARK_MODELINE_CHANGED;
8966 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8967 Force an immediate update of the cursor on FRAME.
8968 FRAME defaults to the selected frame if omitted.
8972 redisplay_redraw_cursor (decode_frame (frame), 1);
8977 /***************************************************************************/
8979 /* Lisp-variable change triggers */
8981 /***************************************************************************/
8984 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
8987 /* Nothing to be done? */
8991 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
8992 Lisp_Object in_object, int flags)
8994 /* #### clip_changed should really be renamed something like
8995 global_redisplay_change. */
9000 /* This is called if the built-in glyphs have their properties
9003 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
9006 if (WINDOWP (locale))
9008 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
9010 else if (FRAMEP (locale))
9012 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
9014 else if (DEVICEP (locale))
9016 Lisp_Object frmcons;
9017 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
9018 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9020 else if (CONSOLEP (locale))
9022 Lisp_Object frmcons, devcons;
9023 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
9024 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9026 else /* global or buffer */
9028 Lisp_Object frmcons, devcons, concons;
9029 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
9030 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
9035 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
9038 if (XFRAME (w->frame)->init_finished)
9039 Fforce_cursor_redisplay (w->frame);
9042 #ifdef MEMORY_USAGE_STATS
9045 /***************************************************************************/
9047 /* memory usage computation */
9049 /***************************************************************************/
9052 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
9054 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9058 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
9059 struct overhead_stats *ovstats)
9066 total = Dynarr_memory_usage (dyn, ovstats);
9067 for (i = 0; i < Dynarr_largest (dyn); i++)
9068 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
9074 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
9075 struct overhead_stats *ovstats)
9077 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9081 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
9082 struct overhead_stats *ovstats)
9089 total = Dynarr_memory_usage (dyn, ovstats);
9090 for (i = 0; i < Dynarr_largest (dyn); i++)
9092 struct display_line *dl = &Dynarr_at (dyn, i);
9093 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
9094 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
9095 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
9102 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
9103 struct overhead_stats *ovstats)
9105 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9108 #endif /* MEMORY_USAGE_STATS */
9111 /***************************************************************************/
9113 /* initialization */
9115 /***************************************************************************/
9118 init_redisplay (void)
9120 disable_preemption = 0;
9121 preemption_count = 0;
9122 max_preempts = INIT_MAX_PREEMPTS;
9128 cmotion_display_lines = Dynarr_new (display_line);
9129 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
9130 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
9131 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
9132 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
9133 internal_cache = Dynarr_new (line_start_cache);
9136 /* window system is nil when in -batch mode */
9137 if (!initialized || noninteractive)
9140 /* If the user wants to use a window system, we shouldn't bother
9141 initializing the terminal. This is especially important when the
9142 terminal is so dumb that emacs gives up before and doesn't bother
9143 using the window system.
9145 If the DISPLAY environment variable is set, try to use X, and die
9146 with an error message if that doesn't work. */
9148 #ifdef HAVE_X_WINDOWS
9149 if (!strcmp (display_use, "x"))
9151 /* Some stuff checks this way early. */
9152 Vwindow_system = Qx;
9153 Vinitial_window_system = Qx;
9156 #endif /* HAVE_X_WINDOWS */
9158 #ifdef HAVE_MS_WINDOWS
9159 if (!strcmp (display_use, "mswindows"))
9161 /* Some stuff checks this way early. */
9162 Vwindow_system = Qmswindows;
9163 Vinitial_window_system = Qmswindows;
9166 #endif /* HAVE_MS_WINDOWS */
9169 /* If no window system has been specified, try to use the terminal. */
9172 stderr_out ("XEmacs: standard input is not a tty\n");
9176 /* Look at the TERM variable */
9177 if (!getenv ("TERM"))
9179 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
9183 Vinitial_window_system = Qtty;
9185 #else /* not HAVE_TTY */
9186 /* No DISPLAY specified, and no TTY support. */
9187 stderr_out ("XEmacs: Cannot open display.\n\
9188 Please set the environmental variable DISPLAY to an appropriate value.\n");
9195 syms_of_redisplay (void)
9197 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
9198 #ifndef INHIBIT_REDISPLAY_HOOKS
9199 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
9200 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
9201 #endif /* INHIBIT_REDISPLAY_HOOKS */
9202 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
9203 defsymbol (&Qbar_cursor, "bar-cursor");
9204 defsymbol (&Qredisplay_end_trigger_functions,
9205 "redisplay-end-trigger-functions");
9207 DEFSUBR (Fredisplay_echo_area);
9208 DEFSUBR (Fredraw_frame);
9209 DEFSUBR (Fredisplay_frame);
9210 DEFSUBR (Fredraw_device);
9211 DEFSUBR (Fredisplay_device);
9212 DEFSUBR (Fredraw_modeline);
9213 DEFSUBR (Fforce_cursor_redisplay);
9217 reinit_vars_of_redisplay (void)
9219 updating_line_start_cache = 0;
9223 vars_of_redisplay (void)
9225 reinit_vars_of_redisplay ();
9228 staticpro (&last_arrow_position);
9229 staticpro (&last_arrow_string);
9230 last_arrow_position = Qnil;
9231 last_arrow_string = Qnil;
9234 /* #### Probably temporary */
9235 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
9236 \(Temporary) Setting this will impact the performance of the internal
9239 cache_adjustment = 2;
9241 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
9242 Minimum pixel height for clipped bottom display line.
9243 A clipped line shorter than this won't be displayed.
9245 redisplay_variable_changed);
9248 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
9249 Minimum visible area for clipped glyphs at right boundary.
9250 Clipped glyphs shorter than this won't be displayed.
9251 Only pixmap glyph instances are currently allowed to be clipped.
9253 redisplay_variable_changed);
9254 horizontal_clip = 5;
9256 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
9257 String displayed by modeline-format's "%m" specification.
9259 Vglobal_mode_string = Qnil;
9261 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
9262 Marker for where to display an arrow on top of the buffer text.
9263 This must be the beginning of a line in order to work.
9264 See also `overlay-arrow-string'.
9266 redisplay_variable_changed);
9267 Voverlay_arrow_position = Qnil;
9269 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
9270 String to display as an arrow. See also `overlay-arrow-position'.
9272 redisplay_variable_changed);
9273 Voverlay_arrow_string = Qnil;
9275 DEFVAR_INT ("scroll-step", &scroll_step /*
9276 *The number of lines to try scrolling a window by when point moves out.
9277 If that fails to bring point back on frame, point is centered instead.
9278 If this is zero, point is always centered after it moves off screen.
9282 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
9283 *Scroll up to this many lines, to bring point back on screen.
9285 scroll_conservatively = 0;
9287 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
9288 &truncate_partial_width_windows /*
9289 *Non-nil means truncate lines in all windows less than full frame wide.
9291 redisplay_variable_changed);
9292 truncate_partial_width_windows = 1;
9294 DEFVAR_BOOL ("visible-bell", &visible_bell /*
9295 *Non-nil means try to flash the frame to represent a bell.
9299 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
9300 *Non-nil means no need to redraw entire frame after suspending.
9301 A non-nil value is useful if the terminal can automatically preserve
9302 Emacs's frame display when you reenter Emacs.
9303 It is up to you to set this variable if your terminal can do that.
9305 no_redraw_on_reenter = 0;
9307 DEFVAR_LISP ("window-system", &Vwindow_system /*
9308 A symbol naming the window-system under which Emacs is running,
9309 such as `x', or nil if emacs is running on an ordinary terminal.
9311 Do not use this variable, except for GNU Emacs compatibility, as it
9312 gives wrong values in a multi-device environment. Use `console-type'
9315 Vwindow_system = Qnil;
9317 /* #### Temporary shit until window-system is eliminated. */
9318 DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /*
9321 Vinitial_window_system = Qnil;
9323 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
9324 Non-nil means put cursor in minibuffer, at end of any message there.
9326 cursor_in_echo_area = 0;
9328 /* #### Shouldn't this be generalized as follows:
9330 if nil, use block cursor.
9331 if a number, use a bar cursor of that width.
9332 Otherwise, use a 1-pixel bar cursor.
9334 #### Or better yet, this variable should be trashed entirely
9335 (use a Lisp-magic variable to maintain compatibility)
9336 and a specifier `cursor-shape' added, which allows a block
9337 cursor, a bar cursor, a flashing block or bar cursor,
9338 maybe a caret cursor, etc. */
9340 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
9341 Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9345 #ifndef INHIBIT_REDISPLAY_HOOKS
9346 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
9347 Function or functions to run before every redisplay.
9348 Functions on this hook must be careful to avoid signalling errors!
9350 Vpre_redisplay_hook = Qnil;
9352 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
9353 Function or functions to run after every redisplay.
9354 Functions on this hook must be careful to avoid signalling errors!
9356 Vpost_redisplay_hook = Qnil;
9357 #endif /* INHIBIT_REDISPLAY_HOOKS */
9359 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
9360 Bump this to tell the C code to call `display-warning-buffer'
9361 at next redisplay. You should not normally change this; the function
9362 `display-warning' automatically does this at appropriate times.
9364 display_warning_tick = 0;
9366 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
9367 Non-nil means inhibit display of warning messages.
9368 You should *bind* this, not set it. Any pending warning messages
9369 will be displayed when the binding no longer applies.
9371 /* reset to 0 by startup.el after the splash screen has displayed.
9372 This way, the warnings don't obliterate the splash screen. */
9373 inhibit_warning_display = 1;
9375 DEFVAR_LISP ("window-size-change-functions",
9376 &Vwindow_size_change_functions /*
9377 Not currently implemented.
9378 Functions called before redisplay, if window sizes have changed.
9379 The value should be a list of functions that take one argument.
9380 Just before redisplay, for each frame, if any of its windows have changed
9381 size since the last redisplay, or have been split or deleted,
9382 all the functions in the list are called, with the frame as argument.
9384 Vwindow_size_change_functions = Qnil;
9386 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
9387 Not currently implemented.
9388 Functions to call before redisplaying a window with scrolling.
9389 Each function is called with two arguments, the window
9390 and its new display-start position. Note that the value of `window-end'
9391 is not valid when these functions are called.
9393 Vwindow_scroll_functions = Qnil;
9395 DEFVAR_LISP ("redisplay-end-trigger-functions",
9396 &Vredisplay_end_trigger_functions /*
9397 See `set-window-redisplay-end-trigger'.
9399 Vredisplay_end_trigger_functions = Qnil;
9401 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
9402 *Non-nil means column display number starts at 1.
9404 column_number_start_at_one = 0;
9408 specifier_vars_of_redisplay (void)
9410 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
9411 *Width of left margin.
9412 This is a specifier; use `set-specifier' to change it.
9414 Vleft_margin_width = Fmake_specifier (Qnatnum);
9415 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
9416 set_specifier_caching (Vleft_margin_width,
9417 offsetof (struct window, left_margin_width),
9418 some_window_value_changed,
9419 offsetof (struct frame, left_margin_width),
9420 margin_width_changed_in_frame);
9422 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
9423 *Width of right margin.
9424 This is a specifier; use `set-specifier' to change it.
9426 Vright_margin_width = Fmake_specifier (Qnatnum);
9427 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
9428 set_specifier_caching (Vright_margin_width,
9429 offsetof (struct window, right_margin_width),
9430 some_window_value_changed,
9431 offsetof (struct frame, right_margin_width),
9432 margin_width_changed_in_frame);
9434 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
9435 *Minimum ascent height of lines.
9436 This is a specifier; use `set-specifier' to change it.
9438 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
9439 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
9440 set_specifier_caching (Vminimum_line_ascent,
9441 offsetof (struct window, minimum_line_ascent),
9442 some_window_value_changed,
9445 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
9446 *Minimum descent height of lines.
9447 This is a specifier; use `set-specifier' to change it.
9449 Vminimum_line_descent = Fmake_specifier (Qnatnum);
9450 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
9451 set_specifier_caching (Vminimum_line_descent,
9452 offsetof (struct window, minimum_line_descent),
9453 some_window_value_changed,
9456 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
9457 *Non-nil means use the left outside margin as extra whitespace when
9458 displaying 'whitespace or 'inside-margin glyphs.
9459 This is a specifier; use `set-specifier' to change it.
9461 Vuse_left_overflow = Fmake_specifier (Qboolean);
9462 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
9463 set_specifier_caching (Vuse_left_overflow,
9464 offsetof (struct window, use_left_overflow),
9465 some_window_value_changed,
9468 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
9469 *Non-nil means use the right outside margin as extra whitespace when
9470 displaying 'whitespace or 'inside-margin glyphs.
9471 This is a specifier; use `set-specifier' to change it.
9473 Vuse_right_overflow = Fmake_specifier (Qboolean);
9474 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
9475 set_specifier_caching (Vuse_right_overflow,
9476 offsetof (struct window, use_right_overflow),
9477 some_window_value_changed,
9480 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9481 *Non-nil means the text cursor is visible (this is usually the case).
9482 This is a specifier; use `set-specifier' to change it.
9484 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
9485 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
9486 set_specifier_caching (Vtext_cursor_visible_p,
9487 offsetof (struct window, text_cursor_visible_p),
9488 text_cursor_visible_p_changed,