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 SXEmacs
10 SXEmacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 SXEmacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 /* Synched up with: Not in FSF. */
26 /* Author: Chuck Thompson */
28 /* Fixed up by Ben Wing for Mule */
30 /* This file has been Mule-ized. */
32 /*****************************************************************************
33 The Golden Rules of Redisplay
35 First: It Is Better To Be Correct Than Fast
36 Second: Thou Shalt Not Run Elisp From Within Redisplay
37 Third: It Is Better To Be Fast Than Not To Be
38 ****************************************************************************/
57 #include "redisplay.h"
60 #include "line-number.h"
62 #include "mule/file-coding.h"
67 /* Note: We have to be careful throughout this code to properly handle
68 and differentiate between Bufbytes and Emchars.
70 Since strings are generally composed of Bufbytes, I've taken the tack
71 that any contiguous set of Bufbytes is called a "string", while
72 any contiguous set of Emchars is called an "array". */
74 /* Return value to indicate a failure by an add_*_rune routine to add
75 a rune, but no propagation information needs to be returned. */
76 #define ADD_FAILED (prop_block_dynarr *) 1
78 #define BEGIN_GLYPHS 0
81 #define RIGHT_GLYPHS 3
83 #define VERTICAL_CLIP(w, display) \
84 ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
88 /* The following structures are completely private to redisplay.c so
89 we put them here instead of in a header file, for modularity. */
91 /* NOTE: Bytinds not Bufpos's in this structure. */
93 typedef struct position_redisplay_data_type {
94 /* This information is normally filled in by the create_*_block
95 routines and is used by the add_*_rune routines. */
97 /* if we are working with strings rather than buffers we need a
98 handle to the string */
101 struct display_block *db;
102 struct display_line *dl;
103 Emchar ch; /* Character that is to be added. This is
104 used to communicate this information to
105 add_emchar_rune(). */
106 Lisp_Object last_charset; /* The charset of the previous character.
107 Used to optimize some lookups -- we
108 only have to do some things when
109 the charset changes. */
110 face_index last_findex; /* The face index of the previous character.
111 Needed to ensure the validity of the
112 last_charset optimization. */
114 int last_char_width; /* The width of the previous character. */
115 int font_is_bogus; /* If true, it means we couldn't instantiate
116 the font for this charset, so we substitute
117 ~'s from the ASCII charset. */
122 int blank_width; /* Width of the blank that is to be added.
123 This is used to communicate this information
126 This is also used rather cheesily to
127 communicate the width of the eol-cursor-size
128 blank that exists at the end of the line.
129 add_emchar_rune() is called cheesily with
130 the non-printing char '\n', which is stuck
131 in the output routines with its width being
133 Bytind bi_cursor_bufpos; /* This stores the buffer position of the cursor. */
134 unsigned int cursor_type:3;
135 int cursor_x; /* rune block cursor is at */
136 int start_col; /* Number of character columns (each column has
137 a width of the default char width) that still
138 need to be skipped. This is used for horizontal
139 scrolling, where a certain number of columns
140 (those off the left side of the screen) need
141 to be skipped before anything is displayed. */
142 Bytind bi_start_col_enabled;
143 int start_col_xoffset; /* Number of pixels that still need to
144 be skipped. This is used for
145 horizontal scrolling of glyphs, where we want
146 to be able to scroll over part of the glyph. */
148 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
149 glyph differs from space_width (w).
150 0 if no hscroll glyph was used,
151 i.e. the window is not scrolled
152 horizontally. Used in tab
155 /* Information about the face the text should be displayed in and
156 any begin-glyphs and end-glyphs. */
157 struct extent_fragment *ef;
160 /* The height of a pixmap may either be predetermined if the user has set a
161 baseline value, or it may be dependent on whatever the line ascent and
162 descent values end up being, based just on font and pixmap-ascent
163 information. In the first case we can immediately update the values, thus
164 their inclusion here. In the last case we cannot determine the actual
165 contribution to the line height until we have finished laying out all text
166 on the line. Thus we propagate the max height of such pixmaps and do a
167 final calculation (in calculate_baseline()) after all text has been added
171 int max_pixmap_height;
172 int need_baseline_computation;
173 int end_glyph_width; /* Well, it is the kitchen sink after all ... */
175 Lisp_Object result_str; /* String where we put the result of
176 generating a formatted string in the modeline. */
177 int is_modeline; /* Non-zero if we're generating the modeline. */
178 Charcount modeline_charpos; /* Number of chars used in result_str so far;
179 corresponds to bytepos. */
180 Bytecount bytepos; /* Number of bytes used in result_str so far.
181 We don't actually copy the bytes into result_str
182 until the end because we don't know how big the
183 string is going to be until then. */
194 /* Data that should be propagated to the next line. Either a single
195 Emchar, a string of Bufbyte's or a glyph.
197 The actual data that is propagated ends up as a Dynarr of these
200 prop_blocks are used to indicate that data that was supposed to go
201 on the previous line couldn't actually be displayed. Generally this
202 shouldn't happen if we are clipping the end of lines. If we are
203 wrapping then we need to display the propagation data before moving
204 on. Its questionable whether we should wrap or clip glyphs in this
205 instance. Most e-lisp relies on clipping so we preserve this
208 #### It's unclean that both Emchars and Bufbytes are here.
211 typedef struct prop_block prop_block;
218 Bytecount len; /* length of the string. */
223 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
224 unsigned int cursor_type:3;
233 /* Not used as yet, but could be used to wrap rather than clip glyphs. */
242 Dynarr_declare(prop_block);
245 static Charcount generate_fstring_runes(struct window *w, pos_data * data,
246 Charcount pos, Charcount min_pos,
247 Charcount max_pos, Lisp_Object elt,
248 int depth, int max_pixsize,
249 face_index findex, int type,
251 Lisp_Object cur_ext);
252 static prop_block_dynarr *add_glyph_rune(pos_data * data,
253 struct glyph_block *gb,
254 int pos_type, int allow_cursor,
255 struct glyph_cachel *cachel);
256 static void add_glyph_rune_noret(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, int overlay_width);
267 static void create_right_glyph_block(struct window *w, struct display_line *dl);
268 static void redisplay_windows(Lisp_Object window, int skip_selected);
269 static void decode_mode_spec(struct window *w, Emchar spec, int type);
270 static void free_display_line(struct display_line *dl);
271 static void update_line_start_cache(struct window *w, Bufpos from, Bufpos to,
272 Bufpos point, int no_regen);
273 static int point_visible(struct window *w, Bufpos point, int type);
274 static void calculate_yoffset(struct display_line *dl,
275 struct display_block *fixup);
276 static void calculate_baseline(pos_data * data);
278 /* This used to be 10 but 30 seems to give much better performance. */
279 #define INIT_MAX_PREEMPTS 30
280 static int max_preempts;
282 #define REDISPLAY_PREEMPTION_CHECK \
285 (!disable_preemption && \
286 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
287 (!INTERACTIVE || detect_input_pending ()))))
290 * Redisplay global variables.
293 /* We need a third set of display structures for the cursor motion
294 routines. We used to just give each window a third set. However,
295 we always fully regenerate the structures when needed so there
296 isn't any reason we need more than a single set. */
297 display_line_dynarr *cmotion_display_lines;
299 /* We store the extents that we need to generate in a Dynarr and then
300 frob them all on at the end of generating the string. We do it
301 this way rather than adding them as we generate the string because
302 we don't store the text into the resulting string until we're done
303 (to avoid having to resize the string multiple times), and we don't
304 want to go around adding extents to a string when the extents might
305 stretch off the end of the string. */
306 static EXTENT_dynarr *formatted_string_extent_dynarr;
307 static Bytecount_dynarr *formatted_string_extent_start_dynarr;
308 static Bytecount_dynarr *formatted_string_extent_end_dynarr;
310 /* #### probably temporary */
311 Fixnum 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. */
326 Fixnum vertical_clip;
328 /* Minimum visible pixel width of clipped glyphs at right margin. */
329 Fixnum horizontal_clip;
331 /* Nonzero means reading single-character input with prompt
332 so put cursor on minibuffer after the prompt. */
333 int cursor_in_echo_area;
334 Lisp_Object Qcursor_in_echo_area;
336 /* Nonzero means truncate lines in all windows less wide than the frame */
337 int truncate_partial_width_windows;
339 /* non-nil if a buffer has changed since the last time redisplay completed */
341 int buffers_changed_set;
343 /* non-nil if hscroll has changed somewhere or a buffer has been
344 narrowed or widened */
346 int clip_changed_set;
348 /* non-nil if any extent has changed since the last time redisplay completed */
350 int extents_changed_set;
352 /* non-nil if any face has changed since the last time redisplay completed */
355 /* Nonzero means some frames have been marked as garbaged */
358 /* non-zero if any of the builtin display glyphs (continuation,
359 hscroll, control-arrow, etc) is in need of updating
362 int glyphs_changed_set;
364 /* non-zero if any subwindow has been deleted. */
365 int subwindows_changed;
366 int subwindows_changed_set;
368 /* non-zero if any displayed subwindow is in need of updating
370 int subwindows_state_changed;
371 int subwindows_state_changed_set;
373 /* This variable is 1 if the icon has to be updated.
374 It is set to 1 when `frame-icon-glyph' changes. */
376 int icon_changed_set;
378 /* This variable is 1 if the menubar widget has to be updated.
379 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
382 int menubar_changed_set;
384 /* true iff we should redraw the modelines on the next redisplay */
385 int modeline_changed;
386 int modeline_changed_set;
388 /* non-nil if point has changed in some buffer since the last time
389 redisplay completed */
391 int point_changed_set;
393 /* non-nil if some frame has changed its size */
396 /* non-nil if some device has signaled that it wants to change size */
397 int asynch_device_change_pending;
399 /* non-nil if any toolbar has changed */
401 int toolbar_changed_set;
403 /* Nonzero if some frame has changed the layout of internal elements
404 (gutters or toolbars). */
405 int frame_layout_changed;
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 Lisp_Object Vvisible_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 Fixnum 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 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook;
456 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
458 #ifndef INHIBIT_REDISPLAY_HOOKS
459 /* #### Chuck says: I think this needs more thought.
460 Think about this for 19.14. */
461 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
462 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
463 #endif /* INHIBIT_REDISPLAY_HOOKS */
465 static Fixnum last_display_warning_tick;
466 static Fixnum display_warning_tick;
467 Lisp_Object Qdisplay_warning_buffer;
468 int inhibit_warning_display;
470 Lisp_Object Vleft_margin_width, Vright_margin_width;
471 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
472 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
473 Lisp_Object Vtext_cursor_visible_p;
475 int column_number_start_at_one;
477 Lisp_Object Qtop_bottom;
479 #define WINDOW_SCROLLED(w) ((w)->hscroll > 0 || (w)->left_xoffset)
481 /***************************************************************************/
483 /* low-level interfaces onto device routines */
485 /***************************************************************************/
488 redisplay_text_width_emchar_string(struct window *w, int findex,
489 Emchar * str, Charcount len)
491 unsigned char charsets[NUM_LEADING_BYTES];
494 find_charsets_in_emchar_string(charsets, str, len);
495 XSETWINDOW(window, w);
496 ensure_face_cachel_complete(WINDOW_FACE_CACHEL(w, findex), window,
498 return DEVMETH(XDEVICE(FRAME_DEVICE(XFRAME(WINDOW_FRAME(w)))),
499 text_width, (XFRAME(WINDOW_FRAME(w)),
500 WINDOW_FACE_CACHEL(w, findex), str, len));
503 static Emchar_dynarr *rtw_emchar_dynarr;
506 redisplay_text_width_string(struct window *w, int findex,
507 Bufbyte * nonreloc, Lisp_Object reloc,
508 Bytecount offset, Bytecount len)
510 if (!rtw_emchar_dynarr)
511 rtw_emchar_dynarr = Dynarr_new(Emchar);
512 Dynarr_reset(rtw_emchar_dynarr);
514 fixup_internal_substring(nonreloc, reloc, offset, &len);
516 nonreloc = XSTRING_DATA(reloc);
517 convert_bufbyte_string_into_emchar_dynarr(nonreloc, len,
519 return redisplay_text_width_emchar_string(w, findex,
520 Dynarr_atp(rtw_emchar_dynarr,
523 (rtw_emchar_dynarr));
527 redisplay_frame_text_width_string(struct frame *f, Lisp_Object face,
528 Bufbyte * nonreloc, Lisp_Object reloc,
529 Bytecount offset, Bytecount len)
531 unsigned char charsets[NUM_LEADING_BYTES];
533 struct face_cachel cachel;
535 if (!rtw_emchar_dynarr)
536 rtw_emchar_dynarr = Dynarr_new(Emchar);
537 Dynarr_reset(rtw_emchar_dynarr);
539 fixup_internal_substring(nonreloc, reloc, offset, &len);
541 nonreloc = XSTRING_DATA(reloc);
542 convert_bufbyte_string_into_emchar_dynarr(nonreloc, len,
544 find_charsets_in_bufbyte_string(charsets, nonreloc, len);
545 reset_face_cachel(&cachel);
548 ensure_face_cachel_complete(&cachel, frame, charsets);
549 return DEVMETH(XDEVICE(FRAME_DEVICE(f)),
550 text_width, (f, &cachel,
551 Dynarr_atp(rtw_emchar_dynarr, 0),
552 Dynarr_length(rtw_emchar_dynarr)));
555 /* Return the display block from DL of the given TYPE. A display line
556 can have only one display block of each possible type. If DL does
557 not have a block of type TYPE, one will be created and added to DL. */
559 struct display_block *get_display_block_from_line(struct display_line *dl,
560 enum display_type type)
563 struct display_block db;
565 /* Check if this display line already has a block of the desired type and
567 if (dl->display_blocks) {
568 for (elt = 0; elt < Dynarr_length(dl->display_blocks); elt++) {
569 if (Dynarr_at(dl->display_blocks, elt).type == type)
570 return Dynarr_atp(dl->display_blocks, elt);
573 /* There isn't an active block of the desired type, but there
574 might still be allocated blocks we need to reuse. */
575 if (elt < Dynarr_largest(dl->display_blocks)) {
576 struct display_block *dbp =
577 Dynarr_atp(dl->display_blocks, elt);
579 /* 'add' the block to the list */
580 Dynarr_increment(dl->display_blocks);
582 /* initialize and return */
587 /* This line doesn't have any display blocks, so initialize the display
589 dl->display_blocks = Dynarr_new(display_block);
592 /* The line doesn't have a block of the desired type so go ahead and create
593 one and add it to the line. */
596 db.runes = Dynarr_new(rune);
597 Dynarr_add(dl->display_blocks, db);
599 /* Return the newly added display block. */
600 elt = Dynarr_length(dl->display_blocks) - 1;
602 return Dynarr_atp(dl->display_blocks, elt);
605 static int tab_char_width(struct window *w)
607 struct buffer *b = XBUFFER(w->buffer);
608 int char_tab_width = XINT(b->tab_width);
610 if (char_tab_width <= 0 || char_tab_width > 1000)
613 return char_tab_width;
616 static int space_width(struct window *w)
618 /* While tabs are traditional composed of spaces, for variable-width
619 fonts the space character tends to give too narrow a value. So
620 we use 'n' instead. Except that we don't. We use the default
621 character width for the default face. If this is actually
622 defined by the font then it is probably the best thing to
623 actually use. If it isn't, we have assumed it is 'n' and have
624 already calculated its width. Thus we can avoid a call to
625 XTextWidth on X frames by just querying the default width. */
626 return XFONT_INSTANCE
627 (WINDOW_FACE_CACHEL_FONT(w, DEFAULT_INDEX, Vcharset_ascii))->width;
630 static int tab_pix_width(struct window *w)
632 return space_width(w) * tab_char_width(w);
635 /* Given a pixel position in a window, return the pixel location of
636 the next tabstop. Tabs are calculated from the left window edge in
637 terms of spaces displayed in the default face. Formerly the space
638 width was determined using the currently active face. That method
639 leads to tabstops which do not line up. */
642 next_tab_position(struct window *w, int start_pixpos, int left_pixpos)
644 int n_pos = left_pixpos;
645 int pix_tab_width = tab_pix_width(w);
647 /* Adjust n_pos for any hscrolling which has happened. */
648 if (WINDOW_SCROLLED(w))
649 n_pos -= space_width(w) * (w->hscroll - 1) + w->left_xoffset;
651 while (n_pos <= start_pixpos)
652 n_pos += pix_tab_width;
657 /* For the given window, calculate the outside and margin boundaries for a
658 display line. The whitespace boundaries must be calculated by the text
661 layout_bounds calculate_display_line_boundaries(struct window * w, int modeline)
663 layout_bounds bounds;
665 /* Set the outermost boundaries which are the boundaries of the
666 window itself minus the gutters (and minus the scrollbars if this
667 is for the modeline). */
669 bounds.left_out = WINDOW_TEXT_LEFT(w);
670 bounds.right_out = WINDOW_TEXT_RIGHT(w);
672 bounds.left_out = WINDOW_MODELINE_LEFT(w);
673 bounds.right_out = WINDOW_MODELINE_RIGHT(w);
676 /* The inner boundaries mark where the glyph margins are located. */
677 bounds.left_in = bounds.left_out + window_left_margin_width(w);
678 bounds.right_in = bounds.right_out - window_right_margin_width(w);
680 /* We cannot fully calculate the whitespace boundaries as they
681 depend on the contents of the line being displayed. */
682 bounds.left_white = bounds.left_in;
683 bounds.right_white = bounds.right_in;
688 /* This takes a display_block and its containing line and corrects the yoffset
689 of each glyph in the block to cater for the ascent of the line as a
690 whole. Must be called *after* the line-ascent is known! */
693 calculate_yoffset(struct display_line *dl, struct display_block *fixup)
696 for (i = 0; i < Dynarr_length(fixup->runes); i++) {
697 struct rune *r = Dynarr_atp(fixup->runes, i);
698 if (r->type == RUNE_DGLYPH) {
699 if (r->object.dglyph.ascent < dl->ascent)
700 r->object.dglyph.yoffset =
701 dl->ascent - r->object.dglyph.ascent +
702 r->object.dglyph.descent;
707 /* Calculate the textual baseline (the ascent and descent values for the
708 display_line as a whole).
710 If the baseline is completely blank, or contains no manually positioned
711 glyphs, then the textual baseline is simply the baseline of the default font.
712 (The `contains no manually positioned glyphs' part is actually done for
713 us by `add_emchar_rune'.)
715 If the baseline contains pixmaps, and they're all manually positioned, then
716 the textual baseline location is constrained that way, and we need do no
719 If the baseline contains pixmaps, and at least one is automatically
720 positioned, then the textual ascent is the largest ascent on the line, and
721 the textual descent is the largest descent (which is how things are set up at
722 entry to this function anyway): except that if the max_ascent + max_descent
723 is too small for the height of the line (say you've adjusted the baseline of
724 a short glyph, and there's a tall one next to it), then take the ascent and
725 descent for the line individually from the largest of the explicitly set
726 ascent/descent, and the rescaled ascent/descent of the default font, scaled
727 such that the largest glyph will fit.
729 This means that if you have a short glyph (but taller than the default
730 font's descent) forced right under the baseline, and a really tall
731 automatically positioned glyph, that the descent for the line is just big
732 enough for the manually positioned short glyph, and the tall one uses as
733 much of that space as the default font would were it as tall as the tall
734 glyph; but that the ascent is big enough for the tall glyph to fit.
736 This behaviour means that under no circumstances will changing the baseline
737 of a short glyph cause a tall glyph to move around; nor will it move the
738 textual baseline more than necessary. (Changing a tall glyph's baseline
739 might move the text's baseline arbitrarily, of course.) */
741 static void calculate_baseline(pos_data * data)
743 /* Blank line: baseline is default font's baseline. */
745 if (!data->new_ascent && !data->new_descent) {
746 /* We've got a blank line so initialize these values from the default
748 default_face_font_info(data->window, &data->new_ascent,
749 &data->new_descent, 0, 0, 0);
752 /* No automatically positioned glyphs? Return at once. */
753 if (!data->need_baseline_computation)
756 /* Is the tallest glyph on the line automatically positioned?
757 If it's manually positioned, or it's automatically positioned
758 and there's enough room for it anyway, we need do no more work. */
759 if (data->max_pixmap_height > data->new_ascent + data->new_descent) {
760 int default_font_ascent, default_font_descent,
762 int scaled_default_font_ascent, scaled_default_font_descent;
764 default_face_font_info(data->window, &default_font_ascent,
765 &default_font_descent,
766 &default_font_height, 0, 0);
768 scaled_default_font_ascent = data->max_pixmap_height *
769 default_font_ascent / default_font_height;
772 max(data->new_ascent, scaled_default_font_ascent);
774 /* The ascent may have expanded now. Do we still need to grow the descent,
775 or are things big enough?
777 The +1 caters for the baseline row itself. */
778 if (data->max_pixmap_height >
779 data->new_ascent + data->new_descent) {
780 scaled_default_font_descent =
781 (data->max_pixmap_height * default_font_descent /
782 default_font_height) + 1;
785 max(data->new_descent, scaled_default_font_descent);
790 /* Given a display line and a starting position, ensure that the
791 contents of the display line accurately represent the visual
792 representation of the buffer contents starting from the given
793 position when displayed in the given window. The display line ends
794 when the contents of the line reach the right boundary of the given
798 generate_display_line(struct window *w, struct display_line *dl, int bounds,
799 Bufpos start_pos, prop_block_dynarr ** prop, int type)
803 struct buffer *b = XBUFFER(WINDOW_BUFFER(w));
805 /* If our caller hasn't already set the boundaries, then do so now. */
807 dl->bounds = calculate_display_line_boundaries(w, 0);
809 /* Reset what this line is using. */
810 if (dl->display_blocks)
811 Dynarr_reset(dl->display_blocks);
812 if (dl->left_glyphs) {
813 Dynarr_free(dl->left_glyphs);
816 if (dl->right_glyphs) {
817 Dynarr_free(dl->right_glyphs);
818 dl->right_glyphs = 0;
821 /* We aren't generating a modeline at the moment. */
824 /* Create a display block for the text region of the line. */
826 /* #### urk urk urk!!! Chuck fix this shit! */
827 Bytind hacked_up_bytind =
828 create_text_block(w, dl, bufpos_to_bytind(b, start_pos),
830 if (hacked_up_bytind > BI_BUF_ZV(b))
831 ret_bufpos = BUF_ZV(b) + 1;
833 ret_bufpos = bytind_to_bufpos(b, hacked_up_bytind);
835 dl->bufpos = start_pos;
836 if (dl->end_bufpos < dl->bufpos)
837 dl->end_bufpos = dl->bufpos;
839 if (MARKERP(Voverlay_arrow_position)
840 && EQ(w->buffer, Fmarker_buffer(Voverlay_arrow_position))
841 && start_pos == marker_position(Voverlay_arrow_position)
842 && (STRINGP(Voverlay_arrow_string)
843 || GLYPHP(Voverlay_arrow_string))) {
844 overlay_width = create_overlay_glyph_block(w, dl);
848 /* If there are left glyphs associated with any character in the
849 text block, then create a display block to handle them. */
850 if (dl->left_glyphs != NULL && Dynarr_length(dl->left_glyphs))
851 create_left_glyph_block(w, dl, overlay_width);
853 /* If there are right glyphs associated with any character in the
854 text block, then create a display block to handle them. */
855 if (dl->right_glyphs != NULL && Dynarr_length(dl->right_glyphs))
856 create_right_glyph_block(w, dl);
858 /* In the future additional types of display blocks may be generated
861 w->last_redisplay_pos = ret_bufpos;
866 /* Adds an hscroll glyph to a display block. If this is called, then
867 the block had better be empty.
869 Yes, there are multiple places where this function is called but
870 that is the way it has to be. Each calling function has to deal
871 with bi_start_col_enabled a little differently depending on the
872 object being worked with. */
874 static prop_block_dynarr *add_hscroll_rune(pos_data * data)
876 struct glyph_block gb;
877 prop_block_dynarr *retval;
878 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
879 unsigned int old_cursor_type = data->cursor_type;
880 Bytind bi_old_bufpos = data->bi_bufpos;
882 if (data->cursor_type == CURSOR_ON
883 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
884 && data->bi_cursor_bufpos <= data->bi_bufpos) {
885 data->bi_cursor_bufpos = data->bi_start_col_enabled;
887 data->cursor_type = NO_CURSOR;
890 data->bi_endpos = data->bi_bufpos;
891 data->bi_bufpos = data->bi_start_col_enabled;
894 gb.glyph = Vhscroll_glyph;
896 int oldpixpos = data->pixpos;
897 retval = add_glyph_rune(data, &gb, BEGIN_GLYPHS, 0,
898 GLYPH_CACHEL(XWINDOW(data->window),
899 HSCROLL_GLYPH_INDEX));
900 data->hscroll_glyph_width_adjust =
901 data->pixpos - oldpixpos -
902 space_width(XWINDOW(data->window));
905 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
906 data->cursor_type = old_cursor_type;
907 data->bi_bufpos = bi_old_bufpos;
909 data->bi_start_col_enabled = 0;
913 /* Adds a character rune to a display block. If there is not enough room
914 to fit the rune on the display block (as determined by the MAX_PIXPOS)
915 then it adds nothing and returns ADD_FAILED. If
916 NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't allow the char's height
917 to affect the total line height. (See add_intbyte_string_runes()). */
919 static prop_block_dynarr *add_emchar_rune_1(pos_data * data,
920 int no_contribute_to_line_height)
922 struct rune rb, *crb;
925 if (data->start_col) {
932 if (data->bi_start_col_enabled) {
933 return add_hscroll_rune(data);
936 if (data->ch == '\n') {
937 data->font_is_bogus = 0;
938 /* Cheesy end-of-line pseudo-character. */
939 width = data->blank_width;
941 Lisp_Object charset = CHAR_CHARSET(data->ch);
942 if (!EQ(charset, data->last_charset) ||
943 data->findex != data->last_findex) {
944 /* OK, we need to do things the hard way. */
945 struct window *w = XWINDOW(data->window);
946 struct face_cachel *cachel =
947 WINDOW_FACE_CACHEL(w, data->findex);
948 Lisp_Object font_instance =
949 ensure_face_cachel_contains_charset(cachel,
952 Lisp_Font_Instance *fi;
954 if (EQ(font_instance, Vthe_null_font_instance)) {
956 FACE_CACHEL_FONT(cachel, Vcharset_ascii);
957 data->font_is_bogus = 1;
959 data->font_is_bogus = 0;
961 fi = XFONT_INSTANCE(font_instance);
962 if (!fi->proportional_p)
963 /* sweetness and light. */
964 data->last_char_width = fi->width;
966 data->last_char_width = -1;
968 if (!no_contribute_to_line_height) {
970 max(data->new_ascent, (int)fi->ascent);
972 max(data->new_descent, (int)fi->descent);
975 data->last_charset = charset;
976 data->last_findex = data->findex;
979 width = data->last_char_width;
981 /* bummer. Proportional fonts. */
983 redisplay_text_width_emchar_string(XWINDOW
990 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos)) {
994 if (Dynarr_length(data->db->runes) < Dynarr_largest(data->db->runes)) {
996 Dynarr_atp(data->db->runes, Dynarr_length(data->db->runes));
1003 crb->findex = data->findex;
1004 crb->xpos = data->pixpos;
1006 if (data->bi_bufpos) {
1007 if (NILP(data->string))
1009 bytind_to_bufpos(XBUFFER
1011 (XWINDOW(data->window))),
1015 bytecount_to_charcount(XSTRING_DATA(data->string),
1017 } else if (data->is_modeline)
1018 crb->bufpos = data->modeline_charpos;
1020 /* Text but not in buffer */
1022 crb->type = RUNE_CHAR;
1023 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
1026 if (data->cursor_type == CURSOR_ON) {
1027 if (data->bi_bufpos == data->bi_cursor_bufpos) {
1028 crb->cursor_type = CURSOR_ON;
1029 data->cursor_x = Dynarr_length(data->db->runes);
1031 crb->cursor_type = CURSOR_OFF;
1032 } else if (data->cursor_type == NEXT_CURSOR) {
1033 crb->cursor_type = CURSOR_ON;
1034 data->cursor_x = Dynarr_length(data->db->runes);
1035 data->cursor_type = NO_CURSOR;
1036 } else if (data->cursor_type == IGNORE_CURSOR)
1037 crb->cursor_type = IGNORE_CURSOR;
1039 crb->cursor_type = CURSOR_OFF;
1042 Dynarr_add(data->db->runes, *crb);
1044 Dynarr_increment(data->db->runes);
1046 data->pixpos += width;
1051 static prop_block_dynarr *add_emchar_rune(pos_data * data)
1053 return add_emchar_rune_1(data, 0);
1056 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune for
1057 each character in the string. Propagate any left-over data unless
1058 NO_PROP is non-zero. If NO_CONTRIBUTE_TO_LINE_HEIGHT is non-zero, don't
1059 allow this character to increase the total height of the line. (This is
1060 used when the character is part of a text glyph. In that case, the
1061 glyph code itself adjusts the line height as necessary, depending on
1062 whether glyph-contrib-p is true.) */
1064 static prop_block_dynarr *add_bufbyte_string_runes(pos_data * data,
1069 no_contribute_to_line_height)
1071 Bufbyte *pos, *end = c_string + c_length;
1072 prop_block_dynarr *prop;
1074 /* #### This function is too simplistic. It needs to do the same
1075 sort of character interpretation (display-table lookup,
1076 ctl-arrow checking), etc. that create_text_block() does.
1077 The functionality to do this in that routine needs to be
1080 for (pos = c_string; pos < end;) {
1081 Bufbyte *old_pos = pos;
1083 data->ch = charptr_emchar(pos);
1085 prop = add_emchar_rune_1(data, no_contribute_to_line_height);
1091 struct prop_block pb;
1092 Bytecount len = end - pos;
1093 prop = Dynarr_new(prop_block);
1095 pb.type = PROP_STRING;
1096 pb.data.p_string.str =
1097 xnew_atomic_array(Bufbyte, len);
1098 strncpy((char *)pb.data.p_string.str,
1100 pb.data.p_string.len = len;
1102 Dynarr_add(prop, pb);
1108 /* #### Duplicate code from add_string_to_fstring_db_runes
1109 should we do more? */
1110 data->bytepos += pos - old_pos;
1116 /* Add a single rune of the specified width. The area covered by this
1117 rune will be displayed in the foreground color of the associated
1120 static prop_block_dynarr *add_blank_rune(pos_data * data, struct window *w,
1125 /* If data->start_col is not 0 then this call to add_blank_rune must have
1126 been to add it as a tab. */
1127 if (data->start_col) {
1128 /* assert (w != NULL) */
1129 prop_block_dynarr *retval;
1131 /* If we have still not fully scrolled horizontally, subtract
1132 the width of this tab and return. */
1133 if (char_tab_width < data->start_col) {
1134 data->start_col -= char_tab_width;
1136 } else if (char_tab_width == data->start_col)
1137 data->blank_width = 0;
1139 int spcwid = space_width(w);
1141 if (spcwid >= data->blank_width)
1142 data->blank_width = 0;
1144 data->blank_width -= spcwid;
1147 data->start_col = 0;
1148 retval = add_hscroll_rune(data);
1150 /* Could be caused by the handling of the hscroll rune. */
1151 if (retval != NULL || !data->blank_width)
1155 /* Blank runes are always calculated to fit. */
1156 assert(data->pixpos + data->blank_width <= data->max_pixpos);
1158 rb.findex = data->findex;
1159 rb.xpos = data->pixpos;
1160 rb.width = data->blank_width;
1161 if (data->bi_bufpos)
1163 bytind_to_bufpos(XBUFFER
1164 (WINDOW_BUFFER(XWINDOW(data->window))),
1167 /* #### and this is really correct too? */
1170 rb.type = RUNE_BLANK;
1172 if (data->cursor_type == CURSOR_ON) {
1173 if (data->bi_bufpos == data->bi_cursor_bufpos) {
1174 rb.cursor_type = CURSOR_ON;
1175 data->cursor_x = Dynarr_length(data->db->runes);
1177 rb.cursor_type = CURSOR_OFF;
1178 } else if (data->cursor_type == NEXT_CURSOR) {
1179 rb.cursor_type = CURSOR_ON;
1180 data->cursor_x = Dynarr_length(data->db->runes);
1181 data->cursor_type = NO_CURSOR;
1183 rb.cursor_type = CURSOR_OFF;
1185 Dynarr_add(data->db->runes, rb);
1186 data->pixpos += data->blank_width;
1191 static void add_blank_rune_noret(pos_data * data, struct window *w,
1194 prop_block_dynarr *prop = add_blank_rune(data,w,char_tab_width);
1195 if (prop && prop != ADD_FAILED )
1199 /* Add runes representing a character in octal. */
1201 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1203 if (add_failed || (add_failed = add_emchar_rune (data))) \
1205 struct prop_block pb; \
1207 prop = Dynarr_new (prop_block); \
1209 pb.type = PROP_CHAR; \
1210 pb.data.p_char.ch = data->ch; \
1211 pb.data.p_char.cursor_type = data->cursor_type; \
1212 Dynarr_add (prop, pb); \
1216 static prop_block_dynarr *add_octal_runes(pos_data * data)
1218 prop_block_dynarr *add_failed, *prop = 0;
1219 Emchar orig_char = data->ch;
1220 unsigned int orig_cursor_type = data->cursor_type;
1225 if (data->start_col)
1228 if (!data->start_col) {
1229 if (data->bi_start_col_enabled) {
1230 add_failed = add_hscroll_rune(data);
1232 struct glyph_block gb;
1233 struct window *w = XWINDOW(data->window);
1236 gb.glyph = Voctal_escape_glyph;
1238 add_glyph_rune(data, &gb, BEGIN_GLYPHS, 1,
1240 OCT_ESC_GLYPH_INDEX));
1244 /* We only propagate information if the glyph was partially
1249 data->cursor_type = IGNORE_CURSOR;
1251 if (data->ch >= 0x100) {
1252 /* If the character is an extended Mule character, it could have
1253 up to 19 bits. For the moment, we treat it as a seven-digit
1254 octal number. This is not that pretty, but whatever. */
1255 data->ch = (7 & (orig_char >> 18)) + '0';
1256 ADD_NEXT_OCTAL_RUNE_CHAR;
1258 data->ch = (7 & (orig_char >> 15)) + '0';
1259 ADD_NEXT_OCTAL_RUNE_CHAR;
1261 data->ch = (7 & (orig_char >> 12)) + '0';
1262 ADD_NEXT_OCTAL_RUNE_CHAR;
1264 data->ch = (7 & (orig_char >> 9)) + '0';
1265 ADD_NEXT_OCTAL_RUNE_CHAR;
1268 data->ch = (7 & (orig_char >> 6)) + '0';
1269 ADD_NEXT_OCTAL_RUNE_CHAR;
1271 data->ch = (7 & (orig_char >> 3)) + '0';
1272 ADD_NEXT_OCTAL_RUNE_CHAR;
1274 data->ch = (7 & orig_char) + '0';
1275 ADD_NEXT_OCTAL_RUNE_CHAR;
1279 data->cursor_type = orig_cursor_type;
1280 if (prop && prop != ADD_FAILED )
1285 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1287 /* Add runes representing a control character to a display block. */
1289 static prop_block_dynarr *add_control_char_runes(pos_data * data,
1292 if (!NILP(b->ctl_arrow)) {
1293 prop_block_dynarr *prop;
1294 Emchar orig_char = data->ch;
1295 unsigned int old_cursor_type = data->cursor_type;
1300 if (data->start_col)
1303 if (!data->start_col) {
1304 if (data->bi_start_col_enabled) {
1305 prop_block_dynarr *retval;
1307 retval = add_hscroll_rune(data);
1311 struct glyph_block gb;
1312 struct window *w = XWINDOW(data->window);
1315 gb.glyph = Vcontrol_arrow_glyph;
1317 /* We only propagate information if the glyph was partially
1319 prop = add_glyph_rune(data, &gb, BEGIN_GLYPHS, 1,
1320 GLYPH_CACHEL(w, CONTROL_GLYPH_INDEX));
1321 if ( prop != NULL ) {
1322 if ( prop != ADD_FAILED )
1329 if (orig_char == 0177)
1332 data->ch = orig_char ^ 0100;
1333 data->cursor_type = IGNORE_CURSOR;
1335 if (add_emchar_rune(data)) {
1336 struct prop_block pb;
1338 prop = Dynarr_new(prop_block);
1340 pb.type = PROP_CHAR;
1341 pb.data.p_char.ch = data->ch;
1342 pb.data.p_char.cursor_type = data->cursor_type;
1343 Dynarr_add(prop, pb);
1346 data->cursor_type = old_cursor_type;
1349 return add_octal_runes(data);
1353 static prop_block_dynarr *add_disp_table_entry_runes_1(pos_data * data,
1356 prop_block_dynarr *prop = NULL;
1358 if (STRINGP(entry)) {
1359 prop = add_bufbyte_string_runes(data,
1360 XSTRING_DATA(entry),
1361 XSTRING_LENGTH(entry), 0, 0);
1362 } else if (GLYPHP(entry)) {
1363 if (data->start_col)
1366 if (!data->start_col && data->bi_start_col_enabled) {
1367 prop = add_hscroll_rune(data);
1369 struct glyph_block gb;
1373 prop = add_glyph_rune(data, &gb, BEGIN_GLYPHS, 0, 0);
1375 } else if (CHAR_OR_CHAR_INTP(entry)) {
1376 data->ch = XCHAR_OR_CHAR_INT(entry);
1377 prop = add_emchar_rune(data);
1378 } else if (CONSP(entry)) {
1379 if (EQ(XCAR(entry), Qformat)
1380 && CONSP(XCDR(entry))
1381 && STRINGP(XCAR(XCDR(entry)))) {
1382 Lisp_Object format = XCAR(XCDR(entry));
1383 Bytind len = XSTRING_LENGTH(format);
1384 Bufbyte *src = XSTRING_DATA(format), *end = src + len;
1385 Bufbyte *result = alloca_array(Bufbyte, len);
1386 Bufbyte *dst = result;
1389 Emchar c = charptr_emchar(src);
1391 if (c != '%' || src == end) {
1392 dst += set_charptr_emchar(dst, c);
1394 c = charptr_emchar(src);
1398 dst += long_to_string_base
1399 ((char *)dst, data->ch, 16);
1402 dst += set_charptr_emchar(
1405 /* #### unimplemented */
1412 add_bufbyte_string_runes(data, result, dst - result,
1417 /* Else blow it off because someone added a bad entry and we don't
1418 have any safe way of signaling an error. */
1422 /* Given a display table entry, call the appropriate functions to
1423 display each element of the entry. */
1425 static prop_block_dynarr *add_disp_table_entry_runes(pos_data * data,
1428 prop_block_dynarr *prop = NULL;
1429 if (VECTORP(entry)) {
1430 Lisp_Vector *de = XVECTOR(entry);
1431 EMACS_INT len = vector_length(de);
1434 for (elt = 0; elt < len; elt++) {
1435 if (NILP(vector_data(de)[elt]))
1439 add_disp_table_entry_runes_1(data,
1442 /* Else blow it off because someone added a bad entry and we
1443 don't have any safe way of signaling an error. Hey, this
1444 comment sounds familiar. */
1446 /* #### Still need to add any remaining elements to the
1447 propagation information. */
1452 prop = add_disp_table_entry_runes_1(data, entry);
1456 /* Add runes which were propagated from the previous line. */
1458 static prop_block_dynarr *add_propagation_runes(prop_block_dynarr ** prop,
1461 /* #### Remember to handle start_col parameter of data when the rest of
1462 this is finished. */
1463 /* #### Chuck -- I've redone this function a bit. It looked like the
1464 case of not all the propagation blocks being added was not handled
1466 /* #### Chuck -- I also think the double indirection of PROP is kind
1467 of bogus. A cleaner solution is just to check for
1468 Dynarr_length (prop) > 0. */
1469 /* #### This function also doesn't even pay attention to ADD_FAILED!
1470 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1473 prop_block_dynarr *add_failed;
1474 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1475 unsigned int old_cursor_type = data->cursor_type;
1477 for (elt = 0; elt < Dynarr_length(*prop); elt++) {
1478 struct prop_block *pb = Dynarr_atp(*prop, elt);
1482 data->ch = pb->data.p_char.ch;
1483 data->bi_cursor_bufpos =
1484 pb->data.p_char.bi_cursor_bufpos;
1485 data->cursor_type = pb->data.p_char.cursor_type;
1486 add_failed = add_emchar_rune(data);
1489 goto oops_no_more_space;
1492 if (pb->data.p_string.str)
1493 xfree(pb->data.p_string.str);
1494 /* #### bogus bogus -- this doesn't do anything!
1495 Should probably call add_bufbyte_string_runes(),
1496 once that function is fixed. */
1498 case PROP_MINIBUF_PROMPT: {
1499 face_index old_findex = data->findex;
1500 Bytind bi_old_bufpos = data->bi_bufpos;
1502 data->findex = DEFAULT_INDEX;
1503 data->bi_bufpos = 0;
1504 data->cursor_type = NO_CURSOR;
1506 while (pb->data.p_string.len > 0) {
1508 charptr_emchar(pb->data.p_string.
1510 add_failed = add_emchar_rune(data);
1513 data->findex = old_findex;
1514 data->bi_bufpos = bi_old_bufpos;
1515 goto oops_no_more_space;
1517 /* Complicated equivalent of ptr++,
1520 pb->data.p_string.str;
1521 INC_CHARPTR(pb->data.p_string.
1523 pb->data.p_string.len -=
1524 pb->data.p_string.str -
1529 data->findex = old_findex;
1530 /* ##### FIXME FIXME FIXME -- Upon successful return
1531 from this function, data->bi_bufpos is automatically
1532 incremented. However, we don't want that to happen
1533 if we were adding the minibuffer prompt. */
1535 struct buffer *buf =
1536 XBUFFER(WINDOW_BUFFER
1537 (XWINDOW(data->window)));
1538 /* #### Chuck fix this shit or I'm gonna
1540 if (bi_old_bufpos > BI_BUF_BEGV(buf)) {
1545 /* #### is this correct?
1547 Does anyone care? Is this a cheesy
1550 BI_BUF_BEGV(buf) - 1;
1556 /* #### I think it's unnecessary and misleading to
1557 preserve the blank_width, as it implies that the
1558 value carries over from one rune to the next,
1560 int old_width = data->blank_width;
1561 face_index old_findex = data->findex;
1563 data->findex = pb->data.p_blank.findex;
1564 data->blank_width = pb->data.p_blank.width;
1565 data->bi_cursor_bufpos = 0;
1566 data->cursor_type = IGNORE_CURSOR;
1568 if (data->pixpos + data->blank_width >
1571 data->max_pixpos - data->pixpos;
1573 /* We pass a bogus value of char_tab_width. It
1574 shouldn't matter because unless something is really
1575 screwed up this call won't cause that arg to be
1577 add_failed = add_blank_rune(
1578 data, XWINDOW(data->window), 0);
1580 /* This can happen in the case where we have a tab which
1581 is wider than the window. */
1582 if (data->blank_width != pb->data.p_blank.width) {
1583 pb->data.p_blank.width -=
1585 add_failed = ADD_FAILED;
1588 data->findex = old_findex;
1589 data->blank_width = old_width;
1592 goto oops_no_more_space;
1604 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1605 data->cursor_type = old_cursor_type;
1606 if (elt < Dynarr_length(*prop)) {
1607 Dynarr_delete_many(*prop, 0, elt);
1615 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1616 the display block, but add all other types to the appropriate list
1617 of the display line. They will be added later by different
1620 static void add_glyph_rune_noret(pos_data * data,
1621 struct glyph_block *gb, int pos_type,
1623 struct glyph_cachel *cachel)
1625 prop_block_dynarr *prop = add_glyph_rune(data,gb,pos_type,allow_cursor,cachel);
1626 if (prop && prop != ADD_FAILED )
1630 static prop_block_dynarr *add_glyph_rune(pos_data * data,
1631 struct glyph_block *gb, int pos_type,
1633 struct glyph_cachel *cachel)
1635 struct window *w = XWINDOW(data->window);
1637 /* If window faces changed, and glyph instance is text, then
1638 glyph sizes might have changed too */
1639 invalidate_glyph_geometry_maybe(gb->glyph, w);
1641 /* This makes sure the glyph is in the cachels.
1643 #### We do this to make sure the glyph is in the glyph cachels,
1644 so that the dirty flag can be reset after redisplay has
1645 finished. We should do this some other way, maybe by iterating
1646 over the window cache of subwindows. */
1647 get_glyph_cachel_index(w, gb->glyph);
1649 /* A nil extent indicates a special glyph (ex. truncator). */
1650 if (NILP(gb->extent)
1651 || (pos_type == BEGIN_GLYPHS &&
1652 extent_begin_glyph_layout(XEXTENT(gb->extent)) == GL_TEXT)
1653 || (pos_type == END_GLYPHS &&
1654 extent_end_glyph_layout(XEXTENT(gb->extent)) == GL_TEXT)
1655 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) {
1659 int ascent, descent;
1660 Lisp_Object baseline;
1662 Lisp_Object instance;
1664 prop_block_dynarr *retval = 0;
1667 width = cachel->width;
1669 width = glyph_width(gb->glyph, data->window);
1674 if (data->start_col || data->start_col_xoffset) {
1675 int glyph_char_width = width / space_width(w);
1677 /* If we still have not fully scrolled horizontally after
1678 taking into account the width of the glyph, subtract its
1679 width and return. */
1680 if (glyph_char_width < data->start_col) {
1681 data->start_col -= glyph_char_width;
1683 } else if (glyph_char_width == data->start_col)
1686 xoffset = space_width(w) * data->start_col;
1689 /* #### Can this happen? */
1694 data->start_col = 0;
1695 retval = add_hscroll_rune(data);
1697 /* Could be caused by the handling of the hscroll rune. */
1698 if (retval != NULL || !width)
1703 if (data->pixpos + width > data->max_pixpos) {
1704 /* If this is the first object we are attempting to add to
1705 the line then we ignore the horizontal_clip threshold.
1706 Otherwise we will loop until the bottom of the window
1707 continually failing to add this glyph because it is wider
1708 than the window. We could alternatively just completely
1709 ignore the glyph and proceed from there but I think that
1710 this is a better solution.
1712 This does, however, create a different problem in that we
1713 can end up adding the object to every single line, never
1714 getting any further - for instance an extent with a long
1715 start-glyph that covers multitple following
1717 if (Dynarr_length(data->db->runes)
1718 && data->max_pixpos - data->pixpos <
1722 struct prop_block pb;
1724 /* We need to account for the width of the end-of-line
1725 glyph if there is nothing more in the line to display,
1726 since we will not display it in this instance. It seems
1727 kind of gross doing it here, but otherwise we have to
1728 search the runes in create_text_block(). */
1729 if (data->ch == '\n')
1731 data->end_glyph_width;
1732 width = data->max_pixpos - data->pixpos;
1733 /* Add the glyph we are displaying, but clipping, to the
1734 propagation data so that we don't try and do it
1736 retval = Dynarr_new(prop_block);
1737 pb.type = PROP_GLYPH;
1738 pb.data.p_glyph.glyph = gb->glyph;
1739 pb.data.p_glyph.width = width;
1740 Dynarr_add(retval, pb);
1745 ascent = cachel->ascent;
1746 descent = cachel->descent;
1748 ascent = glyph_ascent(gb->glyph, data->window);
1749 descent = glyph_descent(gb->glyph, data->window);
1752 baseline = glyph_baseline(gb->glyph, data->window);
1754 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */
1756 if (glyph_contrib_p(gb->glyph, data->window)) {
1757 /* A pixmap that has not had a baseline explicitly set. Its
1758 contribution will be determined later. */
1759 if (NILP(baseline)) {
1760 int height = ascent + descent;
1761 data->need_baseline_computation = 1;
1762 data->max_pixmap_height =
1763 max(data->max_pixmap_height, height);
1766 /* A string so determine contribution normally. */
1767 else if (EQ(baseline, Qt)) {
1769 max(data->new_ascent, ascent);
1771 max(data->new_descent, descent);
1774 /* A pixmap with an explicitly set baseline. We determine the
1775 contribution here. */
1776 else if (INTP(baseline)) {
1777 int height = ascent + descent;
1778 int pix_ascent, pix_descent;
1780 pix_ascent = height * XINT(baseline) / 100;
1781 pix_descent = height - pix_ascent;
1784 max(data->new_ascent, pix_ascent);
1786 max(data->new_descent, pix_descent);
1787 data->max_pixmap_height =
1788 max(data->max_pixmap_height, height);
1790 rb.object.dglyph.descent = pix_descent;
1793 /* Otherwise something is screwed up. */
1798 face = glyph_face(gb->glyph, data->window);
1800 findex = data->findex;
1802 findex = get_builtin_face_cache_index(w, face);
1804 instance = glyph_image_instance(gb->glyph, data->window,
1806 if (TEXT_IMAGE_INSTANCEP(instance)) {
1807 Lisp_Object string =
1808 XIMAGE_INSTANCE_TEXT_STRING(instance);
1809 face_index orig_findex = data->findex;
1810 Bytind orig_bufpos = data->bi_bufpos;
1811 Bytind orig_start_col_enabled =
1812 data->bi_start_col_enabled;
1814 data->findex = findex;
1815 data->bi_start_col_enabled = 0;
1817 data->bi_bufpos = 0;
1818 add_bufbyte_string_runes(data, XSTRING_DATA(string),
1819 XSTRING_LENGTH(string), 0, 1);
1820 data->findex = orig_findex;
1821 data->bi_bufpos = orig_bufpos;
1822 data->bi_start_col_enabled = orig_start_col_enabled;
1827 rb.xpos = data->pixpos;
1829 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1830 if (data->bi_endpos)
1831 /* #### is this necessary at all? */
1832 rb.endpos = bytind_to_bufpos(XBUFFER(WINDOW_BUFFER(w)),
1836 rb.type = RUNE_DGLYPH;
1837 rb.object.dglyph.glyph = gb->glyph;
1838 rb.object.dglyph.extent = gb->extent;
1839 rb.object.dglyph.xoffset = xoffset;
1840 rb.object.dglyph.ascent = ascent;
1841 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has
1842 a normal (textual) baseline. */
1845 rb.bufpos = bytind_to_bufpos(XBUFFER(WINDOW_BUFFER(w)),
1848 if (data->cursor_type == CURSOR_ON) {
1849 if (data->bi_bufpos == data->bi_cursor_bufpos) {
1850 rb.cursor_type = CURSOR_ON;
1852 Dynarr_length(data->db->runes);
1854 rb.cursor_type = CURSOR_OFF;
1855 } else if (data->cursor_type == NEXT_CURSOR) {
1856 rb.cursor_type = CURSOR_ON;
1857 data->cursor_x = Dynarr_length(data->db->runes);
1858 data->cursor_type = NO_CURSOR;
1859 } else if (data->cursor_type == IGNORE_CURSOR)
1860 rb.cursor_type = IGNORE_CURSOR;
1861 else if (data->cursor_type == NO_CURSOR)
1862 rb.cursor_type = NO_CURSOR;
1864 rb.cursor_type = CURSOR_OFF;
1866 rb.cursor_type = CURSOR_OFF;
1868 Dynarr_add(data->db->runes, rb);
1869 data->pixpos += width;
1873 if (!NILP(glyph_face(gb->glyph, data->window)))
1875 get_builtin_face_cache_index(w,
1876 glyph_face(gb->glyph,
1880 gb->findex = data->findex;
1882 if (pos_type == BEGIN_GLYPHS) {
1883 if (!data->dl->left_glyphs)
1884 data->dl->left_glyphs = Dynarr_new(glyph_block);
1885 Dynarr_add(data->dl->left_glyphs, *gb);
1887 } else if (pos_type == END_GLYPHS) {
1888 if (!data->dl->right_glyphs)
1889 data->dl->right_glyphs =
1890 Dynarr_new(glyph_block);
1891 Dynarr_add(data->dl->right_glyphs, *gb);
1894 abort(); /* there are no unknown types */
1900 /* Add all glyphs at position POS_TYPE that are contained in the given
1903 static prop_block_dynarr *add_glyph_runes(pos_data * data)
1905 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1906 why didn't you just modify add_glyph_rune in the first place? */
1908 glyph_block_dynarr *glyph_arr = (data->ef->glyphs);
1909 prop_block_dynarr *prop;
1911 for (elt = 0; elt < Dynarr_length(glyph_arr); elt++) {
1912 struct glyph_block *gb = Dynarr_atp(glyph_arr, elt);
1913 prop = add_glyph_rune(data, gb,
1914 gb->active ? END_GLYPHS : BEGIN_GLYPHS,
1918 /* #### Add some propagation information. */
1923 Dynarr_reset(glyph_arr);
1928 /* Given a position for a buffer in a window, ensure that the given
1929 display line DL accurately represents the text on a line starting
1930 at the given position.
1932 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1933 You must do appropriate conversion. */
1936 create_text_block(struct window *w, struct display_line *dl,
1937 Bytind bi_start_pos, prop_block_dynarr ** prop, int type)
1939 struct frame *f = XFRAME(w->frame);
1940 struct buffer *b = XBUFFER(w->buffer);
1941 struct device *d = XDEVICE(f->device);
1945 /* Don't display anything in the minibuffer if this window is not on
1946 a selected frame. We consider all other windows to be active
1947 minibuffers as it simplifies the coding. */
1948 int active_minibuffer = (!MINI_WINDOW_P(w) ||
1949 (f == device_selected_frame(d)) ||
1950 is_surrogate_for_selected_frame(f));
1952 int truncate_win = window_truncation_on(w);
1954 /* If the buffer's value of selective_display is an integer then
1955 only lines that start with less than selective_display columns of
1956 space will be displayed. If selective_display is t then all text
1957 after a ^M is invisible. */
1958 int selective = (INTP(b->selective_display)
1959 ? XINT(b->selective_display)
1960 : (!NILP(b->selective_display) ? -1 : 0));
1962 /* The variable ctl-arrow allows the user to specify what characters
1963 can actually be displayed and which octal should be used for.
1964 #### This variable should probably have some rethought done to
1967 #### It would also be really nice if you could specify that
1968 the characters come out in hex instead of in octal. Mule
1969 does that by adding a ctl-hexa variable similar to ctl-arrow,
1970 but that's bogus -- we need a more general solution. I
1971 think you need to extend the concept of display tables
1972 into a more general conversion mechanism. Ideally you
1973 could specify a Lisp function that converts characters,
1974 but this violates the Second Golden Rule and besides would
1975 make things way way way way slow.
1977 So instead, we extend the display-table concept, which was
1978 historically limited to 256-byte vectors, to one of the
1981 a) A 256-entry vector, for backward compatibility;
1982 b) char-table, mapping characters to values;
1983 c) range-table, mapping ranges of characters to values;
1984 d) a list of the above.
1986 The (d) option allows you to specify multiple display tables
1987 instead of just one. Each display table can specify conversions
1988 for some characters and leave others unchanged. The way the
1989 character gets displayed is determined by the first display table
1990 with a binding for that character. This way, you could call a
1991 function `enable-hex-display' that adds a hex display-table to
1992 the list of display tables for the current buffer.
1994 #### ...not yet implemented... Also, we extend the concept of
1995 "mapping" to include a printf-like spec. Thus you can make all
1996 extended characters show up as hex with a display table like
1999 #s(range-table data ((256 524288) (format "%x")))
2001 Since more than one display table is possible, you have
2002 great flexibility in mapping ranges of characters. */
2003 Emchar printable_min = (CHAR_OR_CHAR_INTP(b->ctl_arrow)
2004 ? XCHAR_OR_CHAR_INT(b->ctl_arrow)
2005 : ((EQ(b->ctl_arrow, Qt)
2006 || EQ(b->ctl_arrow, Qnil))
2009 Lisp_Object face_dt, window_dt;
2011 /* The text display block for this display line. */
2012 struct display_block *db = get_display_block_from_line(dl, TEXT);
2014 /* The first time through the main loop we need to force the glyph
2015 data to be updated. */
2018 /* Apparently the new extent_fragment_update returns an end position
2019 equal to the position passed in if there are no more runs to be
2021 int no_more_frags = 0;
2023 Lisp_Object synch_minibuffers_value =
2024 symbol_value_in_buffer(Qsynchronize_minibuffers, w->buffer);
2026 dl->used_prop_data = 0;
2028 dl->line_continuation = 0;
2031 data.ef = extent_fragment_new(w->buffer, f);
2033 /* These values are used by all of the rune addition routines. We add
2034 them to this structure for ease of passing. */
2036 XSETWINDOW(data.window, w);
2041 data.bi_bufpos = bi_start_pos;
2042 data.pixpos = dl->bounds.left_in;
2043 data.last_charset = Qunbound;
2044 data.last_findex = DEFAULT_INDEX;
2045 data.result_str = Qnil;
2047 /* Set the right boundary adjusting it to take into account any end
2048 glyph. Save the width of the end glyph for later use. */
2049 data.max_pixpos = dl->bounds.right_in;
2051 data.end_glyph_width = GLYPH_CACHEL_WIDTH(w, TRUN_GLYPH_INDEX);
2053 data.end_glyph_width = GLYPH_CACHEL_WIDTH(w, CONT_GLYPH_INDEX);
2054 data.max_pixpos -= data.end_glyph_width;
2056 if (cursor_in_echo_area && MINI_WINDOW_P(w) && echo_area_active(f)) {
2057 data.bi_cursor_bufpos = BI_BUF_ZV(b);
2058 data.cursor_type = CURSOR_ON;
2059 } else if (MINI_WINDOW_P(w) && !active_minibuffer)
2060 data.cursor_type = NO_CURSOR;
2061 else if (w == XWINDOW(FRAME_SELECTED_WINDOW(f)) &&
2062 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
2064 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))
2065 && f == XFRAME(DEVICE_SELECTED_FRAME(d))) {
2066 data.bi_cursor_bufpos = BI_BUF_PT(b);
2067 data.cursor_type = CURSOR_ON;
2068 } else if (w == XWINDOW(FRAME_SELECTED_WINDOW(f))) {
2069 data.bi_cursor_bufpos = bi_marker_position(w->pointm[type]);
2070 data.cursor_type = CURSOR_ON;
2072 data.cursor_type = NO_CURSOR;
2075 data.start_col = w->hscroll;
2076 data.start_col_xoffset = w->left_xoffset;
2077 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
2078 data.hscroll_glyph_width_adjust = 0;
2080 /* We regenerate the line from the very beginning. */
2081 Dynarr_reset(db->runes);
2083 /* Why is this less than or equal and not just less than? If the
2084 starting position is already equal to the maximum we can't add
2085 anything else, right? Wrong. We might still have a newline to
2086 add. A newline can use the room allocated for an end glyph since
2087 if we add it we know we aren't going to be adding any end
2090 /* #### Chuck -- I think this condition should be while (1).
2091 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
2092 and the begin-glyph ends exactly at the end of the window, the
2093 end-glyph and text might not be displayed. while (1) ensures
2094 that the loop terminates only when either (a) there is
2095 propagation data or (b) the end-of-line or end-of-buffer is hit.
2097 #### Also I think you need to ensure that the operation
2098 "add begin glyphs; add end glyphs; add text" is atomic and
2099 can't get interrupted in the middle. If you run off the end
2100 of the line during that operation, then you keep accumulating
2101 propagation data until you're done. Otherwise, if the (e.g.)
2102 there's a begin glyph at a particular position and attempting
2103 to display that glyph results in window-end being hit and
2104 propagation data being generated, then the character at that
2105 position won't be displayed.
2107 #### See also the comment after the end of this loop, below.
2109 while (data.pixpos <= data.max_pixpos
2110 && (active_minibuffer || !NILP(synch_minibuffers_value))) {
2111 /* #### This check probably should not be necessary. */
2112 if (data.bi_bufpos > BI_BUF_ZV(b)) {
2113 /* #### urk! More of this lossage! */
2118 /* If selective display was an integer and we aren't working on
2119 a continuation line then find the next line we are actually
2120 supposed to display. */
2121 if (selective > 0 && (data.bi_bufpos == BI_BUF_BEGV(b)
2122 || BUF_FETCH_CHAR(b,
2127 while (bi_spaces_at_point(b, data.bi_bufpos) >=
2130 bi_find_next_newline_no_quit(b,
2133 if (data.bi_bufpos >= BI_BUF_ZV(b)) {
2134 data.bi_bufpos = BI_BUF_ZV(b);
2140 /* Check for face changes. */
2142 || (!no_more_frags && data.bi_bufpos == data.ef->end)) {
2143 Lisp_Object last_glyph = Qnil;
2145 /* Deal with glyphs that we have already displayed. The
2146 theory is that if we end up with a PROP_GLYPH in the
2147 propagation data then we are clipping the glyph and there
2148 can be no propagation data before that point. The theory
2149 works because we always recalculate the extent-fragments
2150 for propagated data, we never actually propagate the
2151 fragments that still need to be displayed. */
2152 if (*prop && Dynarr_atp(*prop, 0)->type == PROP_GLYPH) {
2154 Dynarr_atp(*prop, 0)->data.p_glyph.glyph;
2158 /* Now compute the face and begin/end-glyph information. */
2160 /* Remember that the extent-fragment routines deal in Bytind's. */
2161 extent_fragment_update(w, data.ef, data.bi_bufpos,
2164 get_display_tables(w, data.findex, &face_dt,
2167 if (data.bi_bufpos == data.ef->end)
2172 /* Determine what is next to be displayed. We first handle any
2173 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2174 display then we determine what to do based on the character at the
2175 current buffer position. */
2177 /* If there are glyphs, add them to the line. These are
2178 the end glyphs for the previous run of text. We add
2179 them here rather than doing them at the end of handling
2180 the previous run so that glyphs at the beginning and
2181 end of a line are handled correctly. */
2182 if (Dynarr_length (data.ef->glyphs) > 0) {
2183 glyph_block_dynarr* tmpglyphs = 0;
2184 /* #### I think this is safe, but could be wrong. */
2185 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2187 *prop = add_glyph_runes (&data);
2188 tmpglyphs = data.ef->glyphs;
2192 /* If we just clipped a glyph and we are
2193 at the end of a line and there are more
2194 glyphs to display then do appropriate
2195 processing to not get a continuation
2197 if (*prop != ADD_FAILED
2198 && Dynarr_atp (*prop, 0)->type == PROP_GLYPH
2199 && data.ch == '\n') {
2200 /* If there are no more glyphs
2201 then do the normal processing.
2203 #### This doesn't actually work
2204 if the same glyph is present
2205 more than once in the block. To
2206 solve this we would have to
2207 carry the index around which
2208 might be problematic since the
2209 fragment is recalculated for
2211 if (EQ (Dynarr_end (tmpglyphs)->glyph,
2212 Dynarr_atp (*prop, 0)->data.p_glyph.glyph)) {
2213 Dynarr_free (*prop);
2217 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2218 add_emchar_rune (&data); /* discard prop data. */
2227 /* If the current position is covered by an invisible
2228 extent, do nothing (except maybe add some
2230 else if (data.ef->invisible) {
2231 /* #### Chuck, perhaps you could look at this code? I don't
2232 really know what I'm doing. */
2238 /* The extent fragment code only sets this when we should
2239 really display the ellipses. It makes sure the ellipses
2240 don't get displayed more than once in a row. */
2241 if (data.ef->invisible_ellipses) {
2242 struct glyph_block gb;
2244 data.ef->invisible_ellipses_already_displayed =
2246 data.ef->invisible_ellipses = 0;
2248 gb.glyph = Vinvisible_text_glyph;
2250 add_glyph_rune(&data, &gb, BEGIN_GLYPHS, 0,
2252 INVIS_GLYPH_INDEX));
2253 /* Perhaps they shouldn't propagate if the very next thing
2254 is to display a newline (for compatibility with
2255 selective-display-ellipses)? Maybe that's too
2261 /* If point is in an invisible region we place it on the
2262 next visible character. */
2263 if (data.cursor_type == CURSOR_ON
2264 && data.bi_bufpos == data.bi_cursor_bufpos) {
2265 data.cursor_type = NEXT_CURSOR;
2268 /* #### What if we we're dealing with a display table? */
2272 if (data.bi_bufpos == BI_BUF_ZV(b))
2275 INC_BYTIND(b, data.bi_bufpos);
2278 /* If there is propagation data, then it represents the current
2279 buffer position being displayed. Add them and advance the
2280 position counter. This might also add the minibuffer
2283 dl->used_prop_data = 1;
2284 *prop = add_propagation_runes(prop, &data);
2287 goto done; /* gee, a really narrow window */
2288 else if (data.bi_bufpos == BI_BUF_ZV(b))
2290 else if (data.bi_bufpos < BI_BUF_BEGV(b))
2291 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2292 data.bi_bufpos = BI_BUF_BEGV(b);
2294 INC_BYTIND(b, data.bi_bufpos);
2297 /* If at end-of-buffer, we've already processed begin and
2298 end-glyphs at this point and there's no text to process,
2300 else if (data.bi_bufpos == BI_BUF_ZV(b))
2304 Lisp_Object entry = Qnil;
2305 /* Get the character at the current buffer position. */
2306 data.ch = BI_BUF_FETCH_CHAR(b, data.bi_bufpos);
2307 if (!NILP(face_dt) || !NILP(window_dt))
2309 display_table_entry(data.ch, face_dt,
2312 /* If there is a display table entry for it, hand it off to
2313 add_disp_table_entry_runes and let it worry about it. */
2314 if (!NILP(entry) && !EQ(entry, make_char(data.ch))) {
2316 add_disp_table_entry_runes(&data, entry);
2322 /* Check if we have hit a newline character. If so, add a marker
2323 to the line and end this loop. */
2324 else if (data.ch == '\n') {
2325 /* We aren't going to be adding an end glyph so give its
2326 space back in order to make sure that the cursor can
2328 data.max_pixpos += data.end_glyph_width;
2331 && (bi_spaces_at_point
2332 (b, next_bytind(b, data.bi_bufpos))
2335 (b->selective_display_ellipses)) {
2336 struct glyph_block gb;
2340 Vinvisible_text_glyph;
2341 add_glyph_rune_noret(&data, &gb,
2344 INVIS_GLYPH_INDEX));
2346 /* Cheesy, cheesy, cheesy. We mark the end of the
2347 line with a special "character rune" whose width
2348 is the EOL cursor width and whose character is
2349 the non-printing character '\n'. */
2351 DEVMETH(d, eol_cursor_width,
2353 *prop = add_emchar_rune(&data);
2356 /* We need to set data.bi_bufpos to the start of the
2357 next visible region in order to make this line
2358 appear to contain all of the invisible area.
2359 Otherwise, the line cache won't work
2361 INC_BYTIND(b, data.bi_bufpos);
2362 while (bi_spaces_at_point
2364 data.bi_bufpos) >= selective) {
2366 bi_find_next_newline_no_quit
2367 (b, data.bi_bufpos, 1);
2368 if (data.bi_bufpos >=
2375 if (BI_BUF_FETCH_CHAR
2380 DEC_BYTIND(b, data.bi_bufpos);
2383 DEVMETH(d, eol_cursor_width, ());
2384 *prop = add_emchar_rune(&data);
2390 /* If the current character is ^M, and selective display is
2391 enabled, then add the invisible-text-glyph if
2392 selective-display-ellipses is set. In any case, this
2394 else if (data.ch == (('M' & 037)) && selective == -1) {
2395 Bytind bi_next_bufpos;
2397 /* Find the buffer position at the end of the line. */
2399 bi_find_next_newline_no_quit(b,
2402 if (BI_BUF_FETCH_CHAR
2403 (b, prev_bytind(b, bi_next_bufpos))
2405 DEC_BYTIND(b, bi_next_bufpos);
2407 /* If the cursor is somewhere in the elided text make
2408 sure that the cursor gets drawn appropriately. */
2409 if (data.cursor_type == CURSOR_ON
2410 && (data.bi_cursor_bufpos >= data.bi_bufpos
2411 && data.bi_cursor_bufpos <
2413 data.cursor_type = NEXT_CURSOR;
2416 /* We won't be adding a truncation or continuation glyph
2417 so give up the room allocated for them. */
2418 data.max_pixpos += data.end_glyph_width;
2420 if (!NILP(b->selective_display_ellipses)) {
2421 /* We don't propagate anything from the invisible
2422 text glyph if it fails to fit. This is
2424 struct glyph_block gb;
2427 gb.glyph = Vinvisible_text_glyph;
2428 add_glyph_rune(&data, &gb, BEGIN_GLYPHS,
2430 INVIS_GLYPH_INDEX));
2433 /* Set the buffer position to the end of the line. We
2434 need to do this before potentially adding a newline
2435 so that the cursor flag will get set correctly (if
2437 data.bi_bufpos = bi_next_bufpos;
2439 if (NILP(b->selective_display_ellipses)
2440 || data.bi_cursor_bufpos == bi_next_bufpos) {
2441 /* We have to at least add a newline character so
2442 that the cursor shows up properly. */
2445 DEVMETH(d, eol_cursor_width, ());
2446 data.findex = DEFAULT_INDEX;
2448 data.start_col_xoffset = 0;
2449 data.bi_start_col_enabled = 0;
2451 add_emchar_rune(&data);
2454 /* This had better be a newline but doing it this way
2455 we'll see obvious incorrect results if it isn't. No
2456 need to abort here. */
2457 data.ch = BI_BUF_FETCH_CHAR(b, data.bi_bufpos);
2462 /* If the current character is considered to be printable, then
2464 else if (data.ch >= printable_min) {
2465 *prop = add_emchar_rune(&data);
2470 /* If the current character is a tab, determine the next tab
2471 starting position and add a blank rune which extends from the
2472 current pixel position to that starting position. */
2473 else if (data.ch == '\t') {
2474 int tab_start_pixpos = data.pixpos;
2479 if (data.start_col > 1)
2482 (data.start_col - 1))
2483 + data.start_col_xoffset;
2486 next_tab_position(w, tab_start_pixpos,
2487 dl->bounds.left_in +
2489 hscroll_glyph_width_adjust);
2490 if (next_tab_start > data.max_pixpos) {
2492 next_tab_start - data.max_pixpos;
2493 next_tab_start = data.max_pixpos;
2495 data.blank_width = next_tab_start - data.pixpos;
2498 tab_start_pixpos) / space_width(w);
2501 add_blank_rune(&data, w, char_tab_width);
2503 /* add_blank_rune is only supposed to be called with
2504 sizes guaranteed to fit in the available space. */
2508 struct prop_block pb;
2509 *prop = Dynarr_new(prop_block);
2511 pb.type = PROP_BLANK;
2512 pb.data.p_blank.width = prop_width;
2513 pb.data.p_blank.findex = data.findex;
2514 Dynarr_add(*prop, pb);
2520 /* If character is a control character, pass it off to
2521 add_control_char_runes.
2523 The is_*() routines have undefined results on
2524 arguments outside of the range [-1, 255]. (This
2525 often bites people who carelessly use `char' instead
2526 of `unsigned char'.)
2528 else if (data.ch < 0x100 && iscntrl((Bufbyte) data.ch)) {
2529 *prop = add_control_char_runes(&data, b);
2535 /* If the character is above the ASCII range and we have not
2536 already handled it, then print it as an octal number. */
2537 else if (data.ch >= 0200) {
2538 *prop = add_octal_runes(&data);
2544 /* Assume the current character is considered to be printable,
2545 then just add it. */
2547 *prop = add_emchar_rune(&data);
2552 INC_BYTIND(b, data.bi_bufpos);
2558 /* Determine the starting point of the next line if we did not hit the
2559 end of the buffer. */
2560 if (data.bi_bufpos < BI_BUF_ZV(b)
2561 && (active_minibuffer || !NILP(synch_minibuffers_value))) {
2562 /* #### This check is not correct. If the line terminated
2563 due to a begin-glyph or end-glyph hitting window-end, then
2564 data.ch will not point to the character at data.bi_bufpos. If
2565 you make the two changes mentioned at the top of this loop,
2566 you should be able to say '(if (*prop))'. That should also
2567 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2570 /* The common case is that the line ended because we hit a newline.
2571 In that case, the next character is just the next buffer
2573 if (data.ch == '\n') {
2574 /* If data.start_col_enabled is still true, then the window is
2575 scrolled far enough so that nothing on this line is visible.
2576 We need to stick a truncation glyph at the beginning of the
2577 line in that case unless the line is completely blank. */
2578 if (data.bi_start_col_enabled) {
2579 if (data.cursor_type == CURSOR_ON) {
2580 if (data.bi_cursor_bufpos >=
2582 && data.bi_cursor_bufpos <=
2584 data.bi_cursor_bufpos =
2587 data.findex = DEFAULT_INDEX;
2589 data.bi_start_col_enabled = 0;
2591 if (data.bi_bufpos != bi_start_pos) {
2592 struct glyph_block gb;
2595 gb.glyph = Vhscroll_glyph;
2596 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS,
2598 HSCROLL_GLYPH_INDEX));
2600 /* This duplicates code down below to add a newline to
2601 the end of an otherwise empty line. */
2604 DEVMETH(d, eol_cursor_width, ());
2606 add_emchar_rune(&data);
2610 INC_BYTIND(b, data.bi_bufpos);
2613 /* Otherwise we have a buffer line which cannot fit on one display
2616 struct glyph_block gb;
2617 struct glyph_cachel *cachel;
2619 /* If the line is to be truncated then we actually have to look
2620 for the next newline. We also add the end-of-line glyph which
2621 we know will fit because we adjusted the right border before
2622 we starting laying out the line. */
2623 data.max_pixpos += data.end_glyph_width;
2624 data.findex = DEFAULT_INDEX;
2630 /* Now find the start of the next line. */
2632 bi_find_next_newline_no_quit(b,
2636 /* If the cursor is past the truncation line then we
2637 make it appear on the truncation glyph. If we've hit
2638 the end of the buffer then we also make the cursor
2639 appear unless eob is immediately preceded by a
2640 newline. In that case the cursor should actually
2641 appear on the next line. */
2642 if (data.cursor_type == CURSOR_ON
2643 && data.bi_cursor_bufpos >= data.bi_bufpos
2644 && (data.bi_cursor_bufpos < bi_pos ||
2645 (bi_pos == BI_BUF_ZV(b)
2646 && (bi_pos == BI_BUF_BEGV(b)
2649 (b, prev_bytind(b, bi_pos))
2651 data.bi_cursor_bufpos = bi_pos;
2653 data.cursor_type = NO_CURSOR;
2655 data.bi_bufpos = bi_pos;
2656 gb.glyph = Vtruncation_glyph;
2657 cachel = GLYPH_CACHEL(w, TRUN_GLYPH_INDEX);
2659 /* The cursor can never be on the continuation glyph. */
2660 data.cursor_type = NO_CURSOR;
2662 /* data.bi_bufpos is already at the start of the next line. */
2664 dl->line_continuation = 1;
2665 gb.glyph = Vcontinuation_glyph;
2666 cachel = GLYPH_CACHEL(w, CONT_GLYPH_INDEX);
2669 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS, 0, cachel);
2671 if (truncate_win && data.bi_bufpos == BI_BUF_ZV(b)
2672 && BI_BUF_FETCH_CHAR(b,
2676 /* #### Damn this losing shit. */
2679 } else if ((active_minibuffer || !NILP(synch_minibuffers_value))
2680 && (!echo_area_active(f) || data.bi_bufpos == BI_BUF_ZV(b))) {
2681 /* We need to add a marker to the end of the line since there is no
2682 newline character in order for the cursor to get drawn. We label
2683 it as a newline so that it gets handled correctly by the
2684 whitespace routines below. */
2687 data.blank_width = DEVMETH(d, eol_cursor_width, ());
2688 data.findex = DEFAULT_INDEX;
2690 data.start_col_xoffset = 0;
2691 data.bi_start_col_enabled = 0;
2693 data.max_pixpos += data.blank_width;
2694 add_emchar_rune(&data);
2695 data.max_pixpos -= data.blank_width;
2697 /* #### urk! Chuck, this shit is bad news. Going around
2698 manipulating invalid positions is guaranteed to result in
2699 trouble sooner or later. */
2700 data.bi_bufpos = BI_BUF_ZV(b) + 1;
2703 /* Calculate left whitespace boundary. */
2707 /* Whitespace past a newline is considered right whitespace. */
2708 while (elt < Dynarr_length(db->runes)) {
2709 struct rune *rb = Dynarr_atp(db->runes, elt);
2711 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2712 || rb->type == RUNE_BLANK) {
2713 dl->bounds.left_white += rb->width;
2716 elt = Dynarr_length(db->runes);
2720 /* Calculate right whitespace boundary. */
2722 int elt = Dynarr_length(db->runes) - 1;
2725 while (!done && elt >= 0) {
2726 struct rune *rb = Dynarr_atp(db->runes, elt);
2728 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2729 && isspace(rb->object.chr.ch))
2730 && !rb->type == RUNE_BLANK) {
2731 dl->bounds.right_white = rb->xpos + rb->width;
2739 /* The line is blank so everything is considered to be right
2742 dl->bounds.right_white = dl->bounds.left_in;
2745 /* Set the display blocks bounds. */
2746 db->start_pos = dl->bounds.left_in;
2747 if (Dynarr_length(db->runes)) {
2749 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
2751 db->end_pos = rb->xpos + rb->width;
2753 db->end_pos = dl->bounds.right_white;
2755 calculate_baseline(&data);
2757 dl->ascent = data.new_ascent;
2758 dl->descent = data.new_descent;
2761 unsigned short ascent =
2762 (unsigned short)XINT(w->minimum_line_ascent);
2764 if (dl->ascent < ascent)
2765 dl->ascent = ascent;
2768 unsigned short descent =
2769 (unsigned short)XINT(w->minimum_line_descent);
2771 if (dl->descent < descent)
2772 dl->descent = descent;
2775 calculate_yoffset(dl, db);
2777 dl->cursor_elt = data.cursor_x;
2778 /* #### lossage lossage lossage! Fix this shit! */
2779 if (data.bi_bufpos > BI_BUF_ZV(b))
2780 dl->end_bufpos = BUF_ZV(b);
2782 dl->end_bufpos = bytind_to_bufpos(b, data.bi_bufpos) - 1;
2784 data.dl->num_chars = column_at_point(b, dl->end_bufpos, 0);
2786 /* This doesn't correctly take into account tabs and control
2787 characters but if the window isn't being truncated then this
2788 value isn't going to end up being used anyhow. */
2789 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2791 /* #### handle horizontally scrolled line with text none of which
2792 was actually laid out. */
2794 /* #### handle any remainder of overlay arrow */
2796 if (*prop == ADD_FAILED)
2799 if (truncate_win && *prop) {
2804 extent_fragment_delete(data.ef);
2806 /* #### If we started at EOB, then make sure we return a value past
2807 it so that regenerate_window will exit properly. This is bogus.
2808 The main loop should get fixed so that it isn't necessary to call
2809 this function if we are already at EOB. */
2811 if (data.bi_bufpos == BI_BUF_ZV(b) && bi_start_pos == BI_BUF_ZV(b))
2812 return data.bi_bufpos + 1; /* Yuck! */
2814 return data.bi_bufpos;
2817 /* Display the overlay arrow at the beginning of the given line. */
2819 static int create_overlay_glyph_block(struct window *w, struct display_line *dl)
2821 struct frame *f = XFRAME(w->frame);
2822 struct device *d = XDEVICE(f->device);
2825 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2826 if (!STRINGP(Voverlay_arrow_string) && !GLYPHP(Voverlay_arrow_string))
2832 XSETWINDOW(data.window, w);
2833 data.db = get_display_block_from_line(dl, OVERWRITE);
2835 data.pixpos = dl->bounds.left_in;
2836 data.max_pixpos = dl->bounds.right_in;
2837 data.cursor_type = NO_CURSOR;
2839 data.findex = DEFAULT_INDEX;
2840 data.last_charset = Qunbound;
2841 data.last_findex = DEFAULT_INDEX;
2842 data.result_str = Qnil;
2845 Dynarr_reset(data.db->runes);
2847 if (STRINGP(Voverlay_arrow_string)) {
2848 add_bufbyte_string_runes
2850 XSTRING_DATA(Voverlay_arrow_string),
2851 XSTRING_LENGTH(Voverlay_arrow_string), 1, 0);
2852 } else if (GLYPHP(Voverlay_arrow_string)) {
2853 struct glyph_block gb;
2855 gb.glyph = Voverlay_arrow_string;
2857 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS, 0, 0);
2860 calculate_baseline(&data);
2862 dl->ascent = data.new_ascent;
2863 dl->descent = data.new_descent;
2865 data.db->start_pos = dl->bounds.left_in;
2866 data.db->end_pos = data.pixpos;
2868 calculate_yoffset(dl, data.db);
2870 return data.pixpos - dl->bounds.left_in;
2873 /* Add a type of glyph to a margin display block. */
2876 add_margin_runes(struct display_line *dl, struct display_block *db, int start,
2877 int count, enum glyph_layout layout, int side,
2880 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2881 ? dl->left_glyphs : dl->right_glyphs);
2884 struct window *w = XWINDOW(window);
2885 struct frame *f = XFRAME(w->frame);
2886 struct device *d = XDEVICE(f->device);
2891 data.window = window;
2894 data.pixpos = start;
2895 data.cursor_type = NO_CURSOR;
2897 data.last_charset = Qunbound;
2898 data.last_findex = DEFAULT_INDEX;
2899 data.result_str = Qnil;
2901 data.new_ascent = dl->ascent;
2902 data.new_descent = dl->descent;
2904 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2905 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) {
2907 elt = Dynarr_length(gbd) - 1;
2912 end = Dynarr_length(gbd);
2915 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) {
2916 struct glyph_block *gb = Dynarr_atp(gbd, elt);
2918 if (NILP(gb->extent))
2919 abort(); /* these should have been handled in add_glyph_rune */
2922 ((side == LEFT_GLYPHS &&
2923 extent_begin_glyph_layout(XEXTENT(gb->extent)) == layout)
2924 || (side == RIGHT_GLYPHS &&
2925 extent_end_glyph_layout(XEXTENT(gb->extent)) ==
2927 data.findex = gb->findex;
2928 data.max_pixpos = data.pixpos + gb->width;
2929 add_glyph_rune_noret(&data, gb, side, 0, NULL);
2934 (reverse ? elt-- : elt++);
2937 calculate_baseline(&data);
2939 dl->ascent = data.new_ascent;
2940 dl->descent = data.new_descent;
2942 calculate_yoffset(dl, data.db);
2947 /* Add a blank to a margin display block. */
2950 add_margin_blank(struct display_line *dl, struct display_block *db,
2951 struct window *w, int xpos, int width, int side)
2955 rb.findex = (side == LEFT_GLYPHS
2956 ? get_builtin_face_cache_index(w, Vleft_margin_face)
2957 : get_builtin_face_cache_index(w, Vright_margin_face));
2962 rb.type = RUNE_BLANK;
2963 rb.cursor_type = CURSOR_OFF;
2965 Dynarr_add(db->runes, rb);
2968 /* Display glyphs in the left outside margin, left inside margin and
2969 left whitespace area. */
2972 create_left_glyph_block(struct window *w, struct display_line *dl,
2977 int use_overflow = (NILP(w->use_left_overflow) ? 0 : 1);
2979 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2980 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2981 int left_in_start = dl->bounds.left_in;
2982 int left_in_end = dl->bounds.left_in + overlay_width;
2984 struct display_block *odb, *idb;
2986 XSETWINDOW(window, w);
2988 /* We have to add the glyphs to the line in the order outside,
2989 inside, whitespace. However the precedence dictates that we
2990 determine how many will fit in the reverse order. */
2992 /* Determine how many whitespace glyphs we can display and where
2993 they should start. */
2994 white_in_start = dl->bounds.left_white;
2995 white_out_start = left_in_start;
2996 white_out_cnt = white_in_cnt = 0;
2999 while (elt < Dynarr_length(dl->left_glyphs)) {
3000 struct glyph_block *gb = Dynarr_atp(dl->left_glyphs, elt);
3002 if (NILP(gb->extent))
3003 abort(); /* these should have been handled in add_glyph_rune */
3005 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3009 width = glyph_width(gb->glyph, window);
3011 if (white_in_start - width >= left_in_end) {
3013 white_in_start -= width;
3016 } else if (use_overflow
3017 && (white_out_start - width >
3018 dl->bounds.left_out)) {
3020 white_out_start -= width;
3030 /* Determine how many inside margin glyphs we can display and where
3031 they should start. The inside margin glyphs get whatever space
3032 is left after the whitespace glyphs have been displayed. These
3033 are tricky to calculate since if we decide to use the overflow
3034 area we basically have to start over. So for these we build up a
3035 list of just the inside margin glyphs and manipulate it to
3036 determine the needed info. */
3038 glyph_block_dynarr *ib;
3039 int avail_in, avail_out;
3042 int used_in, used_out;
3045 used_in = used_out = 0;
3046 ib = Dynarr_new(glyph_block);
3047 while (elt < Dynarr_length(dl->left_glyphs)) {
3048 struct glyph_block *gb =
3049 Dynarr_atp(dl->left_glyphs, elt);
3051 if (NILP(gb->extent))
3052 abort(); /* these should have been handled in add_glyph_rune */
3054 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3056 gb->width = glyph_width(gb->glyph, window);
3057 used_in += gb->width;
3058 Dynarr_add(ib, *gb);
3067 avail_in = white_in_start - left_in_end;
3075 avail_out = white_out_start - dl->bounds.left_out;
3078 while (!done && marker < Dynarr_length(ib)) {
3079 int width = Dynarr_atp(ib, marker)->width;
3081 /* If everything now fits in the available inside margin
3082 space, we're done. */
3083 if (used_in <= avail_in)
3086 /* Otherwise see if we have room to move a glyph to the
3088 if (used_out + width <= avail_out) {
3099 /* At this point we now know that everything from marker on goes in
3100 the inside margin and everything before it goes in the outside
3101 margin. The stuff going into the outside margin is guaranteed
3102 to fit, but we may have to trim some stuff from the inside. */
3104 in_in_end = left_in_end;
3105 in_out_start = white_out_start;
3106 in_out_cnt = in_in_cnt = 0;
3110 while (elt < Dynarr_length(dl->left_glyphs)) {
3111 struct glyph_block *gb =
3112 Dynarr_atp(dl->left_glyphs, elt);
3114 if (NILP(gb->extent))
3115 abort(); /* these should have been handled in add_glyph_rune */
3117 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3119 int width = glyph_width(gb->glyph, window);
3123 in_out_start -= width;
3127 } else if (in_in_end + width < white_in_start) {
3140 /* Determine how many outside margin glyphs we can display. They
3141 always start at the left outside margin and can only use the
3142 outside margin space. */
3143 out_end = dl->bounds.left_out;
3147 while (elt < Dynarr_length(dl->left_glyphs)) {
3148 struct glyph_block *gb = Dynarr_atp(dl->left_glyphs, elt);
3150 if (NILP(gb->extent))
3151 abort(); /* these should have been handled in add_glyph_rune */
3153 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3154 GL_OUTSIDE_MARGIN) {
3155 int width = glyph_width(gb->glyph, window);
3157 if (out_end + width <= in_out_start) {
3169 /* Now that we know where everything goes, we add the glyphs as
3170 runes to the appropriate display blocks. */
3171 if (out_cnt || in_out_cnt || white_out_cnt) {
3172 odb = get_display_block_from_line(dl, LEFT_OUTSIDE_MARGIN);
3173 odb->start_pos = dl->bounds.left_out;
3174 /* #### We should stop adding a blank to account for the space
3175 between the end of the glyphs and the margin and instead set
3176 this accordingly. */
3177 odb->end_pos = dl->bounds.left_in;
3178 Dynarr_reset(odb->runes);
3182 if (in_in_cnt || white_in_cnt) {
3183 idb = get_display_block_from_line(dl, LEFT_INSIDE_MARGIN);
3184 idb->start_pos = dl->bounds.left_in;
3185 /* #### See above comment for odb->end_pos */
3186 idb->end_pos = dl->bounds.left_white;
3187 Dynarr_reset(idb->runes);
3191 /* First add the outside margin glyphs. */
3194 add_margin_runes(dl, odb, dl->bounds.left_out, out_cnt,
3195 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3197 end_xpos = dl->bounds.left_out;
3199 /* There may be blank space between the outside margin glyphs and
3200 the inside margin glyphs. If so, add a blank. */
3201 if (in_out_cnt && (in_out_start - end_xpos)) {
3202 add_margin_blank(dl, odb, w, end_xpos, in_out_start - end_xpos,
3206 /* Next add the inside margin glyphs which are actually in the
3209 end_xpos = add_margin_runes(dl, odb, in_out_start, in_out_cnt,
3210 GL_INSIDE_MARGIN, LEFT_GLYPHS,
3214 /* If we didn't add any inside margin glyphs to the outside margin,
3215 but are adding whitespace glyphs, then we need to add a blank
3217 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) {
3218 add_margin_blank(dl, odb, w, end_xpos,
3219 white_out_start - end_xpos, LEFT_GLYPHS);
3222 /* Next add the whitespace margin glyphs which are actually in the
3224 if (white_out_cnt) {
3226 add_margin_runes(dl, odb, white_out_start, white_out_cnt,
3227 GL_WHITESPACE, LEFT_GLYPHS, window);
3230 /* We take care of clearing between the end of the glyphs and the
3231 start of the inside margin for lines which have glyphs. */
3232 if (odb && (left_in_start - end_xpos)) {
3233 add_margin_blank(dl, odb, w, end_xpos, left_in_start - end_xpos,
3237 /* Next add the inside margin glyphs which are actually in the
3240 end_xpos = add_margin_runes(dl, idb, left_in_end, in_in_cnt,
3241 GL_INSIDE_MARGIN, LEFT_GLYPHS,
3244 end_xpos = left_in_end;
3246 /* Make sure that the area between the end of the inside margin
3247 glyphs and the whitespace glyphs is cleared. */
3248 if (idb && (white_in_start - end_xpos > 0)) {
3249 add_margin_blank(dl, idb, w, end_xpos,
3250 white_in_start - end_xpos, LEFT_GLYPHS);
3253 /* Next add the whitespace margin glyphs which are actually in the
3256 add_margin_runes(dl, idb, white_in_start, white_in_cnt,
3257 GL_WHITESPACE, LEFT_GLYPHS, window);
3260 /* Whitespace glyphs always end right next to the text block so
3261 there is nothing we have to make sure is cleared after them. */
3264 /* Display glyphs in the right outside margin, right inside margin and
3265 right whitespace area. */
3267 static void create_right_glyph_block(struct window *w, struct display_line *dl)
3271 int use_overflow = (NILP(w->use_right_overflow) ? 0 : 1);
3273 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3274 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3276 struct display_block *odb, *idb;
3278 XSETWINDOW(window, w);
3280 /* We have to add the glyphs to the line in the order outside,
3281 inside, whitespace. However the precedence dictates that we
3282 determine how many will fit in the reverse order. */
3284 /* Determine how many whitespace glyphs we can display and where
3285 they should start. */
3286 white_in_end = dl->bounds.right_white;
3287 white_out_end = dl->bounds.right_in;
3288 white_out_cnt = white_in_cnt = 0;
3291 while (elt < Dynarr_length(dl->right_glyphs)) {
3292 struct glyph_block *gb = Dynarr_atp(dl->right_glyphs, elt);
3294 if (NILP(gb->extent))
3295 abort(); /* these should have been handled in add_glyph_rune */
3297 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3299 int width = glyph_width(gb->glyph, window);
3301 if (white_in_end + width <= dl->bounds.right_in) {
3303 white_in_end += width;
3306 } else if (use_overflow
3307 && (white_out_end + width <=
3308 dl->bounds.right_out)) {
3310 white_out_end += width;
3320 /* Determine how many inside margin glyphs we can display and where
3321 they should start. The inside margin glyphs get whatever space
3322 is left after the whitespace glyphs have been displayed. These
3323 are tricky to calculate since if we decide to use the overflow
3324 area we basically have to start over. So for these we build up a
3325 list of just the inside margin glyphs and manipulate it to
3326 determine the needed info. */
3328 glyph_block_dynarr *ib;
3329 int avail_in, avail_out;
3332 int used_in, used_out;
3335 used_in = used_out = 0;
3336 ib = Dynarr_new(glyph_block);
3337 while (elt < Dynarr_length(dl->right_glyphs)) {
3338 struct glyph_block *gb =
3339 Dynarr_atp(dl->right_glyphs, elt);
3341 if (NILP(gb->extent))
3342 abort(); /* these should have been handled in add_glyph_rune */
3344 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3346 gb->width = glyph_width(gb->glyph, window);
3347 used_in += gb->width;
3348 Dynarr_add(ib, *gb);
3357 avail_in = dl->bounds.right_in - white_in_end;
3362 avail_out = dl->bounds.right_out - white_out_end;
3365 while (!done && marker < Dynarr_length(ib)) {
3366 int width = Dynarr_atp(ib, marker)->width;
3368 /* If everything now fits in the available inside margin
3369 space, we're done. */
3370 if (used_in <= avail_in)
3373 /* Otherwise see if we have room to move a glyph to the
3375 if (used_out + width <= avail_out) {
3386 /* At this point we now know that everything from marker on goes in
3387 the inside margin and everything before it goes in the outside
3388 margin. The stuff going into the outside margin is guaranteed
3389 to fit, but we may have to trim some stuff from the inside. */
3391 in_in_start = dl->bounds.right_in;
3392 in_out_end = dl->bounds.right_in;
3393 in_out_cnt = in_in_cnt = 0;
3397 while (elt < Dynarr_length(dl->right_glyphs)) {
3398 struct glyph_block *gb =
3399 Dynarr_atp(dl->right_glyphs, elt);
3401 if (NILP(gb->extent))
3402 abort(); /* these should have been handled in add_glyph_rune */
3404 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3406 int width = glyph_width(gb->glyph, window);
3410 in_out_end += width;
3414 } else if (in_in_start - width >= white_in_end) {
3416 in_in_start -= width;
3427 /* Determine how many outside margin glyphs we can display. They
3428 always start at the right outside margin and can only use the
3429 outside margin space. */
3430 out_start = dl->bounds.right_out;
3434 while (elt < Dynarr_length(dl->right_glyphs)) {
3435 struct glyph_block *gb = Dynarr_atp(dl->right_glyphs, elt);
3437 if (NILP(gb->extent))
3438 abort(); /* these should have been handled in add_glyph_rune */
3440 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3441 GL_OUTSIDE_MARGIN) {
3442 int width = glyph_width(gb->glyph, window);
3444 if (out_start - width >= in_out_end) {
3456 /* Now that we now where everything goes, we add the glyphs as runes
3457 to the appropriate display blocks. */
3458 if (out_cnt || in_out_cnt || white_out_cnt) {
3459 odb = get_display_block_from_line(dl, RIGHT_OUTSIDE_MARGIN);
3460 /* #### See comments before odb->start_pos init in
3461 create_left_glyph_block */
3462 odb->start_pos = dl->bounds.right_in;
3463 odb->end_pos = dl->bounds.right_out;
3464 Dynarr_reset(odb->runes);
3468 if (in_in_cnt || white_in_cnt) {
3469 idb = get_display_block_from_line(dl, RIGHT_INSIDE_MARGIN);
3470 idb->start_pos = dl->bounds.right_white;
3471 /* #### See comments before odb->start_pos init in
3472 create_left_glyph_block */
3473 idb->end_pos = dl->bounds.right_in;
3474 Dynarr_reset(idb->runes);
3478 /* First add the whitespace margin glyphs which are actually in the
3481 end_xpos = add_margin_runes(dl, idb, dl->bounds.right_white,
3482 white_in_cnt, GL_WHITESPACE,
3483 RIGHT_GLYPHS, window);
3485 end_xpos = dl->bounds.right_white;
3487 /* Make sure that the area between the end of the whitespace glyphs
3488 and the inside margin glyphs is cleared. */
3489 if (in_in_cnt && (in_in_start - end_xpos)) {
3490 add_margin_blank(dl, idb, w, end_xpos, in_in_start - end_xpos,
3494 /* Next add the inside margin glyphs which are actually in the
3497 end_xpos = add_margin_runes(dl, idb, in_in_start, in_in_cnt,
3498 GL_INSIDE_MARGIN, RIGHT_GLYPHS,
3502 /* If we didn't add any inside margin glyphs then make sure the rest
3503 of the inside margin area gets cleared. */
3504 if (idb && (dl->bounds.right_in - end_xpos)) {
3505 add_margin_blank(dl, idb, w, end_xpos,
3506 dl->bounds.right_in - end_xpos, RIGHT_GLYPHS);
3509 /* Next add any whitespace glyphs in the outside margin. */
3510 if (white_out_cnt) {
3512 add_margin_runes(dl, odb, dl->bounds.right_in,
3513 white_out_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3516 end_xpos = dl->bounds.right_in;
3518 /* Next add any inside margin glyphs in the outside margin. */
3520 end_xpos = add_margin_runes(dl, odb, end_xpos, in_out_cnt,
3521 GL_INSIDE_MARGIN, RIGHT_GLYPHS,
3525 /* There may be space between any whitespace or inside margin glyphs
3526 in the outside margin and the actual outside margin glyphs. */
3527 if (odb && (out_start - end_xpos)) {
3528 add_margin_blank(dl, odb, w, end_xpos, out_start - end_xpos,
3532 /* Finally, add the outside margin glyphs. */
3534 add_margin_runes(dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3535 RIGHT_GLYPHS, window);
3539 /***************************************************************************/
3541 /* modeline routines */
3543 /***************************************************************************/
3545 /* This function is also used in frame.c by `generate_title_string' */
3547 generate_formatted_string_db(Lisp_Object format_str, Lisp_Object result_str,
3548 struct window *w, struct display_line *dl,
3549 struct display_block *db, face_index findex,
3550 int min_pixpos, int max_pixpos, int type)
3552 struct frame *f = XFRAME(w->frame);
3553 struct device *d = XDEVICE(f->device);
3557 Charcount offset = 0;
3563 data.findex = findex;
3564 data.pixpos = min_pixpos;
3565 data.max_pixpos = max_pixpos;
3566 data.cursor_type = NO_CURSOR;
3567 data.last_charset = Qunbound;
3568 data.last_findex = DEFAULT_INDEX;
3569 data.result_str = result_str;
3570 data.is_modeline = 1;
3572 XSETWINDOW(data.window, w);
3574 Dynarr_reset(formatted_string_extent_dynarr);
3575 Dynarr_reset(formatted_string_extent_start_dynarr);
3576 Dynarr_reset(formatted_string_extent_end_dynarr);
3578 /* result_str is nil when we're building a frame or icon title. Otherwise,
3579 we're building a modeline, so the offset starts at the modeline
3580 horizontal scrolling amount */
3581 if (!NILP(result_str))
3582 offset = w->modeline_hscroll;
3583 generate_fstring_runes(w, &data, 0, 0, -1, format_str, 0,
3584 max_pixpos - min_pixpos, findex, type, &offset,
3587 if (Dynarr_length(db->runes)) {
3589 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
3590 c_pixpos = rb->xpos + rb->width;
3592 c_pixpos = min_pixpos;
3594 /* If we don't reach the right side of the window, add a blank rune
3595 to make up the difference. This usually only occurs if the
3596 modeline face is using a proportional width font or a fixed width
3597 font of a different size from the default face font. */
3599 if (c_pixpos < max_pixpos) {
3600 data.pixpos = c_pixpos;
3601 data.blank_width = max_pixpos - data.pixpos;
3603 add_blank_rune(&data, NULL, 0);
3606 /* Now create the result string and frob the extents into it. */
3607 if (!NILP(result_str)) {
3611 struct buffer *buf = XBUFFER(WINDOW_BUFFER(w));
3613 in_modeline_generation = 1;
3615 detach_all_extents(result_str);
3616 resize_string(XSTRING(result_str), -1,
3617 data.bytepos - XSTRING_LENGTH(result_str));
3619 strdata = XSTRING_DATA(result_str);
3621 for (elt = 0, len = 0; elt < Dynarr_length(db->runes); elt++) {
3622 if (Dynarr_atp(db->runes, elt)->type == RUNE_CHAR) {
3623 len += (set_charptr_emchar
3624 (strdata + len, Dynarr_atp(db->runes,
3631 elt < Dynarr_length(formatted_string_extent_dynarr);
3633 Lisp_Object extent = Qnil;
3637 Dynarr_at(formatted_string_extent_dynarr,
3640 Fgethash(extent, buf->modeline_extent_table, Qnil);
3642 child = Fmake_extent(Qnil, Qnil, result_str);
3643 Fputhash(extent, child,
3644 buf->modeline_extent_table);
3646 Fset_extent_parent(child, extent);
3647 set_extent_endpoints
3649 Dynarr_at(formatted_string_extent_start_dynarr,
3651 Dynarr_at(formatted_string_extent_end_dynarr, elt),
3655 in_modeline_generation = 0;
3659 /* Ensure that the given display line DL accurately represents the
3660 modeline for the given window. */
3662 generate_modeline(struct window *w, struct display_line *dl, int type)
3664 struct buffer *b = XBUFFER(w->buffer);
3665 struct frame *f = XFRAME(w->frame);
3666 struct device *d = XDEVICE(f->device);
3668 /* Unlike display line and rune pointers, this one can't change underneath
3670 struct display_block *db = get_display_block_from_line(dl, TEXT);
3671 int max_pixpos, min_pixpos, ypos_adj;
3672 Lisp_Object font_inst;
3674 /* This will actually determine incorrect inside boundaries for the
3675 modeline since it ignores the margins. However being aware of this fact
3676 we never use those values anywhere so it doesn't matter. */
3677 dl->bounds = calculate_display_line_boundaries(w, 1);
3679 /* We are generating a modeline. */
3681 dl->cursor_elt = -1;
3683 /* Reset the runes on the modeline. */
3684 Dynarr_reset(db->runes);
3686 if (!WINDOW_HAS_MODELINE_P(w)) {
3689 /* If there is a horizontal scrollbar, don't add anything. */
3690 if (window_scrollbar_height(w))
3693 dl->ascent = DEVMETH(d, divider_height, ());
3695 /* The modeline is at the bottom of the gutters. */
3696 dl->ypos = WINDOW_BOTTOM(w);
3698 rb.findex = MODELINE_INDEX;
3699 rb.xpos = dl->bounds.left_out;
3700 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3703 rb.type = RUNE_HLINE;
3704 rb.object.hline.thickness = 1;
3705 rb.object.hline.yoffset = 0;
3706 rb.cursor_type = NO_CURSOR;
3708 if (!EQ(Qzero, w->modeline_shadow_thickness)
3709 && FRAME_WIN_P(f)) {
3710 int shadow_thickness = MODELINE_SHADOW_THICKNESS(w);
3712 dl->ypos -= shadow_thickness;
3713 rb.xpos += shadow_thickness;
3714 rb.width -= 2 * shadow_thickness;
3717 Dynarr_add(db->runes, rb);
3721 /* !!#### not right; needs to compute the max height of
3723 font_inst = WINDOW_FACE_CACHEL_FONT(w, MODELINE_INDEX, Vcharset_ascii);
3725 dl->ascent = XFONT_INSTANCE(font_inst)->ascent;
3726 dl->descent = XFONT_INSTANCE(font_inst)->descent;
3728 min_pixpos = dl->bounds.left_out;
3729 max_pixpos = dl->bounds.right_out;
3731 if (!EQ(Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P(f)) {
3732 int shadow_thickness = MODELINE_SHADOW_THICKNESS(w);
3734 ypos_adj = shadow_thickness;
3735 min_pixpos += shadow_thickness;
3736 max_pixpos -= shadow_thickness;
3740 generate_formatted_string_db(b->modeline_format,
3741 b->generated_modeline_string, w, dl, db,
3742 MODELINE_INDEX, min_pixpos, max_pixpos,
3745 /* The modeline is at the bottom of the gutters. We have to wait to
3746 set this until we've generated the modeline in order to account
3747 for any embedded faces. */
3748 dl->ypos = WINDOW_BOTTOM(w) - dl->descent - ypos_adj;
3752 add_string_to_fstring_db_runes(pos_data * data, const Bufbyte * str,
3753 Charcount pos, Charcount min_pos,
3756 /* This function has been Mule-ized. */
3758 const Bufbyte *cur_pos = str;
3759 struct display_block *db = data->db;
3761 data->blank_width = space_width(XWINDOW(data->window));
3762 while (Dynarr_length(db->runes) < pos)
3763 add_blank_rune_noret(data, NULL, 0);
3765 end = (Dynarr_length(db->runes) +
3766 bytecount_to_charcount(str, strlen((const char *)str)));
3768 end = min(max_pos, end);
3770 while (pos < end && *cur_pos) {
3771 const Bufbyte *old_cur_pos = cur_pos;
3774 data->ch = charptr_emchar(cur_pos);
3775 succeeded = (add_emchar_rune(data) != ADD_FAILED);
3776 INC_CHARPTR(cur_pos);
3779 data->modeline_charpos++;
3780 data->bytepos += cur_pos - old_cur_pos;
3784 while (Dynarr_length(db->runes) < min_pos &&
3785 (data->pixpos + data->blank_width <= data->max_pixpos))
3786 add_blank_rune_noret(data, NULL, 0);
3788 return Dynarr_length(db->runes);
3791 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3792 modeline extents. */
3794 add_glyph_to_fstring_db_runes(pos_data * data, Lisp_Object glyph,
3795 Charcount pos, Charcount min_pos,
3796 Charcount max_pos, Lisp_Object extent)
3798 /* This function has been Mule-ized. */
3800 struct display_block *db = data->db;
3801 struct glyph_block gb;
3803 data->blank_width = space_width(XWINDOW(data->window));
3804 while (Dynarr_length(db->runes) < pos)
3805 add_blank_rune_noret(data, NULL, 0);
3807 end = Dynarr_length(db->runes) + 1;
3809 end = min(max_pos, end);
3813 add_glyph_rune_noret(data, &gb, BEGIN_GLYPHS, 0, 0);
3816 while (Dynarr_length(db->runes) < pos &&
3817 (data->pixpos + data->blank_width <= data->max_pixpos))
3818 add_blank_rune_noret(data, NULL, 0);
3820 return Dynarr_length(db->runes);
3823 /* If max_pos is == -1, it is considered to be infinite. The same is
3824 true of max_pixsize. */
3825 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3826 if (Dynarr_length (data->db->runes)) \
3827 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3831 /* Note that this function does "positions" in terms of characters and
3832 not in terms of columns. This is necessary to make the formatting
3833 work correctly when proportional width fonts are used in the
3836 generate_fstring_runes(struct window *w, pos_data * data, Charcount pos,
3837 Charcount min_pos, Charcount max_pos,
3838 Lisp_Object elt, int depth, int max_pixsize,
3839 face_index findex, int type, Charcount * offset,
3840 Lisp_Object cur_ext)
3842 /* This function has been Mule-ized. */
3843 /* #### The other losing things in this function are:
3845 -- C zero-terminated-string lossage.
3846 -- Non-printable characters should be converted into something
3847 appropriate (e.g. ^F) instead of blindly being printed anyway.
3857 /* A string. Add to the display line and check for %-constructs
3860 Bufbyte *this = XSTRING_DATA(elt);
3862 while ((pos < max_pos || max_pos == -1) && *this) {
3863 Bufbyte *last = this;
3865 while (*this && *this != '%')
3869 /* No %-construct */
3871 bytecount_to_charcount(last, this - last);
3873 if (size <= *offset)
3879 *offset : min(pos + size - *offset,
3881 const Bufbyte *tmp_last =
3882 charptr_n_addr(last, *offset);
3885 add_string_to_fstring_db_runes(data,
3892 } else { /* *this == '%' */
3894 Charcount spec_width = 0;
3896 this++; /* skip over '%' */
3898 /* We can't allow -ve args due to the "%-" construct.
3899 * Argument specifies minwidth but not maxwidth
3900 * (maxwidth can be specified by
3901 * (<negative-number> . <stuff>) modeline elements)
3903 while (isdigit(*this)) {
3905 spec_width * 10 + (*this - '0');
3912 generate_fstring_runes(w, data, pos,
3915 Vglobal_mode_string,
3921 } else if (*this == '-') {
3922 Charcount num_to_add;
3924 if (max_pixsize < 0)
3926 else if (max_pos != -1)
3927 num_to_add = max_pos - pos;
3932 SET_CURRENT_MODE_CHARS_PIXSIZE;
3935 redisplay_text_width_string
3936 (w, findex, &ch, Qnil, 0,
3946 while (num_to_add--)
3948 add_string_to_fstring_db_runes
3949 (data, (const Bufbyte *)"-",
3951 } else if (*this != 0) {
3952 Emchar ch = charptr_emchar(this);
3956 decode_mode_spec(w, ch, type);
3959 Dynarr_atp(mode_spec_bufbyte_string,
3961 size = bytecount_to_charcount
3962 /* Skip the null character added by `decode_mode_spec' */
3965 (mode_spec_bufbyte_string)) - 1;
3967 if (size <= *offset)
3970 const Bufbyte *tmp_str =
3974 /* #### NOTE: I don't understand why a tmp_max is not
3975 computed and used here as in the plain string case
3978 add_string_to_fstring_db_runes
3979 (data, tmp_str, pos, pos,
3985 /* NOT this++. There could be any sort of character at
3986 the current position. */
3990 if (max_pixsize > 0) {
3992 SET_CURRENT_MODE_CHARS_PIXSIZE;
3994 if (cur_pixsize >= max_pixsize)
3998 } else if (SYMBOLP(elt)) {
3999 /* A symbol: process the value of the symbol recursively
4000 as if it appeared here directly. */
4001 Lisp_Object tem = symbol_value_in_buffer(elt, w->buffer);
4003 if (!UNBOUNDP(tem)) {
4004 /* If value is a string, output that string literally:
4005 don't check for % within it. */
4007 Bufbyte *str = XSTRING_DATA(tem);
4008 Charcount size = XSTRING_CHAR_LENGTH(tem);
4010 if (size <= *offset)
4013 const Bufbyte *tmp_str =
4014 charptr_n_addr(str, *offset);
4016 /* #### NOTE: I don't understand why a tmp_max is not
4017 computed and used here as in the plain string case
4020 add_string_to_fstring_db_runes(data,
4028 /* Give up right away for nil or t. */
4029 else if (!EQ(tem, elt)) {
4034 } else if (GENERIC_SPECIFIERP(elt)) {
4035 Lisp_Object window, tem;
4036 XSETWINDOW(window, w);
4037 tem = specifier_instance_no_quit(elt, Qunbound, window,
4038 ERROR_ME_NOT, 0, Qzero);
4039 if (!UNBOUNDP(tem)) {
4043 } else if (CONSP(elt)) {
4044 /* A cons cell: four distinct cases.
4045 * - If first element is a string or a cons, process all the elements
4046 * and effectively concatenate them.
4047 * - If first element is a negative number, truncate displaying cdr to
4048 * at most that many characters. If positive, pad (with spaces)
4049 * to at least that many characters.
4050 * - If first element is another symbol, process the cadr or caddr
4051 * recursively according to whether the symbol's value is non-nil or
4053 * - If first element is an extent, process the cdr recursively
4054 * and handle the extent's face.
4057 Lisp_Object car, tem;
4065 tem = symbol_value_in_buffer(car, w->buffer);
4066 /* elt is now the cdr, and we know it is a cons cell.
4067 Use its car if CAR has a non-nil value. */
4068 if (!UNBOUNDP(tem)) {
4074 /* Symbol's value is nil (or symbol is unbound)
4075 * Get the cddr of the original list
4076 * and if possible find the caddr and use that.
4080 else if (!CONSP(elt))
4086 } else if (INTP(car)) {
4087 Charcount lim = XINT(car);
4092 /* Negative int means reduce maximum width.
4093 * DO NOT change MIN_PIXPOS here!
4094 * (20 -10 . foo) should truncate foo to 10 col
4095 * and then pad to 20.
4098 max_pos = pos - lim;
4100 max_pos = min(max_pos, pos - lim);
4101 } else if (lim > 0) {
4102 /* Padding specified. Don't let it be more than
4106 if (max_pos != -1 && lim > max_pos)
4108 /* If that's more padding than already wanted, queue it.
4109 * But don't reduce padding already specified even if
4110 * that is beyond the current truncation point.
4116 } else if (STRINGP(car) || CONSP(car)) {
4119 /* LIMIT is to protect against circular lists. */
4120 while (CONSP(elt) && --limit > 0
4121 && (pos < max_pos || max_pos == -1)) {
4123 generate_fstring_runes(w, data, pos, pos,
4126 findex, type, offset,
4130 } else if (EXTENTP(car)) {
4131 struct extent *ext = XEXTENT(car);
4133 if (EXTENT_LIVE_P(ext)) {
4134 face_index old_findex = data->findex;
4136 Lisp_Object font_inst;
4137 face_index new_findex;
4138 Bytecount start = data->bytepos;
4140 face = extent_face(ext);
4142 /* #### needs to merge faces, sigh */
4143 /* #### needs to handle list of faces */
4145 get_builtin_face_cache_index(w,
4147 /* !!#### not right; needs to compute the max height of
4150 WINDOW_FACE_CACHEL_FONT(w,
4154 data->dl->ascent = max(data->dl->ascent,
4159 max(data->dl->descent,
4160 XFONT_INSTANCE(font_inst)->
4163 new_findex = old_findex;
4165 data->findex = new_findex;
4167 generate_fstring_runes(w, data, pos, pos,
4173 data->findex = old_findex;
4174 Dynarr_add(formatted_string_extent_dynarr, ext);
4175 Dynarr_add(formatted_string_extent_start_dynarr,
4177 Dynarr_add(formatted_string_extent_end_dynarr,
4181 } else if (GLYPHP(elt)) {
4182 /* Glyphs are considered as one character with respect to the modeline
4183 horizontal scrolling facility. -- dv */
4188 add_glyph_to_fstring_db_runes(data, elt, pos, pos,
4193 char *str = GETTEXT("*invalid*");
4194 Charcount size = (Charcount) strlen(str); /* is this ok ?? -- dv */
4196 if (size <= *offset)
4199 const Bufbyte *tmp_str =
4200 charptr_n_addr((const Bufbyte *)str,
4203 /* #### NOTE: I don't understand why a tmp_max is not computed and
4204 used here as in the plain string case above. -- dv */
4206 add_string_to_fstring_db_runes(data,
4215 if (min_pos > pos) {
4216 add_string_to_fstring_db_runes(data, (const Bufbyte *)"", pos,
4223 /* Update just the modeline. Assumes the desired display structs. If
4224 they do not have a modeline block, it does nothing. */
4225 static void regenerate_modeline(struct window *w)
4227 display_line_dynarr *dla = window_display_lines(w, DESIRED_DISP);
4229 if (!Dynarr_length(dla) || !Dynarr_atp(dla, 0)->modeline)
4232 generate_modeline(w, Dynarr_atp(dla, 0), DESIRED_DISP);
4233 redisplay_update_line(w, 0, 0, 0);
4237 /* Make sure that modeline display line is present in the given
4238 display structs if the window has a modeline and update that
4239 line. Returns true if a modeline was needed. */
4240 static int ensure_modeline_generated(struct window *w, int type)
4244 /* minibuffer windows don't have modelines */
4245 if (MINI_WINDOW_P(w))
4247 /* windows which haven't had it turned off do */
4248 else if (WINDOW_HAS_MODELINE_P(w))
4250 /* windows which have it turned off don't have a divider if there is
4251 a horizontal scrollbar */
4252 else if (window_scrollbar_height(w))
4254 /* and in this case there is none */
4258 if (need_modeline) {
4259 display_line_dynarr *dla;
4261 dla = window_display_lines(w, type);
4263 /* We don't care if there is a display line which is not
4264 currently a modeline because it is definitely going to become
4265 one if we have gotten to this point. */
4266 if (Dynarr_length(dla) == 0) {
4267 if (Dynarr_largest(dla) > 0) {
4268 struct display_line *mlp = Dynarr_atp(dla, 0);
4269 Dynarr_add(dla, *mlp);
4271 struct display_line modeline;
4273 Dynarr_add(dla, modeline);
4277 /* If we're adding a new place marker go ahead and generate the
4278 modeline so that it is available for use by
4279 window_modeline_height. */
4280 generate_modeline(w, Dynarr_atp(dla, 0), type);
4283 return need_modeline;
4286 /* #### Kludge or not a kludge. I tend towards the former. */
4287 int real_current_modeline_height(struct window *w)
4289 Fset_marker(w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4290 Fset_marker(w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP],
4293 if (ensure_modeline_generated(w, CMOTION_DISP)) {
4294 display_line_dynarr *dla =
4295 window_display_lines(w, CMOTION_DISP);
4297 if (Dynarr_length(dla)) {
4298 if (Dynarr_atp(dla, 0)->modeline)
4299 return (Dynarr_atp(dla, 0)->ascent +
4300 Dynarr_atp(dla, 0)->descent);
4306 /***************************************************************************/
4308 /* displayable string routines */
4310 /***************************************************************************/
4312 /* Given a position for a string in a window, ensure that the given
4313 display line DL accurately represents the text on a line starting
4314 at the given position.
4316 Yes, this is duplicating the code of create_text_block, but it
4317 looked just too hard to change create_text_block to handle strings
4318 *and* buffers. We already make a distinction between the two
4319 elsewhere in the code so I think unifying them would require a
4320 complete MULE rewrite. Besides, the other distinction is that these
4321 functions cover text that the user *cannot edit* so we can remove
4322 everything to do with cursors, minibuffers etc. Eventually the
4323 modeline routines should be modified to use this code as it copes
4324 with many more types of display situation. */
4327 create_string_text_block(struct window *w, Lisp_Object disp_string,
4328 struct display_line *dl,
4330 prop_block_dynarr ** prop, face_index default_face)
4332 struct frame *f = XFRAME(w->frame);
4333 /* Note that a lot of the buffer controlled stuff has been left in
4334 because you might well want to make use of it (selective display
4335 etc), its just the buffer text that we do not use. However, it
4336 seems to be possible for buffer to be nil sometimes so protect
4337 against this case. */
4338 struct buffer *b = BUFFERP(w->buffer) ? XBUFFER(w->buffer) : 0;
4339 struct device *d = XDEVICE(f->device);
4340 Lisp_String *s = XSTRING(disp_string);
4342 /* we're working with these a lot so precalculate them */
4343 Bytecount slen = XSTRING_LENGTH(disp_string);
4344 Bytecount bi_string_zv = slen;
4345 Bytind bi_start_pos = charcount_to_bytecount(string_data(s), start_pos);
4349 int truncate_win = b ? window_truncation_on(w) : 0;
4351 /* We're going to ditch selective display for static text, it's an
4352 FSF thing and invisible extents are the way to go here.
4353 Implementing it also relies on a number of buffer-specific
4354 functions that we don't have the luxury of being able to use
4357 /* The variable ctl-arrow allows the user to specify what characters
4358 can actually be displayed and which octal should be used for.
4359 #### This variable should probably have some rethought done to
4362 #### It would also be really nice if you could specify that
4363 the characters come out in hex instead of in octal. Mule
4364 does that by adding a ctl-hexa variable similar to ctl-arrow,
4365 but that's bogus -- we need a more general solution. I
4366 think you need to extend the concept of display tables
4367 into a more general conversion mechanism. Ideally you
4368 could specify a Lisp function that converts characters,
4369 but this violates the Second Golden Rule and besides would
4370 make things way way way way slow.
4372 So instead, we extend the display-table concept, which was
4373 historically limited to 256-byte vectors, to one of the
4376 a) A 256-entry vector, for backward compatibility;
4377 b) char-table, mapping characters to values;
4378 c) range-table, mapping ranges of characters to values;
4379 d) a list of the above.
4381 The (d) option allows you to specify multiple display tables
4382 instead of just one. Each display table can specify conversions
4383 for some characters and leave others unchanged. The way the
4384 character gets displayed is determined by the first display table
4385 with a binding for that character. This way, you could call a
4386 function `enable-hex-display' that adds a hex display-table to
4387 the list of display tables for the current buffer.
4389 #### ...not yet implemented... Also, we extend the concept of
4390 "mapping" to include a printf-like spec. Thus you can make all
4391 extended characters show up as hex with a display table like
4394 #s(range-table data ((256 524288) (format "%x")))
4396 Since more than one display table is possible, you have
4397 great flexibility in mapping ranges of characters. */
4398 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP(b->ctl_arrow)
4399 ? XCHAR_OR_CHAR_INT(b->ctl_arrow)
4400 : ((EQ(b->ctl_arrow, Qt)
4401 || EQ(b->ctl_arrow, Qnil))
4402 ? 255 : 160)) : 255;
4404 Lisp_Object face_dt, window_dt;
4406 /* The text display block for this display line. */
4407 struct display_block *db = get_display_block_from_line(dl, TEXT);
4409 /* The first time through the main loop we need to force the glyph
4410 data to be updated. */
4413 /* Apparently the new extent_fragment_update returns an end position
4414 equal to the position passed in if there are no more runs to be
4416 int no_more_frags = 0;
4418 dl->used_prop_data = 0;
4420 dl->line_continuation = 0;
4422 /* set up faces to use for clearing areas, used by
4423 output_display_line */
4424 dl->default_findex = default_face;
4426 dl->left_margin_findex = default_face;
4427 dl->right_margin_findex = default_face;
4429 dl->left_margin_findex =
4430 get_builtin_face_cache_index(w, Vleft_margin_face);
4431 dl->right_margin_findex =
4432 get_builtin_face_cache_index(w, Vright_margin_face);
4436 data.ef = extent_fragment_new(disp_string, f);
4438 /* These values are used by all of the rune addition routines. We add
4439 them to this structure for ease of passing. */
4441 XSETWINDOW(data.window, w);
4445 data.bi_bufpos = bi_start_pos;
4446 data.pixpos = dl->bounds.left_in;
4447 data.last_charset = Qunbound;
4448 data.last_findex = default_face;
4449 data.result_str = Qnil;
4450 data.string = disp_string;
4452 /* Set the right boundary adjusting it to take into account any end
4453 glyph. Save the width of the end glyph for later use. */
4454 data.max_pixpos = dl->bounds.right_in;
4455 data.max_pixpos -= data.end_glyph_width;
4457 data.cursor_type = NO_CURSOR;
4461 /* I don't think we want this, string areas should not scroll with
4463 data.start_col = w->hscroll;
4464 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4466 data.bi_start_col_enabled = 0;
4467 data.hscroll_glyph_width_adjust = 0;
4469 /* We regenerate the line from the very beginning. */
4470 Dynarr_reset(db->runes);
4472 /* Why is this less than or equal and not just less than? If the
4473 starting position is already equal to the maximum we can't add
4474 anything else, right? Wrong. We might still have a newline to
4475 add. A newline can use the room allocated for an end glyph since
4476 if we add it we know we aren't going to be adding any end
4479 /* #### Chuck -- I think this condition should be while (1).
4480 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4481 and the begin-glyph ends exactly at the end of the window, the
4482 end-glyph and text might not be displayed. while (1) ensures
4483 that the loop terminates only when either (a) there is
4484 propagation data or (b) the end-of-line or end-of-buffer is hit.
4486 #### Also I think you need to ensure that the operation
4487 "add begin glyphs; add end glyphs; add text" is atomic and
4488 can't get interrupted in the middle. If you run off the end
4489 of the line during that operation, then you keep accumulating
4490 propagation data until you're done. Otherwise, if the (e.g.)
4491 there's a begin glyph at a particular position and attempting
4492 to display that glyph results in window-end being hit and
4493 propagation data being generated, then the character at that
4494 position won't be displayed.
4496 #### See also the comment after the end of this loop, below.
4498 while (data.pixpos <= data.max_pixpos) {
4499 /* #### This check probably should not be necessary. */
4500 if (data.bi_bufpos > bi_string_zv) {
4501 /* #### urk! More of this lossage! */
4506 /* Check for face changes. */
4508 || (!no_more_frags && data.bi_bufpos == data.ef->end)) {
4509 Lisp_Object last_glyph = Qnil;
4510 /* Deal with clipped glyphs that we have already displayed. */
4511 if (*prop && Dynarr_atp(*prop, 0)->type == PROP_GLYPH) {
4513 Dynarr_atp(*prop, 0)->data.p_glyph.glyph;
4517 /* Now compute the face and begin/end-glyph information. */
4519 /* Remember that the extent-fragment routines deal in Bytind's. */
4520 extent_fragment_update(w, data.ef, data.bi_bufpos,
4522 /* This is somewhat cheesy but the alternative is to
4523 propagate default_face into extent_fragment_update. */
4524 if (data.findex == DEFAULT_INDEX)
4525 data.findex = default_face;
4527 get_display_tables(w, data.findex, &face_dt,
4530 if (data.bi_bufpos == data.ef->end)
4535 /* Determine what is next to be displayed. We first handle any
4536 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4537 display then we determine what to do based on the character at the
4538 current buffer position. */
4540 /* If there are glyphs, add them to the line. We add the end
4541 glyphs for the previous run of text here rather than doing
4542 them at the end of handling the previous run so that glyphs
4543 at the beginning and end of a line are handled correctly. */
4544 if (Dynarr_length(data.ef->glyphs) > 0) {
4545 data.ch = string_char(s, data.bi_bufpos);
4546 *prop = add_glyph_runes(&data);
4552 /* If the current position is covered by an invisible extent, do
4553 nothing (except maybe add some ellipses). */
4554 else if (data.ef->invisible) {
4555 /* #### Chuck, perhaps you could look at this code? I don't
4556 really know what I'm doing. */
4562 /* The extent fragment code only sets this when we should
4563 really display the ellipses. It makes sure the ellipses
4564 don't get displayed more than once in a row. */
4565 if (data.ef->invisible_ellipses) {
4566 struct glyph_block gb;
4568 data.ef->invisible_ellipses_already_displayed =
4570 data.ef->invisible_ellipses = 0;
4572 gb.glyph = Vinvisible_text_glyph;
4574 add_glyph_rune(&data, &gb, BEGIN_GLYPHS, 0,
4576 INVIS_GLYPH_INDEX));
4577 /* Perhaps they shouldn't propagate if the very next thing
4578 is to display a newline (for compatibility with
4579 selective-display-ellipses)? Maybe that's too
4585 /* #### What if we're dealing with a display table? */
4589 if (data.bi_bufpos == bi_string_zv)
4592 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4595 /* If there is propagation data, then it represents the current
4596 buffer position being displayed. Add them and advance the
4597 position counter. This might also add the minibuffer
4600 dl->used_prop_data = 1;
4601 *prop = add_propagation_runes(prop, &data);
4604 goto done; /* gee, a really narrow window */
4605 else if (data.bi_bufpos == bi_string_zv)
4607 else if (data.bi_bufpos < 0)
4608 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4611 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4614 /* If at end-of-buffer, we've already processed begin and
4615 end-glyphs at this point and there's no text to process,
4617 else if (data.bi_bufpos == bi_string_zv)
4621 Lisp_Object entry = Qnil;
4622 /* Get the character at the current buffer position. */
4623 data.ch = string_char(s, data.bi_bufpos);
4624 if (!NILP(face_dt) || !NILP(window_dt))
4626 display_table_entry(data.ch, face_dt,
4629 /* If there is a display table entry for it, hand it off to
4630 add_disp_table_entry_runes and let it worry about it. */
4631 if (!NILP(entry) && !EQ(entry, make_char(data.ch))) {
4633 add_disp_table_entry_runes(&data, entry);
4639 /* Check if we have hit a newline character. If so, add a marker
4640 to the line and end this loop. */
4641 else if (data.ch == '\n') {
4642 /* We aren't going to be adding an end glyph so give its
4643 space back in order to make sure that the cursor can
4645 data.max_pixpos += data.end_glyph_width;
4649 /* If the current character is considered to be printable, then
4651 else if (data.ch >= printable_min) {
4652 *prop = add_emchar_rune(&data);
4657 /* If the current character is a tab, determine the next tab
4658 starting position and add a blank rune which extends from the
4659 current pixel position to that starting position. */
4660 else if (data.ch == '\t') {
4661 int tab_start_pixpos = data.pixpos;
4666 if (data.start_col > 1)
4669 (data.start_col - 1));
4672 next_tab_position(w, tab_start_pixpos,
4673 dl->bounds.left_in +
4675 hscroll_glyph_width_adjust);
4676 if (next_tab_start > data.max_pixpos) {
4678 next_tab_start - data.max_pixpos;
4679 next_tab_start = data.max_pixpos;
4681 data.blank_width = next_tab_start - data.pixpos;
4684 tab_start_pixpos) / space_width(w);
4687 add_blank_rune(&data, w, char_tab_width);
4689 /* add_blank_rune is only supposed to be called with
4690 sizes guaranteed to fit in the available space. */
4694 struct prop_block pb;
4695 *prop = Dynarr_new(prop_block);
4697 pb.type = PROP_BLANK;
4698 pb.data.p_blank.width = prop_width;
4699 pb.data.p_blank.findex = data.findex;
4700 Dynarr_add(*prop, pb);
4706 /* If character is a control character, pass it off to
4707 add_control_char_runes.
4709 The is_*() routines have undefined results on
4710 arguments outside of the range [-1, 255]. (This
4711 often bites people who carelessly use `char' instead
4712 of `unsigned char'.)
4714 else if (data.ch < 0x100 && iscntrl((Bufbyte) data.ch)) {
4715 *prop = add_control_char_runes(&data, b);
4721 /* If the character is above the ASCII range and we have not
4722 already handled it, then print it as an octal number. */
4723 else if (data.ch >= 0200) {
4724 *prop = add_octal_runes(&data);
4730 /* Assume the current character is considered to be printable,
4731 then just add it. */
4733 *prop = add_emchar_rune(&data);
4738 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4744 /* Determine the starting point of the next line if we did not hit the
4745 end of the buffer. */
4746 if (data.bi_bufpos < bi_string_zv) {
4747 /* #### This check is not correct. If the line terminated
4748 due to a begin-glyph or end-glyph hitting window-end, then
4749 data.ch will not point to the character at data.bi_bufpos. If
4750 you make the two changes mentioned at the top of this loop,
4751 you should be able to say '(if (*prop))'. That should also
4752 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4755 /* The common case is that the line ended because we hit a newline.
4756 In that case, the next character is just the next buffer
4758 if (data.ch == '\n') {
4759 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4762 /* Otherwise we have a buffer line which cannot fit on one display
4765 struct glyph_block gb;
4766 struct glyph_cachel *cachel;
4768 /* If the line is to be truncated then we actually have to look
4769 for the next newline. We also add the end-of-line glyph which
4770 we know will fit because we adjusted the right border before
4771 we starting laying out the line. */
4772 data.max_pixpos += data.end_glyph_width;
4773 data.findex = default_face;
4779 /* Now find the start of the next line. */
4781 bi_find_next_emchar_in_string(s, '\n',
4785 data.cursor_type = NO_CURSOR;
4786 data.bi_bufpos = bi_pos;
4787 gb.glyph = Vtruncation_glyph;
4788 cachel = GLYPH_CACHEL(w, TRUN_GLYPH_INDEX);
4790 /* The cursor can never be on the continuation glyph. */
4791 data.cursor_type = NO_CURSOR;
4793 /* data.bi_bufpos is already at the start of the next line. */
4795 dl->line_continuation = 1;
4796 gb.glyph = Vcontinuation_glyph;
4797 cachel = GLYPH_CACHEL(w, CONT_GLYPH_INDEX);
4800 if (data.end_glyph_width)
4801 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS, 0,
4804 if (truncate_win && data.bi_bufpos == bi_string_zv) {
4805 const Bufbyte *endb =
4806 charptr_n_addr(string_data(s),
4809 if (charptr_emchar(endb) != '\n') {
4810 /* #### Damn this losing shit. */
4815 } else if (data.bi_bufpos == bi_string_zv) {
4816 /* create_text_block () adds a bogus \n marker here which screws
4817 up subwindow display. Since we never have a cursor in the
4818 gutter we can safely ignore it. */
4820 /* Calculate left whitespace boundary. */
4824 /* Whitespace past a newline is considered right whitespace. */
4825 while (elt < Dynarr_length(db->runes)) {
4826 struct rune *rb = Dynarr_atp(db->runes, elt);
4828 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4829 || rb->type == RUNE_BLANK) {
4830 dl->bounds.left_white += rb->width;
4833 elt = Dynarr_length(db->runes);
4837 /* Calculate right whitespace boundary. */
4839 int elt = Dynarr_length(db->runes) - 1;
4842 while (!done && elt >= 0) {
4843 struct rune *rb = Dynarr_atp(db->runes, elt);
4845 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4846 && isspace(rb->object.chr.ch))
4847 && !rb->type == RUNE_BLANK) {
4848 dl->bounds.right_white = rb->xpos + rb->width;
4856 /* The line is blank so everything is considered to be right
4859 dl->bounds.right_white = dl->bounds.left_in;
4862 /* Set the display blocks bounds. */
4863 db->start_pos = dl->bounds.left_in;
4864 if (Dynarr_length(db->runes)) {
4866 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
4868 db->end_pos = rb->xpos + rb->width;
4870 db->end_pos = dl->bounds.right_white;
4872 calculate_baseline(&data);
4874 dl->ascent = data.new_ascent;
4875 dl->descent = data.new_descent;
4878 unsigned short ascent =
4879 (unsigned short)XINT(w->minimum_line_ascent);
4881 if (dl->ascent < ascent)
4882 dl->ascent = ascent;
4885 unsigned short descent =
4886 (unsigned short)XINT(w->minimum_line_descent);
4888 if (dl->descent < descent)
4889 dl->descent = descent;
4892 calculate_yoffset(dl, db);
4894 dl->cursor_elt = data.cursor_x;
4895 /* #### lossage lossage lossage! Fix this shit! */
4896 if (data.bi_bufpos > bi_string_zv)
4898 buffer_or_string_bytind_to_bufpos(disp_string,
4902 buffer_or_string_bytind_to_bufpos(disp_string,
4903 data.bi_bufpos) - 1;
4905 data.dl->num_chars =
4906 string_column_at_point(s, dl->end_bufpos,
4907 b ? XINT(b->tab_width) : 8);
4909 /* This doesn't correctly take into account tabs and control
4910 characters but if the window isn't being truncated then this
4911 value isn't going to end up being used anyhow. */
4912 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4914 /* #### handle horizontally scrolled line with text none of which
4915 was actually laid out. */
4917 /* #### handle any remainder of overlay arrow */
4919 if (*prop == ADD_FAILED)
4922 if (truncate_win && *prop) {
4927 extent_fragment_delete(data.ef);
4929 /* #### If we started at EOB, then make sure we return a value past
4930 it so that regenerate_window will exit properly. This is bogus.
4931 The main loop should get fixed so that it isn't necessary to call
4932 this function if we are already at EOB. */
4934 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4935 return bytecount_to_charcount(string_data(s), data.bi_bufpos) + 1; /* Yuck! */
4937 return bytecount_to_charcount(string_data(s), data.bi_bufpos);
4940 /* Given a display line and a starting position, ensure that the
4941 contents of the display line accurately represent the visual
4942 representation of the buffer contents starting from the given
4943 position when displayed in the given window. The display line ends
4944 when the contents of the line reach the right boundary of the given
4947 This is very similar to generate_display_line but with the same
4948 limitations as create_string_text_block. I have taken the liberty
4949 of fixing the bytind stuff though.*/
4952 generate_string_display_line(struct window *w, Lisp_Object disp_string,
4953 struct display_line *dl,
4955 prop_block_dynarr ** prop, face_index default_face)
4959 /* you must set bounds before calling this. */
4961 /* Reset what this line is using. */
4962 if (dl->display_blocks)
4963 Dynarr_reset(dl->display_blocks);
4964 if (dl->left_glyphs) {
4965 Dynarr_free(dl->left_glyphs);
4966 dl->left_glyphs = 0;
4968 if (dl->right_glyphs) {
4969 Dynarr_free(dl->right_glyphs);
4970 dl->right_glyphs = 0;
4973 /* We aren't generating a modeline at the moment. */
4976 /* Create a display block for the text region of the line. */
4977 ret_bufpos = create_string_text_block(w, disp_string, dl, start_pos,
4978 prop, default_face);
4979 dl->bufpos = start_pos;
4980 if (dl->end_bufpos < dl->bufpos)
4981 dl->end_bufpos = dl->bufpos;
4983 /* If there are left glyphs associated with any character in the
4984 text block, then create a display block to handle them. */
4985 if (dl->left_glyphs != NULL && Dynarr_length(dl->left_glyphs))
4986 create_left_glyph_block(w, dl, 0);
4988 /* If there are right glyphs associated with any character in the
4989 text block, then create a display block to handle them. */
4990 if (dl->right_glyphs != NULL && Dynarr_length(dl->right_glyphs))
4991 create_right_glyph_block(w, dl);
4996 /* This is ripped off from regenerate_window. All we want to do is
4997 loop through elements in the string creating display lines until we
4998 have covered the provided area. Simple really. */
5000 generate_displayable_area(struct window *w, Lisp_Object disp_string,
5001 int xpos, int ypos, int width, int height,
5002 display_line_dynarr * dla,
5003 Bufpos start_pos, face_index default_face)
5005 int yend = ypos + height;
5008 prop_block_dynarr *prop = 0;
5009 layout_bounds bounds;
5013 /* if there's nothing to do then do nothing. code after this assumes
5014 there is something to do. */
5015 if (NILP(disp_string))
5018 s_zv = XSTRING_CHAR_LENGTH(disp_string);
5020 bounds.left_out = xpos;
5021 bounds.right_out = xpos + width;
5022 /* The inner boundaries mark where the glyph margins are located. */
5023 bounds.left_in = bounds.left_out + window_left_margin_width(w);
5024 bounds.right_in = bounds.right_out - window_right_margin_width(w);
5025 /* We cannot fully calculate the whitespace boundaries as they
5026 depend on the contents of the line being displayed. */
5027 bounds.left_white = bounds.left_in;
5028 bounds.right_white = bounds.right_in;
5030 while (ypos < yend) {
5031 struct display_line dl;
5032 struct display_line *dlp;
5036 if (Dynarr_length(dla) < Dynarr_largest(dla)) {
5037 dlp = Dynarr_atp(dla, Dynarr_length(dla));
5046 dlp->bounds = bounds;
5049 generate_string_display_line(w, disp_string, dlp, start_pos,
5050 &prop, default_face);
5051 /* we need to make sure that we continue along the line if there
5052 is more left to display otherwise we just end up redisplaying
5053 the same chunk over and over again. */
5054 if (next_pos == start_pos && next_pos < s_zv)
5057 start_pos = next_pos;
5059 dlp->ypos = ypos + dlp->ascent;
5060 ypos = dlp->ypos + dlp->descent;
5063 int visible_height = dlp->ascent + dlp->descent;
5065 dlp->clip = (ypos - yend);
5066 visible_height -= dlp->clip;
5068 if (visible_height < VERTICAL_CLIP(w, 1)) {
5070 free_display_line(dlp);
5076 Dynarr_add(dla, *dlp);
5078 /* #### This type of check needs to be done down in the
5079 generate_display_line call. */
5080 if (start_pos >= s_zv)
5088 /***************************************************************************/
5090 /* window-regeneration routines */
5092 /***************************************************************************/
5094 /* For a given window and starting position in the buffer it contains,
5095 ensure that the TYPE display lines accurately represent the
5096 presentation of the window. We pass the buffer instead of getting
5097 it from the window since redisplay_window may have temporarily
5098 changed it to the echo area buffer. */
5101 regenerate_window(struct window *w, Bufpos start_pos, Bufpos point, int type)
5103 struct frame *f = XFRAME(w->frame);
5104 struct buffer *b = XBUFFER(w->buffer);
5105 int ypos = WINDOW_TEXT_TOP(w);
5106 int yend; /* set farther down */
5107 int yclip = WINDOW_TEXT_TOP_CLIP(w);
5110 prop_block_dynarr *prop;
5111 layout_bounds bounds;
5112 display_line_dynarr *dla;
5115 /* The lines had better exist by this point. */
5116 if (!(dla = window_display_lines(w, type)))
5119 w->max_line_len = 0;
5121 /* Normally these get updated in redisplay_window but it is possible
5122 for this function to get called from some other points where that
5123 update may not have occurred. This acts as a safety check. */
5124 if (!Dynarr_length(w->face_cachels))
5125 reset_face_cachels(w);
5126 if (!Dynarr_length(w->glyph_cachels))
5127 reset_glyph_cachels(w);
5129 Fset_marker(w->start[type], make_int(start_pos), w->buffer);
5130 Fset_marker(w->pointm[type], make_int(point), w->buffer);
5131 w->last_point_x[type] = -1;
5132 w->last_point_y[type] = -1;
5134 /* Make sure a modeline is in the structs if needed. */
5135 need_modeline = ensure_modeline_generated(w, type);
5137 /* Wait until here to set this so that the structs have a modeline
5138 generated in the case where one didn't exist. */
5139 yend = WINDOW_TEXT_BOTTOM(w);
5141 bounds = calculate_display_line_boundaries(w, 0);
5143 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5144 if (MINI_WINDOW_P(w)
5145 && (!NILP(Vminibuf_prompt) || !NILP(Vminibuf_preprompt))
5146 && !echo_area_active(f)
5147 && start_pos == BUF_BEGV(b)) {
5148 struct prop_block pb;
5150 prop = Dynarr_new(prop_block);
5152 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5153 pb.type = PROP_MINIBUF_PROMPT;
5154 pb.data.p_string.str = XSTRING_DATA(string);
5155 pb.data.p_string.len = XSTRING_LENGTH(string);
5156 Dynarr_add(prop, pb);
5160 /* When we are computing things for scrolling purposes, make
5161 sure at least one line is always generated */
5162 force = (type == CMOTION_DISP);
5164 /* Make sure this is set always */
5165 /* Note the conversion at end */
5166 w->window_end_pos[type] = start_pos;
5167 while (ypos < yend || force) {
5168 struct display_line dl;
5169 struct display_line *dlp;
5172 if (Dynarr_length(dla) < Dynarr_largest(dla)) {
5173 dlp = Dynarr_atp(dla, Dynarr_length(dla));
5182 dlp->bounds = bounds;
5185 generate_display_line(w, dlp, 1, start_pos, &prop, type);
5187 if (yclip > dlp->ascent) {
5188 /* this should never happen, but if it does just display the
5193 dlp->ypos = (ypos + dlp->ascent) - yclip;
5194 ypos = dlp->ypos + dlp->descent;
5196 /* See if we've been asked to start midway through a line, for
5197 partial display line scrolling. */
5199 dlp->top_clip = yclip;
5205 int visible_height = dlp->ascent + dlp->descent;
5207 dlp->clip = (ypos - yend);
5208 /* Although this seems strange we could have a single very
5209 tall line visible for which we need to account for both
5210 the top clip and the bottom clip. */
5211 visible_height -= (dlp->clip + dlp->top_clip);
5213 if (visible_height < VERTICAL_CLIP(w, 1) && !force) {
5215 free_display_line(dlp);
5221 if (dlp->cursor_elt != -1) {
5222 /* #### This check is steaming crap. Have to get things
5223 fixed so when create_text_block hits EOB, we're done,
5225 if (w->last_point_x[type] == -1) {
5226 w->last_point_x[type] = dlp->cursor_elt;
5227 w->last_point_y[type] = Dynarr_length(dla);
5229 /* #### This means that we've added a cursor at EOB
5230 twice. Yuck oh yuck. */
5231 struct display_block *db =
5232 get_display_block_from_line(dlp, TEXT);
5234 Dynarr_atp(db->runes,
5235 dlp->cursor_elt)->cursor_type =
5237 dlp->cursor_elt = -1;
5241 if (dlp->num_chars > w->max_line_len)
5242 w->max_line_len = dlp->num_chars;
5244 Dynarr_add(dla, *dlp);
5246 /* #### This isn't right, but it is close enough for now. */
5247 w->window_end_pos[type] = start_pos;
5249 /* #### This type of check needs to be done down in the
5250 generate_display_line call. */
5251 if (start_pos > BUF_ZV(b))
5260 /* #### More not quite right, but close enough. */
5261 /* Ben sez: apparently window_end_pos[] is measured
5262 as the number of characters between the window end and the
5263 end of the buffer? This seems rather weirdo. What's
5264 the justification for this?
5266 JV sez: Because BUF_Z (b) would be a good initial value, however
5267 that can change. This representation allows initalizing with 0.
5269 w->window_end_pos[type] = BUF_Z(b) - w->window_end_pos[type];
5271 if (need_modeline) {
5272 /* We know that this is the right thing to use because we put it
5273 there when we first started working in this function. */
5274 generate_modeline(w, Dynarr_atp(dla, 0), type);
5278 #define REGEN_INC_FIND_START_END \
5280 /* Determine start and end of lines. */ \
5281 if (!Dynarr_length (cdla)) \
5285 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5289 else if (!Dynarr_atp (cdla, 0)->modeline \
5290 && !Dynarr_atp (ddla, 0)->modeline) \
5295 abort (); /* structs differ */ \
5297 dla_end = Dynarr_length (cdla) - 1; \
5300 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5301 + Dynarr_atp (cdla, dla_start)->offset); \
5302 /* If this isn't true, then startp has changed and we need to do a \
5304 if (startp != start_pos) \
5307 /* Point is outside the visible region so give up. */ \
5308 if (pointm < start_pos) \
5313 /* This attempts to incrementally update the display structures. It
5314 returns a boolean indicating success or failure. This function is
5315 very similar to regenerate_window_incrementally and is in fact only
5316 called from that function. However, because of the nature of the
5317 changes it deals with it sometimes makes different assumptions
5318 which can lead to success which are much more difficult to make
5319 when dealing with buffer changes. */
5322 regenerate_window_extents_only_changed(struct window *w, Bufpos startp,
5324 Charcount beg_unchanged,
5325 Charcount end_unchanged)
5327 struct buffer *b = XBUFFER(w->buffer);
5328 display_line_dynarr *cdla = window_display_lines(w, CURRENT_DISP);
5329 display_line_dynarr *ddla = window_display_lines(w, DESIRED_DISP);
5333 int first_line, last_line;
5335 /* Don't define this in the loop where it is used because we
5336 definitely want its value to survive between passes. */
5337 prop_block_dynarr *prop = NULL;
5339 /* If we don't have any buffer change recorded but the modiff flag has
5340 been incremented, then fail. I'm not sure of the exact circumstances
5341 under which this can happen, but I believe that it is probably a
5342 reasonable happening. */
5343 if (!point_visible(w, pointm, CURRENT_DISP)
5344 || XINT(w->last_modified[CURRENT_DISP]) < BUF_MODIFF(b))
5347 /* If the cursor is moved we attempt to update it. If we succeed we
5348 go ahead and proceed with the optimization attempt. */
5349 if (!EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5350 || pointm != marker_position(w->last_point[CURRENT_DISP])) {
5351 struct frame *f = XFRAME(w->frame);
5352 struct device *d = XDEVICE(f->device);
5353 struct frame *sel_f = device_selected_frame(d);
5356 if (w->last_point_x[CURRENT_DISP] != -1
5357 && w->last_point_y[CURRENT_DISP] != -1) {
5359 if (redisplay_move_cursor(w, pointm, WINDOW_TTY_P(w))) {
5360 /* Always regenerate the modeline in case it is
5361 displaying the current line or column. */
5362 regenerate_modeline(w);
5365 } else if (w != XWINDOW(FRAME_SELECTED_WINDOW(sel_f))) {
5366 if (f->modeline_changed)
5367 regenerate_modeline(w);
5375 if (beg_unchanged == -1 && end_unchanged == -1)
5378 /* assert: There are no buffer modifications or they are all below the
5379 visible region. We assume that regenerate_window_incrementally has
5380 not called us unless this is true. */
5382 REGEN_INC_FIND_START_END;
5384 /* If the changed are starts before the visible area, give up. */
5385 if (beg_unchanged < startp)
5388 /* Find what display line the extent changes first affect. */
5390 while (line <= dla_end) {
5391 struct display_line *dl = Dynarr_atp(cdla, line);
5392 Bufpos lstart = dl->bufpos + dl->offset;
5393 Bufpos lend = dl->end_bufpos + dl->offset;
5395 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5401 /* If the changes are below the visible area then if point hasn't
5402 moved return success otherwise fail in order to be safe. */
5403 if (line > dla_end) {
5404 if (EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5405 && pointm == marker_position(w->last_point[CURRENT_DISP]))
5411 /* At this point we know what line the changes first affect. We now
5412 begin redrawing lines as long as we are still in the affected
5413 region and the line's size and positioning don't change.
5414 Otherwise we fail. If we fail we will have altered the desired
5415 structs which could lead to an assertion failure. However, if we
5416 fail the next thing that is going to happen is a full regen so we
5417 will actually end up being safe. */
5418 w->last_modified[DESIRED_DISP] = make_int(BUF_MODIFF(b));
5419 w->last_facechange[DESIRED_DISP] = make_int(BUF_FACECHANGE(b));
5420 Fset_marker(w->last_start[DESIRED_DISP], make_int(startp), w->buffer);
5421 Fset_marker(w->last_point[DESIRED_DISP], make_int(pointm), w->buffer);
5423 first_line = last_line = line;
5424 while (line <= dla_end) {
5425 Bufpos old_start, old_end, new_start;
5426 struct display_line *cdl = Dynarr_atp(cdla, line);
5427 struct display_line *ddl = Dynarr_atp(ddla, line);
5428 struct display_block *db;
5431 assert(cdl->bufpos == ddl->bufpos);
5432 assert(cdl->end_bufpos == ddl->end_bufpos);
5433 assert(cdl->offset == ddl->offset);
5435 db = get_display_block_from_line(ddl, TEXT);
5436 initial_size = Dynarr_length(db->runes);
5437 old_start = ddl->bufpos + ddl->offset;
5438 old_end = ddl->end_bufpos + ddl->offset;
5440 /* If this is the first line being updated and it used
5441 propagation data, fail. Otherwise we'll be okay because
5442 we'll have the necessary propagation data. */
5443 if (line == first_line && ddl->used_prop_data)
5447 generate_display_line(w, ddl, 0, ddl->bufpos + ddl->offset,
5448 &prop, DESIRED_DISP);
5451 /* #### If there is propagated stuff the fail. We could
5452 probably actually deal with this if the line had propagated
5453 information when originally created by a full
5460 /* If any line position parameters have changed or a
5461 cursor has disappeared or disappeared, fail. */
5462 db = get_display_block_from_line(ddl, TEXT);
5463 if (cdl->ypos != ddl->ypos
5464 || cdl->ascent != ddl->ascent
5465 || cdl->descent != ddl->descent
5466 || cdl->top_clip != ddl->top_clip
5467 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5468 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5469 || old_start != ddl->bufpos
5470 || old_end != ddl->end_bufpos
5471 || initial_size != Dynarr_length(db->runes)) {
5475 if (ddl->cursor_elt != -1) {
5476 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5477 w->last_point_y[DESIRED_DISP] = line;
5482 /* If the extent changes end on the line we just updated then
5483 we're done. Otherwise go on to the next line. */
5484 if (end_unchanged <= ddl->end_bufpos)
5490 redisplay_update_line(w, first_line, last_line, 1);
5494 /* Attempt to update the display data structures based on knowledge of
5495 the changed region in the buffer. Returns a boolean indicating
5496 success or failure. If this function returns a failure then a
5497 regenerate_window _must_ be performed next in order to maintain
5498 invariants located here. */
5501 regenerate_window_incrementally(struct window *w, Bufpos startp, Bufpos pointm)
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
5524 ? -1 : BUF_Z(b) - BUF_EXTENT_END_UNCHANGED(b));
5526 /* If nothing has changed in the buffer, then make sure point is ok
5528 if (BUF_BEGIN_UNCHANGED(b) == -1 && BUF_END_UNCHANGED(b) == -1)
5529 return regenerate_window_extents_only_changed(w, startp, pointm,
5530 extent_beg_unchanged,
5531 extent_end_unchanged);
5533 /* We can't deal with deleted newlines. */
5534 if (BUF_NEWLINE_WAS_DELETED(b))
5537 beg_unchanged = BUF_BEGIN_UNCHANGED(b);
5538 end_unchanged = (BUF_END_UNCHANGED(b) == -1
5539 ? -1 : BUF_Z(b) - BUF_END_UNCHANGED(b));
5541 REGEN_INC_FIND_START_END;
5543 /* If the changed area starts before the visible area, give up. */
5544 if (beg_unchanged < startp)
5547 /* Find what display line the buffer changes first affect. */
5549 while (line <= dla_end) {
5550 struct display_line *dl = Dynarr_atp(cdla, line);
5551 Bufpos lstart = dl->bufpos + dl->offset;
5552 Bufpos lend = dl->end_bufpos + dl->offset;
5554 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5560 /* If the changes are below the visible area then if point hasn't
5561 moved return success otherwise fail in order to be safe. */
5563 return regenerate_window_extents_only_changed(w, startp, pointm,
5564 extent_beg_unchanged,
5565 extent_end_unchanged);
5567 /* At this point we know what line the changes first affect. We
5568 now redraw that line. If the changes are contained within it
5569 we are going to succeed and can update just that one line.
5570 Otherwise we fail. If we fail we will have altered the desired
5571 structs which could lead to an assertion failure. However, if
5572 we fail the next thing that is going to happen is a full regen
5573 so we will actually end up being safe. */
5576 prop_block_dynarr *prop = NULL;
5577 struct display_line *cdl = Dynarr_atp(cdla, line);
5578 struct display_line *ddl = Dynarr_atp(ddla, line);
5580 assert(cdl->bufpos == ddl->bufpos);
5581 assert(cdl->end_bufpos == ddl->end_bufpos);
5582 assert(cdl->offset == ddl->offset);
5584 /* If the line continues to next display line, fail. */
5585 if (ddl->line_continuation)
5588 /* If the line was generated using propagation data, fail. */
5589 if (ddl->used_prop_data)
5593 generate_display_line(w, ddl, 0, ddl->bufpos + ddl->offset,
5594 &prop, DESIRED_DISP);
5597 /* If there is propagated stuff then it is pretty much a
5598 guarantee that more than just the one line is affected. */
5604 /* If the line continues to next display line, fail. */
5605 if (ddl->line_continuation)
5608 /* If any line position parameters have changed or a
5609 cursor has disappeared or disappeared, fail. */
5610 if (cdl->ypos != ddl->ypos
5611 || cdl->ascent != ddl->ascent
5612 || cdl->descent != ddl->descent
5613 || cdl->top_clip != ddl->top_clip
5614 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5615 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) {
5619 /* If the changed area also ends on this line, then we may be in
5620 business. Update everything and return success. */
5621 if (end_unchanged >= ddl->bufpos
5622 && end_unchanged <= ddl->end_bufpos) {
5623 w->last_modified[DESIRED_DISP] =
5624 make_int(BUF_MODIFF(b));
5625 w->last_facechange[DESIRED_DISP] =
5626 make_int(BUF_FACECHANGE(b));
5627 Fset_marker(w->last_start[DESIRED_DISP],
5628 make_int(startp), w->buffer);
5629 Fset_marker(w->last_point[DESIRED_DISP],
5630 make_int(pointm), w->buffer);
5632 if (ddl->cursor_elt != -1) {
5633 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5634 w->last_point_y[DESIRED_DISP] = line;
5637 redisplay_update_line(w, line, line, 1);
5638 regenerate_modeline(w);
5640 /* #### For now we just flush the cache until this has been
5641 tested. After that is done, this should correct the
5643 Dynarr_reset(w->line_start_cache);
5645 /* Adjust the extent changed boundaries to remove any
5646 overlap with the buffer changes since we've just
5647 successfully updated that area. */
5648 if (extent_beg_unchanged != -1
5649 && extent_beg_unchanged >= beg_unchanged
5650 && extent_beg_unchanged < end_unchanged)
5651 extent_beg_unchanged = end_unchanged;
5653 if (extent_end_unchanged != -1
5654 && extent_end_unchanged >= beg_unchanged
5655 && extent_end_unchanged < end_unchanged)
5656 extent_end_unchanged = beg_unchanged - 1;
5658 if (extent_end_unchanged <= extent_beg_unchanged)
5659 extent_beg_unchanged = extent_end_unchanged =
5662 /* This could lead to odd results if it fails, but since the
5663 buffer changes update succeeded this probably will to.
5664 We already know that the extent changes start at or after
5665 the line because we checked before entering the loop. */
5666 if (extent_beg_unchanged != -1
5667 && extent_end_unchanged != -1
5668 && ((extent_beg_unchanged < ddl->bufpos)
5669 || (extent_end_unchanged > ddl->end_bufpos)))
5670 return regenerate_window_extents_only_changed(w,
5673 extent_beg_unchanged,
5674 extent_end_unchanged);
5684 /* Given a window and a point, update the given display lines such
5685 that point is displayed in the middle of the window.
5686 Return the window's new start position. */
5689 regenerate_window_point_center(struct window *w, Bufpos point, int type)
5693 /* We need to make sure that the modeline is generated so that the
5694 window height can be calculated correctly. */
5695 ensure_modeline_generated(w, type);
5697 startp = start_with_line_at_pixpos(w, point, window_half_pixpos(w));
5698 regenerate_window(w, startp, point, type);
5699 Fset_marker(w->start[type], make_int(startp), w->buffer);
5704 /* Given a window and a set of display lines, return a boolean
5705 indicating whether the given point is contained within. */
5707 static int point_visible(struct window *w, Bufpos point, int type)
5709 struct buffer *b = XBUFFER(w->buffer);
5710 display_line_dynarr *dla = window_display_lines(w, type);
5713 if (Dynarr_length(dla) && Dynarr_atp(dla, 0)->modeline)
5718 if (Dynarr_length(dla) > first_line) {
5720 struct display_line *dl = Dynarr_atp(dla, first_line);
5723 end = BUF_Z(b) - w->window_end_pos[type] - 1;
5725 if (point >= start && point <= end) {
5726 if (!MINI_WINDOW_P(w) && scroll_on_clipped_lines) {
5727 dl = Dynarr_atp(dla, Dynarr_length(dla) - 1);
5729 if (point >= (dl->bufpos + dl->offset)
5730 && point <= (dl->end_bufpos + dl->offset))
5742 /* Return pixel position the middle of the window, not including the
5743 modeline and any potential horizontal scrollbar. */
5745 int window_half_pixpos(struct window *w)
5747 return WINDOW_TEXT_TOP(w) + (WINDOW_TEXT_HEIGHT(w) >> 1);
5750 /* Return the display line which is currently in the middle of the
5751 window W for display lines TYPE. */
5753 int line_at_center(struct window *w, int type, Bufpos start, Bufpos point)
5755 display_line_dynarr *dla;
5758 int first_elt = (MINI_WINDOW_P(w) ? 0 : 1);
5760 if (type == CMOTION_DISP)
5761 regenerate_window(w, start, point, type);
5763 dla = window_display_lines(w, type);
5764 half = window_half_pixpos(w);
5766 for (elt = first_elt; elt < Dynarr_length(dla); elt++) {
5767 struct display_line *dl = Dynarr_atp(dla, elt);
5768 int line_bot = dl->ypos + dl->descent;
5770 if (line_bot > half)
5774 /* We may not have a line at the middle if the end of the buffer is
5779 /* Return a value for point that would place it at the beginning of
5780 the line which is in the middle of the window. */
5782 Bufpos point_at_center(struct window * w, int type, Bufpos start, Bufpos point)
5784 /* line_at_center will regenerate the display structures, if necessary. */
5785 int line = line_at_center(w, type, start, point);
5788 return BUF_ZV(XBUFFER(w->buffer));
5790 display_line_dynarr *dla = window_display_lines(w, type);
5791 struct display_line *dl = Dynarr_atp(dla, line);
5797 /* For a given window, ensure that the current visual representation
5800 static void redisplay_window(Lisp_Object window, int skip_selected)
5802 struct window *w = XWINDOW(window);
5803 struct frame *f = XFRAME(w->frame);
5804 struct device *d = XDEVICE(f->device);
5805 Lisp_Object old_buffer = w->buffer;
5806 Lisp_Object the_buffer = w->buffer;
5808 int echo_active = 0;
5813 int selected_in_its_frame;
5814 int selected_globally;
5815 int skip_output = 0;
5816 int truncation_changed;
5817 int inactive_minibuffer =
5818 (MINI_WINDOW_P(w) &&
5819 (f != device_selected_frame(d)) &&
5820 !is_surrogate_for_selected_frame(f));
5822 /* #### In the new world this function actually does a bunch of
5823 optimizations such as buffer-based scrolling, but none of that is
5826 /* If this is a combination window, do its children; that's all.
5827 The selected window is always a leaf so we don't check for
5828 skip_selected here. */
5829 if (!NILP(w->vchild)) {
5830 redisplay_windows(w->vchild, skip_selected);
5833 if (!NILP(w->hchild)) {
5834 redisplay_windows(w->hchild, skip_selected);
5838 /* Is this window the selected window on its frame? */
5839 selected_in_its_frame = (w == XWINDOW(FRAME_SELECTED_WINDOW(f)));
5841 selected_in_its_frame &&
5842 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5843 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d
5844 && XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5845 if (skip_selected && selected_in_its_frame)
5848 /* It is possible that the window is not fully initialized yet. */
5849 if (NILP(w->buffer))
5852 if (MINI_WINDOW_P(w) && echo_area_active(f)) {
5853 w->buffer = the_buffer = Vecho_area_buffer;
5857 b = XBUFFER(w->buffer);
5860 old_pointm = selected_globally ? BUF_PT(b)
5861 : marker_position(w->pointm[CURRENT_DISP]);
5864 if (selected_globally) {
5867 pointm = marker_position(w->pointm[CURRENT_DISP]);
5869 if (pointm < BUF_BEGV(b))
5870 pointm = BUF_BEGV(b);
5871 else if (pointm > BUF_ZV(b))
5875 Fset_marker(w->pointm[DESIRED_DISP], make_int(pointm), the_buffer);
5877 /* If the buffer has changed we have to invalidate all of our face
5879 if ((!echo_active && b != window_display_buffer(w))
5880 || !Dynarr_length(w->face_cachels)
5881 || f->faces_changed)
5882 reset_face_cachels(w);
5884 mark_face_cachels_as_not_updated(w);
5886 /* Ditto the glyph cache elements, although we do *not* invalidate
5887 the cache purely because glyphs have changed - this is now
5888 handled by the dirty flag. */
5889 if ((!echo_active && b != window_display_buffer(w))
5890 || !Dynarr_length(w->glyph_cachels) || f->faces_changed)
5891 reset_glyph_cachels(w);
5893 mark_glyph_cachels_as_not_updated(w);
5895 /* If the marker's buffer is not the window's buffer, then we need
5896 to find a new starting position. */
5897 if (!MINI_WINDOW_P(w)
5898 && !EQ(Fmarker_buffer(w->start[CURRENT_DISP]), w->buffer)) {
5900 regenerate_window_point_center(w, pointm, DESIRED_DISP);
5902 goto regeneration_done;
5906 old_startp = marker_position(w->start[CURRENT_DISP]);
5909 startp = marker_position(w->start[CURRENT_DISP]);
5910 if (startp < BUF_BEGV(b))
5911 startp = BUF_BEGV(b);
5912 else if (startp > BUF_ZV(b))
5915 Fset_marker(w->start[DESIRED_DISP], make_int(startp), the_buffer);
5917 truncation_changed = (find_window_mirror(w)->truncate_win !=
5918 window_truncation_on(w));
5920 /* If w->force_start is set, then some function set w->start and we
5921 should display from there and change point, if necessary, to
5922 ensure that it is visible. */
5923 if (w->force_start || inactive_minibuffer) {
5925 w->last_modified[DESIRED_DISP] = Qzero;
5926 w->last_facechange[DESIRED_DISP] = Qzero;
5928 regenerate_window(w, startp, pointm, DESIRED_DISP);
5930 if (!point_visible(w, pointm, DESIRED_DISP)
5931 && !inactive_minibuffer) {
5932 pointm = point_at_center(w, DESIRED_DISP, 0, 0);
5934 if (selected_globally)
5935 BUF_SET_PT(b, pointm);
5937 Fset_marker(w->pointm[DESIRED_DISP], make_int(pointm),
5940 /* #### BUFU amounts of overkill just to get the cursor
5941 location marked properly. FIX ME FIX ME FIX ME */
5942 regenerate_window(w, startp, pointm, DESIRED_DISP);
5945 goto regeneration_done;
5948 /* If nothing has changed since the last redisplay, then we just
5949 need to make sure that point is still visible. */
5950 if (XINT(w->last_modified[CURRENT_DISP]) >= BUF_MODIFF(b)
5951 && XINT(w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE(b)
5953 /* This check is to make sure we restore the minibuffer after a
5954 temporary change to the echo area. */
5955 && !(MINI_WINDOW_P(w) && f->buffers_changed)
5956 && !f->frame_changed && !truncation_changed
5957 /* check whether start is really at the beginning of a line GE */
5958 && (!w->start_at_line_beg || beginning_of_line_p(b, startp))
5960 /* Check if the cursor has actually moved. */
5961 if (EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5962 && pointm == marker_position(w->last_point[CURRENT_DISP])
5963 && selected_globally
5964 && !w->windows_changed
5966 && !f->extents_changed
5967 && !f->faces_changed
5968 && !f->glyphs_changed && !f->subwindows_changed
5969 /* && !f->subwindows_state_changed */
5970 && !f->point_changed && !f->windows_structure_changed) {
5971 /* If not, we're done. */
5972 if (f->modeline_changed)
5973 regenerate_modeline(w);
5976 goto regeneration_done;
5978 /* If the new point is visible in the redisplay structures,
5979 then let the output update routines handle it, otherwise
5980 do things the hard way. */
5981 if (!w->windows_changed
5983 && !f->extents_changed
5984 && !f->faces_changed
5985 && !f->glyphs_changed && !f->subwindows_changed
5986 /* && !f->subwindows_state_changed */
5987 && !f->windows_structure_changed) {
5988 if (point_visible(w, pointm, CURRENT_DISP)
5989 && w->last_point_x[CURRENT_DISP] != -1
5990 && w->last_point_y[CURRENT_DISP] != -1) {
5991 if (redisplay_move_cursor
5992 (w, pointm, FRAME_TTY_P(f))) {
5993 /* Always regenerate in case it is displaying
5994 the current line or column. */
5995 regenerate_modeline(w);
5998 goto regeneration_done;
6000 } else if (!selected_in_its_frame
6001 && !f->point_changed) {
6002 if (f->modeline_changed)
6003 regenerate_modeline(w);
6006 goto regeneration_done;
6010 /* If we weren't able to take the shortcut method, then use
6011 the brute force method. */
6012 regenerate_window(w, startp, pointm, DESIRED_DISP);
6014 if (point_visible(w, pointm, DESIRED_DISP))
6015 goto regeneration_done;
6019 /* Check if the starting point is no longer at the beginning of a
6020 line, in which case find a new starting point. We also recenter
6021 if our start position is equal to point-max. Otherwise we'll end
6022 up with a blank window. */
6023 else if (((w->start_at_line_beg || MINI_WINDOW_P(w))
6024 && !(startp == BUF_BEGV(b)
6025 || BUF_FETCH_CHAR(b, startp - 1) == '\n'))
6026 || (pointm == startp &&
6027 EQ(Fmarker_buffer(w->last_start[CURRENT_DISP]), w->buffer)
6028 && startp < marker_position(w->last_start[CURRENT_DISP]))
6029 || (startp == BUF_ZV(b))) {
6031 regenerate_window_point_center(w, pointm, DESIRED_DISP);
6033 goto regeneration_done;
6035 /* See if we can update the data structures locally based on
6036 knowledge of what changed in the buffer. */
6037 else if (!w->windows_changed
6039 && !f->faces_changed
6040 && !f->glyphs_changed && !f->subwindows_changed
6041 /* && !f->subwindows_state_changed */
6042 && !f->windows_structure_changed
6043 && !f->frame_changed
6044 && !truncation_changed
6046 && regenerate_window_incrementally(w, startp, pointm)) {
6047 if (f->modeline_changed
6048 || XINT(w->last_modified[CURRENT_DISP]) < BUF_MODIFF(b)
6049 || XINT(w->last_facechange[CURRENT_DISP]) <
6051 regenerate_modeline(w);
6054 goto regeneration_done;
6056 /* #### This is where a check for structure based scrolling would go. */
6057 /* If all else fails, try just regenerating and see what happens. */
6059 regenerate_window(w, startp, pointm, DESIRED_DISP);
6061 if (point_visible(w, pointm, DESIRED_DISP))
6062 goto regeneration_done;
6065 /* We still haven't gotten the window regenerated with point
6066 visible. Next we try scrolling a little and see if point comes
6067 back onto the screen. */
6068 if (scroll_step > 0) {
6069 int scrolled = scroll_conservatively;
6070 for (; scrolled >= 0; scrolled -= scroll_step) {
6071 startp = vmotion(w, startp,
6073 startp) ? -scroll_step : scroll_step,
6075 regenerate_window(w, startp, pointm, DESIRED_DISP);
6077 if (point_visible(w, pointm, DESIRED_DISP))
6078 goto regeneration_done;
6082 /* We still haven't managed to get the screen drawn with point on
6083 the screen, so just center it and be done with it. */
6084 startp = regenerate_window_point_center(w, pointm, DESIRED_DISP);
6088 /* If the window's frame is changed then reset the current display
6089 lines in order to force a full repaint. */
6090 if (f->frame_changed) {
6091 display_line_dynarr *cla =
6092 window_display_lines(w, CURRENT_DISP);
6097 /* Must do this before calling redisplay_output_window because it
6098 sets some markers on the window. */
6100 w->buffer = old_buffer;
6101 Fset_marker(w->pointm[DESIRED_DISP], make_int(old_pointm),
6103 Fset_marker(w->start[DESIRED_DISP], make_int(old_startp),
6107 /* These also have to be set before calling redisplay_output_window
6108 since it sets the CURRENT_DISP values based on them. */
6109 w->last_modified[DESIRED_DISP] = make_int(BUF_MODIFF(b));
6110 w->last_facechange[DESIRED_DISP] = make_int(BUF_FACECHANGE(b));
6111 Fset_marker(w->last_start[DESIRED_DISP], make_int(startp), w->buffer);
6112 Fset_marker(w->last_point[DESIRED_DISP], make_int(pointm), w->buffer);
6115 Bufpos start = marker_position(w->start[DESIRED_DISP]);
6116 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1 ? BUF_ZV(b)
6117 : BUF_Z(b) - w->window_end_pos[DESIRED_DISP] - 1);
6118 /* Don't pollute the cache if not sure if we are correct */
6119 if (w->start_at_line_beg)
6120 update_line_start_cache(w, start, end, pointm, 1);
6121 redisplay_output_window(w);
6123 * If we just displayed the echo area, the line start cache is
6124 * no longer valid, because the minibuffer window is associated
6125 * with the window now.
6128 w->line_cache_last_updated = make_int(-1);
6131 /* #### This should be dependent on face changes and will need to be
6132 somewhere else once tty updates occur on a per-frame basis. */
6133 mark_face_cachels_as_clean(w);
6135 /* The glyph cachels only get dirty if someone changed something.
6136 Since redisplay has now effectively ended we can reset the dirty
6137 flag since everything must be up-to-date. */
6139 mark_glyph_cachels_as_clean(w);
6141 w->windows_changed = 0;
6144 /* Call buffer_reset_changes for all buffers present in any window
6145 currently visible in all frames on all devices. #### There has to
6146 be a better way to do this. */
6148 static int reset_buffer_changes_mapfun(struct window *w, void *ignored_closure)
6150 buffer_reset_changes(XBUFFER(w->buffer));
6154 static void reset_buffer_changes(void)
6156 Lisp_Object frmcons, devcons, concons;
6158 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
6159 struct frame *f = XFRAME(XCAR(frmcons));
6161 if (FRAME_REPAINT_P(f))
6162 map_windows(f, reset_buffer_changes_mapfun, 0);
6166 /* Ensure that all windows underneath the given window in the window
6167 hierarchy are correctly displayed. */
6169 static void redisplay_windows(Lisp_Object window, int skip_selected)
6171 for (; !NILP(window); window = XWINDOW(window)->next) {
6172 redisplay_window(window, skip_selected);
6176 static int call_redisplay_end_triggers(struct window *w, void *closure)
6178 Bufpos lrpos = w->last_redisplay_pos;
6179 w->last_redisplay_pos = 0;
6180 if (!NILP(w->buffer)
6181 && !NILP(w->redisplay_end_trigger)
6185 if (MARKERP(w->redisplay_end_trigger)
6186 && XMARKER(w->redisplay_end_trigger)->buffer != 0)
6187 pos = marker_position(w->redisplay_end_trigger);
6188 else if (INTP(w->redisplay_end_trigger))
6189 pos = XINT(w->redisplay_end_trigger);
6191 w->redisplay_end_trigger = Qnil;
6197 XSETWINDOW(window, w);
6198 va_run_hook_with_args_in_buffer(XBUFFER(w->buffer),
6199 Qredisplay_end_trigger_functions,
6202 redisplay_end_trigger);
6203 w->redisplay_end_trigger = Qnil;
6210 /* Ensure that all windows on the given frame are correctly displayed. */
6212 int redisplay_frame(struct frame *f, int preemption_check)
6214 struct device *d = XDEVICE(f->device);
6216 if (preemption_check
6217 && !DEVICE_IMPL_FLAG(d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) {
6218 /* The preemption check itself takes a lot of time,
6219 so normally don't do it here. We do it if called
6220 from Lisp, though (`redisplay-frame'). */
6223 REDISPLAY_PREEMPTION_CHECK;
6228 if (!internal_equal(f->old_buffer_alist, f->buffer_alist, 0)) {
6231 f->old_buffer_alist = Freplace_list(f->old_buffer_alist,
6233 XSETFRAME(frame, f);
6234 va_run_hook_with_args(Qbuffer_list_changed_hook, 1, frame);
6237 /* Before we put a hold on frame size changes, attempt to process
6238 any which are already pending. */
6239 if (f->size_change_pending)
6240 change_frame_size(f, f->new_height, f->new_width, 0);
6242 /* If frame size might need to be changed, due to changed size
6243 of toolbars, scrollbars etc, change it now */
6244 if (f->size_slipped) {
6245 adjust_frame_size(f);
6246 assert(!f->size_slipped);
6249 /* The menubar, toolbar, and icon updates must be done before
6250 hold_frame_size_changes is called and we are officially
6251 'in_display'. They may eval lisp code which may call Fsignal.
6252 If in_display is set Fsignal will abort. */
6254 #ifdef HAVE_MENUBARS
6255 /* Update the menubar. It is done first since it could change
6256 the menubar's visibility. This way we avoid having flashing
6257 caused by an Expose event generated by the visibility change
6259 update_frame_menubars(f);
6260 #endif /* HAVE_MENUBARS */
6261 #ifdef HAVE_TOOLBARS
6262 /* Update the toolbars geometry. We don't update the toolbars
6263 themselves at this point since the space they are trying to
6264 occupy may currently by occupied by gutter elements. Instead we
6265 update the geometry, then update the gutter geometry, then update
6266 the gutters - which will cause mapped windows to be repositioned
6267 - and finally update the toolbars. */
6268 update_frame_toolbars_geometry(f);
6269 #endif /* HAVE_TOOLBARS */
6270 /* Gutter update proper has to be done inside display when no frame
6271 size changes can occur, thus we separately update the gutter
6272 geometry here if it needs it. */
6273 update_frame_gutter_geometry(f);
6275 /* If we clear the frame we have to force its contents to be redrawn. */
6277 f->frame_changed = 1;
6279 /* Invalidate the subwindow caches. We use subwindows_changed here
6280 to cause subwindows to get instantiated. This is because
6281 subwindows_state_changed is less strict - dealing with things
6282 like the clicked state of button. We have to do this before
6283 redisplaying the gutters as subwindows get unmapped in the
6285 if (f->frame_changed)
6286 reset_frame_subwindow_instance_cache(f);
6288 if (f->frame_changed || f->subwindows_changed) {
6289 /* we have to do this so the gutter gets regenerated. */
6290 reset_gutter_display_lines(f);
6293 hold_frame_size_changes();
6295 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6296 /* Within this section, we are defenseless and assume that the
6297 following cannot happen:
6299 1) garbage collection
6300 2) Lisp code evaluation
6301 3) frame size changes
6303 We ensure (3) by calling hold_frame_size_changes(), which
6304 will cause any pending frame size changes to get put on hold
6305 till after the end of the critical section. (1) follows
6306 automatically if (2) is met. #### Unfortunately, there are
6307 some places where Lisp code can be called within this section.
6308 We need to remove them.
6310 If Fsignal() is called during this critical section, we
6313 If garbage collection is called during this critical section,
6314 we simply return. #### We should abort instead.
6316 #### If a frame-size change does occur we should probably
6317 actually be preempting redisplay. */
6319 MAYBE_DEVMETH(d, frame_output_begin, (f));
6321 /* Erase the frame before outputting its contents. */
6323 MAYBE_DEVMETH(d, clear_frame, (f));
6326 /* We can now update the gutters, safe in the knowledge that our
6327 efforts won't get undone. */
6329 /* This can call lisp, but redisplay is protected by binding
6330 inhibit_quit. More importantly the code involving display lines
6331 *assumes* that GC will not happen and so does not GCPRO
6332 anything. Since we use this code the whole time with the gutters
6333 we cannot allow GC to happen when manipulating the gutters. */
6334 update_frame_gutters(f);
6336 /* Do the selected window first. */
6337 redisplay_window(FRAME_SELECTED_WINDOW(f), 0);
6339 /* Then do the rest. */
6340 redisplay_windows(f->root_window, 1);
6342 MAYBE_DEVMETH(d, frame_output_end, (f));
6344 update_frame_title(f);
6346 #ifdef HAVE_TOOLBARS
6347 /* Finally update the toolbars. It seems its possible to get in a
6348 cycle between updating the gutter and the toolbars. Basically we
6349 want to end up with both being up-to-date and this doesn't seem
6350 possible in a single pass. */
6351 update_frame_toolbars(f);
6352 #endif /* HAVE_TOOLBARS */
6354 CLASS_RESET_CHANGED_FLAGS(f);
6355 f->window_face_cache_reset = 0;
6356 f->echo_area_garbaged = 0;
6359 if (!f->size_change_pending)
6360 f->size_changed = 0;
6362 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6364 /* Allow frame size changes to occur again.
6366 #### what happens if changes to other frames happen? */
6367 unhold_one_frame_size_changes(f);
6369 map_windows(f, call_redisplay_end_triggers, 0);
6373 /* Ensure that all frames on the given device are correctly displayed.
6374 If AUTOMATIC is non-zero, and the device implementation indicates
6375 no automatic redisplay, as printers do, then the device is not
6376 redisplayed. AUTOMATIC is set to zero when called from lisp
6377 functions (redraw-device) and (redisplay-device), and to non-zero
6378 when called from "lazy" redisplay();
6381 static int redisplay_device(struct device *d, int automatic)
6383 Lisp_Object frame, frmcons;
6384 int size_change_failed = 0;
6387 if (automatic && DEVICE_IMPL_FLAG(d, XDEVIMPF_NO_AUTO_REDISPLAY))
6390 if (DEVICE_STREAM_P(d)) /* nothing to do */
6393 /* It is possible that redisplay has been called before the
6394 device is fully initialized, or that the console implementation
6395 allows frameless devices. If so then continue with the next
6397 if (NILP(DEVICE_SELECTED_FRAME(d)))
6400 if (!DEVICE_IMPL_FLAG(d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) {
6402 REDISPLAY_PREEMPTION_CHECK;
6407 /* Always do the selected frame first. */
6408 frame = DEVICE_SELECTED_FRAME(d);
6412 if (f->icon_changed || f->windows_changed)
6413 update_frame_icon(f);
6415 if (FRAME_REPAINT_P(f)) {
6416 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) {
6417 int preempted = redisplay_frame(f, 0);
6422 /* If the frame redisplay did not get preempted, then this flag
6423 should have gotten set to 0. It might be possible for that
6424 not to happen if a size change event were to occur at an odd
6425 time. To make sure we don't miss anything we simply don't
6426 reset the top level flags until the condition ends up being
6427 in the right state. */
6428 if (f->size_changed)
6429 size_change_failed = 1;
6432 DEVICE_FRAME_LOOP(frmcons, d) {
6433 f = XFRAME(XCAR(frmcons));
6435 if (f == XFRAME(DEVICE_SELECTED_FRAME(d)))
6438 if (f->icon_changed || f->windows_changed)
6439 update_frame_icon(f);
6441 if (FRAME_REPAINT_P(f)) {
6442 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) {
6443 int preempted = redisplay_frame(f, 0);
6448 if (f->size_change_pending)
6449 size_change_failed = 1;
6453 /* If we get here then we redisplayed all of our frames without
6454 getting preempted so mark ourselves as clean. */
6455 CLASS_RESET_CHANGED_FLAGS(d);
6457 if (!size_change_failed)
6458 d->size_changed = 0;
6463 static Lisp_Object restore_profiling_redisplay_flag(Lisp_Object val)
6465 profiling_redisplay_flag = XINT(val);
6469 /* Ensure that all windows on all frames on all devices are displaying
6470 the current contents of their respective buffers. */
6472 static void redisplay_without_hooks(void)
6474 Lisp_Object devcons, concons;
6475 int size_change_failed = 0;
6476 int count = specpdl_depth();
6478 if (profiling_active) {
6479 record_unwind_protect(restore_profiling_redisplay_flag,
6480 make_int(profiling_redisplay_flag));
6481 profiling_redisplay_flag = 1;
6484 if (asynch_device_change_pending)
6485 handle_asynch_device_change();
6487 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6488 !disable_preemption && preemption_count < max_preempts)
6491 DEVICE_LOOP_NO_BREAK(devcons, concons) {
6492 struct device *d = XDEVICE(XCAR(devcons));
6495 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(d)) {
6496 preempted = redisplay_device(d, 1);
6500 RESET_CHANGED_SET_FLAGS;
6504 /* See comment in redisplay_device. */
6505 if (d->size_changed)
6506 size_change_failed = 1;
6509 preemption_count = 0;
6511 /* Mark redisplay as accurate */
6512 GLOBAL_RESET_CHANGED_FLAGS;
6513 RESET_CHANGED_SET_FLAGS;
6515 if (faces_changed) {
6516 mark_all_faces_as_clean();
6520 if (!size_change_failed)
6523 reset_buffer_changes();
6526 unbind_to(count, Qnil);
6529 void redisplay(void)
6531 if (last_display_warning_tick != display_warning_tick &&
6532 !inhibit_warning_display) {
6533 /* If an error occurs during this function, oh well.
6534 If we report another warning, we could get stuck in an
6535 infinite loop reporting warnings. */
6536 call0_trapping_errors(0, Qdisplay_warning_buffer);
6537 last_display_warning_tick = display_warning_tick;
6539 /* The run_hook_trapping_errors functions are smart enough not
6540 to do any evalling if the hook function is empty, so there
6541 should not be any significant time loss. All places in the
6542 C code that call redisplay() are prepared to handle GCing,
6543 so we should be OK. */
6544 #ifndef INHIBIT_REDISPLAY_HOOKS
6545 run_hook_trapping_errors("Error in pre-redisplay-hook",
6546 Qpre_redisplay_hook);
6547 #endif /* INHIBIT_REDISPLAY_HOOKS */
6549 redisplay_without_hooks();
6551 #ifndef INHIBIT_REDISPLAY_HOOKS
6552 run_hook_trapping_errors("Error in post-redisplay-hook",
6553 Qpost_redisplay_hook);
6554 #endif /* INHIBIT_REDISPLAY_HOOKS */
6557 static char window_line_number_buf[32];
6559 /* Efficiently determine the window line number, and return a pointer
6560 to its printed representation. Do this regardless of whether
6561 line-number-mode is on. The first line in the buffer is counted as
6562 1. If narrowing is in effect, the lines are counted from the
6563 beginning of the visible portion of the buffer. */
6564 static char *window_line_number(struct window *w, int type)
6566 struct device *d = XDEVICE(XFRAME(w->frame)->device);
6567 struct buffer *b = XBUFFER(w->buffer);
6568 /* Be careful in the order of these tests. The first clause will
6569 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6570 This can occur when the frame title is computed really early */
6572 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6573 (w == XWINDOW(FRAME_SELECTED_WINDOW(device_selected_frame(d)))) &&
6574 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6575 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) ==
6578 : marker_position(w->pointm[type]));
6581 line = buffer_line_number(b, pos, 1);
6583 long_to_string(window_line_number_buf, line + 1);
6585 return window_line_number_buf;
6588 /* Given a character representing an object in a modeline
6589 specification, return a string (stored into the global array
6590 `mode_spec_bufbyte_string') with the information that object
6593 This function is largely unchanged from previous versions of the
6596 Warning! This code is also used for frame titles and can be called
6597 very early in the device/frame update process! JV
6600 static void decode_mode_spec(struct window *w, Emchar spec, int type)
6602 Lisp_Object obj = Qnil;
6603 const char *str = NULL;
6604 struct buffer *b = XBUFFER(w->buffer);
6606 Dynarr_reset(mode_spec_bufbyte_string);
6609 /* print buffer name */
6614 /* print visited file name */
6619 /* print the current column */
6621 Lisp_Object tmp = Fselected_window(Qnil);
6622 Bufpos pt = (w == XWINDOW(tmp))
6624 : marker_position(w->pointm[type]);
6626 column_at_point(b, pt,
6627 1) + !!column_number_start_at_one;
6628 char buf[sizeof(long)*3+1];
6630 long_to_string(buf, col);
6632 Dynarr_add_many(mode_spec_bufbyte_string,
6633 (const Bufbyte *)buf, strlen(buf));
6635 goto decode_mode_spec_done;
6637 /* print the file coding system */
6640 Lisp_Object codesys = b->buffer_file_coding_system;
6641 /* Be very careful here not to get an error. */
6642 if (NILP(codesys) || SYMBOLP(codesys)
6643 || CODING_SYSTEMP(codesys)) {
6644 codesys = Ffind_coding_system(codesys);
6645 if (CODING_SYSTEMP(codesys))
6646 obj = XCODING_SYSTEM_MNEMONIC(codesys);
6648 #endif /* FILE_CODING */
6652 /* print the current line number */
6654 str = window_line_number(w, type);
6657 /* print value of mode-name (obsolete) */
6662 /* print hyphen and frame number, if != 1 */
6665 struct frame *f = XFRAME(w->frame);
6666 if (FRAME_TTY_P(f) && f->order_count > 1
6667 && f->order_count <= 99999999) {
6668 /* Naughty, naughty */
6669 const size_t order_strmax = sizeof(f->order_count)*3+2;
6670 char *writable_str = alloca_array(char, order_strmax);
6671 int n = snprintf(writable_str, order_strmax, "-%d", f->order_count);
6672 assert(n>=0 && n < order_strmax);
6675 #endif /* HAVE_TTY */
6679 /* print Narrow if appropriate */
6681 if (BUF_BEGV(b) > BUF_BEG(b)
6682 || BUF_ZV(b) < BUF_Z(b))
6686 /* print %, * or hyphen, if buffer is read-only, modified or
6689 str = (!NILP(b->read_only)
6690 ? "%" : ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6694 /* print * or hyphen -- XEmacs change to allow a buffer to be
6695 read-only but still indicate whether it is modified. */
6697 str = ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6698 ? "*" : (!NILP(b->read_only)
6702 /* #### defined in 19.29 decode_mode_spec, but not in
6703 modeline-format doc string. */
6704 /* This differs from %* in that it ignores read-only-ness. */
6706 str = ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6710 /* print process status */
6712 obj = Fget_buffer_process(w->buffer);
6714 str = GETTEXT("no process");
6716 obj = Fsymbol_name(Fprocess_status(obj));
6719 /* Print name of selected frame. */
6721 obj = XFRAME(w->frame)->name;
6724 /* indicate TEXT or BINARY */
6726 /* #### NT does not use this any more. Now what? */
6730 /* print percent of buffer above top of window, or Top, Bot or
6733 Bufpos pos = marker_position(w->start[type]);
6735 /* This had better be while the desired lines are being done. */
6736 if (w->window_end_pos[type] <= BUF_Z(b) - BUF_ZV(b)) {
6737 if (pos <= BUF_BEGV(b))
6741 } else if (pos <= BUF_BEGV(b)) {
6744 /* This hard limit is ok since the string it will hold
6745 has a fixed maximum length of 3. But just to be
6747 char buf[sizeof(long)*3+4];
6749 Charcount chars = pos - BUF_BEGV(b);
6750 Charcount total = BUF_ZV(b) - BUF_BEGV(b);
6752 /* Avoid overflow on big buffers */
6753 int percent = total > LONG_MAX / 200 ?
6754 (chars + total / 200) / (total / 100) :
6755 (chars * 100 + total / 2) / total;
6757 /* We can't normally display a 3-digit number, so get us
6758 a 2-digit number that is close. */
6762 n = snprintf(buf, sizeof(buf), "%d%%", percent);
6763 assert(n>=0 && n < sizeof(buf));
6764 Dynarr_add_many(mode_spec_bufbyte_string,
6765 (Bufbyte *) buf, strlen(buf));
6767 goto decode_mode_spec_done;
6772 /* print percent of buffer above bottom of window, perhaps plus
6773 Top, or print Bottom or All */
6775 Bufpos toppos = marker_position(w->start[type]);
6776 Bufpos botpos = BUF_Z(b) - w->window_end_pos[type];
6778 /* botpos is only accurate as of the last redisplay, so we can
6779 only treat it as a hint. In particular, after erase-buffer,
6780 botpos may be negative. */
6781 if (botpos < toppos)
6784 if (botpos >= BUF_ZV(b)) {
6785 if (toppos <= BUF_BEGV(b))
6790 /* This hard limit is ok since the string it will hold
6791 has a fixed maximum length of around 6. But just to
6793 char buf[sizeof(long)*3+6];
6795 Charcount chars = botpos - BUF_BEGV(b);
6796 Charcount total = BUF_ZV(b) - BUF_BEGV(b);
6798 /* Avoid overflow on big buffers */
6799 int percent = total > LONG_MAX / 200 ?
6800 (chars + total / 200) / (total / 100) :
6801 (chars * 100 + total / 2) / max(total, 1);
6803 /* We can't normally display a 3-digit number, so get us
6804 a 2-digit number that is close. */
6808 if (toppos <= BUF_BEGV(b))
6809 n = snprintf(buf, sizeof(buf), "Top%d%%", percent);
6811 n = snprintf(buf, sizeof(buf), "%d%%", percent);
6812 assert(n>=0 && n < sizeof(buf));
6813 Dynarr_add_many(mode_spec_bufbyte_string,
6814 (Bufbyte *) buf, strlen(buf));
6816 goto decode_mode_spec_done;
6826 /* print one [ for each recursive editing level. */
6830 if (command_loop_level > 5) {
6835 for (i = 0; i < command_loop_level; i++)
6836 Dynarr_add(mode_spec_bufbyte_string, '[');
6838 goto decode_mode_spec_done;
6841 /* print one ] for each recursive editing level. */
6845 if (command_loop_level > 5) {
6850 for (i = 0; i < command_loop_level; i++)
6851 Dynarr_add(mode_spec_bufbyte_string, ']');
6853 goto decode_mode_spec_done;
6856 /* print infinitely many dashes -- handle at top level now */
6865 Dynarr_add_many(mode_spec_bufbyte_string,
6866 XSTRING_DATA(obj), XSTRING_LENGTH(obj));
6868 Dynarr_add_many(mode_spec_bufbyte_string,
6869 (const Bufbyte*)str, strlen(str));
6872 decode_mode_spec_done:
6873 Dynarr_add(mode_spec_bufbyte_string, '\0');
6877 /* Given a display line, free all of its data structures. */
6879 static void free_display_line(struct display_line *dl)
6883 if (dl->display_blocks) {
6884 for (block = 0; block < Dynarr_largest(dl->display_blocks);
6886 struct display_block *db =
6887 Dynarr_atp(dl->display_blocks, block);
6889 Dynarr_free(db->runes);
6892 Dynarr_free(dl->display_blocks);
6893 dl->display_blocks = NULL;
6896 if (dl->left_glyphs) {
6897 Dynarr_free(dl->left_glyphs);
6898 dl->left_glyphs = NULL;
6901 if (dl->right_glyphs) {
6902 Dynarr_free(dl->right_glyphs);
6903 dl->right_glyphs = NULL;
6907 /* Given an array of display lines, free them and all data structures
6908 contained within them. */
6910 void free_display_lines(display_line_dynarr * dla)
6914 for (line = 0; line < Dynarr_largest(dla); line++) {
6915 free_display_line(Dynarr_atp(dla, line));
6921 /* Call internal free routine for each set of display lines. */
6923 void free_display_structs(struct window_mirror *mir)
6925 if (mir->current_display_lines) {
6926 free_display_lines(mir->current_display_lines);
6927 mir->current_display_lines = 0;
6930 if (mir->desired_display_lines) {
6931 free_display_lines(mir->desired_display_lines);
6932 mir->desired_display_lines = 0;
6936 static void mark_glyph_block_dynarr(glyph_block_dynarr * gba)
6939 glyph_block *gb = Dynarr_atp(gba, 0);
6940 glyph_block *gb_last = Dynarr_atp(gba, Dynarr_length(gba));
6942 for (; gb < gb_last; gb++) {
6943 if (!NILP(gb->glyph))
6944 mark_object(gb->glyph);
6945 if (!NILP(gb->extent))
6946 mark_object(gb->extent);
6951 /* See the comment in image_instantiate_cache_result as to why marking
6952 the glyph will also mark the image_instance. */
6953 void mark_redisplay_structs(display_line_dynarr * dla)
6955 display_line *dl = Dynarr_atp(dla, 0);
6956 display_line *dl_last = Dynarr_atp(dla, Dynarr_length(dla));
6958 for (; dl < dl_last; dl++) {
6959 display_block_dynarr *dba = dl->display_blocks;
6960 display_block *db = Dynarr_atp(dba, 0);
6961 display_block *db_last = Dynarr_atp(dba, Dynarr_length(dba));
6963 for (; db < db_last; db++) {
6964 rune_dynarr *ra = db->runes;
6965 rune *r = Dynarr_atp(ra, 0);
6966 rune *r_last = Dynarr_atp(ra, Dynarr_length(ra));
6968 for (; r < r_last; r++) {
6969 if (r->type == RUNE_DGLYPH) {
6970 if (!NILP(r->object.dglyph.glyph))
6971 mark_object(r->object.dglyph.
6973 if (!NILP(r->object.dglyph.extent))
6974 mark_object(r->object.dglyph.
6980 mark_glyph_block_dynarr(dl->left_glyphs);
6981 mark_glyph_block_dynarr(dl->right_glyphs);
6985 static void mark_window_mirror(struct window_mirror *mir)
6987 mark_redisplay_structs(mir->current_display_lines);
6988 mark_redisplay_structs(mir->desired_display_lines);
6991 mark_window_mirror(mir->next);
6994 mark_window_mirror(mir->hchild);
6995 else if (mir->vchild)
6996 mark_window_mirror(mir->vchild);
6999 void mark_redisplay(void)
7001 Lisp_Object frmcons, devcons, concons;
7003 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
7004 struct frame *f = XFRAME(XCAR(frmcons));
7005 mark_window_mirror(f->root_mirror);
7010 /*****************************************************************************
7011 Line Start Cache Description and Rationale
7013 The traditional scrolling code in Emacs breaks in a variable height world.
7014 It depends on the key assumption that the number of lines that can be
7015 displayed at any given time is fixed. This led to a complete separation
7016 of the scrolling code from the redisplay code. In order to fully support
7017 variable height lines, the scrolling code must actually be tightly
7018 integrated with redisplay. Only redisplay can determine how many lines
7019 will be displayed on a screen for any given starting point.
7021 What is ideally wanted is a complete list of the starting buffer position
7022 for every possible display line of a buffer along with the height of that
7023 display line. Maintaining such a full list would be very expensive. We
7024 settle for having it include information for all areas which we happen to
7025 generate anyhow (i.e. the region currently being displayed) and for those
7026 areas we need to work with.
7028 In order to ensure that the cache accurately represents what redisplay
7029 would actually show, it is necessary to invalidate it in many situations.
7030 If the buffer changes, the starting positions may no longer be correct.
7031 If a face or an extent has changed then the line heights may have altered.
7032 These events happen frequently enough that the cache can end up being
7033 constantly disabled. With this potentially constant invalidation when is
7034 the cache ever useful?
7036 Even if the cache is invalidated before every single usage, it is
7037 necessary. Scrolling often requires knowledge about display lines which
7038 are actually above or below the visible region. The cache provides a
7039 convenient light-weight method of storing this information for multiple
7040 display regions. This knowledge is necessary for the scrolling code to
7041 always obey the First Golden Rule of Redisplay.
7043 If the cache already contains all of the information that the scrolling
7044 routines happen to need so that it doesn't have to go generate it, then we
7045 are able to obey the Third Golden Rule of Redisplay. The first thing we
7046 do to help out the cache is to always add the displayed region. This
7047 region had to be generated anyway, so the cache ends up getting the
7048 information basically for free. In those cases where a user is simply
7049 scrolling around viewing a buffer there is a high probability that this is
7050 sufficient to always provide the needed information. The second thing we
7051 can do is be smart about invalidating the cache.
7053 TODO -- Be smart about invalidating the cache. Potential places:
7055 + Insertions at end-of-line which don't cause line-wraps do not alter the
7056 starting positions of any display lines. These types of buffer
7057 modifications should not invalidate the cache. This is actually a large
7058 optimization for redisplay speed as well.
7060 + Buffer modifications frequently only affect the display of lines at and
7061 below where they occur. In these situations we should only invalidate
7062 the part of the cache starting at where the modification occurs.
7064 In case you're wondering, the Second Golden Rule of Redisplay is not
7066 ****************************************************************************/
7068 /* This will get used quite a bit so we don't want to be constantly
7069 allocating and freeing it. */
7070 static line_start_cache_dynarr *internal_cache;
7072 /* Makes internal_cache represent the TYPE display structs and only
7073 the TYPE display structs. */
7075 static void update_internal_cache_list(struct window *w, int type)
7078 display_line_dynarr *dla = window_display_lines(w, type);
7080 Dynarr_reset(internal_cache);
7081 for (line = 0; line < Dynarr_length(dla); line++) {
7082 struct display_line *dl = Dynarr_atp(dla, line);
7087 struct line_start_cache lsc;
7089 lsc.start = dl->bufpos;
7090 lsc.end = dl->end_bufpos;
7091 lsc.height = dl->ascent + dl->descent;
7093 Dynarr_add(internal_cache, lsc);
7098 /* Reset the line cache if necessary. This should be run at the
7099 beginning of any function which access the cache. */
7101 static void validate_line_start_cache(struct window *w)
7103 struct buffer *b = XBUFFER(w->buffer);
7104 struct frame *f = XFRAME(w->frame);
7106 if (!w->line_cache_validation_override) {
7107 /* f->extents_changed used to be in here because extent face and
7108 size changes can cause text shifting. However, the extent
7109 covering the region is constantly having its face set and
7110 priority altered by the mouse code. This means that the line
7111 start cache is constantly being invalidated. This is bad
7112 since the mouse code also triggers heavy usage of the cache.
7113 Since it is an unlikely that f->extents being changed
7114 indicates that the cache really needs to be updated and if it
7115 does redisplay will catch it pretty quickly we no longer
7116 invalidate the cache if it is set. This greatly speeds up
7117 dragging out regions with the mouse. */
7118 if (XINT(w->line_cache_last_updated) < BUF_MODIFF(b)
7119 || f->faces_changed || f->clip_changed) {
7120 Dynarr_reset(w->line_start_cache);
7125 /* Return the very first buffer position contained in the given
7126 window's cache, or -1 if the cache is empty. Assumes that the
7129 static Bufpos line_start_cache_start(struct window *w)
7131 line_start_cache_dynarr *cache = w->line_start_cache;
7133 if (!Dynarr_length(cache))
7136 return Dynarr_atp(cache, 0)->start;
7139 /* Return the very last buffer position contained in the given
7140 window's cache, or -1 if the cache is empty. Assumes that the
7143 static Bufpos line_start_cache_end(struct window *w)
7145 line_start_cache_dynarr *cache = w->line_start_cache;
7147 if (!Dynarr_length(cache))
7150 return Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7153 /* Return the index of the line POINT is contained within in window
7154 W's line start cache. It will enlarge the cache or move the cache
7155 window in order to have POINT be present in the cache. MIN_PAST is
7156 a guarantee of the number of entries in the cache present on either
7157 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7158 then it will be treated as 0, but the cache window will not be
7159 allowed to shift. Returns -1 if POINT cannot be found in the cache
7162 int point_in_line_start_cache(struct window *w, Bufpos point, int min_past)
7164 struct buffer *b = XBUFFER(w->buffer);
7165 line_start_cache_dynarr *cache = w->line_start_cache;
7166 unsigned int top, bottom;
7169 validate_line_start_cache(w);
7170 w->line_cache_validation_override++;
7172 /* Let functions pass in negative values, but we still treat -1
7174 /* #### bogosity alert */
7175 if (min_past < 0 && min_past != -1)
7176 min_past = -min_past;
7178 if (!Dynarr_length(cache) || line_start_cache_start(w) > point
7179 || line_start_cache_end(w) < point) {
7181 int win_char_height = window_char_height(w, 1);
7183 /* Occasionally we get here with a 0 height
7184 window. find_next_newline_no_quit will abort if we pass it a
7185 count of 0 so handle that case. */
7186 if (!win_char_height)
7187 win_char_height = 1;
7189 if (!Dynarr_length(cache)) {
7190 Bufpos from = find_next_newline_no_quit(b, point, -1);
7192 find_next_newline_no_quit(b, from, win_char_height);
7194 update_line_start_cache(w, from, to, point, 0);
7196 if (!Dynarr_length(cache)) {
7197 w->line_cache_validation_override--;
7202 assert(Dynarr_length(cache));
7205 while (line_start_cache_start(w) > point
7206 && (loop < cache_adjustment || min_past == -1)) {
7209 from = line_start_cache_start(w);
7210 if (from <= BUF_BEGV(b))
7214 find_next_newline_no_quit(b, from,
7216 to = line_start_cache_end(w);
7218 update_line_start_cache(w, from, to, point, 0);
7222 if (line_start_cache_start(w) > point) {
7225 from = find_next_newline_no_quit(b, point, -1);
7226 if (from >= BUF_ZV(b)) {
7227 to = find_next_newline_no_quit(b, from,
7232 to = find_next_newline_no_quit(b, from,
7235 update_line_start_cache(w, from, to, point, 0);
7239 while (line_start_cache_end(w) < point
7240 && (loop < cache_adjustment || min_past == -1)) {
7243 to = line_start_cache_end(w);
7244 if (to >= BUF_ZV(b))
7247 from = line_start_cache_end(w);
7248 to = find_next_newline_no_quit(b, from,
7251 update_line_start_cache(w, from, to, point, 0);
7255 if (line_start_cache_end(w) < point) {
7258 from = find_next_newline_no_quit(b, point, -1);
7259 if (from >= BUF_ZV(b)) {
7260 to = find_next_newline_no_quit(b, from,
7265 to = find_next_newline_no_quit(b, from,
7268 update_line_start_cache(w, from, to, point, 0);
7272 assert(Dynarr_length(cache));
7277 /* This could happen if the buffer is narrowed. */
7278 if (line_start_cache_start(w) > point
7279 || line_start_cache_end(w) < point) {
7280 w->line_cache_validation_override--;
7286 top = Dynarr_length(cache) - 1;
7293 pos = (bottom + top + 1) >> 1;
7294 start = Dynarr_atp(cache, pos)->start;
7295 end = Dynarr_atp(cache, pos)->end;
7297 if (point >= start && point <= end) {
7299 && line_start_cache_start(w) > BUF_BEGV(b)) {
7301 find_next_newline_no_quit(b,
7302 line_start_cache_start
7305 Bufpos to = line_start_cache_end(w);
7307 update_line_start_cache(w, from, to, point, 0);
7308 goto find_point_loop;
7309 } else if ((Dynarr_length(cache) - pos - 1) < min_past
7310 && line_start_cache_end(w) < BUF_ZV(b)) {
7311 Bufpos from = line_start_cache_end(w);
7312 Bufpos to = find_next_newline_no_quit(b, from,
7318 update_line_start_cache(w, from, to, point, 0);
7319 goto find_point_loop;
7321 w->line_cache_validation_override--;
7324 } else if (point > end)
7326 else if (point < start)
7331 new_pos = (bottom + top + 1) >> 1;
7332 if (pos == new_pos) {
7333 w->line_cache_validation_override--;
7339 /* Return a boolean indicating if POINT would be visible in window W
7340 if display of the window was to begin at STARTP. */
7342 int point_would_be_visible(struct window *w, Bufpos startp, Bufpos point)
7344 struct buffer *b = XBUFFER(w->buffer);
7345 int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
7346 int bottom = WINDOW_TEXT_HEIGHT(w);
7349 /* If point is before the intended start it obviously can't be visible. */
7353 /* If point or start are not in the accessible buffer range, then
7355 if (startp < BUF_BEGV(b) || startp > BUF_ZV(b)
7356 || point < BUF_BEGV(b) || point > BUF_ZV(b))
7359 validate_line_start_cache(w);
7360 w->line_cache_validation_override++;
7362 start_elt = point_in_line_start_cache(w, startp, 0);
7363 if (start_elt == -1) {
7364 w->line_cache_validation_override--;
7368 assert(line_start_cache_start(w) <= startp
7369 && line_start_cache_end(w) >= startp);
7374 /* Expand the cache if necessary. */
7375 if (start_elt == Dynarr_length(w->line_start_cache)) {
7377 Dynarr_atp(w->line_start_cache,
7378 start_elt - 1)->start;
7380 start_elt = point_in_line_start_cache(w, old_startp,
7384 /* We've already actually processed old_startp, so increment
7388 /* If this happens we didn't add any extra elements. Bummer. */
7389 if (start_elt == Dynarr_length(w->line_start_cache)) {
7390 w->line_cache_validation_override--;
7395 height = Dynarr_atp(w->line_start_cache, start_elt)->height;
7397 if (pixpos + height > bottom) {
7398 if (bottom - pixpos < VERTICAL_CLIP(w, 0)) {
7399 w->line_cache_validation_override--;
7405 if (point <= Dynarr_atp(w->line_start_cache, start_elt)->end) {
7406 w->line_cache_validation_override--;
7414 /* For the given window W, if display starts at STARTP, what will be
7415 the buffer position at the beginning or end of the last line
7416 displayed. The end of the last line is also know as the window end
7419 WARNING: It is possible that redisplay failed to layout any lines for the
7420 windows. Under normal circumstances this is rare. However it seems that it
7421 does occur in the following situation: A mouse event has come in and we
7422 need to compute its location in a window. That code (in
7423 pixel_to_glyph_translation) already can handle 0 as an error return value.
7425 #### With a little work this could probably be reworked as just a
7426 call to start_with_line_at_pixpos. */
7429 start_end_of_last_line(struct window *w, Bufpos startp, int end, int may_error)
7431 struct buffer *b = XBUFFER(w->buffer);
7432 line_start_cache_dynarr *cache = w->line_start_cache;
7434 int bottom = WINDOW_TEXT_HEIGHT(w);
7438 validate_line_start_cache(w);
7439 w->line_cache_validation_override++;
7441 if (startp < BUF_BEGV(b))
7442 startp = BUF_BEGV(b);
7443 else if (startp > BUF_ZV(b))
7447 start_elt = point_in_line_start_cache(w, cur_start, 0);
7448 if (start_elt == -1)
7449 return may_error ? 0 : startp;
7452 int height = Dynarr_atp(cache, start_elt)->height;
7454 cur_start = Dynarr_atp(cache, start_elt)->start;
7456 if (pixpos + height > bottom) {
7457 /* Adjust for any possible clip. */
7458 if (bottom - pixpos < VERTICAL_CLIP(w, 0))
7461 if (start_elt < 0) {
7462 w->line_cache_validation_override--;
7468 w->line_cache_validation_override--;
7470 return Dynarr_atp(cache,
7473 return Dynarr_atp(cache,
7480 if (start_elt == Dynarr_length(cache)) {
7481 Bufpos from = line_start_cache_end(w);
7482 int win_char_height = window_char_height(w, 0);
7483 Bufpos to = find_next_newline_no_quit(b, from,
7488 /* We've hit the end of the bottom so that's what it is. */
7489 if (from >= BUF_ZV(b)) {
7490 w->line_cache_validation_override--;
7494 update_line_start_cache(w, from, to, BUF_PT(b), 0);
7496 /* Updating the cache invalidates any current indexes. */
7498 point_in_line_start_cache(w, cur_start, -1) + 1;
7503 /* For the given window W, if display starts at STARTP, what will be
7504 the buffer position at the beginning of the last line displayed. */
7506 Bufpos start_of_last_line(struct window * w, Bufpos startp)
7508 return start_end_of_last_line(w, startp, 0, 0);
7511 /* For the given window W, if display starts at STARTP, what will be
7512 the buffer position at the end of the last line displayed. This is
7513 also know as the window end position. */
7515 Bufpos end_of_last_line(struct window * w, Bufpos startp)
7517 return start_end_of_last_line(w, startp, 1, 0);
7520 static Bufpos end_of_last_line_may_error(struct window *w, Bufpos startp)
7522 return start_end_of_last_line(w, startp, 1, 1);
7525 /* For window W, what does the starting position have to be so that
7526 the line containing POINT will cover pixel position PIXPOS. */
7528 Bufpos start_with_line_at_pixpos(struct window * w, Bufpos point, int pixpos)
7530 struct buffer *b = XBUFFER(w->buffer);
7532 Bufpos cur_pos, prev_pos = point;
7533 int point_line_height;
7534 int pixheight = pixpos - WINDOW_TEXT_TOP(w);
7536 validate_line_start_cache(w);
7537 w->line_cache_validation_override++;
7539 cur_elt = point_in_line_start_cache(w, point, 0);
7540 /* #### See comment in update_line_start_cache about big minibuffers. */
7542 w->line_cache_validation_override--;
7546 point_line_height = Dynarr_atp(w->line_start_cache, cur_elt)->height;
7549 cur_pos = Dynarr_atp(w->line_start_cache, cur_elt)->start;
7551 pixheight -= Dynarr_atp(w->line_start_cache, cur_elt)->height;
7553 /* Do not take into account the value of vertical_clip here.
7554 That is the responsibility of the calling functions. */
7555 if (pixheight < 0) {
7556 w->line_cache_validation_override--;
7557 if (-pixheight > point_line_height)
7558 /* We can't make the target line cover pixpos, so put it
7559 above pixpos. That way it will at least be visible. */
7566 while (cur_elt < 0) {
7568 int win_char_height;
7570 if (cur_pos <= BUF_BEGV(b)) {
7571 w->line_cache_validation_override--;
7575 win_char_height = window_char_height(w, 0);
7576 if (!win_char_height)
7577 win_char_height = 1;
7580 find_next_newline_no_quit(b, cur_pos,
7582 to = line_start_cache_end(w);
7583 update_line_start_cache(w, from, to, point, 0);
7585 cur_elt = point_in_line_start_cache(w, cur_pos, 2) - 1;
7586 assert(cur_elt >= -1);
7587 /* This used to be cur_elt>=0 under the assumption that if
7588 point is in the top line and not at BUF_BEGV, then
7589 setting the window_start to a newline before the start of
7590 the first line will always cause scrolling.
7592 However in my (jv) opinion this is wrong. That new line
7593 can be hidden in various ways: invisible extents, an
7594 explicit window-start not at a newline character etc.
7595 The existence of those are indeed known to create crashes
7596 on that assert. So we have no option but to continue the
7597 search if we found point at the top of the line_start_cache
7599 cur_pos = Dynarr_atp(w->line_start_cache, 0)->start;
7605 /* For window W, what does the starting position have to be so that
7606 the line containing point is on display line LINE. If LINE is
7607 positive it is considered to be the number of lines from the top of
7608 the window (0 is the top line). If it is negative the number is
7609 considered to be the number of lines from the bottom (-1 is the
7613 start_with_point_on_display_line(struct window *w, Bufpos point, int line)
7615 validate_line_start_cache(w);
7616 w->line_cache_validation_override++;
7619 int cur_elt = point_in_line_start_cache(w, point, line);
7621 if (cur_elt - line < 0)
7622 cur_elt = 0; /* Hit the top */
7626 w->line_cache_validation_override--;
7627 return Dynarr_atp(w->line_start_cache, cur_elt)->start;
7629 /* The calculated value of pixpos is correct for the bottom line
7630 or what we want when line is -1. Therefore we subtract one
7631 because we have already handled one line. */
7632 int new_line = -line - 1;
7633 int cur_elt = point_in_line_start_cache(w, point, new_line);
7634 int pixpos = WINDOW_TEXT_BOTTOM(w);
7635 Bufpos retval, search_point;
7637 /* If scroll_on_clipped_lines is false, the last "visible" line of
7638 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7639 If s_o_c_l is true, then we don't want to count a clipped
7640 line, so back up from the bottom by the height of the line
7641 containing point. */
7642 if (scroll_on_clipped_lines)
7644 Dynarr_atp(w->line_start_cache, cur_elt)->height;
7648 if (cur_elt + new_line >= Dynarr_length(w->line_start_cache)) {
7649 /* Hit the bottom of the buffer. */
7651 (cur_elt + new_line) -
7652 Dynarr_length(w->line_start_cache) + 1;
7656 XSETWINDOW(window, w);
7657 default_face_height_and_width(window, &defheight, 0);
7659 cur_elt = Dynarr_length(w->line_start_cache) - 1;
7661 pixpos -= (adjustment * defheight);
7662 if (pixpos < WINDOW_TEXT_TOP(w))
7663 pixpos = WINDOW_TEXT_TOP(w);
7665 cur_elt = cur_elt + new_line;
7667 search_point = Dynarr_atp(w->line_start_cache, cur_elt)->start;
7669 retval = start_with_line_at_pixpos(w, search_point, pixpos);
7670 w->line_cache_validation_override--;
7675 /* This is used to speed up vertical scrolling by caching the known
7676 buffer starting positions for display lines. This allows the
7677 scrolling routines to avoid costly calls to regenerate_window. If
7678 NO_REGEN is true then it will only add the values in the DESIRED
7679 display structs which are in the given range.
7681 Note also that the FROM/TO values are minimums. It is possible
7682 that this function will actually add information outside of the
7683 lines containing those positions. This can't hurt but it could
7686 #### We currently force the cache to have only 1 contiguous region.
7687 It might help to make the cache a dynarr of caches so that we can
7688 cover more areas. This might, however, turn out to be a lot of
7689 overhead for too little gain. */
7692 update_line_start_cache(struct window *w, Bufpos from, Bufpos to,
7693 Bufpos point, int no_regen)
7695 struct buffer *b = XBUFFER(w->buffer);
7696 line_start_cache_dynarr *cache = w->line_start_cache;
7697 Bufpos low_bound, high_bound;
7699 validate_line_start_cache(w);
7700 w->line_cache_validation_override++;
7702 if (from < BUF_BEGV(b))
7708 w->line_cache_validation_override--;
7712 if (Dynarr_length(cache)) {
7713 low_bound = line_start_cache_start(w);
7714 high_bound = line_start_cache_end(w);
7716 /* Check to see if the desired range is already in the cache. */
7717 if (from >= low_bound && to <= high_bound) {
7718 w->line_cache_validation_override--;
7722 /* Check to make sure that the desired range is adjacent to the
7723 current cache. If not, invalidate the cache. */
7724 if (to < low_bound || from > high_bound) {
7725 Dynarr_reset(cache);
7726 low_bound = high_bound = -1;
7729 low_bound = high_bound = -1;
7732 w->line_cache_last_updated = make_int(BUF_MODIFF(b));
7734 /* This could be integrated into the next two sections, but it is easier
7735 to follow what's going on by having it separate. */
7739 update_internal_cache_list(w, DESIRED_DISP);
7740 if (!Dynarr_length(internal_cache)) {
7741 w->line_cache_validation_override--;
7745 start = Dynarr_atp(internal_cache, 0)->start;
7747 Dynarr_atp(internal_cache,
7748 Dynarr_length(internal_cache) - 1)->end;
7750 /* We aren't allowed to generate additional information to fill in
7751 gaps, so if the DESIRED structs don't overlap the cache, reset the
7753 if (Dynarr_length(cache)) {
7754 if (end < low_bound || start > high_bound)
7755 Dynarr_reset(cache);
7757 /* #### What should really happen if what we are doing is
7758 extending a line (the last line)? */
7759 if (Dynarr_length(cache) == 1
7760 && Dynarr_length(internal_cache) == 1)
7761 Dynarr_reset(cache);
7764 if (!Dynarr_length(cache)) {
7765 Dynarr_add_many(cache, Dynarr_atp(internal_cache, 0),
7766 Dynarr_length(internal_cache));
7767 w->line_cache_validation_override--;
7771 /* An extra check just in case the calling function didn't pass in
7772 the bounds of the DESIRED structs in the first place. */
7773 if (start >= low_bound && end <= high_bound) {
7774 w->line_cache_validation_override--;
7778 /* At this point we know that the internal cache partially overlaps
7780 if (start < low_bound) {
7781 int ic_elt = Dynarr_length(internal_cache) - 1;
7782 while (ic_elt >= 0) {
7783 if (Dynarr_atp(internal_cache, ic_elt)->start <
7790 if (!(ic_elt >= 0)) {
7791 Dynarr_reset(cache);
7792 Dynarr_add_many(cache,
7793 Dynarr_atp(internal_cache, 0),
7794 Dynarr_length(internal_cache));
7795 w->line_cache_validation_override--;
7799 Dynarr_insert_many_at_start(cache,
7800 Dynarr_atp(internal_cache,
7804 if (end > high_bound) {
7807 while (ic_elt < Dynarr_length(internal_cache)) {
7808 if (Dynarr_atp(internal_cache, ic_elt)->start >
7815 if (!(ic_elt < Dynarr_length(internal_cache))) {
7816 Dynarr_reset(cache);
7817 Dynarr_add_many(cache,
7818 Dynarr_atp(internal_cache, 0),
7819 Dynarr_length(internal_cache));
7820 w->line_cache_validation_override--;
7824 Dynarr_add_many(cache,
7825 Dynarr_atp(internal_cache, ic_elt),
7826 Dynarr_length(internal_cache) - ic_elt);
7829 w->line_cache_validation_override--;
7833 if (!Dynarr_length(cache) || from < low_bound) {
7834 Bufpos startp = find_next_newline_no_quit(b, from, -1);
7836 int old_lb = low_bound;
7838 while (startp < old_lb || low_bound == -1) {
7842 regenerate_window(w, startp, point, CMOTION_DISP);
7843 update_internal_cache_list(w, CMOTION_DISP);
7845 /* If this assert is triggered then regenerate_window failed
7846 to layout a single line. This is not possible since we
7847 force at least a single line to be layout for CMOTION_DISP */
7848 assert(Dynarr_length(internal_cache));
7849 assert(startp == Dynarr_atp(internal_cache, 0)->start);
7851 ic_elt = Dynarr_length(internal_cache) - 1;
7852 if (low_bound != -1) {
7853 while (ic_elt >= 0) {
7854 if (Dynarr_atp(internal_cache, ic_elt)->
7861 assert(ic_elt >= 0);
7864 Dynarr_atp(internal_cache, ic_elt)->end + 1;
7867 * Handle invisible text properly:
7868 * If the last line we're inserting has the same end as the
7869 * line before which it will be added, merge the two lines.
7871 if (Dynarr_length(cache) &&
7872 Dynarr_atp(internal_cache, ic_elt)->end ==
7873 Dynarr_atp(cache, marker)->end) {
7874 Dynarr_atp(cache, marker)->start
7875 = Dynarr_atp(internal_cache, ic_elt)->start;
7876 Dynarr_atp(cache, marker)->height
7878 Dynarr_atp(internal_cache, ic_elt)->height;
7882 if (ic_elt >= 0) { /* we still have lines to add.. */
7883 Dynarr_insert_many(cache,
7884 Dynarr_atp(internal_cache,
7887 marker += (ic_elt + 1);
7890 if (startp < low_bound || low_bound == -1)
7892 startp = new_startp;
7893 if (startp > BUF_ZV(b)) {
7894 w->line_cache_validation_override--;
7900 assert(Dynarr_length(cache));
7901 assert(from >= low_bound);
7903 /* Readjust the high_bound to account for any changes made while
7904 correcting the low_bound. */
7905 high_bound = Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7907 if (to > high_bound) {
7909 Dynarr_atp(cache, Dynarr_length(cache) - 1)->end + 1;
7912 regenerate_window(w, startp, point, CMOTION_DISP);
7913 update_internal_cache_list(w, CMOTION_DISP);
7915 /* See comment above about regenerate_window failing. */
7916 assert(Dynarr_length(internal_cache));
7918 Dynarr_add_many(cache, Dynarr_atp(internal_cache, 0),
7919 Dynarr_length(internal_cache));
7921 Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7922 startp = high_bound + 1;
7924 while (to > high_bound);
7927 w->line_cache_validation_override--;
7928 assert(to <= high_bound);
7931 /* Given x and y coordinates in characters, relative to a window,
7932 return the pixel location corresponding to those coordinates. The
7933 pixel location returned is the center of the given character
7934 position. The pixel values are generated relative to the window,
7937 The modeline is considered to be part of the window. */
7940 glyph_to_pixel_translation(struct window *w, int char_x, int char_y,
7941 int *pix_x, int *pix_y)
7943 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
7944 int num_disp_lines, modeline;
7946 int defheight, defwidth;
7948 XSETWINDOW(window, w);
7949 default_face_height_and_width(window, &defheight, &defwidth);
7951 /* If we get a bogus value indicating somewhere above or to the left of
7952 the window, use the first window line or character position
7959 num_disp_lines = Dynarr_length(dla);
7961 if (num_disp_lines) {
7962 if (Dynarr_atp(dla, 0)->modeline) {
7968 /* First check if the y position intersects the display lines. */
7969 if (char_y < num_disp_lines) {
7970 struct display_line *dl = Dynarr_atp(dla, char_y + modeline);
7971 struct display_block *db =
7972 get_display_block_from_line(dl, TEXT);
7974 *pix_y = (dl->ypos - dl->ascent +
7975 ((unsigned int)(dl->ascent + dl->descent -
7978 if (char_x < Dynarr_length(db->runes)) {
7979 struct rune *rb = Dynarr_atp(db->runes, char_x);
7981 *pix_x = rb->xpos + (rb->width >> 1);
7983 int last_rune = Dynarr_length(db->runes) - 1;
7984 struct rune *rb = Dynarr_atp(db->runes, last_rune);
7986 char_x -= last_rune;
7988 *pix_x = rb->xpos + rb->width;
7989 *pix_x += ((char_x - 1) * defwidth);
7990 *pix_x += (defwidth >> 1);
7993 /* It didn't intersect, so extrapolate. #### For now, we include the
7994 modeline in this since we don't have true character positions in
7997 if (!Dynarr_length(w->face_cachels))
7998 reset_face_cachels(w);
8000 char_y -= num_disp_lines;
8002 if (Dynarr_length(dla)) {
8003 struct display_line *dl =
8004 Dynarr_atp(dla, Dynarr_length(dla) - 1);
8005 *pix_y = dl->ypos + dl->descent - dl->clip;
8007 *pix_y = WINDOW_TEXT_TOP(w);
8009 *pix_y += (char_y * defheight);
8010 *pix_y += (defheight >> 1);
8012 *pix_x = WINDOW_TEXT_LEFT(w);
8013 /* Don't adjust by one because this is still the unadjusted value. */
8014 *pix_x += (char_x * defwidth);
8015 *pix_x += (defwidth >> 1);
8018 if (*pix_x > w->pixel_left + w->pixel_width)
8019 *pix_x = w->pixel_left + w->pixel_width;
8020 if (*pix_y > w->pixel_top + w->pixel_height)
8021 *pix_y = w->pixel_top + w->pixel_height;
8023 *pix_x -= w->pixel_left;
8024 *pix_y -= w->pixel_top;
8027 /* Given a display line and a position, determine if there is a glyph
8028 there and return information about it if there is. */
8031 get_position_object(struct display_line *dl, Lisp_Object * obj1,
8032 Lisp_Object * obj2, int x_coord, int *low_x_coord,
8035 struct display_block *db;
8038 get_next_display_block(dl->bounds, dl->display_blocks, x_coord, 0);
8040 /* We use get_next_display_block to get the actual display block
8041 that would be displayed at x_coord. */
8043 if (block == NO_BLOCK)
8046 db = Dynarr_atp(dl->display_blocks, block);
8048 for (elt = 0; elt < Dynarr_length(db->runes); elt++) {
8049 struct rune *rb = Dynarr_atp(db->runes, elt);
8051 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) {
8052 if (rb->type == RUNE_DGLYPH) {
8053 *obj1 = rb->object.dglyph.glyph;
8054 *obj2 = rb->object.dglyph.extent;
8061 *low_x_coord = rb->xpos;
8063 *high_x_coord = rb->xpos + rb->width;
8070 #define UPDATE_CACHE_RETURN \
8072 d->pixel_to_glyph_cache.valid = 1; \
8073 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8074 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8075 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8076 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8077 d->pixel_to_glyph_cache.frame = f; \
8078 d->pixel_to_glyph_cache.col = *col; \
8079 d->pixel_to_glyph_cache.row = *row; \
8080 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8081 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8082 d->pixel_to_glyph_cache.w = *w; \
8083 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8084 d->pixel_to_glyph_cache.closest = *closest; \
8085 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8086 d->pixel_to_glyph_cache.obj1 = *obj1; \
8087 d->pixel_to_glyph_cache.obj2 = *obj2; \
8088 d->pixel_to_glyph_cache.retval = position; \
8089 RETURN_SANS_WARNINGS position; \
8092 /* Given x and y coordinates in pixels relative to a frame, return
8093 information about what is located under those coordinates.
8095 The return value will be one of:
8097 OVER_TOOLBAR: over one of the 4 frame toolbars
8098 OVER_MODELINE: over a modeline
8099 OVER_BORDER: over an internal border
8100 OVER_NOTHING: over the text area, but not over text
8101 OVER_OUTSIDE: outside of the frame border
8102 OVER_TEXT: over text in the text area
8108 -- nil if the coordinates are not over a glyph or a toolbar button.
8112 -- an extent, if the coordinates are over a glyph in the text area
8115 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8116 equivalent coordinates relative to the upper-left corner of the glyph.
8118 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8119 equivalent coordinates relative to the upper-left corner of the character.
8121 Otherwise, OBJ_X and OBJ_Y are undefined.
8125 pixel_to_glyph_translation(struct frame *f, int x_coord, int y_coord,
8126 int *col, int *row, int *obj_x, int *obj_y,
8127 struct window **w, Bufpos * bufpos,
8128 Bufpos * closest, Charcount * modeline_closest,
8129 Lisp_Object * obj1, Lisp_Object * obj2)
8132 struct pixel_to_glyph_translation_cache *cache;
8134 int frm_left, frm_right, frm_top, frm_bottom;
8135 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8136 int position = OVER_NOTHING;
8137 int device_check_failed = 0;
8138 display_line_dynarr *dla;
8140 /* This is a safety valve in case this got called with a frame in
8141 the middle of being deleted. */
8142 if (!DEVICEP(f->device) || !DEVICE_LIVE_P(XDEVICE(f->device))) {
8143 device_check_failed = 1;
8144 d = NULL, cache = NULL; /* Warning suppression */
8146 d = XDEVICE(f->device);
8147 cache = &d->pixel_to_glyph_cache;
8150 if (!device_check_failed
8152 && cache->frame == f
8153 && cache->low_x_coord <= x_coord
8154 && cache->high_x_coord > x_coord
8155 && cache->low_y_coord <= y_coord && cache->high_y_coord > y_coord) {
8158 *obj_x = cache->obj_x;
8159 *obj_y = cache->obj_y;
8161 *bufpos = cache->bufpos;
8162 *closest = cache->closest;
8163 *modeline_closest = cache->modeline_closest;
8164 *obj1 = cache->obj1;
8165 *obj2 = cache->obj2;
8167 return cache->retval;
8176 *modeline_closest = -1;
8180 low_x_coord = x_coord;
8181 high_x_coord = x_coord + 1;
8182 low_y_coord = y_coord;
8183 high_y_coord = y_coord + 1;
8186 if (device_check_failed)
8187 return OVER_NOTHING;
8189 frm_left = FRAME_LEFT_BORDER_END(f);
8190 frm_right = FRAME_RIGHT_BORDER_START(f);
8191 frm_top = FRAME_TOP_BORDER_END(f);
8192 frm_bottom = FRAME_BOTTOM_BORDER_START(f);
8194 /* Check if the mouse is outside of the text area actually used by
8196 if (y_coord < frm_top) {
8197 if (y_coord >= FRAME_TOP_BORDER_START(f)) {
8198 low_y_coord = FRAME_TOP_BORDER_START(f);
8199 high_y_coord = frm_top;
8200 position = OVER_BORDER;
8201 } else if (y_coord >= 0) {
8203 high_y_coord = FRAME_TOP_BORDER_START(f);
8204 position = OVER_TOOLBAR;
8206 low_y_coord = y_coord;
8208 position = OVER_OUTSIDE;
8210 } else if (y_coord >= frm_bottom) {
8211 if (y_coord < FRAME_BOTTOM_BORDER_END(f)) {
8212 low_y_coord = frm_bottom;
8213 high_y_coord = FRAME_BOTTOM_BORDER_END(f);
8214 position = OVER_BORDER;
8215 } else if (y_coord < FRAME_PIXHEIGHT(f)) {
8216 low_y_coord = FRAME_BOTTOM_BORDER_END(f);
8217 high_y_coord = FRAME_PIXHEIGHT(f);
8218 position = OVER_TOOLBAR;
8220 low_y_coord = FRAME_PIXHEIGHT(f);
8221 high_y_coord = y_coord;
8222 position = OVER_OUTSIDE;
8226 if (position != OVER_TOOLBAR && position != OVER_BORDER) {
8227 if (x_coord < frm_left) {
8228 if (x_coord >= FRAME_LEFT_BORDER_START(f)) {
8229 low_x_coord = FRAME_LEFT_BORDER_START(f);
8230 high_x_coord = frm_left;
8231 position = OVER_BORDER;
8232 } else if (x_coord >= 0) {
8234 high_x_coord = FRAME_LEFT_BORDER_START(f);
8235 position = OVER_TOOLBAR;
8237 low_x_coord = x_coord;
8239 position = OVER_OUTSIDE;
8241 } else if (x_coord >= frm_right) {
8242 if (x_coord < FRAME_RIGHT_BORDER_END(f)) {
8243 low_x_coord = frm_right;
8244 high_x_coord = FRAME_RIGHT_BORDER_END(f);
8245 position = OVER_BORDER;
8246 } else if (x_coord < FRAME_PIXWIDTH(f)) {
8247 low_x_coord = FRAME_RIGHT_BORDER_END(f);
8248 high_x_coord = FRAME_PIXWIDTH(f);
8249 position = OVER_TOOLBAR;
8251 low_x_coord = FRAME_PIXWIDTH(f);
8252 high_x_coord = x_coord;
8253 position = OVER_OUTSIDE;
8257 #ifdef HAVE_TOOLBARS
8258 if (position == OVER_TOOLBAR) {
8259 *obj1 = toolbar_button_at_pixpos(f, x_coord, y_coord);
8262 UPDATE_CACHE_RETURN;
8264 #endif /* HAVE_TOOLBARS */
8266 /* We still have to return the window the pointer is next to and its
8267 relative y position even if it is outside the x boundary. */
8268 if (x_coord < frm_left)
8270 else if (x_coord > frm_right)
8271 x_coord = frm_right;
8273 /* Same in reverse. */
8274 if (y_coord < frm_top)
8276 else if (y_coord > frm_bottom)
8277 y_coord = frm_bottom;
8279 /* Find what window the given coordinates are actually in. */
8280 window = f->root_window;
8281 *w = find_window_by_pixel_pos(x_coord, y_coord, window);
8283 /* If we didn't find a window, we're done. */
8285 UPDATE_CACHE_RETURN;
8286 } else if (position != OVER_NOTHING) {
8288 *modeline_closest = -1;
8290 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) {
8292 UPDATE_CACHE_RETURN;
8296 /* Check if the window is a minibuffer but isn't active. */
8297 if (MINI_WINDOW_P(*w) && !minibuf_level) {
8298 /* Must reset the window value since some callers will ignore
8299 the return value if it is set. */
8301 UPDATE_CACHE_RETURN;
8304 /* See if the point is over window vertical divider */
8305 if (window_needs_vertical_divider(*w)) {
8306 int div_x_high = WINDOW_RIGHT(*w);
8307 int div_x_low = div_x_high - window_divider_width(*w);
8308 int div_y_high = WINDOW_BOTTOM(*w);
8309 int div_y_low = WINDOW_TOP(*w);
8311 if (div_x_low < x_coord && x_coord <= div_x_high &&
8312 div_y_low < y_coord && y_coord <= div_y_high) {
8313 low_x_coord = div_x_low;
8314 high_x_coord = div_x_high;
8315 low_y_coord = div_y_low;
8316 high_y_coord = div_y_high;
8317 position = OVER_V_DIVIDER;
8318 UPDATE_CACHE_RETURN;
8322 dla = window_display_lines(*w, CURRENT_DISP);
8324 for (*row = 0; *row < Dynarr_length(dla); (*row)++) {
8325 int really_over_nothing = 0;
8326 struct display_line *dl = Dynarr_atp(dla, *row);
8328 if ((int)(dl->ypos - dl->ascent) <= y_coord
8329 && y_coord <= (int)(dl->ypos + dl->descent)) {
8330 int check_margin_glyphs = 0;
8331 struct display_block *db =
8332 get_display_block_from_line(dl, TEXT);
8333 struct rune *rb = 0;
8335 if (x_coord < dl->bounds.left_white
8336 || x_coord >= dl->bounds.right_white)
8337 check_margin_glyphs = 1;
8339 low_y_coord = dl->ypos - dl->ascent;
8340 high_y_coord = dl->ypos + dl->descent + 1;
8342 if (position == OVER_BORDER
8343 || position == OVER_OUTSIDE
8344 || check_margin_glyphs) {
8345 int x_check, left_bound;
8347 if (check_margin_glyphs) {
8349 left_bound = dl->bounds.left_white;
8351 x_check = high_x_coord;
8352 left_bound = frm_left;
8355 if (Dynarr_length(db->runes)) {
8356 if (x_check <= left_bound) {
8391 *modeline_closest += dl->offset;
8393 *closest += dl->offset;
8395 /* #### What should be here. */
8397 *modeline_closest = 0;
8402 if (check_margin_glyphs) {
8403 if (x_coord < dl->bounds.left_in
8404 || x_coord >= dl->bounds.right_in) {
8405 /* If we are over the outside margins then we
8406 know the loop over the text block isn't going
8407 to accomplish anything. So we go ahead and
8408 set what information we can right here and
8412 y_coord - (dl->ypos -
8414 get_position_object(dl, obj1,
8420 UPDATE_CACHE_RETURN;
8423 UPDATE_CACHE_RETURN;
8426 for (*col = 0; *col <= Dynarr_length(db->runes);
8429 (*col == Dynarr_length(db->runes));
8432 rb = Dynarr_atp(db->runes, *col);
8435 (rb->xpos <= x_coord
8436 && x_coord < rb->xpos + rb->width)) {
8439 rb = Dynarr_atp(db->runes,
8443 *bufpos = rb->bufpos + dl->offset;
8444 low_x_coord = rb->xpos;
8445 high_x_coord = rb->xpos + rb->width;
8447 if (rb->type == RUNE_DGLYPH) {
8450 /* Find the first character after the glyph. */
8487 /* In this case we failed to find a non-glyph
8488 character so we return the last position
8489 displayed on the line. */
8491 Dynarr_length(db->runes)) {
8503 really_over_nothing = 1;
8518 window_displayed_height(*w);
8520 if (position == OVER_NOTHING)
8524 if (rb->type == RUNE_DGLYPH) {
8531 } else if (rb->type ==
8540 UPDATE_CACHE_RETURN;
8542 || (rb->type == RUNE_CHAR
8543 && rb->object.chr.ch ==
8546 /* At this point we may have glyphs in the right
8548 if (check_margin_glyphs)
8549 get_position_object(dl,
8555 UPDATE_CACHE_RETURN;
8558 if (rb->type == RUNE_DGLYPH) {
8565 } else if (rb->type ==
8574 *obj_x = x_coord - rb->xpos;
8576 y_coord - (dl->ypos -
8579 /* At this point we may have glyphs in the left
8581 if (check_margin_glyphs)
8582 get_position_object(dl,
8589 if (position == OVER_NOTHING
8590 && !really_over_nothing)
8591 position = OVER_TEXT;
8593 UPDATE_CACHE_RETURN;
8600 *row = Dynarr_length(dla) - 1;
8601 if (FRAME_WIN_P(f)) {
8602 int bot_elt = Dynarr_length(dla) - 1;
8605 struct display_line *dl = Dynarr_atp(dla, bot_elt);
8606 int adj_area = y_coord - (dl->ypos + dl->descent);
8610 XSETWINDOW(lwin, *w);
8611 default_face_height_and_width(lwin, 0, &defheight);
8613 *row += (adj_area / defheight);
8617 /* #### This should be checked out some more to determine what
8618 should really be going on. */
8619 if (!MARKERP((*w)->start[CURRENT_DISP]))
8622 *closest = end_of_last_line_may_error(*w,
8623 marker_position((*w)->
8627 UPDATE_CACHE_RETURN;
8630 #undef UPDATE_CACHE_RETURN
8632 /***************************************************************************/
8634 /* Lisp functions */
8636 /***************************************************************************/
8638 DEFUN("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8639 Ensure that all minibuffers are correctly showing the echo area.
8643 Lisp_Object devcons, concons;
8645 DEVICE_LOOP_NO_BREAK(devcons, concons) {
8646 struct device *d = XDEVICE(XCAR(devcons));
8647 Lisp_Object frmcons;
8649 DEVICE_FRAME_LOOP(frmcons, d) {
8650 struct frame *f = XFRAME(XCAR(frmcons));
8652 if (FRAME_REPAINT_P(f) && FRAME_HAS_MINIBUF_P(f)) {
8653 Lisp_Object window = FRAME_MINIBUF_WINDOW(f);
8655 MAYBE_DEVMETH(d, frame_output_begin, (f));
8658 * If the frame size has changed, there may be random
8659 * chud on the screen left from previous messages
8660 * because redisplay_frame hasn't been called yet.
8661 * Clear the screen to get rid of the potential mess.
8663 if (f->echo_area_garbaged) {
8664 MAYBE_DEVMETH(d, clear_frame, (f));
8665 f->echo_area_garbaged = 0;
8667 redisplay_window(window, 0);
8668 MAYBE_DEVMETH(d, frame_output_end, (f));
8670 call_redisplay_end_triggers(XWINDOW(window), 0);
8678 static Lisp_Object restore_disable_preemption_value(Lisp_Object value)
8680 disable_preemption = XINT(value);
8684 DEFUN("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8685 Clear frame FRAME and output again what is supposed to appear on it.
8686 FRAME defaults to the selected frame if omitted.
8687 Normally, redisplay is preempted as normal if input arrives. However,
8688 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8689 input and is guaranteed to proceed to completion.
8691 (frame, no_preempt))
8693 struct frame *f = decode_frame(frame);
8694 int count = specpdl_depth();
8696 if (!NILP(no_preempt)) {
8697 record_unwind_protect(restore_disable_preemption_value,
8698 make_int(disable_preemption));
8699 disable_preemption++;
8703 redisplay_frame(f, 1);
8705 /* See the comment in Fredisplay_frame. */
8706 RESET_CHANGED_SET_FLAGS;
8708 return unbind_to(count, Qnil);
8711 DEFUN("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8712 Ensure that FRAME's contents are correctly displayed.
8713 This differs from `redraw-frame' in that it only redraws what needs to
8714 be updated, as opposed to unconditionally clearing and redrawing
8716 FRAME defaults to the selected frame if omitted.
8717 Normally, redisplay is preempted as normal if input arrives. However,
8718 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8719 input and is guaranteed to proceed to completion.
8721 (frame, no_preempt))
8723 struct frame *f = decode_frame(frame);
8724 int count = specpdl_depth();
8726 if (!NILP(no_preempt)) {
8727 record_unwind_protect(restore_disable_preemption_value,
8728 make_int(disable_preemption));
8729 disable_preemption++;
8732 redisplay_frame(f, 1);
8734 /* If we don't reset the global redisplay flags here, subsequent
8735 changes to the display will not get registered by redisplay
8736 because it thinks it already has registered changes. If you
8737 really knew what you were doing you could confuse redisplay by
8738 calling Fredisplay_frame while updating another frame. We assume
8739 that if you know what you are doing you will not be that
8741 RESET_CHANGED_SET_FLAGS;
8743 return unbind_to(count, Qnil);
8746 DEFUN("redraw-device", Fredraw_device, 0, 2, 0, /*
8747 Clear device DEVICE and output again what is supposed to appear on it.
8748 DEVICE defaults to the selected device if omitted.
8749 Normally, redisplay is preempted as normal if input arrives. However,
8750 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8751 input and is guaranteed to proceed to completion.
8753 (device, no_preempt))
8755 struct device *d = decode_device(device);
8756 Lisp_Object frmcons;
8757 int count = specpdl_depth();
8759 if (!NILP(no_preempt)) {
8760 record_unwind_protect(restore_disable_preemption_value,
8761 make_int(disable_preemption));
8762 disable_preemption++;
8765 DEVICE_FRAME_LOOP(frmcons, d) {
8766 XFRAME(XCAR(frmcons))->clear = 1;
8768 redisplay_device(d, 0);
8770 /* See the comment in Fredisplay_frame. */
8771 RESET_CHANGED_SET_FLAGS;
8773 return unbind_to(count, Qnil);
8776 DEFUN("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8777 Ensure that DEVICE's contents are correctly displayed.
8778 This differs from `redraw-device' in that it only redraws what needs to
8779 be updated, as opposed to unconditionally clearing and redrawing
8781 DEVICE defaults to the selected device if omitted.
8782 Normally, redisplay is preempted as normal if input arrives. However,
8783 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8784 input and is guaranteed to proceed to completion.
8786 (device, no_preempt))
8788 struct device *d = decode_device(device);
8789 int count = specpdl_depth();
8791 if (!NILP(no_preempt)) {
8792 record_unwind_protect(restore_disable_preemption_value,
8793 make_int(disable_preemption));
8794 disable_preemption++;
8797 redisplay_device(d, 0);
8799 /* See the comment in Fredisplay_frame. */
8800 RESET_CHANGED_SET_FLAGS;
8802 return unbind_to(count, Qnil);
8805 /* Big lie. Big lie. This will force all modelines to be updated
8806 regardless if the all flag is set or not. It remains in existence
8807 solely for backwards compatibility. */
8808 DEFUN("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8809 Force the modeline of the current buffer to be redisplayed.
8810 With optional non-nil ALL, force redisplay of all modelines.
8814 MARK_MODELINE_CHANGED;
8818 DEFUN("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8819 Force an immediate update of the cursor on FRAME.
8820 FRAME defaults to the selected frame if omitted.
8824 redisplay_redraw_cursor(decode_frame(frame), 1);
8828 /***************************************************************************/
8830 /* Lisp-variable change triggers */
8832 /***************************************************************************/
8835 margin_width_changed_in_frame(Lisp_Object specifier, struct frame *f,
8838 /* Nothing to be done? */
8842 redisplay_variable_changed(Lisp_Object sym, Lisp_Object * val,
8843 Lisp_Object in_object, int flags)
8845 /* #### clip_changed should really be renamed something like
8846 global_redisplay_change. */
8851 /* This is called if the built-in glyphs have their properties
8854 redisplay_glyph_changed(Lisp_Object glyph, Lisp_Object property,
8857 if (WINDOWP(locale)) {
8858 MARK_FRAME_GLYPHS_CHANGED(XFRAME
8859 (WINDOW_FRAME(XWINDOW(locale))));
8860 } else if (FRAMEP(locale)) {
8861 MARK_FRAME_GLYPHS_CHANGED(XFRAME(locale));
8862 } else if (DEVICEP(locale)) {
8863 Lisp_Object frmcons;
8864 DEVICE_FRAME_LOOP(frmcons, XDEVICE(locale))
8865 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8866 } else if (CONSOLEP(locale)) {
8867 Lisp_Object frmcons, devcons;
8868 CONSOLE_FRAME_LOOP_NO_BREAK(frmcons, devcons, XCONSOLE(locale))
8869 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8870 } else { /* global or buffer */
8872 Lisp_Object frmcons, devcons, concons;
8873 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
8874 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8879 text_cursor_visible_p_changed(Lisp_Object specifier, struct window *w,
8882 if (XFRAME(w->frame)->init_finished)
8883 Fforce_cursor_redisplay(w->frame);
8886 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
8888 /***************************************************************************/
8890 /* memory usage computation */
8892 /***************************************************************************/
8895 compute_rune_dynarr_usage(rune_dynarr * dyn, struct overhead_stats *ovstats)
8897 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8901 compute_display_block_dynarr_usage(display_block_dynarr * dyn,
8902 struct overhead_stats *ovstats)
8909 total = Dynarr_memory_usage(dyn, ovstats);
8910 for (i = 0; i < Dynarr_largest(dyn); i++)
8912 compute_rune_dynarr_usage(Dynarr_at(dyn, i).runes, ovstats);
8918 compute_glyph_block_dynarr_usage(glyph_block_dynarr * dyn,
8919 struct overhead_stats *ovstats)
8921 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8925 compute_display_line_dynarr_usage(display_line_dynarr * dyn,
8926 struct overhead_stats *ovstats)
8933 total = Dynarr_memory_usage(dyn, ovstats);
8934 for (i = 0; i < Dynarr_largest(dyn); i++) {
8935 struct display_line *dl = &Dynarr_at(dyn, i);
8937 compute_display_block_dynarr_usage(dl->display_blocks,
8940 compute_glyph_block_dynarr_usage(dl->left_glyphs, ovstats);
8942 compute_glyph_block_dynarr_usage(dl->right_glyphs, ovstats);
8949 compute_line_start_cache_dynarr_usage(line_start_cache_dynarr * dyn,
8950 struct overhead_stats *ovstats)
8952 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8955 #endif /* MEMORY_USAGE_STATS */
8957 /***************************************************************************/
8959 /* initialization */
8961 /***************************************************************************/
8963 void init_redisplay(void)
8965 disable_preemption = 0;
8966 preemption_count = 0;
8967 max_preempts = INIT_MAX_PREEMPTS;
8973 if (!cmotion_display_lines)
8974 cmotion_display_lines = Dynarr_new(display_line);
8975 if (!mode_spec_bufbyte_string)
8976 mode_spec_bufbyte_string = Dynarr_new(Bufbyte);
8977 if (!formatted_string_extent_dynarr)
8978 formatted_string_extent_dynarr = Dynarr_new(EXTENT);
8979 if (!formatted_string_extent_start_dynarr)
8980 formatted_string_extent_start_dynarr =
8981 Dynarr_new(Bytecount);
8982 if (!formatted_string_extent_end_dynarr)
8983 formatted_string_extent_end_dynarr =
8984 Dynarr_new(Bytecount);
8985 if (!internal_cache)
8986 internal_cache = Dynarr_new(line_start_cache);
8989 /* window system is nil when in -batch mode */
8990 if (!initialized || noninteractive)
8993 /* If the user wants to use a window system, we shouldn't bother
8994 initializing the terminal. This is especially important when the
8995 terminal is so dumb that emacs gives up before and doesn't bother
8996 using the window system.
8998 If the DISPLAY environment variable is set, try to use X, and die
8999 with an error message if that doesn't work. */
9001 #ifdef HAVE_X_WINDOWS
9002 if (!strcmp(display_use, "x")) {
9003 /* Some stuff checks this way early. */
9004 Vwindow_system = Qx;
9005 Vinitial_window_system = Qx;
9008 #endif /* HAVE_X_WINDOWS */
9011 if (!strcmp(display_use, "gtk")) {
9012 Vwindow_system = Qgtk;
9013 Vinitial_window_system = Qgtk;
9019 /* If no window system has been specified, try to use the terminal. */
9021 stderr_out("SXEmacs: standard input is not a tty\n");
9025 /* Look at the TERM variable */
9026 if (!getenv("TERM")) {
9028 ("Please set the environment variable TERM; see tset(1).\n");
9032 Vinitial_window_system = Qtty;
9034 #else /* not HAVE_TTY */
9035 /* No DISPLAY specified, and no TTY support. */
9036 stderr_out("SXEmacs: Cannot open display.\n\
9037 Please set the environmental variable DISPLAY to an appropriate value.\n");
9043 void syms_of_redisplay(void)
9045 defsymbol(&Qcursor_in_echo_area, "cursor-in-echo-area");
9046 #ifndef INHIBIT_REDISPLAY_HOOKS
9047 defsymbol(&Qpre_redisplay_hook, "pre-redisplay-hook");
9048 defsymbol(&Qpost_redisplay_hook, "post-redisplay-hook");
9049 #endif /* INHIBIT_REDISPLAY_HOOKS */
9050 defsymbol(&Qdisplay_warning_buffer, "display-warning-buffer");
9051 defsymbol(&Qbar_cursor, "bar-cursor");
9052 defsymbol(&Qredisplay_end_trigger_functions,
9053 "redisplay-end-trigger-functions");
9054 defsymbol(&Qtop_bottom, "top-bottom");
9055 defsymbol(&Qbuffer_list_changed_hook, "buffer-list-changed-hook");
9057 DEFSUBR(Fredisplay_echo_area);
9058 DEFSUBR(Fredraw_frame);
9059 DEFSUBR(Fredisplay_frame);
9060 DEFSUBR(Fredraw_device);
9061 DEFSUBR(Fredisplay_device);
9062 DEFSUBR(Fredraw_modeline);
9063 DEFSUBR(Fforce_cursor_redisplay);
9066 void vars_of_redisplay(void)
9070 staticpro(&last_arrow_position);
9071 staticpro(&last_arrow_string);
9072 last_arrow_position = Qnil;
9073 last_arrow_string = Qnil;
9076 /* #### Probably temporary */
9077 DEFVAR_INT("redisplay-cache-adjustment", &cache_adjustment /*
9078 \(Temporary) Setting this will impact the performance of the internal
9081 cache_adjustment = 2;
9083 DEFVAR_INT_MAGIC("pixel-vertical-clip-threshold", &vertical_clip /*
9084 Minimum pixel height for clipped bottom display line.
9085 A clipped line shorter than this won't be displayed.
9087 redisplay_variable_changed);
9090 DEFVAR_INT_MAGIC("pixel-horizontal-clip-threshold", &horizontal_clip /*
9091 Minimum visible area for clipped glyphs at right boundary.
9092 Clipped glyphs shorter than this won't be displayed.
9093 Only pixmap glyph instances are currently allowed to be clipped.
9095 redisplay_variable_changed);
9096 horizontal_clip = 5;
9098 DEFVAR_LISP("global-mode-string", &Vglobal_mode_string /*
9099 String displayed by modeline-format's "%m" specification.
9101 Vglobal_mode_string = Qnil;
9103 DEFVAR_LISP_MAGIC("overlay-arrow-position", &Voverlay_arrow_position /*
9104 Marker for where to display an arrow on top of the buffer text.
9105 This must be the beginning of a line in order to work.
9106 See also `overlay-arrow-string'.
9108 redisplay_variable_changed);
9109 Voverlay_arrow_position = Qnil;
9111 DEFVAR_LISP_MAGIC("overlay-arrow-string", &Voverlay_arrow_string /*
9112 String or glyph to display as an arrow. See also `overlay-arrow-position'.
9113 \(Note that despite the name of this variable, it can be set to a glyph as
9116 redisplay_variable_changed);
9117 Voverlay_arrow_string = Qnil;
9119 DEFVAR_INT("scroll-step", &scroll_step /*
9120 *The number of lines to try scrolling a window by when point moves out.
9121 If that fails to bring point back on frame, point is centered instead.
9122 If this is zero, point is always centered after it moves off screen.
9126 DEFVAR_INT("scroll-conservatively", &scroll_conservatively /*
9127 *Scroll up to this many lines, to bring point back on screen.
9129 scroll_conservatively = 0;
9131 DEFVAR_BOOL_MAGIC("truncate-partial-width-windows", &truncate_partial_width_windows /*
9132 *Non-nil means truncate lines in all windows less than full frame wide.
9134 redisplay_variable_changed);
9135 truncate_partial_width_windows = 1;
9137 DEFVAR_LISP("visible-bell", &Vvisible_bell /*
9138 *Non-nil substitutes a visual signal for the audible bell.
9140 Default behavior is to flash the whole screen. On some platforms,
9141 special effects are available using the following values:
9143 'display Flash the whole screen (ie, the default behavior).
9144 'top-bottom Flash only the top and bottom lines of the selected frame.
9146 When effects are unavailable on a platform, the visual bell is the
9147 default, whole screen. (Currently only X supports any special effects.)
9149 Vvisible_bell = Qnil;
9151 DEFVAR_BOOL("no-redraw-on-reenter", &no_redraw_on_reenter /*
9152 *Non-nil means no need to redraw entire frame after suspending.
9153 A non-nil value is useful if the terminal can automatically preserve
9154 Emacs's frame display when you reenter Emacs.
9155 It is up to you to set this variable if your terminal can do that.
9157 no_redraw_on_reenter = 0;
9159 DEFVAR_LISP("window-system", &Vwindow_system /*
9160 A symbol naming the window-system under which Emacs is running,
9161 such as `x', or nil if emacs is running on an ordinary terminal.
9163 Do not use this variable, except for GNU Emacs compatibility, as it
9164 gives wrong values in a multi-device environment. Use `console-type'
9167 Vwindow_system = Qnil;
9169 /* #### Temporary shit until window-system is eliminated. */
9170 DEFVAR_CONST_LISP("initial-window-system", &Vinitial_window_system /*
9173 Vinitial_window_system = Qnil;
9175 DEFVAR_BOOL("cursor-in-echo-area", &cursor_in_echo_area /*
9176 Non-nil means put cursor in minibuffer, at end of any message there.
9178 cursor_in_echo_area = 0;
9180 /* #### Shouldn't this be generalized as follows:
9182 if nil, use block cursor.
9183 if a number, use a bar cursor of that width.
9184 Otherwise, use a 1-pixel bar cursor.
9186 #### Or better yet, this variable should be trashed entirely
9187 (use a Lisp-magic variable to maintain compatibility)
9188 and a specifier `cursor-shape' added, which allows a block
9189 cursor, a bar cursor, a flashing block or bar cursor,
9190 maybe a caret cursor, etc. */
9192 DEFVAR_LISP("bar-cursor", &Vbar_cursor /*
9193 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9197 #ifndef INHIBIT_REDISPLAY_HOOKS
9198 xxDEFVAR_LISP("pre-redisplay-hook", &Vpre_redisplay_hook /*
9199 Function or functions to run before every redisplay.
9201 Vpre_redisplay_hook = Qnil;
9203 xxDEFVAR_LISP("post-redisplay-hook", &Vpost_redisplay_hook /*
9204 Function or functions to run after every redisplay.
9206 Vpost_redisplay_hook = Qnil;
9207 #endif /* INHIBIT_REDISPLAY_HOOKS */
9209 DEFVAR_LISP("buffer-list-changed-hook", &Vbuffer_list_changed_hook /*
9210 Function or functions to call when a frame's buffer list has changed.
9211 This is called during redisplay, before redisplaying each frame.
9212 Functions on this hook are called with one argument, the frame.
9214 Vbuffer_list_changed_hook = Qnil;
9216 DEFVAR_INT("display-warning-tick", &display_warning_tick /*
9217 Bump this to tell the C code to call `display-warning-buffer'
9218 at next redisplay. You should not normally change this; the function
9219 `display-warning' automatically does this at appropriate times.
9221 display_warning_tick = 0;
9223 DEFVAR_BOOL("inhibit-warning-display", &inhibit_warning_display /*
9224 Non-nil means inhibit display of warning messages.
9225 You should *bind* this, not set it. Any pending warning messages
9226 will be displayed when the binding no longer applies.
9228 /* reset to 0 by startup.el after the splash screen has displayed.
9229 This way, the warnings don't obliterate the splash screen. */
9230 inhibit_warning_display = 1;
9232 DEFVAR_LISP("window-size-change-functions", &Vwindow_size_change_functions /*
9233 Not currently implemented.
9234 Functions called before redisplay, if window sizes have changed.
9235 The value should be a list of functions that take one argument.
9236 Just before redisplay, for each frame, if any of its windows have changed
9237 size since the last redisplay, or have been split or deleted,
9238 all the functions in the list are called, with the frame as argument.
9240 Vwindow_size_change_functions = Qnil;
9242 DEFVAR_LISP("window-scroll-functions", &Vwindow_scroll_functions /*
9243 Not currently implemented.
9244 Functions to call before redisplaying a window with scrolling.
9245 Each function is called with two arguments, the window
9246 and its new display-start position. Note that the value of `window-end'
9247 is not valid when these functions are called.
9249 Vwindow_scroll_functions = Qnil;
9251 DEFVAR_LISP("redisplay-end-trigger-functions", &Vredisplay_end_trigger_functions /*
9252 See `set-window-redisplay-end-trigger'.
9254 Vredisplay_end_trigger_functions = Qnil;
9256 DEFVAR_BOOL("column-number-start-at-one", &column_number_start_at_one /*
9257 *Non-nil means column display number starts at 1.
9259 column_number_start_at_one = 0;
9262 void specifier_vars_of_redisplay(void)
9264 DEFVAR_SPECIFIER("left-margin-width", &Vleft_margin_width /*
9265 *Width of left margin.
9266 This is a specifier; use `set-specifier' to change it.
9268 Vleft_margin_width = Fmake_specifier(Qnatnum);
9269 set_specifier_fallback(Vleft_margin_width, list1(Fcons(Qnil, Qzero)));
9270 set_specifier_caching(Vleft_margin_width,
9271 offsetof(struct window, left_margin_width),
9272 some_window_value_changed,
9273 offsetof(struct frame, left_margin_width),
9274 margin_width_changed_in_frame, 0);
9276 DEFVAR_SPECIFIER("right-margin-width", &Vright_margin_width /*
9277 *Width of right margin.
9278 This is a specifier; use `set-specifier' to change it.
9280 Vright_margin_width = Fmake_specifier(Qnatnum);
9281 set_specifier_fallback(Vright_margin_width, list1(Fcons(Qnil, Qzero)));
9282 set_specifier_caching(Vright_margin_width,
9283 offsetof(struct window, right_margin_width),
9284 some_window_value_changed,
9285 offsetof(struct frame, right_margin_width),
9286 margin_width_changed_in_frame, 0);
9288 DEFVAR_SPECIFIER("minimum-line-ascent", &Vminimum_line_ascent /*
9289 *Minimum ascent height of lines.
9290 This is a specifier; use `set-specifier' to change it.
9292 Vminimum_line_ascent = Fmake_specifier(Qnatnum);
9293 set_specifier_fallback(Vminimum_line_ascent, list1(Fcons(Qnil, Qzero)));
9294 set_specifier_caching(Vminimum_line_ascent,
9295 offsetof(struct window, minimum_line_ascent),
9296 some_window_value_changed, 0, 0, 0);
9298 DEFVAR_SPECIFIER("minimum-line-descent", &Vminimum_line_descent /*
9299 *Minimum descent height of lines.
9300 This is a specifier; use `set-specifier' to change it.
9302 Vminimum_line_descent = Fmake_specifier(Qnatnum);
9303 set_specifier_fallback(Vminimum_line_descent,
9304 list1(Fcons(Qnil, Qzero)));
9305 set_specifier_caching(Vminimum_line_descent,
9306 offsetof(struct window, minimum_line_descent),
9307 some_window_value_changed, 0, 0, 0);
9309 DEFVAR_SPECIFIER("use-left-overflow", &Vuse_left_overflow /*
9310 *Non-nil means use the left outside margin as extra whitespace when
9311 displaying 'whitespace or 'inside-margin glyphs.
9312 This is a specifier; use `set-specifier' to change it.
9314 Vuse_left_overflow = Fmake_specifier(Qboolean);
9315 set_specifier_fallback(Vuse_left_overflow, list1(Fcons(Qnil, Qnil)));
9316 set_specifier_caching(Vuse_left_overflow,
9317 offsetof(struct window, use_left_overflow),
9318 some_window_value_changed, 0, 0, 0);
9320 DEFVAR_SPECIFIER("use-right-overflow", &Vuse_right_overflow /*
9321 *Non-nil means use the right outside margin as extra whitespace when
9322 displaying 'whitespace or 'inside-margin glyphs.
9323 This is a specifier; use `set-specifier' to change it.
9325 Vuse_right_overflow = Fmake_specifier(Qboolean);
9326 set_specifier_fallback(Vuse_right_overflow, list1(Fcons(Qnil, Qnil)));
9327 set_specifier_caching(Vuse_right_overflow,
9328 offsetof(struct window, use_right_overflow),
9329 some_window_value_changed, 0, 0, 0);
9331 DEFVAR_SPECIFIER("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9332 *Non-nil means the text cursor is visible (this is usually the case).
9333 This is a specifier; use `set-specifier' to change it.
9335 Vtext_cursor_visible_p = Fmake_specifier(Qboolean);
9336 set_specifier_fallback(Vtext_cursor_visible_p, list1(Fcons(Qnil, Qt)));
9337 set_specifier_caching(Vtext_cursor_visible_p,
9338 offsetof(struct window, text_cursor_visible_p),
9339 text_cursor_visible_p_changed, 0, 0, 0);