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;
1277 data->cursor_type = orig_cursor_type;
1278 if (prop && prop != ADD_FAILED )
1283 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1285 /* Add runes representing a control character to a display block. */
1287 static prop_block_dynarr *add_control_char_runes(pos_data * data,
1290 if (!NILP(b->ctl_arrow)) {
1291 prop_block_dynarr *prop;
1292 Emchar orig_char = data->ch;
1293 unsigned int old_cursor_type = data->cursor_type;
1298 if (data->start_col)
1301 if (!data->start_col) {
1302 if (data->bi_start_col_enabled) {
1303 prop_block_dynarr *retval;
1305 retval = add_hscroll_rune(data);
1309 struct glyph_block gb;
1310 struct window *w = XWINDOW(data->window);
1313 gb.glyph = Vcontrol_arrow_glyph;
1315 /* We only propagate information if the glyph was partially
1317 prop = add_glyph_rune(data, &gb, BEGIN_GLYPHS, 1,
1318 GLYPH_CACHEL(w, CONTROL_GLYPH_INDEX));
1319 if ( prop != NULL ) {
1320 if ( prop != ADD_FAILED )
1327 if (orig_char == 0177)
1330 data->ch = orig_char ^ 0100;
1331 data->cursor_type = IGNORE_CURSOR;
1333 if (add_emchar_rune(data)) {
1334 struct prop_block pb;
1336 prop = Dynarr_new(prop_block);
1338 pb.type = PROP_CHAR;
1339 pb.data.p_char.ch = data->ch;
1340 pb.data.p_char.cursor_type = data->cursor_type;
1341 Dynarr_add(prop, pb);
1344 data->cursor_type = old_cursor_type;
1347 return add_octal_runes(data);
1351 static prop_block_dynarr *add_disp_table_entry_runes_1(pos_data * data,
1354 prop_block_dynarr *prop = NULL;
1356 if (STRINGP(entry)) {
1357 prop = add_bufbyte_string_runes(data,
1358 XSTRING_DATA(entry),
1359 XSTRING_LENGTH(entry), 0, 0);
1360 } else if (GLYPHP(entry)) {
1361 if (data->start_col)
1364 if (!data->start_col && data->bi_start_col_enabled) {
1365 prop = add_hscroll_rune(data);
1367 struct glyph_block gb;
1371 prop = add_glyph_rune(data, &gb, BEGIN_GLYPHS, 0, 0);
1373 } else if (CHAR_OR_CHAR_INTP(entry)) {
1374 data->ch = XCHAR_OR_CHAR_INT(entry);
1375 prop = add_emchar_rune(data);
1376 } else if (CONSP(entry)) {
1377 if (EQ(XCAR(entry), Qformat)
1378 && CONSP(XCDR(entry))
1379 && STRINGP(XCAR(XCDR(entry)))) {
1380 Lisp_Object format = XCAR(XCDR(entry));
1381 Bytind len = XSTRING_LENGTH(format);
1382 Bufbyte *src = XSTRING_DATA(format), *end = src + len;
1383 Bufbyte *result = alloca_array(Bufbyte, len);
1384 Bufbyte *dst = result;
1387 Emchar c = charptr_emchar(src);
1389 if (c != '%' || src == end) {
1390 dst += set_charptr_emchar(dst, c);
1392 c = charptr_emchar(src);
1396 dst += long_to_string_base
1397 ((char *)dst, data->ch, 16);
1400 dst += set_charptr_emchar(
1403 /* #### unimplemented */
1410 add_bufbyte_string_runes(data, result, dst - result,
1415 /* Else blow it off because someone added a bad entry and we don't
1416 have any safe way of signaling an error. */
1420 /* Given a display table entry, call the appropriate functions to
1421 display each element of the entry. */
1423 static prop_block_dynarr *add_disp_table_entry_runes(pos_data * data,
1426 prop_block_dynarr *prop = NULL;
1427 if (VECTORP(entry)) {
1428 Lisp_Vector *de = XVECTOR(entry);
1429 EMACS_INT len = vector_length(de);
1432 for (elt = 0; elt < len; elt++) {
1433 if (NILP(vector_data(de)[elt]))
1437 add_disp_table_entry_runes_1(data,
1440 /* Else blow it off because someone added a bad entry and we
1441 don't have any safe way of signaling an error. Hey, this
1442 comment sounds familiar. */
1444 /* #### Still need to add any remaining elements to the
1445 propagation information. */
1450 prop = add_disp_table_entry_runes_1(data, entry);
1454 /* Add runes which were propagated from the previous line. */
1456 static prop_block_dynarr *add_propagation_runes(prop_block_dynarr ** prop,
1459 /* #### Remember to handle start_col parameter of data when the rest of
1460 this is finished. */
1461 /* #### Chuck -- I've redone this function a bit. It looked like the
1462 case of not all the propagation blocks being added was not handled
1464 /* #### Chuck -- I also think the double indirection of PROP is kind
1465 of bogus. A cleaner solution is just to check for
1466 Dynarr_length (prop) > 0. */
1467 /* #### This function also doesn't even pay attention to ADD_FAILED!
1468 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1471 prop_block_dynarr *add_failed;
1472 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1473 unsigned int old_cursor_type = data->cursor_type;
1475 for (elt = 0; elt < Dynarr_length(*prop); elt++) {
1476 struct prop_block *pb = Dynarr_atp(*prop, elt);
1480 data->ch = pb->data.p_char.ch;
1481 data->bi_cursor_bufpos =
1482 pb->data.p_char.bi_cursor_bufpos;
1483 data->cursor_type = pb->data.p_char.cursor_type;
1484 add_failed = add_emchar_rune(data);
1487 goto oops_no_more_space;
1490 if (pb->data.p_string.str)
1491 xfree(pb->data.p_string.str);
1492 /* #### bogus bogus -- this doesn't do anything!
1493 Should probably call add_bufbyte_string_runes(),
1494 once that function is fixed. */
1496 case PROP_MINIBUF_PROMPT: {
1497 face_index old_findex = data->findex;
1498 Bytind bi_old_bufpos = data->bi_bufpos;
1500 data->findex = DEFAULT_INDEX;
1501 data->bi_bufpos = 0;
1502 data->cursor_type = NO_CURSOR;
1504 while (pb->data.p_string.len > 0) {
1506 charptr_emchar(pb->data.p_string.
1508 add_failed = add_emchar_rune(data);
1511 data->findex = old_findex;
1512 data->bi_bufpos = bi_old_bufpos;
1513 goto oops_no_more_space;
1515 /* Complicated equivalent of ptr++,
1518 pb->data.p_string.str;
1519 INC_CHARPTR(pb->data.p_string.
1521 pb->data.p_string.len -=
1522 pb->data.p_string.str -
1527 data->findex = old_findex;
1528 /* ##### FIXME FIXME FIXME -- Upon successful return
1529 from this function, data->bi_bufpos is automatically
1530 incremented. However, we don't want that to happen
1531 if we were adding the minibuffer prompt. */
1533 struct buffer *buf =
1534 XBUFFER(WINDOW_BUFFER
1535 (XWINDOW(data->window)));
1536 /* #### Chuck fix this shit or I'm gonna
1538 if (bi_old_bufpos > BI_BUF_BEGV(buf)) {
1543 /* #### is this correct?
1545 Does anyone care? Is this a cheesy
1548 BI_BUF_BEGV(buf) - 1;
1554 /* #### I think it's unnecessary and misleading to
1555 preserve the blank_width, as it implies that the
1556 value carries over from one rune to the next,
1558 int old_width = data->blank_width;
1559 face_index old_findex = data->findex;
1561 data->findex = pb->data.p_blank.findex;
1562 data->blank_width = pb->data.p_blank.width;
1563 data->bi_cursor_bufpos = 0;
1564 data->cursor_type = IGNORE_CURSOR;
1566 if (data->pixpos + data->blank_width >
1569 data->max_pixpos - data->pixpos;
1571 /* We pass a bogus value of char_tab_width. It
1572 shouldn't matter because unless something is really
1573 screwed up this call won't cause that arg to be
1575 add_failed = add_blank_rune(
1576 data, XWINDOW(data->window), 0);
1578 /* This can happen in the case where we have a tab which
1579 is wider than the window. */
1580 if (data->blank_width != pb->data.p_blank.width) {
1581 pb->data.p_blank.width -=
1583 add_failed = ADD_FAILED;
1586 data->findex = old_findex;
1587 data->blank_width = old_width;
1590 goto oops_no_more_space;
1602 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1603 data->cursor_type = old_cursor_type;
1604 if (elt < Dynarr_length(*prop)) {
1605 Dynarr_delete_many(*prop, 0, elt);
1613 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1614 the display block, but add all other types to the appropriate list
1615 of the display line. They will be added later by different
1618 static void add_glyph_rune_noret(pos_data * data,
1619 struct glyph_block *gb, int pos_type,
1621 struct glyph_cachel *cachel)
1623 prop_block_dynarr *prop = add_glyph_rune(data,gb,pos_type,allow_cursor,cachel);
1624 if (prop && prop != ADD_FAILED )
1628 static prop_block_dynarr *add_glyph_rune(pos_data * data,
1629 struct glyph_block *gb, int pos_type,
1631 struct glyph_cachel *cachel)
1633 struct window *w = XWINDOW(data->window);
1635 /* If window faces changed, and glyph instance is text, then
1636 glyph sizes might have changed too */
1637 invalidate_glyph_geometry_maybe(gb->glyph, w);
1639 /* This makes sure the glyph is in the cachels.
1641 #### We do this to make sure the glyph is in the glyph cachels,
1642 so that the dirty flag can be reset after redisplay has
1643 finished. We should do this some other way, maybe by iterating
1644 over the window cache of subwindows. */
1645 get_glyph_cachel_index(w, gb->glyph);
1647 /* A nil extent indicates a special glyph (ex. truncator). */
1648 if (NILP(gb->extent)
1649 || (pos_type == BEGIN_GLYPHS &&
1650 extent_begin_glyph_layout(XEXTENT(gb->extent)) == GL_TEXT)
1651 || (pos_type == END_GLYPHS &&
1652 extent_end_glyph_layout(XEXTENT(gb->extent)) == GL_TEXT)
1653 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) {
1657 int ascent, descent;
1658 Lisp_Object baseline;
1660 Lisp_Object instance;
1662 prop_block_dynarr *retval = 0;
1665 width = cachel->width;
1667 width = glyph_width(gb->glyph, data->window);
1672 if (data->start_col || data->start_col_xoffset) {
1673 int glyph_char_width = width / space_width(w);
1675 /* If we still have not fully scrolled horizontally after
1676 taking into account the width of the glyph, subtract its
1677 width and return. */
1678 if (glyph_char_width < data->start_col) {
1679 data->start_col -= glyph_char_width;
1681 } else if (glyph_char_width == data->start_col)
1684 xoffset = space_width(w) * data->start_col;
1687 /* #### Can this happen? */
1692 data->start_col = 0;
1693 retval = add_hscroll_rune(data);
1695 /* Could be caused by the handling of the hscroll rune. */
1696 if (retval != NULL || !width)
1701 if (data->pixpos + width > data->max_pixpos) {
1702 /* If this is the first object we are attempting to add to
1703 the line then we ignore the horizontal_clip threshold.
1704 Otherwise we will loop until the bottom of the window
1705 continually failing to add this glyph because it is wider
1706 than the window. We could alternatively just completely
1707 ignore the glyph and proceed from there but I think that
1708 this is a better solution.
1710 This does, however, create a different problem in that we
1711 can end up adding the object to every single line, never
1712 getting any further - for instance an extent with a long
1713 start-glyph that covers multitple following
1715 if (Dynarr_length(data->db->runes)
1716 && data->max_pixpos - data->pixpos <
1720 struct prop_block pb;
1722 /* We need to account for the width of the end-of-line
1723 glyph if there is nothing more in the line to display,
1724 since we will not display it in this instance. It seems
1725 kind of gross doing it here, but otherwise we have to
1726 search the runes in create_text_block(). */
1727 if (data->ch == '\n')
1729 data->end_glyph_width;
1730 width = data->max_pixpos - data->pixpos;
1731 /* Add the glyph we are displaying, but clipping, to the
1732 propagation data so that we don't try and do it
1734 retval = Dynarr_new(prop_block);
1735 pb.type = PROP_GLYPH;
1736 pb.data.p_glyph.glyph = gb->glyph;
1737 pb.data.p_glyph.width = width;
1738 Dynarr_add(retval, pb);
1743 ascent = cachel->ascent;
1744 descent = cachel->descent;
1746 ascent = glyph_ascent(gb->glyph, data->window);
1747 descent = glyph_descent(gb->glyph, data->window);
1750 baseline = glyph_baseline(gb->glyph, data->window);
1752 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */
1754 if (glyph_contrib_p(gb->glyph, data->window)) {
1755 /* A pixmap that has not had a baseline explicitly set. Its
1756 contribution will be determined later. */
1757 if (NILP(baseline)) {
1758 int height = ascent + descent;
1759 data->need_baseline_computation = 1;
1760 data->max_pixmap_height =
1761 max(data->max_pixmap_height, height);
1764 /* A string so determine contribution normally. */
1765 else if (EQ(baseline, Qt)) {
1767 max(data->new_ascent, ascent);
1769 max(data->new_descent, descent);
1772 /* A pixmap with an explicitly set baseline. We determine the
1773 contribution here. */
1774 else if (INTP(baseline)) {
1775 int height = ascent + descent;
1776 int pix_ascent, pix_descent;
1778 pix_ascent = height * XINT(baseline) / 100;
1779 pix_descent = height - pix_ascent;
1782 max(data->new_ascent, pix_ascent);
1784 max(data->new_descent, pix_descent);
1785 data->max_pixmap_height =
1786 max(data->max_pixmap_height, height);
1788 rb.object.dglyph.descent = pix_descent;
1791 /* Otherwise something is screwed up. */
1796 face = glyph_face(gb->glyph, data->window);
1798 findex = data->findex;
1800 findex = get_builtin_face_cache_index(w, face);
1802 instance = glyph_image_instance(gb->glyph, data->window,
1804 if (TEXT_IMAGE_INSTANCEP(instance)) {
1805 Lisp_Object string =
1806 XIMAGE_INSTANCE_TEXT_STRING(instance);
1807 face_index orig_findex = data->findex;
1808 Bytind orig_bufpos = data->bi_bufpos;
1809 Bytind orig_start_col_enabled =
1810 data->bi_start_col_enabled;
1812 data->findex = findex;
1813 data->bi_start_col_enabled = 0;
1815 data->bi_bufpos = 0;
1816 add_bufbyte_string_runes(data, XSTRING_DATA(string),
1817 XSTRING_LENGTH(string), 0, 1);
1818 data->findex = orig_findex;
1819 data->bi_bufpos = orig_bufpos;
1820 data->bi_start_col_enabled = orig_start_col_enabled;
1825 rb.xpos = data->pixpos;
1827 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1828 if (data->bi_endpos)
1829 /* #### is this necessary at all? */
1830 rb.endpos = bytind_to_bufpos(XBUFFER(WINDOW_BUFFER(w)),
1834 rb.type = RUNE_DGLYPH;
1835 rb.object.dglyph.glyph = gb->glyph;
1836 rb.object.dglyph.extent = gb->extent;
1837 rb.object.dglyph.xoffset = xoffset;
1838 rb.object.dglyph.ascent = ascent;
1839 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has
1840 a normal (textual) baseline. */
1843 rb.bufpos = bytind_to_bufpos(XBUFFER(WINDOW_BUFFER(w)),
1846 if (data->cursor_type == CURSOR_ON) {
1847 if (data->bi_bufpos == data->bi_cursor_bufpos) {
1848 rb.cursor_type = CURSOR_ON;
1850 Dynarr_length(data->db->runes);
1852 rb.cursor_type = CURSOR_OFF;
1853 } else if (data->cursor_type == NEXT_CURSOR) {
1854 rb.cursor_type = CURSOR_ON;
1855 data->cursor_x = Dynarr_length(data->db->runes);
1856 data->cursor_type = NO_CURSOR;
1857 } else if (data->cursor_type == IGNORE_CURSOR)
1858 rb.cursor_type = IGNORE_CURSOR;
1859 else if (data->cursor_type == NO_CURSOR)
1860 rb.cursor_type = NO_CURSOR;
1862 rb.cursor_type = CURSOR_OFF;
1864 rb.cursor_type = CURSOR_OFF;
1866 Dynarr_add(data->db->runes, rb);
1867 data->pixpos += width;
1871 if (!NILP(glyph_face(gb->glyph, data->window)))
1873 get_builtin_face_cache_index(w,
1874 glyph_face(gb->glyph,
1878 gb->findex = data->findex;
1880 if (pos_type == BEGIN_GLYPHS) {
1881 if (!data->dl->left_glyphs)
1882 data->dl->left_glyphs = Dynarr_new(glyph_block);
1883 Dynarr_add(data->dl->left_glyphs, *gb);
1885 } else if (pos_type == END_GLYPHS) {
1886 if (!data->dl->right_glyphs)
1887 data->dl->right_glyphs =
1888 Dynarr_new(glyph_block);
1889 Dynarr_add(data->dl->right_glyphs, *gb);
1892 abort(); /* there are no unknown types */
1898 /* Add all glyphs at position POS_TYPE that are contained in the given
1901 static prop_block_dynarr *add_glyph_runes(pos_data * data)
1903 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1904 why didn't you just modify add_glyph_rune in the first place? */
1906 glyph_block_dynarr *glyph_arr = (data->ef->glyphs);
1907 prop_block_dynarr *prop;
1909 for (elt = 0; elt < Dynarr_length(glyph_arr); elt++) {
1910 struct glyph_block *gb = Dynarr_atp(glyph_arr, elt);
1911 prop = add_glyph_rune(data, gb,
1912 gb->active ? END_GLYPHS : BEGIN_GLYPHS,
1916 /* #### Add some propagation information. */
1921 Dynarr_reset(glyph_arr);
1926 /* Given a position for a buffer in a window, ensure that the given
1927 display line DL accurately represents the text on a line starting
1928 at the given position.
1930 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1931 You must do appropriate conversion. */
1934 create_text_block(struct window *w, struct display_line *dl,
1935 Bytind bi_start_pos, prop_block_dynarr ** prop, int type)
1937 struct frame *f = XFRAME(w->frame);
1938 struct buffer *b = XBUFFER(w->buffer);
1939 struct device *d = XDEVICE(f->device);
1943 /* Don't display anything in the minibuffer if this window is not on
1944 a selected frame. We consider all other windows to be active
1945 minibuffers as it simplifies the coding. */
1946 int active_minibuffer = (!MINI_WINDOW_P(w) ||
1947 (f == device_selected_frame(d)) ||
1948 is_surrogate_for_selected_frame(f));
1950 int truncate_win = window_truncation_on(w);
1952 /* If the buffer's value of selective_display is an integer then
1953 only lines that start with less than selective_display columns of
1954 space will be displayed. If selective_display is t then all text
1955 after a ^M is invisible. */
1956 int selective = (INTP(b->selective_display)
1957 ? XINT(b->selective_display)
1958 : (!NILP(b->selective_display) ? -1 : 0));
1960 /* The variable ctl-arrow allows the user to specify what characters
1961 can actually be displayed and which octal should be used for.
1962 #### This variable should probably have some rethought done to
1965 #### It would also be really nice if you could specify that
1966 the characters come out in hex instead of in octal. Mule
1967 does that by adding a ctl-hexa variable similar to ctl-arrow,
1968 but that's bogus -- we need a more general solution. I
1969 think you need to extend the concept of display tables
1970 into a more general conversion mechanism. Ideally you
1971 could specify a Lisp function that converts characters,
1972 but this violates the Second Golden Rule and besides would
1973 make things way way way way slow.
1975 So instead, we extend the display-table concept, which was
1976 historically limited to 256-byte vectors, to one of the
1979 a) A 256-entry vector, for backward compatibility;
1980 b) char-table, mapping characters to values;
1981 c) range-table, mapping ranges of characters to values;
1982 d) a list of the above.
1984 The (d) option allows you to specify multiple display tables
1985 instead of just one. Each display table can specify conversions
1986 for some characters and leave others unchanged. The way the
1987 character gets displayed is determined by the first display table
1988 with a binding for that character. This way, you could call a
1989 function `enable-hex-display' that adds a hex display-table to
1990 the list of display tables for the current buffer.
1992 #### ...not yet implemented... Also, we extend the concept of
1993 "mapping" to include a printf-like spec. Thus you can make all
1994 extended characters show up as hex with a display table like
1997 #s(range-table data ((256 524288) (format "%x")))
1999 Since more than one display table is possible, you have
2000 great flexibility in mapping ranges of characters. */
2001 Emchar printable_min = (CHAR_OR_CHAR_INTP(b->ctl_arrow)
2002 ? XCHAR_OR_CHAR_INT(b->ctl_arrow)
2003 : ((EQ(b->ctl_arrow, Qt)
2004 || EQ(b->ctl_arrow, Qnil))
2007 Lisp_Object face_dt, window_dt;
2009 /* The text display block for this display line. */
2010 struct display_block *db = get_display_block_from_line(dl, TEXT);
2012 /* The first time through the main loop we need to force the glyph
2013 data to be updated. */
2016 /* Apparently the new extent_fragment_update returns an end position
2017 equal to the position passed in if there are no more runs to be
2019 int no_more_frags = 0;
2021 Lisp_Object synch_minibuffers_value =
2022 symbol_value_in_buffer(Qsynchronize_minibuffers, w->buffer);
2024 dl->used_prop_data = 0;
2026 dl->line_continuation = 0;
2029 data.ef = extent_fragment_new(w->buffer, f);
2031 /* These values are used by all of the rune addition routines. We add
2032 them to this structure for ease of passing. */
2034 XSETWINDOW(data.window, w);
2039 data.bi_bufpos = bi_start_pos;
2040 data.pixpos = dl->bounds.left_in;
2041 data.last_charset = Qunbound;
2042 data.last_findex = DEFAULT_INDEX;
2043 data.result_str = Qnil;
2045 /* Set the right boundary adjusting it to take into account any end
2046 glyph. Save the width of the end glyph for later use. */
2047 data.max_pixpos = dl->bounds.right_in;
2049 data.end_glyph_width = GLYPH_CACHEL_WIDTH(w, TRUN_GLYPH_INDEX);
2051 data.end_glyph_width = GLYPH_CACHEL_WIDTH(w, CONT_GLYPH_INDEX);
2052 data.max_pixpos -= data.end_glyph_width;
2054 if (cursor_in_echo_area && MINI_WINDOW_P(w) && echo_area_active(f)) {
2055 data.bi_cursor_bufpos = BI_BUF_ZV(b);
2056 data.cursor_type = CURSOR_ON;
2057 } else if (MINI_WINDOW_P(w) && !active_minibuffer)
2058 data.cursor_type = NO_CURSOR;
2059 else if (w == XWINDOW(FRAME_SELECTED_WINDOW(f)) &&
2060 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
2062 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))
2063 && f == XFRAME(DEVICE_SELECTED_FRAME(d))) {
2064 data.bi_cursor_bufpos = BI_BUF_PT(b);
2065 data.cursor_type = CURSOR_ON;
2066 } else if (w == XWINDOW(FRAME_SELECTED_WINDOW(f))) {
2067 data.bi_cursor_bufpos = bi_marker_position(w->pointm[type]);
2068 data.cursor_type = CURSOR_ON;
2070 data.cursor_type = NO_CURSOR;
2073 data.start_col = w->hscroll;
2074 data.start_col_xoffset = w->left_xoffset;
2075 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
2076 data.hscroll_glyph_width_adjust = 0;
2078 /* We regenerate the line from the very beginning. */
2079 Dynarr_reset(db->runes);
2081 /* Why is this less than or equal and not just less than? If the
2082 starting position is already equal to the maximum we can't add
2083 anything else, right? Wrong. We might still have a newline to
2084 add. A newline can use the room allocated for an end glyph since
2085 if we add it we know we aren't going to be adding any end
2088 /* #### Chuck -- I think this condition should be while (1).
2089 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
2090 and the begin-glyph ends exactly at the end of the window, the
2091 end-glyph and text might not be displayed. while (1) ensures
2092 that the loop terminates only when either (a) there is
2093 propagation data or (b) the end-of-line or end-of-buffer is hit.
2095 #### Also I think you need to ensure that the operation
2096 "add begin glyphs; add end glyphs; add text" is atomic and
2097 can't get interrupted in the middle. If you run off the end
2098 of the line during that operation, then you keep accumulating
2099 propagation data until you're done. Otherwise, if the (e.g.)
2100 there's a begin glyph at a particular position and attempting
2101 to display that glyph results in window-end being hit and
2102 propagation data being generated, then the character at that
2103 position won't be displayed.
2105 #### See also the comment after the end of this loop, below.
2107 while (data.pixpos <= data.max_pixpos
2108 && (active_minibuffer || !NILP(synch_minibuffers_value))) {
2109 /* #### This check probably should not be necessary. */
2110 if (data.bi_bufpos > BI_BUF_ZV(b)) {
2111 /* #### urk! More of this lossage! */
2116 /* If selective display was an integer and we aren't working on
2117 a continuation line then find the next line we are actually
2118 supposed to display. */
2119 if (selective > 0 && (data.bi_bufpos == BI_BUF_BEGV(b)
2120 || BUF_FETCH_CHAR(b,
2125 while (bi_spaces_at_point(b, data.bi_bufpos) >=
2128 bi_find_next_newline_no_quit(b,
2131 if (data.bi_bufpos >= BI_BUF_ZV(b)) {
2132 data.bi_bufpos = BI_BUF_ZV(b);
2138 /* Check for face changes. */
2140 || (!no_more_frags && data.bi_bufpos == data.ef->end)) {
2141 Lisp_Object last_glyph = Qnil;
2143 /* Deal with glyphs that we have already displayed. The
2144 theory is that if we end up with a PROP_GLYPH in the
2145 propagation data then we are clipping the glyph and there
2146 can be no propagation data before that point. The theory
2147 works because we always recalculate the extent-fragments
2148 for propagated data, we never actually propagate the
2149 fragments that still need to be displayed. */
2150 if (*prop && Dynarr_atp(*prop, 0)->type == PROP_GLYPH) {
2152 Dynarr_atp(*prop, 0)->data.p_glyph.glyph;
2156 /* Now compute the face and begin/end-glyph information. */
2158 /* Remember that the extent-fragment routines deal in Bytind's. */
2159 extent_fragment_update(w, data.ef, data.bi_bufpos,
2162 get_display_tables(w, data.findex, &face_dt,
2165 if (data.bi_bufpos == data.ef->end)
2170 /* Determine what is next to be displayed. We first handle any
2171 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2172 display then we determine what to do based on the character at the
2173 current buffer position. */
2175 /* If there are glyphs, add them to the line. These are
2176 the end glyphs for the previous run of text. We add
2177 them here rather than doing them at the end of handling
2178 the previous run so that glyphs at the beginning and
2179 end of a line are handled correctly. */
2180 if (Dynarr_length (data.ef->glyphs) > 0) {
2181 glyph_block_dynarr* tmpglyphs = 0;
2182 /* #### I think this is safe, but could be wrong. */
2183 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2185 *prop = add_glyph_runes (&data);
2186 tmpglyphs = data.ef->glyphs;
2190 /* If we just clipped a glyph and we are
2191 at the end of a line and there are more
2192 glyphs to display then do appropriate
2193 processing to not get a continuation
2195 if (*prop != ADD_FAILED
2196 && Dynarr_atp (*prop, 0)->type == PROP_GLYPH
2197 && data.ch == '\n') {
2198 /* If there are no more glyphs
2199 then do the normal processing.
2201 #### This doesn't actually work
2202 if the same glyph is present
2203 more than once in the block. To
2204 solve this we would have to
2205 carry the index around which
2206 might be problematic since the
2207 fragment is recalculated for
2209 if (EQ (Dynarr_end (tmpglyphs)->glyph,
2210 Dynarr_atp (*prop, 0)->data.p_glyph.glyph)) {
2211 Dynarr_free (*prop);
2215 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2216 add_emchar_rune (&data); /* discard prop data. */
2225 /* If the current position is covered by an invisible
2226 extent, do nothing (except maybe add some
2228 else if (data.ef->invisible) {
2229 /* #### Chuck, perhaps you could look at this code? I don't
2230 really know what I'm doing. */
2236 /* The extent fragment code only sets this when we should
2237 really display the ellipses. It makes sure the ellipses
2238 don't get displayed more than once in a row. */
2239 if (data.ef->invisible_ellipses) {
2240 struct glyph_block gb;
2242 data.ef->invisible_ellipses_already_displayed =
2244 data.ef->invisible_ellipses = 0;
2246 gb.glyph = Vinvisible_text_glyph;
2248 add_glyph_rune(&data, &gb, BEGIN_GLYPHS, 0,
2250 INVIS_GLYPH_INDEX));
2251 /* Perhaps they shouldn't propagate if the very next thing
2252 is to display a newline (for compatibility with
2253 selective-display-ellipses)? Maybe that's too
2259 /* If point is in an invisible region we place it on the
2260 next visible character. */
2261 if (data.cursor_type == CURSOR_ON
2262 && data.bi_bufpos == data.bi_cursor_bufpos) {
2263 data.cursor_type = NEXT_CURSOR;
2266 /* #### What if we we're dealing with a display table? */
2270 if (data.bi_bufpos == BI_BUF_ZV(b))
2273 INC_BYTIND(b, data.bi_bufpos);
2276 /* If there is propagation data, then it represents the current
2277 buffer position being displayed. Add them and advance the
2278 position counter. This might also add the minibuffer
2281 dl->used_prop_data = 1;
2282 *prop = add_propagation_runes(prop, &data);
2285 goto done; /* gee, a really narrow window */
2286 else if (data.bi_bufpos == BI_BUF_ZV(b))
2288 else if (data.bi_bufpos < BI_BUF_BEGV(b))
2289 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2290 data.bi_bufpos = BI_BUF_BEGV(b);
2292 INC_BYTIND(b, data.bi_bufpos);
2295 /* If at end-of-buffer, we've already processed begin and
2296 end-glyphs at this point and there's no text to process,
2298 else if (data.bi_bufpos == BI_BUF_ZV(b))
2302 Lisp_Object entry = Qnil;
2303 /* Get the character at the current buffer position. */
2304 data.ch = BI_BUF_FETCH_CHAR(b, data.bi_bufpos);
2305 if (!NILP(face_dt) || !NILP(window_dt))
2307 display_table_entry(data.ch, face_dt,
2310 /* If there is a display table entry for it, hand it off to
2311 add_disp_table_entry_runes and let it worry about it. */
2312 if (!NILP(entry) && !EQ(entry, make_char(data.ch))) {
2314 add_disp_table_entry_runes(&data, entry);
2320 /* Check if we have hit a newline character. If so, add a marker
2321 to the line and end this loop. */
2322 else if (data.ch == '\n') {
2323 /* We aren't going to be adding an end glyph so give its
2324 space back in order to make sure that the cursor can
2326 data.max_pixpos += data.end_glyph_width;
2329 && (bi_spaces_at_point
2330 (b, next_bytind(b, data.bi_bufpos))
2333 (b->selective_display_ellipses)) {
2334 struct glyph_block gb;
2338 Vinvisible_text_glyph;
2339 add_glyph_rune_noret(&data, &gb,
2342 INVIS_GLYPH_INDEX));
2344 /* Cheesy, cheesy, cheesy. We mark the end of the
2345 line with a special "character rune" whose width
2346 is the EOL cursor width and whose character is
2347 the non-printing character '\n'. */
2349 DEVMETH(d, eol_cursor_width,
2351 *prop = add_emchar_rune(&data);
2354 /* We need to set data.bi_bufpos to the start of the
2355 next visible region in order to make this line
2356 appear to contain all of the invisible area.
2357 Otherwise, the line cache won't work
2359 INC_BYTIND(b, data.bi_bufpos);
2360 while (bi_spaces_at_point
2362 data.bi_bufpos) >= selective) {
2364 bi_find_next_newline_no_quit
2365 (b, data.bi_bufpos, 1);
2366 if (data.bi_bufpos >=
2373 if (BI_BUF_FETCH_CHAR
2378 DEC_BYTIND(b, data.bi_bufpos);
2381 DEVMETH(d, eol_cursor_width, ());
2382 *prop = add_emchar_rune(&data);
2388 /* If the current character is ^M, and selective display is
2389 enabled, then add the invisible-text-glyph if
2390 selective-display-ellipses is set. In any case, this
2392 else if (data.ch == (('M' & 037)) && selective == -1) {
2393 Bytind bi_next_bufpos;
2395 /* Find the buffer position at the end of the line. */
2397 bi_find_next_newline_no_quit(b,
2400 if (BI_BUF_FETCH_CHAR
2401 (b, prev_bytind(b, bi_next_bufpos))
2403 DEC_BYTIND(b, bi_next_bufpos);
2405 /* If the cursor is somewhere in the elided text make
2406 sure that the cursor gets drawn appropriately. */
2407 if (data.cursor_type == CURSOR_ON
2408 && (data.bi_cursor_bufpos >= data.bi_bufpos
2409 && data.bi_cursor_bufpos <
2411 data.cursor_type = NEXT_CURSOR;
2414 /* We won't be adding a truncation or continuation glyph
2415 so give up the room allocated for them. */
2416 data.max_pixpos += data.end_glyph_width;
2418 if (!NILP(b->selective_display_ellipses)) {
2419 /* We don't propagate anything from the invisible
2420 text glyph if it fails to fit. This is
2422 struct glyph_block gb;
2425 gb.glyph = Vinvisible_text_glyph;
2426 add_glyph_rune(&data, &gb, BEGIN_GLYPHS,
2428 INVIS_GLYPH_INDEX));
2431 /* Set the buffer position to the end of the line. We
2432 need to do this before potentially adding a newline
2433 so that the cursor flag will get set correctly (if
2435 data.bi_bufpos = bi_next_bufpos;
2437 if (NILP(b->selective_display_ellipses)
2438 || data.bi_cursor_bufpos == bi_next_bufpos) {
2439 /* We have to at least add a newline character so
2440 that the cursor shows up properly. */
2443 DEVMETH(d, eol_cursor_width, ());
2444 data.findex = DEFAULT_INDEX;
2446 data.start_col_xoffset = 0;
2447 data.bi_start_col_enabled = 0;
2449 add_emchar_rune(&data);
2452 /* This had better be a newline but doing it this way
2453 we'll see obvious incorrect results if it isn't. No
2454 need to abort here. */
2455 data.ch = BI_BUF_FETCH_CHAR(b, data.bi_bufpos);
2460 /* If the current character is considered to be printable, then
2462 else if (data.ch >= printable_min) {
2463 *prop = add_emchar_rune(&data);
2468 /* If the current character is a tab, determine the next tab
2469 starting position and add a blank rune which extends from the
2470 current pixel position to that starting position. */
2471 else if (data.ch == '\t') {
2472 int tab_start_pixpos = data.pixpos;
2477 if (data.start_col > 1)
2480 (data.start_col - 1))
2481 + data.start_col_xoffset;
2484 next_tab_position(w, tab_start_pixpos,
2485 dl->bounds.left_in +
2487 hscroll_glyph_width_adjust);
2488 if (next_tab_start > data.max_pixpos) {
2490 next_tab_start - data.max_pixpos;
2491 next_tab_start = data.max_pixpos;
2493 data.blank_width = next_tab_start - data.pixpos;
2496 tab_start_pixpos) / space_width(w);
2499 add_blank_rune(&data, w, char_tab_width);
2501 /* add_blank_rune is only supposed to be called with
2502 sizes guaranteed to fit in the available space. */
2506 struct prop_block pb;
2507 *prop = Dynarr_new(prop_block);
2509 pb.type = PROP_BLANK;
2510 pb.data.p_blank.width = prop_width;
2511 pb.data.p_blank.findex = data.findex;
2512 Dynarr_add(*prop, pb);
2518 /* If character is a control character, pass it off to
2519 add_control_char_runes.
2521 The is_*() routines have undefined results on
2522 arguments outside of the range [-1, 255]. (This
2523 often bites people who carelessly use `char' instead
2524 of `unsigned char'.)
2526 else if (data.ch < 0x100 && iscntrl((Bufbyte) data.ch)) {
2527 *prop = add_control_char_runes(&data, b);
2533 /* If the character is above the ASCII range and we have not
2534 already handled it, then print it as an octal number. */
2535 else if (data.ch >= 0200) {
2536 *prop = add_octal_runes(&data);
2542 /* Assume the current character is considered to be printable,
2543 then just add it. */
2545 *prop = add_emchar_rune(&data);
2550 INC_BYTIND(b, data.bi_bufpos);
2556 /* Determine the starting point of the next line if we did not hit the
2557 end of the buffer. */
2558 if (data.bi_bufpos < BI_BUF_ZV(b)
2559 && (active_minibuffer || !NILP(synch_minibuffers_value))) {
2560 /* #### This check is not correct. If the line terminated
2561 due to a begin-glyph or end-glyph hitting window-end, then
2562 data.ch will not point to the character at data.bi_bufpos. If
2563 you make the two changes mentioned at the top of this loop,
2564 you should be able to say '(if (*prop))'. That should also
2565 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2568 /* The common case is that the line ended because we hit a newline.
2569 In that case, the next character is just the next buffer
2571 if (data.ch == '\n') {
2572 /* If data.start_col_enabled is still true, then the window is
2573 scrolled far enough so that nothing on this line is visible.
2574 We need to stick a truncation glyph at the beginning of the
2575 line in that case unless the line is completely blank. */
2576 if (data.bi_start_col_enabled) {
2577 if (data.cursor_type == CURSOR_ON) {
2578 if (data.bi_cursor_bufpos >=
2580 && data.bi_cursor_bufpos <=
2582 data.bi_cursor_bufpos =
2585 data.findex = DEFAULT_INDEX;
2587 data.bi_start_col_enabled = 0;
2589 if (data.bi_bufpos != bi_start_pos) {
2590 struct glyph_block gb;
2593 gb.glyph = Vhscroll_glyph;
2594 add_glyph_rune(&data, &gb, BEGIN_GLYPHS,
2596 HSCROLL_GLYPH_INDEX));
2598 /* This duplicates code down below to add a newline to
2599 the end of an otherwise empty line. */
2602 DEVMETH(d, eol_cursor_width, ());
2604 add_emchar_rune(&data);
2608 INC_BYTIND(b, data.bi_bufpos);
2611 /* Otherwise we have a buffer line which cannot fit on one display
2614 struct glyph_block gb;
2615 struct glyph_cachel *cachel;
2617 /* If the line is to be truncated then we actually have to look
2618 for the next newline. We also add the end-of-line glyph which
2619 we know will fit because we adjusted the right border before
2620 we starting laying out the line. */
2621 data.max_pixpos += data.end_glyph_width;
2622 data.findex = DEFAULT_INDEX;
2628 /* Now find the start of the next line. */
2630 bi_find_next_newline_no_quit(b,
2634 /* If the cursor is past the truncation line then we
2635 make it appear on the truncation glyph. If we've hit
2636 the end of the buffer then we also make the cursor
2637 appear unless eob is immediately preceded by a
2638 newline. In that case the cursor should actually
2639 appear on the next line. */
2640 if (data.cursor_type == CURSOR_ON
2641 && data.bi_cursor_bufpos >= data.bi_bufpos
2642 && (data.bi_cursor_bufpos < bi_pos ||
2643 (bi_pos == BI_BUF_ZV(b)
2644 && (bi_pos == BI_BUF_BEGV(b)
2647 (b, prev_bytind(b, bi_pos))
2649 data.bi_cursor_bufpos = bi_pos;
2651 data.cursor_type = NO_CURSOR;
2653 data.bi_bufpos = bi_pos;
2654 gb.glyph = Vtruncation_glyph;
2655 cachel = GLYPH_CACHEL(w, TRUN_GLYPH_INDEX);
2657 /* The cursor can never be on the continuation glyph. */
2658 data.cursor_type = NO_CURSOR;
2660 /* data.bi_bufpos is already at the start of the next line. */
2662 dl->line_continuation = 1;
2663 gb.glyph = Vcontinuation_glyph;
2664 cachel = GLYPH_CACHEL(w, CONT_GLYPH_INDEX);
2667 add_glyph_rune(&data, &gb, BEGIN_GLYPHS, 0, cachel);
2669 if (truncate_win && data.bi_bufpos == BI_BUF_ZV(b)
2670 && BI_BUF_FETCH_CHAR(b,
2674 /* #### Damn this losing shit. */
2677 } else if ((active_minibuffer || !NILP(synch_minibuffers_value))
2678 && (!echo_area_active(f) || data.bi_bufpos == BI_BUF_ZV(b))) {
2679 /* We need to add a marker to the end of the line since there is no
2680 newline character in order for the cursor to get drawn. We label
2681 it as a newline so that it gets handled correctly by the
2682 whitespace routines below. */
2685 data.blank_width = DEVMETH(d, eol_cursor_width, ());
2686 data.findex = DEFAULT_INDEX;
2688 data.start_col_xoffset = 0;
2689 data.bi_start_col_enabled = 0;
2691 data.max_pixpos += data.blank_width;
2692 add_emchar_rune(&data);
2693 data.max_pixpos -= data.blank_width;
2695 /* #### urk! Chuck, this shit is bad news. Going around
2696 manipulating invalid positions is guaranteed to result in
2697 trouble sooner or later. */
2698 data.bi_bufpos = BI_BUF_ZV(b) + 1;
2701 /* Calculate left whitespace boundary. */
2705 /* Whitespace past a newline is considered right whitespace. */
2706 while (elt < Dynarr_length(db->runes)) {
2707 struct rune *rb = Dynarr_atp(db->runes, elt);
2709 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2710 || rb->type == RUNE_BLANK) {
2711 dl->bounds.left_white += rb->width;
2714 elt = Dynarr_length(db->runes);
2718 /* Calculate right whitespace boundary. */
2720 int elt = Dynarr_length(db->runes) - 1;
2723 while (!done && elt >= 0) {
2724 struct rune *rb = Dynarr_atp(db->runes, elt);
2726 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2727 && isspace(rb->object.chr.ch))
2728 && !rb->type == RUNE_BLANK) {
2729 dl->bounds.right_white = rb->xpos + rb->width;
2737 /* The line is blank so everything is considered to be right
2740 dl->bounds.right_white = dl->bounds.left_in;
2743 /* Set the display blocks bounds. */
2744 db->start_pos = dl->bounds.left_in;
2745 if (Dynarr_length(db->runes)) {
2747 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
2749 db->end_pos = rb->xpos + rb->width;
2751 db->end_pos = dl->bounds.right_white;
2753 calculate_baseline(&data);
2755 dl->ascent = data.new_ascent;
2756 dl->descent = data.new_descent;
2759 unsigned short ascent =
2760 (unsigned short)XINT(w->minimum_line_ascent);
2762 if (dl->ascent < ascent)
2763 dl->ascent = ascent;
2766 unsigned short descent =
2767 (unsigned short)XINT(w->minimum_line_descent);
2769 if (dl->descent < descent)
2770 dl->descent = descent;
2773 calculate_yoffset(dl, db);
2775 dl->cursor_elt = data.cursor_x;
2776 /* #### lossage lossage lossage! Fix this shit! */
2777 if (data.bi_bufpos > BI_BUF_ZV(b))
2778 dl->end_bufpos = BUF_ZV(b);
2780 dl->end_bufpos = bytind_to_bufpos(b, data.bi_bufpos) - 1;
2782 data.dl->num_chars = column_at_point(b, dl->end_bufpos, 0);
2784 /* This doesn't correctly take into account tabs and control
2785 characters but if the window isn't being truncated then this
2786 value isn't going to end up being used anyhow. */
2787 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2789 /* #### handle horizontally scrolled line with text none of which
2790 was actually laid out. */
2792 /* #### handle any remainder of overlay arrow */
2794 if (*prop == ADD_FAILED)
2797 if (truncate_win && *prop) {
2802 extent_fragment_delete(data.ef);
2804 /* #### If we started at EOB, then make sure we return a value past
2805 it so that regenerate_window will exit properly. This is bogus.
2806 The main loop should get fixed so that it isn't necessary to call
2807 this function if we are already at EOB. */
2809 if (data.bi_bufpos == BI_BUF_ZV(b) && bi_start_pos == BI_BUF_ZV(b))
2810 return data.bi_bufpos + 1; /* Yuck! */
2812 return data.bi_bufpos;
2815 /* Display the overlay arrow at the beginning of the given line. */
2817 static int create_overlay_glyph_block(struct window *w, struct display_line *dl)
2819 struct frame *f = XFRAME(w->frame);
2820 struct device *d = XDEVICE(f->device);
2823 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2824 if (!STRINGP(Voverlay_arrow_string) && !GLYPHP(Voverlay_arrow_string))
2830 XSETWINDOW(data.window, w);
2831 data.db = get_display_block_from_line(dl, OVERWRITE);
2833 data.pixpos = dl->bounds.left_in;
2834 data.max_pixpos = dl->bounds.right_in;
2835 data.cursor_type = NO_CURSOR;
2837 data.findex = DEFAULT_INDEX;
2838 data.last_charset = Qunbound;
2839 data.last_findex = DEFAULT_INDEX;
2840 data.result_str = Qnil;
2843 Dynarr_reset(data.db->runes);
2845 if (STRINGP(Voverlay_arrow_string)) {
2846 add_bufbyte_string_runes
2848 XSTRING_DATA(Voverlay_arrow_string),
2849 XSTRING_LENGTH(Voverlay_arrow_string), 1, 0);
2850 } else if (GLYPHP(Voverlay_arrow_string)) {
2851 struct glyph_block gb;
2853 gb.glyph = Voverlay_arrow_string;
2855 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS, 0, 0);
2858 calculate_baseline(&data);
2860 dl->ascent = data.new_ascent;
2861 dl->descent = data.new_descent;
2863 data.db->start_pos = dl->bounds.left_in;
2864 data.db->end_pos = data.pixpos;
2866 calculate_yoffset(dl, data.db);
2868 return data.pixpos - dl->bounds.left_in;
2871 /* Add a type of glyph to a margin display block. */
2874 add_margin_runes(struct display_line *dl, struct display_block *db, int start,
2875 int count, enum glyph_layout layout, int side,
2878 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2879 ? dl->left_glyphs : dl->right_glyphs);
2882 struct window *w = XWINDOW(window);
2883 struct frame *f = XFRAME(w->frame);
2884 struct device *d = XDEVICE(f->device);
2889 data.window = window;
2892 data.pixpos = start;
2893 data.cursor_type = NO_CURSOR;
2895 data.last_charset = Qunbound;
2896 data.last_findex = DEFAULT_INDEX;
2897 data.result_str = Qnil;
2899 data.new_ascent = dl->ascent;
2900 data.new_descent = dl->descent;
2902 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2903 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) {
2905 elt = Dynarr_length(gbd) - 1;
2910 end = Dynarr_length(gbd);
2913 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) {
2914 struct glyph_block *gb = Dynarr_atp(gbd, elt);
2916 if (NILP(gb->extent))
2917 abort(); /* these should have been handled in add_glyph_rune */
2920 ((side == LEFT_GLYPHS &&
2921 extent_begin_glyph_layout(XEXTENT(gb->extent)) == layout)
2922 || (side == RIGHT_GLYPHS &&
2923 extent_end_glyph_layout(XEXTENT(gb->extent)) ==
2925 data.findex = gb->findex;
2926 data.max_pixpos = data.pixpos + gb->width;
2927 add_glyph_rune_noret(&data, gb, side, 0, NULL);
2932 (reverse ? elt-- : elt++);
2935 calculate_baseline(&data);
2937 dl->ascent = data.new_ascent;
2938 dl->descent = data.new_descent;
2940 calculate_yoffset(dl, data.db);
2945 /* Add a blank to a margin display block. */
2948 add_margin_blank(struct display_line *dl, struct display_block *db,
2949 struct window *w, int xpos, int width, int side)
2953 rb.findex = (side == LEFT_GLYPHS
2954 ? get_builtin_face_cache_index(w, Vleft_margin_face)
2955 : get_builtin_face_cache_index(w, Vright_margin_face));
2960 rb.type = RUNE_BLANK;
2961 rb.cursor_type = CURSOR_OFF;
2963 Dynarr_add(db->runes, rb);
2966 /* Display glyphs in the left outside margin, left inside margin and
2967 left whitespace area. */
2970 create_left_glyph_block(struct window *w, struct display_line *dl,
2975 int use_overflow = (NILP(w->use_left_overflow) ? 0 : 1);
2977 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2978 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2979 int left_in_start = dl->bounds.left_in;
2980 int left_in_end = dl->bounds.left_in + overlay_width;
2982 struct display_block *odb, *idb;
2984 XSETWINDOW(window, w);
2986 /* We have to add the glyphs to the line in the order outside,
2987 inside, whitespace. However the precedence dictates that we
2988 determine how many will fit in the reverse order. */
2990 /* Determine how many whitespace glyphs we can display and where
2991 they should start. */
2992 white_in_start = dl->bounds.left_white;
2993 white_out_start = left_in_start;
2994 white_out_cnt = white_in_cnt = 0;
2997 while (elt < Dynarr_length(dl->left_glyphs)) {
2998 struct glyph_block *gb = Dynarr_atp(dl->left_glyphs, elt);
3000 if (NILP(gb->extent))
3001 abort(); /* these should have been handled in add_glyph_rune */
3003 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3007 width = glyph_width(gb->glyph, window);
3009 if (white_in_start - width >= left_in_end) {
3011 white_in_start -= width;
3014 } else if (use_overflow
3015 && (white_out_start - width >
3016 dl->bounds.left_out)) {
3018 white_out_start -= width;
3028 /* Determine how many inside margin glyphs we can display and where
3029 they should start. The inside margin glyphs get whatever space
3030 is left after the whitespace glyphs have been displayed. These
3031 are tricky to calculate since if we decide to use the overflow
3032 area we basically have to start over. So for these we build up a
3033 list of just the inside margin glyphs and manipulate it to
3034 determine the needed info. */
3036 glyph_block_dynarr *ib;
3037 int avail_in, avail_out;
3040 int used_in, used_out;
3043 used_in = used_out = 0;
3044 ib = Dynarr_new(glyph_block);
3045 while (elt < Dynarr_length(dl->left_glyphs)) {
3046 struct glyph_block *gb =
3047 Dynarr_atp(dl->left_glyphs, elt);
3049 if (NILP(gb->extent))
3050 abort(); /* these should have been handled in add_glyph_rune */
3052 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3054 gb->width = glyph_width(gb->glyph, window);
3055 used_in += gb->width;
3056 Dynarr_add(ib, *gb);
3065 avail_in = white_in_start - left_in_end;
3073 avail_out = white_out_start - dl->bounds.left_out;
3076 while (!done && marker < Dynarr_length(ib)) {
3077 int width = Dynarr_atp(ib, marker)->width;
3079 /* If everything now fits in the available inside margin
3080 space, we're done. */
3081 if (used_in <= avail_in)
3084 /* Otherwise see if we have room to move a glyph to the
3086 if (used_out + width <= avail_out) {
3097 /* At this point we now know that everything from marker on goes in
3098 the inside margin and everything before it goes in the outside
3099 margin. The stuff going into the outside margin is guaranteed
3100 to fit, but we may have to trim some stuff from the inside. */
3102 in_in_end = left_in_end;
3103 in_out_start = white_out_start;
3104 in_out_cnt = in_in_cnt = 0;
3108 while (elt < Dynarr_length(dl->left_glyphs)) {
3109 struct glyph_block *gb =
3110 Dynarr_atp(dl->left_glyphs, elt);
3112 if (NILP(gb->extent))
3113 abort(); /* these should have been handled in add_glyph_rune */
3115 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3117 int width = glyph_width(gb->glyph, window);
3121 in_out_start -= width;
3125 } else if (in_in_end + width < white_in_start) {
3138 /* Determine how many outside margin glyphs we can display. They
3139 always start at the left outside margin and can only use the
3140 outside margin space. */
3141 out_end = dl->bounds.left_out;
3145 while (elt < Dynarr_length(dl->left_glyphs)) {
3146 struct glyph_block *gb = Dynarr_atp(dl->left_glyphs, elt);
3148 if (NILP(gb->extent))
3149 abort(); /* these should have been handled in add_glyph_rune */
3151 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3152 GL_OUTSIDE_MARGIN) {
3153 int width = glyph_width(gb->glyph, window);
3155 if (out_end + width <= in_out_start) {
3167 /* Now that we know where everything goes, we add the glyphs as
3168 runes to the appropriate display blocks. */
3169 if (out_cnt || in_out_cnt || white_out_cnt) {
3170 odb = get_display_block_from_line(dl, LEFT_OUTSIDE_MARGIN);
3171 odb->start_pos = dl->bounds.left_out;
3172 /* #### We should stop adding a blank to account for the space
3173 between the end of the glyphs and the margin and instead set
3174 this accordingly. */
3175 odb->end_pos = dl->bounds.left_in;
3176 Dynarr_reset(odb->runes);
3180 if (in_in_cnt || white_in_cnt) {
3181 idb = get_display_block_from_line(dl, LEFT_INSIDE_MARGIN);
3182 idb->start_pos = dl->bounds.left_in;
3183 /* #### See above comment for odb->end_pos */
3184 idb->end_pos = dl->bounds.left_white;
3185 Dynarr_reset(idb->runes);
3189 /* First add the outside margin glyphs. */
3192 add_margin_runes(dl, odb, dl->bounds.left_out, out_cnt,
3193 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3195 end_xpos = dl->bounds.left_out;
3197 /* There may be blank space between the outside margin glyphs and
3198 the inside margin glyphs. If so, add a blank. */
3199 if (in_out_cnt && (in_out_start - end_xpos)) {
3200 add_margin_blank(dl, odb, w, end_xpos, in_out_start - end_xpos,
3204 /* Next add the inside margin glyphs which are actually in the
3207 end_xpos = add_margin_runes(dl, odb, in_out_start, in_out_cnt,
3208 GL_INSIDE_MARGIN, LEFT_GLYPHS,
3212 /* If we didn't add any inside margin glyphs to the outside margin,
3213 but are adding whitespace glyphs, then we need to add a blank
3215 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) {
3216 add_margin_blank(dl, odb, w, end_xpos,
3217 white_out_start - end_xpos, LEFT_GLYPHS);
3220 /* Next add the whitespace margin glyphs which are actually in the
3222 if (white_out_cnt) {
3224 add_margin_runes(dl, odb, white_out_start, white_out_cnt,
3225 GL_WHITESPACE, LEFT_GLYPHS, window);
3228 /* We take care of clearing between the end of the glyphs and the
3229 start of the inside margin for lines which have glyphs. */
3230 if (odb && (left_in_start - end_xpos)) {
3231 add_margin_blank(dl, odb, w, end_xpos, left_in_start - end_xpos,
3235 /* Next add the inside margin glyphs which are actually in the
3238 end_xpos = add_margin_runes(dl, idb, left_in_end, in_in_cnt,
3239 GL_INSIDE_MARGIN, LEFT_GLYPHS,
3242 end_xpos = left_in_end;
3244 /* Make sure that the area between the end of the inside margin
3245 glyphs and the whitespace glyphs is cleared. */
3246 if (idb && (white_in_start - end_xpos > 0)) {
3247 add_margin_blank(dl, idb, w, end_xpos,
3248 white_in_start - end_xpos, LEFT_GLYPHS);
3251 /* Next add the whitespace margin glyphs which are actually in the
3254 add_margin_runes(dl, idb, white_in_start, white_in_cnt,
3255 GL_WHITESPACE, LEFT_GLYPHS, window);
3258 /* Whitespace glyphs always end right next to the text block so
3259 there is nothing we have to make sure is cleared after them. */
3262 /* Display glyphs in the right outside margin, right inside margin and
3263 right whitespace area. */
3265 static void create_right_glyph_block(struct window *w, struct display_line *dl)
3269 int use_overflow = (NILP(w->use_right_overflow) ? 0 : 1);
3271 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3272 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3274 struct display_block *odb, *idb;
3276 XSETWINDOW(window, w);
3278 /* We have to add the glyphs to the line in the order outside,
3279 inside, whitespace. However the precedence dictates that we
3280 determine how many will fit in the reverse order. */
3282 /* Determine how many whitespace glyphs we can display and where
3283 they should start. */
3284 white_in_end = dl->bounds.right_white;
3285 white_out_end = dl->bounds.right_in;
3286 white_out_cnt = white_in_cnt = 0;
3289 while (elt < Dynarr_length(dl->right_glyphs)) {
3290 struct glyph_block *gb = Dynarr_atp(dl->right_glyphs, elt);
3292 if (NILP(gb->extent))
3293 abort(); /* these should have been handled in add_glyph_rune */
3295 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3297 int width = glyph_width(gb->glyph, window);
3299 if (white_in_end + width <= dl->bounds.right_in) {
3301 white_in_end += width;
3304 } else if (use_overflow
3305 && (white_out_end + width <=
3306 dl->bounds.right_out)) {
3308 white_out_end += width;
3318 /* Determine how many inside margin glyphs we can display and where
3319 they should start. The inside margin glyphs get whatever space
3320 is left after the whitespace glyphs have been displayed. These
3321 are tricky to calculate since if we decide to use the overflow
3322 area we basically have to start over. So for these we build up a
3323 list of just the inside margin glyphs and manipulate it to
3324 determine the needed info. */
3326 glyph_block_dynarr *ib;
3327 int avail_in, avail_out;
3330 int used_in, used_out;
3333 used_in = used_out = 0;
3334 ib = Dynarr_new(glyph_block);
3335 while (elt < Dynarr_length(dl->right_glyphs)) {
3336 struct glyph_block *gb =
3337 Dynarr_atp(dl->right_glyphs, elt);
3339 if (NILP(gb->extent))
3340 abort(); /* these should have been handled in add_glyph_rune */
3342 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3344 gb->width = glyph_width(gb->glyph, window);
3345 used_in += gb->width;
3346 Dynarr_add(ib, *gb);
3355 avail_in = dl->bounds.right_in - white_in_end;
3360 avail_out = dl->bounds.right_out - white_out_end;
3363 while (!done && marker < Dynarr_length(ib)) {
3364 int width = Dynarr_atp(ib, marker)->width;
3366 /* If everything now fits in the available inside margin
3367 space, we're done. */
3368 if (used_in <= avail_in)
3371 /* Otherwise see if we have room to move a glyph to the
3373 if (used_out + width <= avail_out) {
3384 /* At this point we now know that everything from marker on goes in
3385 the inside margin and everything before it goes in the outside
3386 margin. The stuff going into the outside margin is guaranteed
3387 to fit, but we may have to trim some stuff from the inside. */
3389 in_in_start = dl->bounds.right_in;
3390 in_out_end = dl->bounds.right_in;
3391 in_out_cnt = in_in_cnt = 0;
3395 while (elt < Dynarr_length(dl->right_glyphs)) {
3396 struct glyph_block *gb =
3397 Dynarr_atp(dl->right_glyphs, elt);
3399 if (NILP(gb->extent))
3400 abort(); /* these should have been handled in add_glyph_rune */
3402 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3404 int width = glyph_width(gb->glyph, window);
3408 in_out_end += width;
3412 } else if (in_in_start - width >= white_in_end) {
3414 in_in_start -= width;
3425 /* Determine how many outside margin glyphs we can display. They
3426 always start at the right outside margin and can only use the
3427 outside margin space. */
3428 out_start = dl->bounds.right_out;
3432 while (elt < Dynarr_length(dl->right_glyphs)) {
3433 struct glyph_block *gb = Dynarr_atp(dl->right_glyphs, elt);
3435 if (NILP(gb->extent))
3436 abort(); /* these should have been handled in add_glyph_rune */
3438 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3439 GL_OUTSIDE_MARGIN) {
3440 int width = glyph_width(gb->glyph, window);
3442 if (out_start - width >= in_out_end) {
3454 /* Now that we now where everything goes, we add the glyphs as runes
3455 to the appropriate display blocks. */
3456 if (out_cnt || in_out_cnt || white_out_cnt) {
3457 odb = get_display_block_from_line(dl, RIGHT_OUTSIDE_MARGIN);
3458 /* #### See comments before odb->start_pos init in
3459 create_left_glyph_block */
3460 odb->start_pos = dl->bounds.right_in;
3461 odb->end_pos = dl->bounds.right_out;
3462 Dynarr_reset(odb->runes);
3466 if (in_in_cnt || white_in_cnt) {
3467 idb = get_display_block_from_line(dl, RIGHT_INSIDE_MARGIN);
3468 idb->start_pos = dl->bounds.right_white;
3469 /* #### See comments before odb->start_pos init in
3470 create_left_glyph_block */
3471 idb->end_pos = dl->bounds.right_in;
3472 Dynarr_reset(idb->runes);
3476 /* First add the whitespace margin glyphs which are actually in the
3479 end_xpos = add_margin_runes(dl, idb, dl->bounds.right_white,
3480 white_in_cnt, GL_WHITESPACE,
3481 RIGHT_GLYPHS, window);
3483 end_xpos = dl->bounds.right_white;
3485 /* Make sure that the area between the end of the whitespace glyphs
3486 and the inside margin glyphs is cleared. */
3487 if (in_in_cnt && (in_in_start - end_xpos)) {
3488 add_margin_blank(dl, idb, w, end_xpos, in_in_start - end_xpos,
3492 /* Next add the inside margin glyphs which are actually in the
3495 end_xpos = add_margin_runes(dl, idb, in_in_start, in_in_cnt,
3496 GL_INSIDE_MARGIN, RIGHT_GLYPHS,
3500 /* If we didn't add any inside margin glyphs then make sure the rest
3501 of the inside margin area gets cleared. */
3502 if (idb && (dl->bounds.right_in - end_xpos)) {
3503 add_margin_blank(dl, idb, w, end_xpos,
3504 dl->bounds.right_in - end_xpos, RIGHT_GLYPHS);
3507 /* Next add any whitespace glyphs in the outside margin. */
3508 if (white_out_cnt) {
3510 add_margin_runes(dl, odb, dl->bounds.right_in,
3511 white_out_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3514 end_xpos = dl->bounds.right_in;
3516 /* Next add any inside margin glyphs in the outside margin. */
3518 end_xpos = add_margin_runes(dl, odb, end_xpos, in_out_cnt,
3519 GL_INSIDE_MARGIN, RIGHT_GLYPHS,
3523 /* There may be space between any whitespace or inside margin glyphs
3524 in the outside margin and the actual outside margin glyphs. */
3525 if (odb && (out_start - end_xpos)) {
3526 add_margin_blank(dl, odb, w, end_xpos, out_start - end_xpos,
3530 /* Finally, add the outside margin glyphs. */
3532 add_margin_runes(dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3533 RIGHT_GLYPHS, window);
3537 /***************************************************************************/
3539 /* modeline routines */
3541 /***************************************************************************/
3543 /* This function is also used in frame.c by `generate_title_string' */
3545 generate_formatted_string_db(Lisp_Object format_str, Lisp_Object result_str,
3546 struct window *w, struct display_line *dl,
3547 struct display_block *db, face_index findex,
3548 int min_pixpos, int max_pixpos, int type)
3550 struct frame *f = XFRAME(w->frame);
3551 struct device *d = XDEVICE(f->device);
3555 Charcount offset = 0;
3561 data.findex = findex;
3562 data.pixpos = min_pixpos;
3563 data.max_pixpos = max_pixpos;
3564 data.cursor_type = NO_CURSOR;
3565 data.last_charset = Qunbound;
3566 data.last_findex = DEFAULT_INDEX;
3567 data.result_str = result_str;
3568 data.is_modeline = 1;
3570 XSETWINDOW(data.window, w);
3572 Dynarr_reset(formatted_string_extent_dynarr);
3573 Dynarr_reset(formatted_string_extent_start_dynarr);
3574 Dynarr_reset(formatted_string_extent_end_dynarr);
3576 /* result_str is nil when we're building a frame or icon title. Otherwise,
3577 we're building a modeline, so the offset starts at the modeline
3578 horizontal scrolling amount */
3579 if (!NILP(result_str))
3580 offset = w->modeline_hscroll;
3581 generate_fstring_runes(w, &data, 0, 0, -1, format_str, 0,
3582 max_pixpos - min_pixpos, findex, type, &offset,
3585 if (Dynarr_length(db->runes)) {
3587 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
3588 c_pixpos = rb->xpos + rb->width;
3590 c_pixpos = min_pixpos;
3592 /* If we don't reach the right side of the window, add a blank rune
3593 to make up the difference. This usually only occurs if the
3594 modeline face is using a proportional width font or a fixed width
3595 font of a different size from the default face font. */
3597 if (c_pixpos < max_pixpos) {
3598 data.pixpos = c_pixpos;
3599 data.blank_width = max_pixpos - data.pixpos;
3601 add_blank_rune(&data, NULL, 0);
3604 /* Now create the result string and frob the extents into it. */
3605 if (!NILP(result_str)) {
3609 struct buffer *buf = XBUFFER(WINDOW_BUFFER(w));
3611 in_modeline_generation = 1;
3613 detach_all_extents(result_str);
3614 resize_string(XSTRING(result_str), -1,
3615 data.bytepos - XSTRING_LENGTH(result_str));
3617 strdata = XSTRING_DATA(result_str);
3619 for (elt = 0, len = 0; elt < Dynarr_length(db->runes); elt++) {
3620 if (Dynarr_atp(db->runes, elt)->type == RUNE_CHAR) {
3621 len += (set_charptr_emchar
3622 (strdata + len, Dynarr_atp(db->runes,
3629 elt < Dynarr_length(formatted_string_extent_dynarr);
3631 Lisp_Object extent = Qnil;
3635 Dynarr_at(formatted_string_extent_dynarr,
3638 Fgethash(extent, buf->modeline_extent_table, Qnil);
3640 child = Fmake_extent(Qnil, Qnil, result_str);
3641 Fputhash(extent, child,
3642 buf->modeline_extent_table);
3644 Fset_extent_parent(child, extent);
3645 set_extent_endpoints
3647 Dynarr_at(formatted_string_extent_start_dynarr,
3649 Dynarr_at(formatted_string_extent_end_dynarr, elt),
3653 in_modeline_generation = 0;
3657 /* Ensure that the given display line DL accurately represents the
3658 modeline for the given window. */
3660 generate_modeline(struct window *w, struct display_line *dl, int type)
3662 struct buffer *b = XBUFFER(w->buffer);
3663 struct frame *f = XFRAME(w->frame);
3664 struct device *d = XDEVICE(f->device);
3666 /* Unlike display line and rune pointers, this one can't change underneath
3668 struct display_block *db = get_display_block_from_line(dl, TEXT);
3669 int max_pixpos, min_pixpos, ypos_adj;
3670 Lisp_Object font_inst;
3672 /* This will actually determine incorrect inside boundaries for the
3673 modeline since it ignores the margins. However being aware of this fact
3674 we never use those values anywhere so it doesn't matter. */
3675 dl->bounds = calculate_display_line_boundaries(w, 1);
3677 /* We are generating a modeline. */
3679 dl->cursor_elt = -1;
3681 /* Reset the runes on the modeline. */
3682 Dynarr_reset(db->runes);
3684 if (!WINDOW_HAS_MODELINE_P(w)) {
3687 /* If there is a horizontal scrollbar, don't add anything. */
3688 if (window_scrollbar_height(w))
3691 dl->ascent = DEVMETH(d, divider_height, ());
3693 /* The modeline is at the bottom of the gutters. */
3694 dl->ypos = WINDOW_BOTTOM(w);
3696 rb.findex = MODELINE_INDEX;
3697 rb.xpos = dl->bounds.left_out;
3698 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3701 rb.type = RUNE_HLINE;
3702 rb.object.hline.thickness = 1;
3703 rb.object.hline.yoffset = 0;
3704 rb.cursor_type = NO_CURSOR;
3706 if (!EQ(Qzero, w->modeline_shadow_thickness)
3707 && FRAME_WIN_P(f)) {
3708 int shadow_thickness = MODELINE_SHADOW_THICKNESS(w);
3710 dl->ypos -= shadow_thickness;
3711 rb.xpos += shadow_thickness;
3712 rb.width -= 2 * shadow_thickness;
3715 Dynarr_add(db->runes, rb);
3719 /* !!#### not right; needs to compute the max height of
3721 font_inst = WINDOW_FACE_CACHEL_FONT(w, MODELINE_INDEX, Vcharset_ascii);
3723 dl->ascent = XFONT_INSTANCE(font_inst)->ascent;
3724 dl->descent = XFONT_INSTANCE(font_inst)->descent;
3726 min_pixpos = dl->bounds.left_out;
3727 max_pixpos = dl->bounds.right_out;
3729 if (!EQ(Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P(f)) {
3730 int shadow_thickness = MODELINE_SHADOW_THICKNESS(w);
3732 ypos_adj = shadow_thickness;
3733 min_pixpos += shadow_thickness;
3734 max_pixpos -= shadow_thickness;
3738 generate_formatted_string_db(b->modeline_format,
3739 b->generated_modeline_string, w, dl, db,
3740 MODELINE_INDEX, min_pixpos, max_pixpos,
3743 /* The modeline is at the bottom of the gutters. We have to wait to
3744 set this until we've generated the modeline in order to account
3745 for any embedded faces. */
3746 dl->ypos = WINDOW_BOTTOM(w) - dl->descent - ypos_adj;
3750 add_string_to_fstring_db_runes(pos_data * data, const Bufbyte * str,
3751 Charcount pos, Charcount min_pos,
3754 /* This function has been Mule-ized. */
3756 const Bufbyte *cur_pos = str;
3757 struct display_block *db = data->db;
3759 data->blank_width = space_width(XWINDOW(data->window));
3760 while (Dynarr_length(db->runes) < pos)
3761 add_blank_rune(data, NULL, 0);
3763 end = (Dynarr_length(db->runes) +
3764 bytecount_to_charcount(str, strlen((const char *)str)));
3766 end = min(max_pos, end);
3768 while (pos < end && *cur_pos) {
3769 const Bufbyte *old_cur_pos = cur_pos;
3772 data->ch = charptr_emchar(cur_pos);
3773 succeeded = (add_emchar_rune(data) != ADD_FAILED);
3774 INC_CHARPTR(cur_pos);
3777 data->modeline_charpos++;
3778 data->bytepos += cur_pos - old_cur_pos;
3782 while (Dynarr_length(db->runes) < min_pos &&
3783 (data->pixpos + data->blank_width <= data->max_pixpos))
3784 add_blank_rune_noret(data, NULL, 0);
3786 return Dynarr_length(db->runes);
3789 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3790 modeline extents. */
3792 add_glyph_to_fstring_db_runes(pos_data * data, Lisp_Object glyph,
3793 Charcount pos, Charcount min_pos,
3794 Charcount max_pos, Lisp_Object extent)
3796 /* This function has been Mule-ized. */
3798 struct display_block *db = data->db;
3799 struct glyph_block gb;
3801 data->blank_width = space_width(XWINDOW(data->window));
3802 while (Dynarr_length(db->runes) < pos)
3803 add_blank_rune_noret(data, NULL, 0);
3805 end = Dynarr_length(db->runes) + 1;
3807 end = min(max_pos, end);
3811 add_glyph_rune_noret(data, &gb, BEGIN_GLYPHS, 0, 0);
3814 while (Dynarr_length(db->runes) < pos &&
3815 (data->pixpos + data->blank_width <= data->max_pixpos))
3816 add_blank_rune(data, NULL, 0);
3818 return Dynarr_length(db->runes);
3821 /* If max_pos is == -1, it is considered to be infinite. The same is
3822 true of max_pixsize. */
3823 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3824 if (Dynarr_length (data->db->runes)) \
3825 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3829 /* Note that this function does "positions" in terms of characters and
3830 not in terms of columns. This is necessary to make the formatting
3831 work correctly when proportional width fonts are used in the
3834 generate_fstring_runes(struct window *w, pos_data * data, Charcount pos,
3835 Charcount min_pos, Charcount max_pos,
3836 Lisp_Object elt, int depth, int max_pixsize,
3837 face_index findex, int type, Charcount * offset,
3838 Lisp_Object cur_ext)
3840 /* This function has been Mule-ized. */
3841 /* #### The other losing things in this function are:
3843 -- C zero-terminated-string lossage.
3844 -- Non-printable characters should be converted into something
3845 appropriate (e.g. ^F) instead of blindly being printed anyway.
3855 /* A string. Add to the display line and check for %-constructs
3858 Bufbyte *this = XSTRING_DATA(elt);
3860 while ((pos < max_pos || max_pos == -1) && *this) {
3861 Bufbyte *last = this;
3863 while (*this && *this != '%')
3867 /* No %-construct */
3869 bytecount_to_charcount(last, this - last);
3871 if (size <= *offset)
3877 *offset : min(pos + size - *offset,
3879 const Bufbyte *tmp_last =
3880 charptr_n_addr(last, *offset);
3883 add_string_to_fstring_db_runes(data,
3890 } else { /* *this == '%' */
3892 Charcount spec_width = 0;
3894 this++; /* skip over '%' */
3896 /* We can't allow -ve args due to the "%-" construct.
3897 * Argument specifies minwidth but not maxwidth
3898 * (maxwidth can be specified by
3899 * (<negative-number> . <stuff>) modeline elements)
3901 while (isdigit(*this)) {
3903 spec_width * 10 + (*this - '0');
3910 generate_fstring_runes(w, data, pos,
3913 Vglobal_mode_string,
3919 } else if (*this == '-') {
3920 Charcount num_to_add;
3922 if (max_pixsize < 0)
3924 else if (max_pos != -1)
3925 num_to_add = max_pos - pos;
3930 SET_CURRENT_MODE_CHARS_PIXSIZE;
3933 redisplay_text_width_string
3934 (w, findex, &ch, Qnil, 0,
3944 while (num_to_add--)
3946 add_string_to_fstring_db_runes
3947 (data, (const Bufbyte *)"-",
3949 } else if (*this != 0) {
3950 Emchar ch = charptr_emchar(this);
3954 decode_mode_spec(w, ch, type);
3957 Dynarr_atp(mode_spec_bufbyte_string,
3959 size = bytecount_to_charcount
3960 /* Skip the null character added by `decode_mode_spec' */
3963 (mode_spec_bufbyte_string)) - 1;
3965 if (size <= *offset)
3968 const Bufbyte *tmp_str =
3972 /* #### NOTE: I don't understand why a tmp_max is not
3973 computed and used here as in the plain string case
3976 add_string_to_fstring_db_runes
3977 (data, tmp_str, pos, pos,
3983 /* NOT this++. There could be any sort of character at
3984 the current position. */
3988 if (max_pixsize > 0) {
3990 SET_CURRENT_MODE_CHARS_PIXSIZE;
3992 if (cur_pixsize >= max_pixsize)
3996 } else if (SYMBOLP(elt)) {
3997 /* A symbol: process the value of the symbol recursively
3998 as if it appeared here directly. */
3999 Lisp_Object tem = symbol_value_in_buffer(elt, w->buffer);
4001 if (!UNBOUNDP(tem)) {
4002 /* If value is a string, output that string literally:
4003 don't check for % within it. */
4005 Bufbyte *str = XSTRING_DATA(tem);
4006 Charcount size = XSTRING_CHAR_LENGTH(tem);
4008 if (size <= *offset)
4011 const Bufbyte *tmp_str =
4012 charptr_n_addr(str, *offset);
4014 /* #### NOTE: I don't understand why a tmp_max is not
4015 computed and used here as in the plain string case
4018 add_string_to_fstring_db_runes(data,
4026 /* Give up right away for nil or t. */
4027 else if (!EQ(tem, elt)) {
4032 } else if (GENERIC_SPECIFIERP(elt)) {
4033 Lisp_Object window, tem;
4034 XSETWINDOW(window, w);
4035 tem = specifier_instance_no_quit(elt, Qunbound, window,
4036 ERROR_ME_NOT, 0, Qzero);
4037 if (!UNBOUNDP(tem)) {
4041 } else if (CONSP(elt)) {
4042 /* A cons cell: four distinct cases.
4043 * - If first element is a string or a cons, process all the elements
4044 * and effectively concatenate them.
4045 * - If first element is a negative number, truncate displaying cdr to
4046 * at most that many characters. If positive, pad (with spaces)
4047 * to at least that many characters.
4048 * - If first element is another symbol, process the cadr or caddr
4049 * recursively according to whether the symbol's value is non-nil or
4051 * - If first element is an extent, process the cdr recursively
4052 * and handle the extent's face.
4055 Lisp_Object car, tem;
4063 tem = symbol_value_in_buffer(car, w->buffer);
4064 /* elt is now the cdr, and we know it is a cons cell.
4065 Use its car if CAR has a non-nil value. */
4066 if (!UNBOUNDP(tem)) {
4072 /* Symbol's value is nil (or symbol is unbound)
4073 * Get the cddr of the original list
4074 * and if possible find the caddr and use that.
4078 else if (!CONSP(elt))
4084 } else if (INTP(car)) {
4085 Charcount lim = XINT(car);
4090 /* Negative int means reduce maximum width.
4091 * DO NOT change MIN_PIXPOS here!
4092 * (20 -10 . foo) should truncate foo to 10 col
4093 * and then pad to 20.
4096 max_pos = pos - lim;
4098 max_pos = min(max_pos, pos - lim);
4099 } else if (lim > 0) {
4100 /* Padding specified. Don't let it be more than
4104 if (max_pos != -1 && lim > max_pos)
4106 /* If that's more padding than already wanted, queue it.
4107 * But don't reduce padding already specified even if
4108 * that is beyond the current truncation point.
4114 } else if (STRINGP(car) || CONSP(car)) {
4117 /* LIMIT is to protect against circular lists. */
4118 while (CONSP(elt) && --limit > 0
4119 && (pos < max_pos || max_pos == -1)) {
4121 generate_fstring_runes(w, data, pos, pos,
4124 findex, type, offset,
4128 } else if (EXTENTP(car)) {
4129 struct extent *ext = XEXTENT(car);
4131 if (EXTENT_LIVE_P(ext)) {
4132 face_index old_findex = data->findex;
4134 Lisp_Object font_inst;
4135 face_index new_findex;
4136 Bytecount start = data->bytepos;
4138 face = extent_face(ext);
4140 /* #### needs to merge faces, sigh */
4141 /* #### needs to handle list of faces */
4143 get_builtin_face_cache_index(w,
4145 /* !!#### not right; needs to compute the max height of
4148 WINDOW_FACE_CACHEL_FONT(w,
4152 data->dl->ascent = max(data->dl->ascent,
4157 max(data->dl->descent,
4158 XFONT_INSTANCE(font_inst)->
4161 new_findex = old_findex;
4163 data->findex = new_findex;
4165 generate_fstring_runes(w, data, pos, pos,
4171 data->findex = old_findex;
4172 Dynarr_add(formatted_string_extent_dynarr, ext);
4173 Dynarr_add(formatted_string_extent_start_dynarr,
4175 Dynarr_add(formatted_string_extent_end_dynarr,
4179 } else if (GLYPHP(elt)) {
4180 /* Glyphs are considered as one character with respect to the modeline
4181 horizontal scrolling facility. -- dv */
4186 add_glyph_to_fstring_db_runes(data, elt, pos, pos,
4191 char *str = GETTEXT("*invalid*");
4192 Charcount size = (Charcount) strlen(str); /* is this ok ?? -- dv */
4194 if (size <= *offset)
4197 const Bufbyte *tmp_str =
4198 charptr_n_addr((const Bufbyte *)str,
4201 /* #### NOTE: I don't understand why a tmp_max is not computed and
4202 used here as in the plain string case above. -- dv */
4204 add_string_to_fstring_db_runes(data,
4213 if (min_pos > pos) {
4214 add_string_to_fstring_db_runes(data, (const Bufbyte *)"", pos,
4221 /* Update just the modeline. Assumes the desired display structs. If
4222 they do not have a modeline block, it does nothing. */
4223 static void regenerate_modeline(struct window *w)
4225 display_line_dynarr *dla = window_display_lines(w, DESIRED_DISP);
4227 if (!Dynarr_length(dla) || !Dynarr_atp(dla, 0)->modeline)
4230 generate_modeline(w, Dynarr_atp(dla, 0), DESIRED_DISP);
4231 redisplay_update_line(w, 0, 0, 0);
4235 /* Make sure that modeline display line is present in the given
4236 display structs if the window has a modeline and update that
4237 line. Returns true if a modeline was needed. */
4238 static int ensure_modeline_generated(struct window *w, int type)
4242 /* minibuffer windows don't have modelines */
4243 if (MINI_WINDOW_P(w))
4245 /* windows which haven't had it turned off do */
4246 else if (WINDOW_HAS_MODELINE_P(w))
4248 /* windows which have it turned off don't have a divider if there is
4249 a horizontal scrollbar */
4250 else if (window_scrollbar_height(w))
4252 /* and in this case there is none */
4256 if (need_modeline) {
4257 display_line_dynarr *dla;
4259 dla = window_display_lines(w, type);
4261 /* We don't care if there is a display line which is not
4262 currently a modeline because it is definitely going to become
4263 one if we have gotten to this point. */
4264 if (Dynarr_length(dla) == 0) {
4265 if (Dynarr_largest(dla) > 0) {
4266 struct display_line *mlp = Dynarr_atp(dla, 0);
4267 Dynarr_add(dla, *mlp);
4269 struct display_line modeline;
4271 Dynarr_add(dla, modeline);
4275 /* If we're adding a new place marker go ahead and generate the
4276 modeline so that it is available for use by
4277 window_modeline_height. */
4278 generate_modeline(w, Dynarr_atp(dla, 0), type);
4281 return need_modeline;
4284 /* #### Kludge or not a kludge. I tend towards the former. */
4285 int real_current_modeline_height(struct window *w)
4287 Fset_marker(w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4288 Fset_marker(w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP],
4291 if (ensure_modeline_generated(w, CMOTION_DISP)) {
4292 display_line_dynarr *dla =
4293 window_display_lines(w, CMOTION_DISP);
4295 if (Dynarr_length(dla)) {
4296 if (Dynarr_atp(dla, 0)->modeline)
4297 return (Dynarr_atp(dla, 0)->ascent +
4298 Dynarr_atp(dla, 0)->descent);
4304 /***************************************************************************/
4306 /* displayable string routines */
4308 /***************************************************************************/
4310 /* Given a position for a string in a window, ensure that the given
4311 display line DL accurately represents the text on a line starting
4312 at the given position.
4314 Yes, this is duplicating the code of create_text_block, but it
4315 looked just too hard to change create_text_block to handle strings
4316 *and* buffers. We already make a distinction between the two
4317 elsewhere in the code so I think unifying them would require a
4318 complete MULE rewrite. Besides, the other distinction is that these
4319 functions cover text that the user *cannot edit* so we can remove
4320 everything to do with cursors, minibuffers etc. Eventually the
4321 modeline routines should be modified to use this code as it copes
4322 with many more types of display situation. */
4325 create_string_text_block(struct window *w, Lisp_Object disp_string,
4326 struct display_line *dl,
4328 prop_block_dynarr ** prop, face_index default_face)
4330 struct frame *f = XFRAME(w->frame);
4331 /* Note that a lot of the buffer controlled stuff has been left in
4332 because you might well want to make use of it (selective display
4333 etc), its just the buffer text that we do not use. However, it
4334 seems to be possible for buffer to be nil sometimes so protect
4335 against this case. */
4336 struct buffer *b = BUFFERP(w->buffer) ? XBUFFER(w->buffer) : 0;
4337 struct device *d = XDEVICE(f->device);
4338 Lisp_String *s = XSTRING(disp_string);
4340 /* we're working with these a lot so precalculate them */
4341 Bytecount slen = XSTRING_LENGTH(disp_string);
4342 Bytecount bi_string_zv = slen;
4343 Bytind bi_start_pos = charcount_to_bytecount(string_data(s), start_pos);
4347 int truncate_win = b ? window_truncation_on(w) : 0;
4349 /* We're going to ditch selective display for static text, it's an
4350 FSF thing and invisible extents are the way to go here.
4351 Implementing it also relies on a number of buffer-specific
4352 functions that we don't have the luxury of being able to use
4355 /* The variable ctl-arrow allows the user to specify what characters
4356 can actually be displayed and which octal should be used for.
4357 #### This variable should probably have some rethought done to
4360 #### It would also be really nice if you could specify that
4361 the characters come out in hex instead of in octal. Mule
4362 does that by adding a ctl-hexa variable similar to ctl-arrow,
4363 but that's bogus -- we need a more general solution. I
4364 think you need to extend the concept of display tables
4365 into a more general conversion mechanism. Ideally you
4366 could specify a Lisp function that converts characters,
4367 but this violates the Second Golden Rule and besides would
4368 make things way way way way slow.
4370 So instead, we extend the display-table concept, which was
4371 historically limited to 256-byte vectors, to one of the
4374 a) A 256-entry vector, for backward compatibility;
4375 b) char-table, mapping characters to values;
4376 c) range-table, mapping ranges of characters to values;
4377 d) a list of the above.
4379 The (d) option allows you to specify multiple display tables
4380 instead of just one. Each display table can specify conversions
4381 for some characters and leave others unchanged. The way the
4382 character gets displayed is determined by the first display table
4383 with a binding for that character. This way, you could call a
4384 function `enable-hex-display' that adds a hex display-table to
4385 the list of display tables for the current buffer.
4387 #### ...not yet implemented... Also, we extend the concept of
4388 "mapping" to include a printf-like spec. Thus you can make all
4389 extended characters show up as hex with a display table like
4392 #s(range-table data ((256 524288) (format "%x")))
4394 Since more than one display table is possible, you have
4395 great flexibility in mapping ranges of characters. */
4396 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP(b->ctl_arrow)
4397 ? XCHAR_OR_CHAR_INT(b->ctl_arrow)
4398 : ((EQ(b->ctl_arrow, Qt)
4399 || EQ(b->ctl_arrow, Qnil))
4400 ? 255 : 160)) : 255;
4402 Lisp_Object face_dt, window_dt;
4404 /* The text display block for this display line. */
4405 struct display_block *db = get_display_block_from_line(dl, TEXT);
4407 /* The first time through the main loop we need to force the glyph
4408 data to be updated. */
4411 /* Apparently the new extent_fragment_update returns an end position
4412 equal to the position passed in if there are no more runs to be
4414 int no_more_frags = 0;
4416 dl->used_prop_data = 0;
4418 dl->line_continuation = 0;
4420 /* set up faces to use for clearing areas, used by
4421 output_display_line */
4422 dl->default_findex = default_face;
4424 dl->left_margin_findex = default_face;
4425 dl->right_margin_findex = default_face;
4427 dl->left_margin_findex =
4428 get_builtin_face_cache_index(w, Vleft_margin_face);
4429 dl->right_margin_findex =
4430 get_builtin_face_cache_index(w, Vright_margin_face);
4434 data.ef = extent_fragment_new(disp_string, f);
4436 /* These values are used by all of the rune addition routines. We add
4437 them to this structure for ease of passing. */
4439 XSETWINDOW(data.window, w);
4443 data.bi_bufpos = bi_start_pos;
4444 data.pixpos = dl->bounds.left_in;
4445 data.last_charset = Qunbound;
4446 data.last_findex = default_face;
4447 data.result_str = Qnil;
4448 data.string = disp_string;
4450 /* Set the right boundary adjusting it to take into account any end
4451 glyph. Save the width of the end glyph for later use. */
4452 data.max_pixpos = dl->bounds.right_in;
4453 data.max_pixpos -= data.end_glyph_width;
4455 data.cursor_type = NO_CURSOR;
4459 /* I don't think we want this, string areas should not scroll with
4461 data.start_col = w->hscroll;
4462 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4464 data.bi_start_col_enabled = 0;
4465 data.hscroll_glyph_width_adjust = 0;
4467 /* We regenerate the line from the very beginning. */
4468 Dynarr_reset(db->runes);
4470 /* Why is this less than or equal and not just less than? If the
4471 starting position is already equal to the maximum we can't add
4472 anything else, right? Wrong. We might still have a newline to
4473 add. A newline can use the room allocated for an end glyph since
4474 if we add it we know we aren't going to be adding any end
4477 /* #### Chuck -- I think this condition should be while (1).
4478 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4479 and the begin-glyph ends exactly at the end of the window, the
4480 end-glyph and text might not be displayed. while (1) ensures
4481 that the loop terminates only when either (a) there is
4482 propagation data or (b) the end-of-line or end-of-buffer is hit.
4484 #### Also I think you need to ensure that the operation
4485 "add begin glyphs; add end glyphs; add text" is atomic and
4486 can't get interrupted in the middle. If you run off the end
4487 of the line during that operation, then you keep accumulating
4488 propagation data until you're done. Otherwise, if the (e.g.)
4489 there's a begin glyph at a particular position and attempting
4490 to display that glyph results in window-end being hit and
4491 propagation data being generated, then the character at that
4492 position won't be displayed.
4494 #### See also the comment after the end of this loop, below.
4496 while (data.pixpos <= data.max_pixpos) {
4497 /* #### This check probably should not be necessary. */
4498 if (data.bi_bufpos > bi_string_zv) {
4499 /* #### urk! More of this lossage! */
4504 /* Check for face changes. */
4506 || (!no_more_frags && data.bi_bufpos == data.ef->end)) {
4507 Lisp_Object last_glyph = Qnil;
4508 /* Deal with clipped glyphs that we have already displayed. */
4509 if (*prop && Dynarr_atp(*prop, 0)->type == PROP_GLYPH) {
4511 Dynarr_atp(*prop, 0)->data.p_glyph.glyph;
4515 /* Now compute the face and begin/end-glyph information. */
4517 /* Remember that the extent-fragment routines deal in Bytind's. */
4518 extent_fragment_update(w, data.ef, data.bi_bufpos,
4520 /* This is somewhat cheesy but the alternative is to
4521 propagate default_face into extent_fragment_update. */
4522 if (data.findex == DEFAULT_INDEX)
4523 data.findex = default_face;
4525 get_display_tables(w, data.findex, &face_dt,
4528 if (data.bi_bufpos == data.ef->end)
4533 /* Determine what is next to be displayed. We first handle any
4534 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4535 display then we determine what to do based on the character at the
4536 current buffer position. */
4538 /* If there are glyphs, add them to the line. We add the end
4539 glyphs for the previous run of text here rather than doing
4540 them at the end of handling the previous run so that glyphs
4541 at the beginning and end of a line are handled correctly. */
4542 if (Dynarr_length(data.ef->glyphs) > 0) {
4543 data.ch = string_char(s, data.bi_bufpos);
4544 *prop = add_glyph_runes(&data);
4550 /* If the current position is covered by an invisible extent, do
4551 nothing (except maybe add some ellipses). */
4552 else if (data.ef->invisible) {
4553 /* #### Chuck, perhaps you could look at this code? I don't
4554 really know what I'm doing. */
4560 /* The extent fragment code only sets this when we should
4561 really display the ellipses. It makes sure the ellipses
4562 don't get displayed more than once in a row. */
4563 if (data.ef->invisible_ellipses) {
4564 struct glyph_block gb;
4566 data.ef->invisible_ellipses_already_displayed =
4568 data.ef->invisible_ellipses = 0;
4570 gb.glyph = Vinvisible_text_glyph;
4572 add_glyph_rune(&data, &gb, BEGIN_GLYPHS, 0,
4574 INVIS_GLYPH_INDEX));
4575 /* Perhaps they shouldn't propagate if the very next thing
4576 is to display a newline (for compatibility with
4577 selective-display-ellipses)? Maybe that's too
4583 /* #### What if we're dealing with a display table? */
4587 if (data.bi_bufpos == bi_string_zv)
4590 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4593 /* If there is propagation data, then it represents the current
4594 buffer position being displayed. Add them and advance the
4595 position counter. This might also add the minibuffer
4598 dl->used_prop_data = 1;
4599 *prop = add_propagation_runes(prop, &data);
4602 goto done; /* gee, a really narrow window */
4603 else if (data.bi_bufpos == bi_string_zv)
4605 else if (data.bi_bufpos < 0)
4606 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4609 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4612 /* If at end-of-buffer, we've already processed begin and
4613 end-glyphs at this point and there's no text to process,
4615 else if (data.bi_bufpos == bi_string_zv)
4619 Lisp_Object entry = Qnil;
4620 /* Get the character at the current buffer position. */
4621 data.ch = string_char(s, data.bi_bufpos);
4622 if (!NILP(face_dt) || !NILP(window_dt))
4624 display_table_entry(data.ch, face_dt,
4627 /* If there is a display table entry for it, hand it off to
4628 add_disp_table_entry_runes and let it worry about it. */
4629 if (!NILP(entry) && !EQ(entry, make_char(data.ch))) {
4631 add_disp_table_entry_runes(&data, entry);
4637 /* Check if we have hit a newline character. If so, add a marker
4638 to the line and end this loop. */
4639 else if (data.ch == '\n') {
4640 /* We aren't going to be adding an end glyph so give its
4641 space back in order to make sure that the cursor can
4643 data.max_pixpos += data.end_glyph_width;
4647 /* If the current character is considered to be printable, then
4649 else if (data.ch >= printable_min) {
4650 *prop = add_emchar_rune(&data);
4655 /* If the current character is a tab, determine the next tab
4656 starting position and add a blank rune which extends from the
4657 current pixel position to that starting position. */
4658 else if (data.ch == '\t') {
4659 int tab_start_pixpos = data.pixpos;
4664 if (data.start_col > 1)
4667 (data.start_col - 1));
4670 next_tab_position(w, tab_start_pixpos,
4671 dl->bounds.left_in +
4673 hscroll_glyph_width_adjust);
4674 if (next_tab_start > data.max_pixpos) {
4676 next_tab_start - data.max_pixpos;
4677 next_tab_start = data.max_pixpos;
4679 data.blank_width = next_tab_start - data.pixpos;
4682 tab_start_pixpos) / space_width(w);
4685 add_blank_rune(&data, w, char_tab_width);
4687 /* add_blank_rune is only supposed to be called with
4688 sizes guaranteed to fit in the available space. */
4692 struct prop_block pb;
4693 *prop = Dynarr_new(prop_block);
4695 pb.type = PROP_BLANK;
4696 pb.data.p_blank.width = prop_width;
4697 pb.data.p_blank.findex = data.findex;
4698 Dynarr_add(*prop, pb);
4704 /* If character is a control character, pass it off to
4705 add_control_char_runes.
4707 The is_*() routines have undefined results on
4708 arguments outside of the range [-1, 255]. (This
4709 often bites people who carelessly use `char' instead
4710 of `unsigned char'.)
4712 else if (data.ch < 0x100 && iscntrl((Bufbyte) data.ch)) {
4713 *prop = add_control_char_runes(&data, b);
4719 /* If the character is above the ASCII range and we have not
4720 already handled it, then print it as an octal number. */
4721 else if (data.ch >= 0200) {
4722 *prop = add_octal_runes(&data);
4728 /* Assume the current character is considered to be printable,
4729 then just add it. */
4731 *prop = add_emchar_rune(&data);
4736 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4742 /* Determine the starting point of the next line if we did not hit the
4743 end of the buffer. */
4744 if (data.bi_bufpos < bi_string_zv) {
4745 /* #### This check is not correct. If the line terminated
4746 due to a begin-glyph or end-glyph hitting window-end, then
4747 data.ch will not point to the character at data.bi_bufpos. If
4748 you make the two changes mentioned at the top of this loop,
4749 you should be able to say '(if (*prop))'. That should also
4750 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4753 /* The common case is that the line ended because we hit a newline.
4754 In that case, the next character is just the next buffer
4756 if (data.ch == '\n') {
4757 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4760 /* Otherwise we have a buffer line which cannot fit on one display
4763 struct glyph_block gb;
4764 struct glyph_cachel *cachel;
4766 /* If the line is to be truncated then we actually have to look
4767 for the next newline. We also add the end-of-line glyph which
4768 we know will fit because we adjusted the right border before
4769 we starting laying out the line. */
4770 data.max_pixpos += data.end_glyph_width;
4771 data.findex = default_face;
4777 /* Now find the start of the next line. */
4779 bi_find_next_emchar_in_string(s, '\n',
4783 data.cursor_type = NO_CURSOR;
4784 data.bi_bufpos = bi_pos;
4785 gb.glyph = Vtruncation_glyph;
4786 cachel = GLYPH_CACHEL(w, TRUN_GLYPH_INDEX);
4788 /* The cursor can never be on the continuation glyph. */
4789 data.cursor_type = NO_CURSOR;
4791 /* data.bi_bufpos is already at the start of the next line. */
4793 dl->line_continuation = 1;
4794 gb.glyph = Vcontinuation_glyph;
4795 cachel = GLYPH_CACHEL(w, CONT_GLYPH_INDEX);
4798 if (data.end_glyph_width)
4799 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS, 0,
4802 if (truncate_win && data.bi_bufpos == bi_string_zv) {
4803 const Bufbyte *endb =
4804 charptr_n_addr(string_data(s),
4807 if (charptr_emchar(endb) != '\n') {
4808 /* #### Damn this losing shit. */
4813 } else if (data.bi_bufpos == bi_string_zv) {
4814 /* create_text_block () adds a bogus \n marker here which screws
4815 up subwindow display. Since we never have a cursor in the
4816 gutter we can safely ignore it. */
4818 /* Calculate left whitespace boundary. */
4822 /* Whitespace past a newline is considered right whitespace. */
4823 while (elt < Dynarr_length(db->runes)) {
4824 struct rune *rb = Dynarr_atp(db->runes, elt);
4826 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4827 || rb->type == RUNE_BLANK) {
4828 dl->bounds.left_white += rb->width;
4831 elt = Dynarr_length(db->runes);
4835 /* Calculate right whitespace boundary. */
4837 int elt = Dynarr_length(db->runes) - 1;
4840 while (!done && elt >= 0) {
4841 struct rune *rb = Dynarr_atp(db->runes, elt);
4843 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4844 && isspace(rb->object.chr.ch))
4845 && !rb->type == RUNE_BLANK) {
4846 dl->bounds.right_white = rb->xpos + rb->width;
4854 /* The line is blank so everything is considered to be right
4857 dl->bounds.right_white = dl->bounds.left_in;
4860 /* Set the display blocks bounds. */
4861 db->start_pos = dl->bounds.left_in;
4862 if (Dynarr_length(db->runes)) {
4864 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
4866 db->end_pos = rb->xpos + rb->width;
4868 db->end_pos = dl->bounds.right_white;
4870 calculate_baseline(&data);
4872 dl->ascent = data.new_ascent;
4873 dl->descent = data.new_descent;
4876 unsigned short ascent =
4877 (unsigned short)XINT(w->minimum_line_ascent);
4879 if (dl->ascent < ascent)
4880 dl->ascent = ascent;
4883 unsigned short descent =
4884 (unsigned short)XINT(w->minimum_line_descent);
4886 if (dl->descent < descent)
4887 dl->descent = descent;
4890 calculate_yoffset(dl, db);
4892 dl->cursor_elt = data.cursor_x;
4893 /* #### lossage lossage lossage! Fix this shit! */
4894 if (data.bi_bufpos > bi_string_zv)
4896 buffer_or_string_bytind_to_bufpos(disp_string,
4900 buffer_or_string_bytind_to_bufpos(disp_string,
4901 data.bi_bufpos) - 1;
4903 data.dl->num_chars =
4904 string_column_at_point(s, dl->end_bufpos,
4905 b ? XINT(b->tab_width) : 8);
4907 /* This doesn't correctly take into account tabs and control
4908 characters but if the window isn't being truncated then this
4909 value isn't going to end up being used anyhow. */
4910 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4912 /* #### handle horizontally scrolled line with text none of which
4913 was actually laid out. */
4915 /* #### handle any remainder of overlay arrow */
4917 if (*prop == ADD_FAILED)
4920 if (truncate_win && *prop) {
4925 extent_fragment_delete(data.ef);
4927 /* #### If we started at EOB, then make sure we return a value past
4928 it so that regenerate_window will exit properly. This is bogus.
4929 The main loop should get fixed so that it isn't necessary to call
4930 this function if we are already at EOB. */
4932 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4933 return bytecount_to_charcount(string_data(s), data.bi_bufpos) + 1; /* Yuck! */
4935 return bytecount_to_charcount(string_data(s), data.bi_bufpos);
4938 /* Given a display line and a starting position, ensure that the
4939 contents of the display line accurately represent the visual
4940 representation of the buffer contents starting from the given
4941 position when displayed in the given window. The display line ends
4942 when the contents of the line reach the right boundary of the given
4945 This is very similar to generate_display_line but with the same
4946 limitations as create_string_text_block. I have taken the liberty
4947 of fixing the bytind stuff though.*/
4950 generate_string_display_line(struct window *w, Lisp_Object disp_string,
4951 struct display_line *dl,
4953 prop_block_dynarr ** prop, face_index default_face)
4957 /* you must set bounds before calling this. */
4959 /* Reset what this line is using. */
4960 if (dl->display_blocks)
4961 Dynarr_reset(dl->display_blocks);
4962 if (dl->left_glyphs) {
4963 Dynarr_free(dl->left_glyphs);
4964 dl->left_glyphs = 0;
4966 if (dl->right_glyphs) {
4967 Dynarr_free(dl->right_glyphs);
4968 dl->right_glyphs = 0;
4971 /* We aren't generating a modeline at the moment. */
4974 /* Create a display block for the text region of the line. */
4975 ret_bufpos = create_string_text_block(w, disp_string, dl, start_pos,
4976 prop, default_face);
4977 dl->bufpos = start_pos;
4978 if (dl->end_bufpos < dl->bufpos)
4979 dl->end_bufpos = dl->bufpos;
4981 /* If there are left glyphs associated with any character in the
4982 text block, then create a display block to handle them. */
4983 if (dl->left_glyphs != NULL && Dynarr_length(dl->left_glyphs))
4984 create_left_glyph_block(w, dl, 0);
4986 /* If there are right glyphs associated with any character in the
4987 text block, then create a display block to handle them. */
4988 if (dl->right_glyphs != NULL && Dynarr_length(dl->right_glyphs))
4989 create_right_glyph_block(w, dl);
4994 /* This is ripped off from regenerate_window. All we want to do is
4995 loop through elements in the string creating display lines until we
4996 have covered the provided area. Simple really. */
4998 generate_displayable_area(struct window *w, Lisp_Object disp_string,
4999 int xpos, int ypos, int width, int height,
5000 display_line_dynarr * dla,
5001 Bufpos start_pos, face_index default_face)
5003 int yend = ypos + height;
5006 prop_block_dynarr *prop = 0;
5007 layout_bounds bounds;
5011 /* if there's nothing to do then do nothing. code after this assumes
5012 there is something to do. */
5013 if (NILP(disp_string))
5016 s_zv = XSTRING_CHAR_LENGTH(disp_string);
5018 bounds.left_out = xpos;
5019 bounds.right_out = xpos + width;
5020 /* The inner boundaries mark where the glyph margins are located. */
5021 bounds.left_in = bounds.left_out + window_left_margin_width(w);
5022 bounds.right_in = bounds.right_out - window_right_margin_width(w);
5023 /* We cannot fully calculate the whitespace boundaries as they
5024 depend on the contents of the line being displayed. */
5025 bounds.left_white = bounds.left_in;
5026 bounds.right_white = bounds.right_in;
5028 while (ypos < yend) {
5029 struct display_line dl;
5030 struct display_line *dlp;
5034 if (Dynarr_length(dla) < Dynarr_largest(dla)) {
5035 dlp = Dynarr_atp(dla, Dynarr_length(dla));
5044 dlp->bounds = bounds;
5047 generate_string_display_line(w, disp_string, dlp, start_pos,
5048 &prop, default_face);
5049 /* we need to make sure that we continue along the line if there
5050 is more left to display otherwise we just end up redisplaying
5051 the same chunk over and over again. */
5052 if (next_pos == start_pos && next_pos < s_zv)
5055 start_pos = next_pos;
5057 dlp->ypos = ypos + dlp->ascent;
5058 ypos = dlp->ypos + dlp->descent;
5061 int visible_height = dlp->ascent + dlp->descent;
5063 dlp->clip = (ypos - yend);
5064 visible_height -= dlp->clip;
5066 if (visible_height < VERTICAL_CLIP(w, 1)) {
5068 free_display_line(dlp);
5074 Dynarr_add(dla, *dlp);
5076 /* #### This type of check needs to be done down in the
5077 generate_display_line call. */
5078 if (start_pos >= s_zv)
5086 /***************************************************************************/
5088 /* window-regeneration routines */
5090 /***************************************************************************/
5092 /* For a given window and starting position in the buffer it contains,
5093 ensure that the TYPE display lines accurately represent the
5094 presentation of the window. We pass the buffer instead of getting
5095 it from the window since redisplay_window may have temporarily
5096 changed it to the echo area buffer. */
5099 regenerate_window(struct window *w, Bufpos start_pos, Bufpos point, int type)
5101 struct frame *f = XFRAME(w->frame);
5102 struct buffer *b = XBUFFER(w->buffer);
5103 int ypos = WINDOW_TEXT_TOP(w);
5104 int yend; /* set farther down */
5105 int yclip = WINDOW_TEXT_TOP_CLIP(w);
5108 prop_block_dynarr *prop;
5109 layout_bounds bounds;
5110 display_line_dynarr *dla;
5113 /* The lines had better exist by this point. */
5114 if (!(dla = window_display_lines(w, type)))
5117 w->max_line_len = 0;
5119 /* Normally these get updated in redisplay_window but it is possible
5120 for this function to get called from some other points where that
5121 update may not have occurred. This acts as a safety check. */
5122 if (!Dynarr_length(w->face_cachels))
5123 reset_face_cachels(w);
5124 if (!Dynarr_length(w->glyph_cachels))
5125 reset_glyph_cachels(w);
5127 Fset_marker(w->start[type], make_int(start_pos), w->buffer);
5128 Fset_marker(w->pointm[type], make_int(point), w->buffer);
5129 w->last_point_x[type] = -1;
5130 w->last_point_y[type] = -1;
5132 /* Make sure a modeline is in the structs if needed. */
5133 need_modeline = ensure_modeline_generated(w, type);
5135 /* Wait until here to set this so that the structs have a modeline
5136 generated in the case where one didn't exist. */
5137 yend = WINDOW_TEXT_BOTTOM(w);
5139 bounds = calculate_display_line_boundaries(w, 0);
5141 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5142 if (MINI_WINDOW_P(w)
5143 && (!NILP(Vminibuf_prompt) || !NILP(Vminibuf_preprompt))
5144 && !echo_area_active(f)
5145 && start_pos == BUF_BEGV(b)) {
5146 struct prop_block pb;
5148 prop = Dynarr_new(prop_block);
5150 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5151 pb.type = PROP_MINIBUF_PROMPT;
5152 pb.data.p_string.str = XSTRING_DATA(string);
5153 pb.data.p_string.len = XSTRING_LENGTH(string);
5154 Dynarr_add(prop, pb);
5158 /* When we are computing things for scrolling purposes, make
5159 sure at least one line is always generated */
5160 force = (type == CMOTION_DISP);
5162 /* Make sure this is set always */
5163 /* Note the conversion at end */
5164 w->window_end_pos[type] = start_pos;
5165 while (ypos < yend || force) {
5166 struct display_line dl;
5167 struct display_line *dlp;
5170 if (Dynarr_length(dla) < Dynarr_largest(dla)) {
5171 dlp = Dynarr_atp(dla, Dynarr_length(dla));
5180 dlp->bounds = bounds;
5183 generate_display_line(w, dlp, 1, start_pos, &prop, type);
5185 if (yclip > dlp->ascent) {
5186 /* this should never happen, but if it does just display the
5191 dlp->ypos = (ypos + dlp->ascent) - yclip;
5192 ypos = dlp->ypos + dlp->descent;
5194 /* See if we've been asked to start midway through a line, for
5195 partial display line scrolling. */
5197 dlp->top_clip = yclip;
5203 int visible_height = dlp->ascent + dlp->descent;
5205 dlp->clip = (ypos - yend);
5206 /* Although this seems strange we could have a single very
5207 tall line visible for which we need to account for both
5208 the top clip and the bottom clip. */
5209 visible_height -= (dlp->clip + dlp->top_clip);
5211 if (visible_height < VERTICAL_CLIP(w, 1) && !force) {
5213 free_display_line(dlp);
5219 if (dlp->cursor_elt != -1) {
5220 /* #### This check is steaming crap. Have to get things
5221 fixed so when create_text_block hits EOB, we're done,
5223 if (w->last_point_x[type] == -1) {
5224 w->last_point_x[type] = dlp->cursor_elt;
5225 w->last_point_y[type] = Dynarr_length(dla);
5227 /* #### This means that we've added a cursor at EOB
5228 twice. Yuck oh yuck. */
5229 struct display_block *db =
5230 get_display_block_from_line(dlp, TEXT);
5232 Dynarr_atp(db->runes,
5233 dlp->cursor_elt)->cursor_type =
5235 dlp->cursor_elt = -1;
5239 if (dlp->num_chars > w->max_line_len)
5240 w->max_line_len = dlp->num_chars;
5242 Dynarr_add(dla, *dlp);
5244 /* #### This isn't right, but it is close enough for now. */
5245 w->window_end_pos[type] = start_pos;
5247 /* #### This type of check needs to be done down in the
5248 generate_display_line call. */
5249 if (start_pos > BUF_ZV(b))
5258 /* #### More not quite right, but close enough. */
5259 /* Ben sez: apparently window_end_pos[] is measured
5260 as the number of characters between the window end and the
5261 end of the buffer? This seems rather weirdo. What's
5262 the justification for this?
5264 JV sez: Because BUF_Z (b) would be a good initial value, however
5265 that can change. This representation allows initalizing with 0.
5267 w->window_end_pos[type] = BUF_Z(b) - w->window_end_pos[type];
5269 if (need_modeline) {
5270 /* We know that this is the right thing to use because we put it
5271 there when we first started working in this function. */
5272 generate_modeline(w, Dynarr_atp(dla, 0), type);
5276 #define REGEN_INC_FIND_START_END \
5278 /* Determine start and end of lines. */ \
5279 if (!Dynarr_length (cdla)) \
5283 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5287 else if (!Dynarr_atp (cdla, 0)->modeline \
5288 && !Dynarr_atp (ddla, 0)->modeline) \
5293 abort (); /* structs differ */ \
5295 dla_end = Dynarr_length (cdla) - 1; \
5298 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5299 + Dynarr_atp (cdla, dla_start)->offset); \
5300 /* If this isn't true, then startp has changed and we need to do a \
5302 if (startp != start_pos) \
5305 /* Point is outside the visible region so give up. */ \
5306 if (pointm < start_pos) \
5311 /* This attempts to incrementally update the display structures. It
5312 returns a boolean indicating success or failure. This function is
5313 very similar to regenerate_window_incrementally and is in fact only
5314 called from that function. However, because of the nature of the
5315 changes it deals with it sometimes makes different assumptions
5316 which can lead to success which are much more difficult to make
5317 when dealing with buffer changes. */
5320 regenerate_window_extents_only_changed(struct window *w, Bufpos startp,
5322 Charcount beg_unchanged,
5323 Charcount end_unchanged)
5325 struct buffer *b = XBUFFER(w->buffer);
5326 display_line_dynarr *cdla = window_display_lines(w, CURRENT_DISP);
5327 display_line_dynarr *ddla = window_display_lines(w, DESIRED_DISP);
5331 int first_line, last_line;
5333 /* Don't define this in the loop where it is used because we
5334 definitely want its value to survive between passes. */
5335 prop_block_dynarr *prop = NULL;
5337 /* If we don't have any buffer change recorded but the modiff flag has
5338 been incremented, then fail. I'm not sure of the exact circumstances
5339 under which this can happen, but I believe that it is probably a
5340 reasonable happening. */
5341 if (!point_visible(w, pointm, CURRENT_DISP)
5342 || XINT(w->last_modified[CURRENT_DISP]) < BUF_MODIFF(b))
5345 /* If the cursor is moved we attempt to update it. If we succeed we
5346 go ahead and proceed with the optimization attempt. */
5347 if (!EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5348 || pointm != marker_position(w->last_point[CURRENT_DISP])) {
5349 struct frame *f = XFRAME(w->frame);
5350 struct device *d = XDEVICE(f->device);
5351 struct frame *sel_f = device_selected_frame(d);
5354 if (w->last_point_x[CURRENT_DISP] != -1
5355 && w->last_point_y[CURRENT_DISP] != -1) {
5357 if (redisplay_move_cursor(w, pointm, WINDOW_TTY_P(w))) {
5358 /* Always regenerate the modeline in case it is
5359 displaying the current line or column. */
5360 regenerate_modeline(w);
5363 } else if (w != XWINDOW(FRAME_SELECTED_WINDOW(sel_f))) {
5364 if (f->modeline_changed)
5365 regenerate_modeline(w);
5373 if (beg_unchanged == -1 && end_unchanged == -1)
5376 /* assert: There are no buffer modifications or they are all below the
5377 visible region. We assume that regenerate_window_incrementally has
5378 not called us unless this is true. */
5380 REGEN_INC_FIND_START_END;
5382 /* If the changed are starts before the visible area, give up. */
5383 if (beg_unchanged < startp)
5386 /* Find what display line the extent changes first affect. */
5388 while (line <= dla_end) {
5389 struct display_line *dl = Dynarr_atp(cdla, line);
5390 Bufpos lstart = dl->bufpos + dl->offset;
5391 Bufpos lend = dl->end_bufpos + dl->offset;
5393 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5399 /* If the changes are below the visible area then if point hasn't
5400 moved return success otherwise fail in order to be safe. */
5401 if (line > dla_end) {
5402 if (EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5403 && pointm == marker_position(w->last_point[CURRENT_DISP]))
5409 /* At this point we know what line the changes first affect. We now
5410 begin redrawing lines as long as we are still in the affected
5411 region and the line's size and positioning don't change.
5412 Otherwise we fail. If we fail we will have altered the desired
5413 structs which could lead to an assertion failure. However, if we
5414 fail the next thing that is going to happen is a full regen so we
5415 will actually end up being safe. */
5416 w->last_modified[DESIRED_DISP] = make_int(BUF_MODIFF(b));
5417 w->last_facechange[DESIRED_DISP] = make_int(BUF_FACECHANGE(b));
5418 Fset_marker(w->last_start[DESIRED_DISP], make_int(startp), w->buffer);
5419 Fset_marker(w->last_point[DESIRED_DISP], make_int(pointm), w->buffer);
5421 first_line = last_line = line;
5422 while (line <= dla_end) {
5423 Bufpos old_start, old_end, new_start;
5424 struct display_line *cdl = Dynarr_atp(cdla, line);
5425 struct display_line *ddl = Dynarr_atp(ddla, line);
5426 struct display_block *db;
5429 assert(cdl->bufpos == ddl->bufpos);
5430 assert(cdl->end_bufpos == ddl->end_bufpos);
5431 assert(cdl->offset == ddl->offset);
5433 db = get_display_block_from_line(ddl, TEXT);
5434 initial_size = Dynarr_length(db->runes);
5435 old_start = ddl->bufpos + ddl->offset;
5436 old_end = ddl->end_bufpos + ddl->offset;
5438 /* If this is the first line being updated and it used
5439 propagation data, fail. Otherwise we'll be okay because
5440 we'll have the necessary propagation data. */
5441 if (line == first_line && ddl->used_prop_data)
5445 generate_display_line(w, ddl, 0, ddl->bufpos + ddl->offset,
5446 &prop, DESIRED_DISP);
5449 /* #### If there is propagated stuff the fail. We could
5450 probably actually deal with this if the line had propagated
5451 information when originally created by a full
5458 /* If any line position parameters have changed or a
5459 cursor has disappeared or disappeared, fail. */
5460 db = get_display_block_from_line(ddl, TEXT);
5461 if (cdl->ypos != ddl->ypos
5462 || cdl->ascent != ddl->ascent
5463 || cdl->descent != ddl->descent
5464 || cdl->top_clip != ddl->top_clip
5465 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5466 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5467 || old_start != ddl->bufpos
5468 || old_end != ddl->end_bufpos
5469 || initial_size != Dynarr_length(db->runes)) {
5473 if (ddl->cursor_elt != -1) {
5474 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5475 w->last_point_y[DESIRED_DISP] = line;
5480 /* If the extent changes end on the line we just updated then
5481 we're done. Otherwise go on to the next line. */
5482 if (end_unchanged <= ddl->end_bufpos)
5488 redisplay_update_line(w, first_line, last_line, 1);
5492 /* Attempt to update the display data structures based on knowledge of
5493 the changed region in the buffer. Returns a boolean indicating
5494 success or failure. If this function returns a failure then a
5495 regenerate_window _must_ be performed next in order to maintain
5496 invariants located here. */
5499 regenerate_window_incrementally(struct window *w, Bufpos startp, Bufpos pointm)
5501 struct buffer *b = XBUFFER(w->buffer);
5502 display_line_dynarr *cdla = window_display_lines(w, CURRENT_DISP);
5503 display_line_dynarr *ddla = window_display_lines(w, DESIRED_DISP);
5504 Charcount beg_unchanged, end_unchanged;
5505 Charcount extent_beg_unchanged, extent_end_unchanged;
5511 /* If this function is called, the current and desired structures
5512 had better be identical. If they are not, then that is a bug. */
5513 assert(Dynarr_length(cdla) == Dynarr_length(ddla));
5515 /* We don't handle minibuffer windows yet. The minibuffer prompt
5517 if (MINI_WINDOW_P(w))
5520 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED(b);
5521 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED(b) == -1
5522 ? -1 : BUF_Z(b) - BUF_EXTENT_END_UNCHANGED(b));
5524 /* If nothing has changed in the buffer, then make sure point is ok
5526 if (BUF_BEGIN_UNCHANGED(b) == -1 && BUF_END_UNCHANGED(b) == -1)
5527 return regenerate_window_extents_only_changed(w, startp, pointm,
5528 extent_beg_unchanged,
5529 extent_end_unchanged);
5531 /* We can't deal with deleted newlines. */
5532 if (BUF_NEWLINE_WAS_DELETED(b))
5535 beg_unchanged = BUF_BEGIN_UNCHANGED(b);
5536 end_unchanged = (BUF_END_UNCHANGED(b) == -1
5537 ? -1 : BUF_Z(b) - BUF_END_UNCHANGED(b));
5539 REGEN_INC_FIND_START_END;
5541 /* If the changed area starts before the visible area, give up. */
5542 if (beg_unchanged < startp)
5545 /* Find what display line the buffer changes first affect. */
5547 while (line <= dla_end) {
5548 struct display_line *dl = Dynarr_atp(cdla, line);
5549 Bufpos lstart = dl->bufpos + dl->offset;
5550 Bufpos lend = dl->end_bufpos + dl->offset;
5552 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5558 /* If the changes are below the visible area then if point hasn't
5559 moved return success otherwise fail in order to be safe. */
5561 return regenerate_window_extents_only_changed(w, startp, pointm,
5562 extent_beg_unchanged,
5563 extent_end_unchanged);
5565 /* At this point we know what line the changes first affect. We
5566 now redraw that line. If the changes are contained within it
5567 we are going to succeed and can update just that one line.
5568 Otherwise we fail. If we fail we will have altered the desired
5569 structs which could lead to an assertion failure. However, if
5570 we fail the next thing that is going to happen is a full regen
5571 so we will actually end up being safe. */
5574 prop_block_dynarr *prop = NULL;
5575 struct display_line *cdl = Dynarr_atp(cdla, line);
5576 struct display_line *ddl = Dynarr_atp(ddla, line);
5578 assert(cdl->bufpos == ddl->bufpos);
5579 assert(cdl->end_bufpos == ddl->end_bufpos);
5580 assert(cdl->offset == ddl->offset);
5582 /* If the line continues to next display line, fail. */
5583 if (ddl->line_continuation)
5586 /* If the line was generated using propagation data, fail. */
5587 if (ddl->used_prop_data)
5591 generate_display_line(w, ddl, 0, ddl->bufpos + ddl->offset,
5592 &prop, DESIRED_DISP);
5595 /* If there is propagated stuff then it is pretty much a
5596 guarantee that more than just the one line is affected. */
5602 /* If the line continues to next display line, fail. */
5603 if (ddl->line_continuation)
5606 /* If any line position parameters have changed or a
5607 cursor has disappeared or disappeared, fail. */
5608 if (cdl->ypos != ddl->ypos
5609 || cdl->ascent != ddl->ascent
5610 || cdl->descent != ddl->descent
5611 || cdl->top_clip != ddl->top_clip
5612 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5613 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) {
5617 /* If the changed area also ends on this line, then we may be in
5618 business. Update everything and return success. */
5619 if (end_unchanged >= ddl->bufpos
5620 && end_unchanged <= ddl->end_bufpos) {
5621 w->last_modified[DESIRED_DISP] =
5622 make_int(BUF_MODIFF(b));
5623 w->last_facechange[DESIRED_DISP] =
5624 make_int(BUF_FACECHANGE(b));
5625 Fset_marker(w->last_start[DESIRED_DISP],
5626 make_int(startp), w->buffer);
5627 Fset_marker(w->last_point[DESIRED_DISP],
5628 make_int(pointm), w->buffer);
5630 if (ddl->cursor_elt != -1) {
5631 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5632 w->last_point_y[DESIRED_DISP] = line;
5635 redisplay_update_line(w, line, line, 1);
5636 regenerate_modeline(w);
5638 /* #### For now we just flush the cache until this has been
5639 tested. After that is done, this should correct the
5641 Dynarr_reset(w->line_start_cache);
5643 /* Adjust the extent changed boundaries to remove any
5644 overlap with the buffer changes since we've just
5645 successfully updated that area. */
5646 if (extent_beg_unchanged != -1
5647 && extent_beg_unchanged >= beg_unchanged
5648 && extent_beg_unchanged < end_unchanged)
5649 extent_beg_unchanged = end_unchanged;
5651 if (extent_end_unchanged != -1
5652 && extent_end_unchanged >= beg_unchanged
5653 && extent_end_unchanged < end_unchanged)
5654 extent_end_unchanged = beg_unchanged - 1;
5656 if (extent_end_unchanged <= extent_beg_unchanged)
5657 extent_beg_unchanged = extent_end_unchanged =
5660 /* This could lead to odd results if it fails, but since the
5661 buffer changes update succeeded this probably will to.
5662 We already know that the extent changes start at or after
5663 the line because we checked before entering the loop. */
5664 if (extent_beg_unchanged != -1
5665 && extent_end_unchanged != -1
5666 && ((extent_beg_unchanged < ddl->bufpos)
5667 || (extent_end_unchanged > ddl->end_bufpos)))
5668 return regenerate_window_extents_only_changed(w,
5671 extent_beg_unchanged,
5672 extent_end_unchanged);
5682 /* Given a window and a point, update the given display lines such
5683 that point is displayed in the middle of the window.
5684 Return the window's new start position. */
5687 regenerate_window_point_center(struct window *w, Bufpos point, int type)
5691 /* We need to make sure that the modeline is generated so that the
5692 window height can be calculated correctly. */
5693 ensure_modeline_generated(w, type);
5695 startp = start_with_line_at_pixpos(w, point, window_half_pixpos(w));
5696 regenerate_window(w, startp, point, type);
5697 Fset_marker(w->start[type], make_int(startp), w->buffer);
5702 /* Given a window and a set of display lines, return a boolean
5703 indicating whether the given point is contained within. */
5705 static int point_visible(struct window *w, Bufpos point, int type)
5707 struct buffer *b = XBUFFER(w->buffer);
5708 display_line_dynarr *dla = window_display_lines(w, type);
5711 if (Dynarr_length(dla) && Dynarr_atp(dla, 0)->modeline)
5716 if (Dynarr_length(dla) > first_line) {
5718 struct display_line *dl = Dynarr_atp(dla, first_line);
5721 end = BUF_Z(b) - w->window_end_pos[type] - 1;
5723 if (point >= start && point <= end) {
5724 if (!MINI_WINDOW_P(w) && scroll_on_clipped_lines) {
5725 dl = Dynarr_atp(dla, Dynarr_length(dla) - 1);
5727 if (point >= (dl->bufpos + dl->offset)
5728 && point <= (dl->end_bufpos + dl->offset))
5740 /* Return pixel position the middle of the window, not including the
5741 modeline and any potential horizontal scrollbar. */
5743 int window_half_pixpos(struct window *w)
5745 return WINDOW_TEXT_TOP(w) + (WINDOW_TEXT_HEIGHT(w) >> 1);
5748 /* Return the display line which is currently in the middle of the
5749 window W for display lines TYPE. */
5751 int line_at_center(struct window *w, int type, Bufpos start, Bufpos point)
5753 display_line_dynarr *dla;
5756 int first_elt = (MINI_WINDOW_P(w) ? 0 : 1);
5758 if (type == CMOTION_DISP)
5759 regenerate_window(w, start, point, type);
5761 dla = window_display_lines(w, type);
5762 half = window_half_pixpos(w);
5764 for (elt = first_elt; elt < Dynarr_length(dla); elt++) {
5765 struct display_line *dl = Dynarr_atp(dla, elt);
5766 int line_bot = dl->ypos + dl->descent;
5768 if (line_bot > half)
5772 /* We may not have a line at the middle if the end of the buffer is
5777 /* Return a value for point that would place it at the beginning of
5778 the line which is in the middle of the window. */
5780 Bufpos point_at_center(struct window * w, int type, Bufpos start, Bufpos point)
5782 /* line_at_center will regenerate the display structures, if necessary. */
5783 int line = line_at_center(w, type, start, point);
5786 return BUF_ZV(XBUFFER(w->buffer));
5788 display_line_dynarr *dla = window_display_lines(w, type);
5789 struct display_line *dl = Dynarr_atp(dla, line);
5795 /* For a given window, ensure that the current visual representation
5798 static void redisplay_window(Lisp_Object window, int skip_selected)
5800 struct window *w = XWINDOW(window);
5801 struct frame *f = XFRAME(w->frame);
5802 struct device *d = XDEVICE(f->device);
5803 Lisp_Object old_buffer = w->buffer;
5804 Lisp_Object the_buffer = w->buffer;
5806 int echo_active = 0;
5811 int selected_in_its_frame;
5812 int selected_globally;
5813 int skip_output = 0;
5814 int truncation_changed;
5815 int inactive_minibuffer =
5816 (MINI_WINDOW_P(w) &&
5817 (f != device_selected_frame(d)) &&
5818 !is_surrogate_for_selected_frame(f));
5820 /* #### In the new world this function actually does a bunch of
5821 optimizations such as buffer-based scrolling, but none of that is
5824 /* If this is a combination window, do its children; that's all.
5825 The selected window is always a leaf so we don't check for
5826 skip_selected here. */
5827 if (!NILP(w->vchild)) {
5828 redisplay_windows(w->vchild, skip_selected);
5831 if (!NILP(w->hchild)) {
5832 redisplay_windows(w->hchild, skip_selected);
5836 /* Is this window the selected window on its frame? */
5837 selected_in_its_frame = (w == XWINDOW(FRAME_SELECTED_WINDOW(f)));
5839 selected_in_its_frame &&
5840 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5841 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d
5842 && XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5843 if (skip_selected && selected_in_its_frame)
5846 /* It is possible that the window is not fully initialized yet. */
5847 if (NILP(w->buffer))
5850 if (MINI_WINDOW_P(w) && echo_area_active(f)) {
5851 w->buffer = the_buffer = Vecho_area_buffer;
5855 b = XBUFFER(w->buffer);
5858 old_pointm = selected_globally ? BUF_PT(b)
5859 : marker_position(w->pointm[CURRENT_DISP]);
5862 if (selected_globally) {
5865 pointm = marker_position(w->pointm[CURRENT_DISP]);
5867 if (pointm < BUF_BEGV(b))
5868 pointm = BUF_BEGV(b);
5869 else if (pointm > BUF_ZV(b))
5873 Fset_marker(w->pointm[DESIRED_DISP], make_int(pointm), the_buffer);
5875 /* If the buffer has changed we have to invalidate all of our face
5877 if ((!echo_active && b != window_display_buffer(w))
5878 || !Dynarr_length(w->face_cachels)
5879 || f->faces_changed)
5880 reset_face_cachels(w);
5882 mark_face_cachels_as_not_updated(w);
5884 /* Ditto the glyph cache elements, although we do *not* invalidate
5885 the cache purely because glyphs have changed - this is now
5886 handled by the dirty flag. */
5887 if ((!echo_active && b != window_display_buffer(w))
5888 || !Dynarr_length(w->glyph_cachels) || f->faces_changed)
5889 reset_glyph_cachels(w);
5891 mark_glyph_cachels_as_not_updated(w);
5893 /* If the marker's buffer is not the window's buffer, then we need
5894 to find a new starting position. */
5895 if (!MINI_WINDOW_P(w)
5896 && !EQ(Fmarker_buffer(w->start[CURRENT_DISP]), w->buffer)) {
5898 regenerate_window_point_center(w, pointm, DESIRED_DISP);
5900 goto regeneration_done;
5904 old_startp = marker_position(w->start[CURRENT_DISP]);
5907 startp = marker_position(w->start[CURRENT_DISP]);
5908 if (startp < BUF_BEGV(b))
5909 startp = BUF_BEGV(b);
5910 else if (startp > BUF_ZV(b))
5913 Fset_marker(w->start[DESIRED_DISP], make_int(startp), the_buffer);
5915 truncation_changed = (find_window_mirror(w)->truncate_win !=
5916 window_truncation_on(w));
5918 /* If w->force_start is set, then some function set w->start and we
5919 should display from there and change point, if necessary, to
5920 ensure that it is visible. */
5921 if (w->force_start || inactive_minibuffer) {
5923 w->last_modified[DESIRED_DISP] = Qzero;
5924 w->last_facechange[DESIRED_DISP] = Qzero;
5926 regenerate_window(w, startp, pointm, DESIRED_DISP);
5928 if (!point_visible(w, pointm, DESIRED_DISP)
5929 && !inactive_minibuffer) {
5930 pointm = point_at_center(w, DESIRED_DISP, 0, 0);
5932 if (selected_globally)
5933 BUF_SET_PT(b, pointm);
5935 Fset_marker(w->pointm[DESIRED_DISP], make_int(pointm),
5938 /* #### BUFU amounts of overkill just to get the cursor
5939 location marked properly. FIX ME FIX ME FIX ME */
5940 regenerate_window(w, startp, pointm, DESIRED_DISP);
5943 goto regeneration_done;
5946 /* If nothing has changed since the last redisplay, then we just
5947 need to make sure that point is still visible. */
5948 if (XINT(w->last_modified[CURRENT_DISP]) >= BUF_MODIFF(b)
5949 && XINT(w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE(b)
5951 /* This check is to make sure we restore the minibuffer after a
5952 temporary change to the echo area. */
5953 && !(MINI_WINDOW_P(w) && f->buffers_changed)
5954 && !f->frame_changed && !truncation_changed
5955 /* check whether start is really at the beginning of a line GE */
5956 && (!w->start_at_line_beg || beginning_of_line_p(b, startp))
5958 /* Check if the cursor has actually moved. */
5959 if (EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5960 && pointm == marker_position(w->last_point[CURRENT_DISP])
5961 && selected_globally
5962 && !w->windows_changed
5964 && !f->extents_changed
5965 && !f->faces_changed
5966 && !f->glyphs_changed && !f->subwindows_changed
5967 /* && !f->subwindows_state_changed */
5968 && !f->point_changed && !f->windows_structure_changed) {
5969 /* If not, we're done. */
5970 if (f->modeline_changed)
5971 regenerate_modeline(w);
5974 goto regeneration_done;
5976 /* If the new point is visible in the redisplay structures,
5977 then let the output update routines handle it, otherwise
5978 do things the hard way. */
5979 if (!w->windows_changed
5981 && !f->extents_changed
5982 && !f->faces_changed
5983 && !f->glyphs_changed && !f->subwindows_changed
5984 /* && !f->subwindows_state_changed */
5985 && !f->windows_structure_changed) {
5986 if (point_visible(w, pointm, CURRENT_DISP)
5987 && w->last_point_x[CURRENT_DISP] != -1
5988 && w->last_point_y[CURRENT_DISP] != -1) {
5989 if (redisplay_move_cursor
5990 (w, pointm, FRAME_TTY_P(f))) {
5991 /* Always regenerate in case it is displaying
5992 the current line or column. */
5993 regenerate_modeline(w);
5996 goto regeneration_done;
5998 } else if (!selected_in_its_frame
5999 && !f->point_changed) {
6000 if (f->modeline_changed)
6001 regenerate_modeline(w);
6004 goto regeneration_done;
6008 /* If we weren't able to take the shortcut method, then use
6009 the brute force method. */
6010 regenerate_window(w, startp, pointm, DESIRED_DISP);
6012 if (point_visible(w, pointm, DESIRED_DISP))
6013 goto regeneration_done;
6017 /* Check if the starting point is no longer at the beginning of a
6018 line, in which case find a new starting point. We also recenter
6019 if our start position is equal to point-max. Otherwise we'll end
6020 up with a blank window. */
6021 else if (((w->start_at_line_beg || MINI_WINDOW_P(w))
6022 && !(startp == BUF_BEGV(b)
6023 || BUF_FETCH_CHAR(b, startp - 1) == '\n'))
6024 || (pointm == startp &&
6025 EQ(Fmarker_buffer(w->last_start[CURRENT_DISP]), w->buffer)
6026 && startp < marker_position(w->last_start[CURRENT_DISP]))
6027 || (startp == BUF_ZV(b))) {
6029 regenerate_window_point_center(w, pointm, DESIRED_DISP);
6031 goto regeneration_done;
6033 /* See if we can update the data structures locally based on
6034 knowledge of what changed in the buffer. */
6035 else if (!w->windows_changed
6037 && !f->faces_changed
6038 && !f->glyphs_changed && !f->subwindows_changed
6039 /* && !f->subwindows_state_changed */
6040 && !f->windows_structure_changed
6041 && !f->frame_changed
6042 && !truncation_changed
6044 && regenerate_window_incrementally(w, startp, pointm)) {
6045 if (f->modeline_changed
6046 || XINT(w->last_modified[CURRENT_DISP]) < BUF_MODIFF(b)
6047 || XINT(w->last_facechange[CURRENT_DISP]) <
6049 regenerate_modeline(w);
6052 goto regeneration_done;
6054 /* #### This is where a check for structure based scrolling would go. */
6055 /* If all else fails, try just regenerating and see what happens. */
6057 regenerate_window(w, startp, pointm, DESIRED_DISP);
6059 if (point_visible(w, pointm, DESIRED_DISP))
6060 goto regeneration_done;
6063 /* We still haven't gotten the window regenerated with point
6064 visible. Next we try scrolling a little and see if point comes
6065 back onto the screen. */
6066 if (scroll_step > 0) {
6067 int scrolled = scroll_conservatively;
6068 for (; scrolled >= 0; scrolled -= scroll_step) {
6069 startp = vmotion(w, startp,
6071 startp) ? -scroll_step : scroll_step,
6073 regenerate_window(w, startp, pointm, DESIRED_DISP);
6075 if (point_visible(w, pointm, DESIRED_DISP))
6076 goto regeneration_done;
6080 /* We still haven't managed to get the screen drawn with point on
6081 the screen, so just center it and be done with it. */
6082 startp = regenerate_window_point_center(w, pointm, DESIRED_DISP);
6086 /* If the window's frame is changed then reset the current display
6087 lines in order to force a full repaint. */
6088 if (f->frame_changed) {
6089 display_line_dynarr *cla =
6090 window_display_lines(w, CURRENT_DISP);
6095 /* Must do this before calling redisplay_output_window because it
6096 sets some markers on the window. */
6098 w->buffer = old_buffer;
6099 Fset_marker(w->pointm[DESIRED_DISP], make_int(old_pointm),
6101 Fset_marker(w->start[DESIRED_DISP], make_int(old_startp),
6105 /* These also have to be set before calling redisplay_output_window
6106 since it sets the CURRENT_DISP values based on them. */
6107 w->last_modified[DESIRED_DISP] = make_int(BUF_MODIFF(b));
6108 w->last_facechange[DESIRED_DISP] = make_int(BUF_FACECHANGE(b));
6109 Fset_marker(w->last_start[DESIRED_DISP], make_int(startp), w->buffer);
6110 Fset_marker(w->last_point[DESIRED_DISP], make_int(pointm), w->buffer);
6113 Bufpos start = marker_position(w->start[DESIRED_DISP]);
6114 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1 ? BUF_ZV(b)
6115 : BUF_Z(b) - w->window_end_pos[DESIRED_DISP] - 1);
6116 /* Don't pollute the cache if not sure if we are correct */
6117 if (w->start_at_line_beg)
6118 update_line_start_cache(w, start, end, pointm, 1);
6119 redisplay_output_window(w);
6121 * If we just displayed the echo area, the line start cache is
6122 * no longer valid, because the minibuffer window is associated
6123 * with the window now.
6126 w->line_cache_last_updated = make_int(-1);
6129 /* #### This should be dependent on face changes and will need to be
6130 somewhere else once tty updates occur on a per-frame basis. */
6131 mark_face_cachels_as_clean(w);
6133 /* The glyph cachels only get dirty if someone changed something.
6134 Since redisplay has now effectively ended we can reset the dirty
6135 flag since everything must be up-to-date. */
6137 mark_glyph_cachels_as_clean(w);
6139 w->windows_changed = 0;
6142 /* Call buffer_reset_changes for all buffers present in any window
6143 currently visible in all frames on all devices. #### There has to
6144 be a better way to do this. */
6146 static int reset_buffer_changes_mapfun(struct window *w, void *ignored_closure)
6148 buffer_reset_changes(XBUFFER(w->buffer));
6152 static void reset_buffer_changes(void)
6154 Lisp_Object frmcons, devcons, concons;
6156 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
6157 struct frame *f = XFRAME(XCAR(frmcons));
6159 if (FRAME_REPAINT_P(f))
6160 map_windows(f, reset_buffer_changes_mapfun, 0);
6164 /* Ensure that all windows underneath the given window in the window
6165 hierarchy are correctly displayed. */
6167 static void redisplay_windows(Lisp_Object window, int skip_selected)
6169 for (; !NILP(window); window = XWINDOW(window)->next) {
6170 redisplay_window(window, skip_selected);
6174 static int call_redisplay_end_triggers(struct window *w, void *closure)
6176 Bufpos lrpos = w->last_redisplay_pos;
6177 w->last_redisplay_pos = 0;
6178 if (!NILP(w->buffer)
6179 && !NILP(w->redisplay_end_trigger)
6183 if (MARKERP(w->redisplay_end_trigger)
6184 && XMARKER(w->redisplay_end_trigger)->buffer != 0)
6185 pos = marker_position(w->redisplay_end_trigger);
6186 else if (INTP(w->redisplay_end_trigger))
6187 pos = XINT(w->redisplay_end_trigger);
6189 w->redisplay_end_trigger = Qnil;
6195 XSETWINDOW(window, w);
6196 va_run_hook_with_args_in_buffer(XBUFFER(w->buffer),
6197 Qredisplay_end_trigger_functions,
6200 redisplay_end_trigger);
6201 w->redisplay_end_trigger = Qnil;
6208 /* Ensure that all windows on the given frame are correctly displayed. */
6210 int redisplay_frame(struct frame *f, int preemption_check)
6212 struct device *d = XDEVICE(f->device);
6214 if (preemption_check
6215 && !DEVICE_IMPL_FLAG(d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) {
6216 /* The preemption check itself takes a lot of time,
6217 so normally don't do it here. We do it if called
6218 from Lisp, though (`redisplay-frame'). */
6221 REDISPLAY_PREEMPTION_CHECK;
6226 if (!internal_equal(f->old_buffer_alist, f->buffer_alist, 0)) {
6229 f->old_buffer_alist = Freplace_list(f->old_buffer_alist,
6231 XSETFRAME(frame, f);
6232 va_run_hook_with_args(Qbuffer_list_changed_hook, 1, frame);
6235 /* Before we put a hold on frame size changes, attempt to process
6236 any which are already pending. */
6237 if (f->size_change_pending)
6238 change_frame_size(f, f->new_height, f->new_width, 0);
6240 /* If frame size might need to be changed, due to changed size
6241 of toolbars, scrollbars etc, change it now */
6242 if (f->size_slipped) {
6243 adjust_frame_size(f);
6244 assert(!f->size_slipped);
6247 /* The menubar, toolbar, and icon updates must be done before
6248 hold_frame_size_changes is called and we are officially
6249 'in_display'. They may eval lisp code which may call Fsignal.
6250 If in_display is set Fsignal will abort. */
6252 #ifdef HAVE_MENUBARS
6253 /* Update the menubar. It is done first since it could change
6254 the menubar's visibility. This way we avoid having flashing
6255 caused by an Expose event generated by the visibility change
6257 update_frame_menubars(f);
6258 #endif /* HAVE_MENUBARS */
6259 #ifdef HAVE_TOOLBARS
6260 /* Update the toolbars geometry. We don't update the toolbars
6261 themselves at this point since the space they are trying to
6262 occupy may currently by occupied by gutter elements. Instead we
6263 update the geometry, then update the gutter geometry, then update
6264 the gutters - which will cause mapped windows to be repositioned
6265 - and finally update the toolbars. */
6266 update_frame_toolbars_geometry(f);
6267 #endif /* HAVE_TOOLBARS */
6268 /* Gutter update proper has to be done inside display when no frame
6269 size changes can occur, thus we separately update the gutter
6270 geometry here if it needs it. */
6271 update_frame_gutter_geometry(f);
6273 /* If we clear the frame we have to force its contents to be redrawn. */
6275 f->frame_changed = 1;
6277 /* Invalidate the subwindow caches. We use subwindows_changed here
6278 to cause subwindows to get instantiated. This is because
6279 subwindows_state_changed is less strict - dealing with things
6280 like the clicked state of button. We have to do this before
6281 redisplaying the gutters as subwindows get unmapped in the
6283 if (f->frame_changed)
6284 reset_frame_subwindow_instance_cache(f);
6286 if (f->frame_changed || f->subwindows_changed) {
6287 /* we have to do this so the gutter gets regenerated. */
6288 reset_gutter_display_lines(f);
6291 hold_frame_size_changes();
6293 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6294 /* Within this section, we are defenseless and assume that the
6295 following cannot happen:
6297 1) garbage collection
6298 2) Lisp code evaluation
6299 3) frame size changes
6301 We ensure (3) by calling hold_frame_size_changes(), which
6302 will cause any pending frame size changes to get put on hold
6303 till after the end of the critical section. (1) follows
6304 automatically if (2) is met. #### Unfortunately, there are
6305 some places where Lisp code can be called within this section.
6306 We need to remove them.
6308 If Fsignal() is called during this critical section, we
6311 If garbage collection is called during this critical section,
6312 we simply return. #### We should abort instead.
6314 #### If a frame-size change does occur we should probably
6315 actually be preempting redisplay. */
6317 MAYBE_DEVMETH(d, frame_output_begin, (f));
6319 /* Erase the frame before outputting its contents. */
6321 MAYBE_DEVMETH(d, clear_frame, (f));
6324 /* We can now update the gutters, safe in the knowledge that our
6325 efforts won't get undone. */
6327 /* This can call lisp, but redisplay is protected by binding
6328 inhibit_quit. More importantly the code involving display lines
6329 *assumes* that GC will not happen and so does not GCPRO
6330 anything. Since we use this code the whole time with the gutters
6331 we cannot allow GC to happen when manipulating the gutters. */
6332 update_frame_gutters(f);
6334 /* Do the selected window first. */
6335 redisplay_window(FRAME_SELECTED_WINDOW(f), 0);
6337 /* Then do the rest. */
6338 redisplay_windows(f->root_window, 1);
6340 MAYBE_DEVMETH(d, frame_output_end, (f));
6342 update_frame_title(f);
6344 #ifdef HAVE_TOOLBARS
6345 /* Finally update the toolbars. It seems its possible to get in a
6346 cycle between updating the gutter and the toolbars. Basically we
6347 want to end up with both being up-to-date and this doesn't seem
6348 possible in a single pass. */
6349 update_frame_toolbars(f);
6350 #endif /* HAVE_TOOLBARS */
6352 CLASS_RESET_CHANGED_FLAGS(f);
6353 f->window_face_cache_reset = 0;
6354 f->echo_area_garbaged = 0;
6357 if (!f->size_change_pending)
6358 f->size_changed = 0;
6360 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6362 /* Allow frame size changes to occur again.
6364 #### what happens if changes to other frames happen? */
6365 unhold_one_frame_size_changes(f);
6367 map_windows(f, call_redisplay_end_triggers, 0);
6371 /* Ensure that all frames on the given device are correctly displayed.
6372 If AUTOMATIC is non-zero, and the device implementation indicates
6373 no automatic redisplay, as printers do, then the device is not
6374 redisplayed. AUTOMATIC is set to zero when called from lisp
6375 functions (redraw-device) and (redisplay-device), and to non-zero
6376 when called from "lazy" redisplay();
6379 static int redisplay_device(struct device *d, int automatic)
6381 Lisp_Object frame, frmcons;
6382 int size_change_failed = 0;
6385 if (automatic && DEVICE_IMPL_FLAG(d, XDEVIMPF_NO_AUTO_REDISPLAY))
6388 if (DEVICE_STREAM_P(d)) /* nothing to do */
6391 /* It is possible that redisplay has been called before the
6392 device is fully initialized, or that the console implementation
6393 allows frameless devices. If so then continue with the next
6395 if (NILP(DEVICE_SELECTED_FRAME(d)))
6398 if (!DEVICE_IMPL_FLAG(d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) {
6400 REDISPLAY_PREEMPTION_CHECK;
6405 /* Always do the selected frame first. */
6406 frame = DEVICE_SELECTED_FRAME(d);
6410 if (f->icon_changed || f->windows_changed)
6411 update_frame_icon(f);
6413 if (FRAME_REPAINT_P(f)) {
6414 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) {
6415 int preempted = redisplay_frame(f, 0);
6420 /* If the frame redisplay did not get preempted, then this flag
6421 should have gotten set to 0. It might be possible for that
6422 not to happen if a size change event were to occur at an odd
6423 time. To make sure we don't miss anything we simply don't
6424 reset the top level flags until the condition ends up being
6425 in the right state. */
6426 if (f->size_changed)
6427 size_change_failed = 1;
6430 DEVICE_FRAME_LOOP(frmcons, d) {
6431 f = XFRAME(XCAR(frmcons));
6433 if (f == XFRAME(DEVICE_SELECTED_FRAME(d)))
6436 if (f->icon_changed || f->windows_changed)
6437 update_frame_icon(f);
6439 if (FRAME_REPAINT_P(f)) {
6440 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) {
6441 int preempted = redisplay_frame(f, 0);
6446 if (f->size_change_pending)
6447 size_change_failed = 1;
6451 /* If we get here then we redisplayed all of our frames without
6452 getting preempted so mark ourselves as clean. */
6453 CLASS_RESET_CHANGED_FLAGS(d);
6455 if (!size_change_failed)
6456 d->size_changed = 0;
6461 static Lisp_Object restore_profiling_redisplay_flag(Lisp_Object val)
6463 profiling_redisplay_flag = XINT(val);
6467 /* Ensure that all windows on all frames on all devices are displaying
6468 the current contents of their respective buffers. */
6470 static void redisplay_without_hooks(void)
6472 Lisp_Object devcons, concons;
6473 int size_change_failed = 0;
6474 int count = specpdl_depth();
6476 if (profiling_active) {
6477 record_unwind_protect(restore_profiling_redisplay_flag,
6478 make_int(profiling_redisplay_flag));
6479 profiling_redisplay_flag = 1;
6482 if (asynch_device_change_pending)
6483 handle_asynch_device_change();
6485 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6486 !disable_preemption && preemption_count < max_preempts)
6489 DEVICE_LOOP_NO_BREAK(devcons, concons) {
6490 struct device *d = XDEVICE(XCAR(devcons));
6493 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(d)) {
6494 preempted = redisplay_device(d, 1);
6498 RESET_CHANGED_SET_FLAGS;
6502 /* See comment in redisplay_device. */
6503 if (d->size_changed)
6504 size_change_failed = 1;
6507 preemption_count = 0;
6509 /* Mark redisplay as accurate */
6510 GLOBAL_RESET_CHANGED_FLAGS;
6511 RESET_CHANGED_SET_FLAGS;
6513 if (faces_changed) {
6514 mark_all_faces_as_clean();
6518 if (!size_change_failed)
6521 reset_buffer_changes();
6524 unbind_to(count, Qnil);
6527 void redisplay(void)
6529 if (last_display_warning_tick != display_warning_tick &&
6530 !inhibit_warning_display) {
6531 /* If an error occurs during this function, oh well.
6532 If we report another warning, we could get stuck in an
6533 infinite loop reporting warnings. */
6534 call0_trapping_errors(0, Qdisplay_warning_buffer);
6535 last_display_warning_tick = display_warning_tick;
6537 /* The run_hook_trapping_errors functions are smart enough not
6538 to do any evalling if the hook function is empty, so there
6539 should not be any significant time loss. All places in the
6540 C code that call redisplay() are prepared to handle GCing,
6541 so we should be OK. */
6542 #ifndef INHIBIT_REDISPLAY_HOOKS
6543 run_hook_trapping_errors("Error in pre-redisplay-hook",
6544 Qpre_redisplay_hook);
6545 #endif /* INHIBIT_REDISPLAY_HOOKS */
6547 redisplay_without_hooks();
6549 #ifndef INHIBIT_REDISPLAY_HOOKS
6550 run_hook_trapping_errors("Error in post-redisplay-hook",
6551 Qpost_redisplay_hook);
6552 #endif /* INHIBIT_REDISPLAY_HOOKS */
6555 static char window_line_number_buf[32];
6557 /* Efficiently determine the window line number, and return a pointer
6558 to its printed representation. Do this regardless of whether
6559 line-number-mode is on. The first line in the buffer is counted as
6560 1. If narrowing is in effect, the lines are counted from the
6561 beginning of the visible portion of the buffer. */
6562 static char *window_line_number(struct window *w, int type)
6564 struct device *d = XDEVICE(XFRAME(w->frame)->device);
6565 struct buffer *b = XBUFFER(w->buffer);
6566 /* Be careful in the order of these tests. The first clause will
6567 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6568 This can occur when the frame title is computed really early */
6570 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6571 (w == XWINDOW(FRAME_SELECTED_WINDOW(device_selected_frame(d)))) &&
6572 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6573 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) ==
6576 : marker_position(w->pointm[type]));
6579 line = buffer_line_number(b, pos, 1);
6581 long_to_string(window_line_number_buf, line + 1);
6583 return window_line_number_buf;
6586 /* Given a character representing an object in a modeline
6587 specification, return a string (stored into the global array
6588 `mode_spec_bufbyte_string') with the information that object
6591 This function is largely unchanged from previous versions of the
6594 Warning! This code is also used for frame titles and can be called
6595 very early in the device/frame update process! JV
6598 static void decode_mode_spec(struct window *w, Emchar spec, int type)
6600 Lisp_Object obj = Qnil;
6601 const char *str = NULL;
6602 struct buffer *b = XBUFFER(w->buffer);
6604 Dynarr_reset(mode_spec_bufbyte_string);
6607 /* print buffer name */
6612 /* print visited file name */
6617 /* print the current column */
6619 Lisp_Object tmp = Fselected_window(Qnil);
6620 Bufpos pt = (w == XWINDOW(tmp))
6622 : marker_position(w->pointm[type]);
6624 column_at_point(b, pt,
6625 1) + !!column_number_start_at_one;
6628 long_to_string(buf, col);
6630 Dynarr_add_many(mode_spec_bufbyte_string,
6631 (const Bufbyte *)buf, strlen(buf));
6633 goto decode_mode_spec_done;
6635 /* print the file coding system */
6638 Lisp_Object codesys = b->buffer_file_coding_system;
6639 /* Be very careful here not to get an error. */
6640 if (NILP(codesys) || SYMBOLP(codesys)
6641 || CODING_SYSTEMP(codesys)) {
6642 codesys = Ffind_coding_system(codesys);
6643 if (CODING_SYSTEMP(codesys))
6644 obj = XCODING_SYSTEM_MNEMONIC(codesys);
6646 #endif /* FILE_CODING */
6650 /* print the current line number */
6652 str = window_line_number(w, type);
6655 /* print value of mode-name (obsolete) */
6660 /* print hyphen and frame number, if != 1 */
6663 struct frame *f = XFRAME(w->frame);
6664 if (FRAME_TTY_P(f) && f->order_count > 1
6665 && f->order_count <= 99999999) {
6666 /* Naughty, naughty */
6667 char *writable_str = alloca_array(char, 10);
6668 sprintf(writable_str, "-%d", f->order_count);
6671 #endif /* HAVE_TTY */
6675 /* print Narrow if appropriate */
6677 if (BUF_BEGV(b) > BUF_BEG(b)
6678 || BUF_ZV(b) < BUF_Z(b))
6682 /* print %, * or hyphen, if buffer is read-only, modified or
6685 str = (!NILP(b->read_only)
6686 ? "%" : ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6690 /* print * or hyphen -- XEmacs change to allow a buffer to be
6691 read-only but still indicate whether it is modified. */
6693 str = ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6694 ? "*" : (!NILP(b->read_only)
6698 /* #### defined in 19.29 decode_mode_spec, but not in
6699 modeline-format doc string. */
6700 /* This differs from %* in that it ignores read-only-ness. */
6702 str = ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6706 /* print process status */
6708 obj = Fget_buffer_process(w->buffer);
6710 str = GETTEXT("no process");
6712 obj = Fsymbol_name(Fprocess_status(obj));
6715 /* Print name of selected frame. */
6717 obj = XFRAME(w->frame)->name;
6720 /* indicate TEXT or BINARY */
6722 /* #### NT does not use this any more. Now what? */
6726 /* print percent of buffer above top of window, or Top, Bot or
6729 Bufpos pos = marker_position(w->start[type]);
6731 /* This had better be while the desired lines are being done. */
6732 if (w->window_end_pos[type] <= BUF_Z(b) - BUF_ZV(b)) {
6733 if (pos <= BUF_BEGV(b))
6737 } else if (pos <= BUF_BEGV(b)) {
6740 /* This hard limit is ok since the string it will hold
6741 has a fixed maximum length of 3. But just to be
6744 Charcount chars = pos - BUF_BEGV(b);
6745 Charcount total = BUF_ZV(b) - BUF_BEGV(b);
6747 /* Avoid overflow on big buffers */
6748 int percent = total > LONG_MAX / 200 ?
6749 (chars + total / 200) / (total / 100) :
6750 (chars * 100 + total / 2) / total;
6752 /* We can't normally display a 3-digit number, so get us
6753 a 2-digit number that is close. */
6757 sprintf(buf, "%d%%", percent);
6758 Dynarr_add_many(mode_spec_bufbyte_string,
6759 (Bufbyte *) buf, strlen(buf));
6761 goto decode_mode_spec_done;
6766 /* print percent of buffer above bottom of window, perhaps plus
6767 Top, or print Bottom or All */
6769 Bufpos toppos = marker_position(w->start[type]);
6770 Bufpos botpos = BUF_Z(b) - w->window_end_pos[type];
6772 /* botpos is only accurate as of the last redisplay, so we can
6773 only treat it as a hint. In particular, after erase-buffer,
6774 botpos may be negative. */
6775 if (botpos < toppos)
6778 if (botpos >= BUF_ZV(b)) {
6779 if (toppos <= BUF_BEGV(b))
6784 /* This hard limit is ok since the string it will hold
6785 has a fixed maximum length of around 6. But just to
6788 Charcount chars = botpos - BUF_BEGV(b);
6789 Charcount total = BUF_ZV(b) - BUF_BEGV(b);
6791 /* Avoid overflow on big buffers */
6792 int percent = total > LONG_MAX / 200 ?
6793 (chars + total / 200) / (total / 100) :
6794 (chars * 100 + total / 2) / max(total, 1);
6796 /* We can't normally display a 3-digit number, so get us
6797 a 2-digit number that is close. */
6801 if (toppos <= BUF_BEGV(b))
6802 sprintf(buf, "Top%d%%", percent);
6804 sprintf(buf, "%d%%", percent);
6806 Dynarr_add_many(mode_spec_bufbyte_string,
6807 (Bufbyte *) buf, strlen(buf));
6809 goto decode_mode_spec_done;
6819 /* print one [ for each recursive editing level. */
6823 if (command_loop_level > 5) {
6828 for (i = 0; i < command_loop_level; i++)
6829 Dynarr_add(mode_spec_bufbyte_string, '[');
6831 goto decode_mode_spec_done;
6834 /* print one ] for each recursive editing level. */
6838 if (command_loop_level > 5) {
6843 for (i = 0; i < command_loop_level; i++)
6844 Dynarr_add(mode_spec_bufbyte_string, ']');
6846 goto decode_mode_spec_done;
6849 /* print infinitely many dashes -- handle at top level now */
6858 Dynarr_add_many(mode_spec_bufbyte_string,
6859 XSTRING_DATA(obj), XSTRING_LENGTH(obj));
6861 Dynarr_add_many(mode_spec_bufbyte_string,
6862 (const Bufbyte*)str, strlen(str));
6865 decode_mode_spec_done:
6866 Dynarr_add(mode_spec_bufbyte_string, '\0');
6870 /* Given a display line, free all of its data structures. */
6872 static void free_display_line(struct display_line *dl)
6876 if (dl->display_blocks) {
6877 for (block = 0; block < Dynarr_largest(dl->display_blocks);
6879 struct display_block *db =
6880 Dynarr_atp(dl->display_blocks, block);
6882 Dynarr_free(db->runes);
6885 Dynarr_free(dl->display_blocks);
6886 dl->display_blocks = NULL;
6889 if (dl->left_glyphs) {
6890 Dynarr_free(dl->left_glyphs);
6891 dl->left_glyphs = NULL;
6894 if (dl->right_glyphs) {
6895 Dynarr_free(dl->right_glyphs);
6896 dl->right_glyphs = NULL;
6900 /* Given an array of display lines, free them and all data structures
6901 contained within them. */
6903 void free_display_lines(display_line_dynarr * dla)
6907 for (line = 0; line < Dynarr_largest(dla); line++) {
6908 free_display_line(Dynarr_atp(dla, line));
6914 /* Call internal free routine for each set of display lines. */
6916 void free_display_structs(struct window_mirror *mir)
6918 if (mir->current_display_lines) {
6919 free_display_lines(mir->current_display_lines);
6920 mir->current_display_lines = 0;
6923 if (mir->desired_display_lines) {
6924 free_display_lines(mir->desired_display_lines);
6925 mir->desired_display_lines = 0;
6929 static void mark_glyph_block_dynarr(glyph_block_dynarr * gba)
6932 glyph_block *gb = Dynarr_atp(gba, 0);
6933 glyph_block *gb_last = Dynarr_atp(gba, Dynarr_length(gba));
6935 for (; gb < gb_last; gb++) {
6936 if (!NILP(gb->glyph))
6937 mark_object(gb->glyph);
6938 if (!NILP(gb->extent))
6939 mark_object(gb->extent);
6944 /* See the comment in image_instantiate_cache_result as to why marking
6945 the glyph will also mark the image_instance. */
6946 void mark_redisplay_structs(display_line_dynarr * dla)
6948 display_line *dl = Dynarr_atp(dla, 0);
6949 display_line *dl_last = Dynarr_atp(dla, Dynarr_length(dla));
6951 for (; dl < dl_last; dl++) {
6952 display_block_dynarr *dba = dl->display_blocks;
6953 display_block *db = Dynarr_atp(dba, 0);
6954 display_block *db_last = Dynarr_atp(dba, Dynarr_length(dba));
6956 for (; db < db_last; db++) {
6957 rune_dynarr *ra = db->runes;
6958 rune *r = Dynarr_atp(ra, 0);
6959 rune *r_last = Dynarr_atp(ra, Dynarr_length(ra));
6961 for (; r < r_last; r++) {
6962 if (r->type == RUNE_DGLYPH) {
6963 if (!NILP(r->object.dglyph.glyph))
6964 mark_object(r->object.dglyph.
6966 if (!NILP(r->object.dglyph.extent))
6967 mark_object(r->object.dglyph.
6973 mark_glyph_block_dynarr(dl->left_glyphs);
6974 mark_glyph_block_dynarr(dl->right_glyphs);
6978 static void mark_window_mirror(struct window_mirror *mir)
6980 mark_redisplay_structs(mir->current_display_lines);
6981 mark_redisplay_structs(mir->desired_display_lines);
6984 mark_window_mirror(mir->next);
6987 mark_window_mirror(mir->hchild);
6988 else if (mir->vchild)
6989 mark_window_mirror(mir->vchild);
6992 void mark_redisplay(void)
6994 Lisp_Object frmcons, devcons, concons;
6996 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
6997 struct frame *f = XFRAME(XCAR(frmcons));
6998 mark_window_mirror(f->root_mirror);
7003 /*****************************************************************************
7004 Line Start Cache Description and Rationale
7006 The traditional scrolling code in Emacs breaks in a variable height world.
7007 It depends on the key assumption that the number of lines that can be
7008 displayed at any given time is fixed. This led to a complete separation
7009 of the scrolling code from the redisplay code. In order to fully support
7010 variable height lines, the scrolling code must actually be tightly
7011 integrated with redisplay. Only redisplay can determine how many lines
7012 will be displayed on a screen for any given starting point.
7014 What is ideally wanted is a complete list of the starting buffer position
7015 for every possible display line of a buffer along with the height of that
7016 display line. Maintaining such a full list would be very expensive. We
7017 settle for having it include information for all areas which we happen to
7018 generate anyhow (i.e. the region currently being displayed) and for those
7019 areas we need to work with.
7021 In order to ensure that the cache accurately represents what redisplay
7022 would actually show, it is necessary to invalidate it in many situations.
7023 If the buffer changes, the starting positions may no longer be correct.
7024 If a face or an extent has changed then the line heights may have altered.
7025 These events happen frequently enough that the cache can end up being
7026 constantly disabled. With this potentially constant invalidation when is
7027 the cache ever useful?
7029 Even if the cache is invalidated before every single usage, it is
7030 necessary. Scrolling often requires knowledge about display lines which
7031 are actually above or below the visible region. The cache provides a
7032 convenient light-weight method of storing this information for multiple
7033 display regions. This knowledge is necessary for the scrolling code to
7034 always obey the First Golden Rule of Redisplay.
7036 If the cache already contains all of the information that the scrolling
7037 routines happen to need so that it doesn't have to go generate it, then we
7038 are able to obey the Third Golden Rule of Redisplay. The first thing we
7039 do to help out the cache is to always add the displayed region. This
7040 region had to be generated anyway, so the cache ends up getting the
7041 information basically for free. In those cases where a user is simply
7042 scrolling around viewing a buffer there is a high probability that this is
7043 sufficient to always provide the needed information. The second thing we
7044 can do is be smart about invalidating the cache.
7046 TODO -- Be smart about invalidating the cache. Potential places:
7048 + Insertions at end-of-line which don't cause line-wraps do not alter the
7049 starting positions of any display lines. These types of buffer
7050 modifications should not invalidate the cache. This is actually a large
7051 optimization for redisplay speed as well.
7053 + Buffer modifications frequently only affect the display of lines at and
7054 below where they occur. In these situations we should only invalidate
7055 the part of the cache starting at where the modification occurs.
7057 In case you're wondering, the Second Golden Rule of Redisplay is not
7059 ****************************************************************************/
7061 /* This will get used quite a bit so we don't want to be constantly
7062 allocating and freeing it. */
7063 static line_start_cache_dynarr *internal_cache;
7065 /* Makes internal_cache represent the TYPE display structs and only
7066 the TYPE display structs. */
7068 static void update_internal_cache_list(struct window *w, int type)
7071 display_line_dynarr *dla = window_display_lines(w, type);
7073 Dynarr_reset(internal_cache);
7074 for (line = 0; line < Dynarr_length(dla); line++) {
7075 struct display_line *dl = Dynarr_atp(dla, line);
7080 struct line_start_cache lsc;
7082 lsc.start = dl->bufpos;
7083 lsc.end = dl->end_bufpos;
7084 lsc.height = dl->ascent + dl->descent;
7086 Dynarr_add(internal_cache, lsc);
7091 /* Reset the line cache if necessary. This should be run at the
7092 beginning of any function which access the cache. */
7094 static void validate_line_start_cache(struct window *w)
7096 struct buffer *b = XBUFFER(w->buffer);
7097 struct frame *f = XFRAME(w->frame);
7099 if (!w->line_cache_validation_override) {
7100 /* f->extents_changed used to be in here because extent face and
7101 size changes can cause text shifting. However, the extent
7102 covering the region is constantly having its face set and
7103 priority altered by the mouse code. This means that the line
7104 start cache is constantly being invalidated. This is bad
7105 since the mouse code also triggers heavy usage of the cache.
7106 Since it is an unlikely that f->extents being changed
7107 indicates that the cache really needs to be updated and if it
7108 does redisplay will catch it pretty quickly we no longer
7109 invalidate the cache if it is set. This greatly speeds up
7110 dragging out regions with the mouse. */
7111 if (XINT(w->line_cache_last_updated) < BUF_MODIFF(b)
7112 || f->faces_changed || f->clip_changed) {
7113 Dynarr_reset(w->line_start_cache);
7118 /* Return the very first buffer position contained in the given
7119 window's cache, or -1 if the cache is empty. Assumes that the
7122 static Bufpos line_start_cache_start(struct window *w)
7124 line_start_cache_dynarr *cache = w->line_start_cache;
7126 if (!Dynarr_length(cache))
7129 return Dynarr_atp(cache, 0)->start;
7132 /* Return the very last buffer position contained in the given
7133 window's cache, or -1 if the cache is empty. Assumes that the
7136 static Bufpos line_start_cache_end(struct window *w)
7138 line_start_cache_dynarr *cache = w->line_start_cache;
7140 if (!Dynarr_length(cache))
7143 return Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7146 /* Return the index of the line POINT is contained within in window
7147 W's line start cache. It will enlarge the cache or move the cache
7148 window in order to have POINT be present in the cache. MIN_PAST is
7149 a guarantee of the number of entries in the cache present on either
7150 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7151 then it will be treated as 0, but the cache window will not be
7152 allowed to shift. Returns -1 if POINT cannot be found in the cache
7155 int point_in_line_start_cache(struct window *w, Bufpos point, int min_past)
7157 struct buffer *b = XBUFFER(w->buffer);
7158 line_start_cache_dynarr *cache = w->line_start_cache;
7159 unsigned int top, bottom;
7162 validate_line_start_cache(w);
7163 w->line_cache_validation_override++;
7165 /* Let functions pass in negative values, but we still treat -1
7167 /* #### bogosity alert */
7168 if (min_past < 0 && min_past != -1)
7169 min_past = -min_past;
7171 if (!Dynarr_length(cache) || line_start_cache_start(w) > point
7172 || line_start_cache_end(w) < point) {
7174 int win_char_height = window_char_height(w, 1);
7176 /* Occasionally we get here with a 0 height
7177 window. find_next_newline_no_quit will abort if we pass it a
7178 count of 0 so handle that case. */
7179 if (!win_char_height)
7180 win_char_height = 1;
7182 if (!Dynarr_length(cache)) {
7183 Bufpos from = find_next_newline_no_quit(b, point, -1);
7185 find_next_newline_no_quit(b, from, win_char_height);
7187 update_line_start_cache(w, from, to, point, 0);
7189 if (!Dynarr_length(cache)) {
7190 w->line_cache_validation_override--;
7195 assert(Dynarr_length(cache));
7198 while (line_start_cache_start(w) > point
7199 && (loop < cache_adjustment || min_past == -1)) {
7202 from = line_start_cache_start(w);
7203 if (from <= BUF_BEGV(b))
7207 find_next_newline_no_quit(b, from,
7209 to = line_start_cache_end(w);
7211 update_line_start_cache(w, from, to, point, 0);
7215 if (line_start_cache_start(w) > point) {
7218 from = find_next_newline_no_quit(b, point, -1);
7219 if (from >= BUF_ZV(b)) {
7220 to = find_next_newline_no_quit(b, from,
7225 to = find_next_newline_no_quit(b, from,
7228 update_line_start_cache(w, from, to, point, 0);
7232 while (line_start_cache_end(w) < point
7233 && (loop < cache_adjustment || min_past == -1)) {
7236 to = line_start_cache_end(w);
7237 if (to >= BUF_ZV(b))
7240 from = line_start_cache_end(w);
7241 to = find_next_newline_no_quit(b, from,
7244 update_line_start_cache(w, from, to, point, 0);
7248 if (line_start_cache_end(w) < point) {
7251 from = find_next_newline_no_quit(b, point, -1);
7252 if (from >= BUF_ZV(b)) {
7253 to = find_next_newline_no_quit(b, from,
7258 to = find_next_newline_no_quit(b, from,
7261 update_line_start_cache(w, from, to, point, 0);
7265 assert(Dynarr_length(cache));
7270 /* This could happen if the buffer is narrowed. */
7271 if (line_start_cache_start(w) > point
7272 || line_start_cache_end(w) < point) {
7273 w->line_cache_validation_override--;
7279 top = Dynarr_length(cache) - 1;
7286 pos = (bottom + top + 1) >> 1;
7287 start = Dynarr_atp(cache, pos)->start;
7288 end = Dynarr_atp(cache, pos)->end;
7290 if (point >= start && point <= end) {
7292 && line_start_cache_start(w) > BUF_BEGV(b)) {
7294 find_next_newline_no_quit(b,
7295 line_start_cache_start
7298 Bufpos to = line_start_cache_end(w);
7300 update_line_start_cache(w, from, to, point, 0);
7301 goto find_point_loop;
7302 } else if ((Dynarr_length(cache) - pos - 1) < min_past
7303 && line_start_cache_end(w) < BUF_ZV(b)) {
7304 Bufpos from = line_start_cache_end(w);
7305 Bufpos to = find_next_newline_no_quit(b, from,
7311 update_line_start_cache(w, from, to, point, 0);
7312 goto find_point_loop;
7314 w->line_cache_validation_override--;
7317 } else if (point > end)
7319 else if (point < start)
7324 new_pos = (bottom + top + 1) >> 1;
7325 if (pos == new_pos) {
7326 w->line_cache_validation_override--;
7332 /* Return a boolean indicating if POINT would be visible in window W
7333 if display of the window was to begin at STARTP. */
7335 int point_would_be_visible(struct window *w, Bufpos startp, Bufpos point)
7337 struct buffer *b = XBUFFER(w->buffer);
7338 int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
7339 int bottom = WINDOW_TEXT_HEIGHT(w);
7342 /* If point is before the intended start it obviously can't be visible. */
7346 /* If point or start are not in the accessible buffer range, then
7348 if (startp < BUF_BEGV(b) || startp > BUF_ZV(b)
7349 || point < BUF_BEGV(b) || point > BUF_ZV(b))
7352 validate_line_start_cache(w);
7353 w->line_cache_validation_override++;
7355 start_elt = point_in_line_start_cache(w, startp, 0);
7356 if (start_elt == -1) {
7357 w->line_cache_validation_override--;
7361 assert(line_start_cache_start(w) <= startp
7362 && line_start_cache_end(w) >= startp);
7367 /* Expand the cache if necessary. */
7368 if (start_elt == Dynarr_length(w->line_start_cache)) {
7370 Dynarr_atp(w->line_start_cache,
7371 start_elt - 1)->start;
7373 start_elt = point_in_line_start_cache(w, old_startp,
7377 /* We've already actually processed old_startp, so increment
7381 /* If this happens we didn't add any extra elements. Bummer. */
7382 if (start_elt == Dynarr_length(w->line_start_cache)) {
7383 w->line_cache_validation_override--;
7388 height = Dynarr_atp(w->line_start_cache, start_elt)->height;
7390 if (pixpos + height > bottom) {
7391 if (bottom - pixpos < VERTICAL_CLIP(w, 0)) {
7392 w->line_cache_validation_override--;
7398 if (point <= Dynarr_atp(w->line_start_cache, start_elt)->end) {
7399 w->line_cache_validation_override--;
7407 /* For the given window W, if display starts at STARTP, what will be
7408 the buffer position at the beginning or end of the last line
7409 displayed. The end of the last line is also know as the window end
7412 WARNING: It is possible that redisplay failed to layout any lines for the
7413 windows. Under normal circumstances this is rare. However it seems that it
7414 does occur in the following situation: A mouse event has come in and we
7415 need to compute its location in a window. That code (in
7416 pixel_to_glyph_translation) already can handle 0 as an error return value.
7418 #### With a little work this could probably be reworked as just a
7419 call to start_with_line_at_pixpos. */
7422 start_end_of_last_line(struct window *w, Bufpos startp, int end, int may_error)
7424 struct buffer *b = XBUFFER(w->buffer);
7425 line_start_cache_dynarr *cache = w->line_start_cache;
7427 int bottom = WINDOW_TEXT_HEIGHT(w);
7431 validate_line_start_cache(w);
7432 w->line_cache_validation_override++;
7434 if (startp < BUF_BEGV(b))
7435 startp = BUF_BEGV(b);
7436 else if (startp > BUF_ZV(b))
7440 start_elt = point_in_line_start_cache(w, cur_start, 0);
7441 if (start_elt == -1)
7442 return may_error ? 0 : startp;
7445 int height = Dynarr_atp(cache, start_elt)->height;
7447 cur_start = Dynarr_atp(cache, start_elt)->start;
7449 if (pixpos + height > bottom) {
7450 /* Adjust for any possible clip. */
7451 if (bottom - pixpos < VERTICAL_CLIP(w, 0))
7454 if (start_elt < 0) {
7455 w->line_cache_validation_override--;
7461 w->line_cache_validation_override--;
7463 return Dynarr_atp(cache,
7466 return Dynarr_atp(cache,
7473 if (start_elt == Dynarr_length(cache)) {
7474 Bufpos from = line_start_cache_end(w);
7475 int win_char_height = window_char_height(w, 0);
7476 Bufpos to = find_next_newline_no_quit(b, from,
7481 /* We've hit the end of the bottom so that's what it is. */
7482 if (from >= BUF_ZV(b)) {
7483 w->line_cache_validation_override--;
7487 update_line_start_cache(w, from, to, BUF_PT(b), 0);
7489 /* Updating the cache invalidates any current indexes. */
7491 point_in_line_start_cache(w, cur_start, -1) + 1;
7496 /* For the given window W, if display starts at STARTP, what will be
7497 the buffer position at the beginning of the last line displayed. */
7499 Bufpos start_of_last_line(struct window * w, Bufpos startp)
7501 return start_end_of_last_line(w, startp, 0, 0);
7504 /* For the given window W, if display starts at STARTP, what will be
7505 the buffer position at the end of the last line displayed. This is
7506 also know as the window end position. */
7508 Bufpos end_of_last_line(struct window * w, Bufpos startp)
7510 return start_end_of_last_line(w, startp, 1, 0);
7513 static Bufpos end_of_last_line_may_error(struct window *w, Bufpos startp)
7515 return start_end_of_last_line(w, startp, 1, 1);
7518 /* For window W, what does the starting position have to be so that
7519 the line containing POINT will cover pixel position PIXPOS. */
7521 Bufpos start_with_line_at_pixpos(struct window * w, Bufpos point, int pixpos)
7523 struct buffer *b = XBUFFER(w->buffer);
7525 Bufpos cur_pos, prev_pos = point;
7526 int point_line_height;
7527 int pixheight = pixpos - WINDOW_TEXT_TOP(w);
7529 validate_line_start_cache(w);
7530 w->line_cache_validation_override++;
7532 cur_elt = point_in_line_start_cache(w, point, 0);
7533 /* #### See comment in update_line_start_cache about big minibuffers. */
7535 w->line_cache_validation_override--;
7539 point_line_height = Dynarr_atp(w->line_start_cache, cur_elt)->height;
7542 cur_pos = Dynarr_atp(w->line_start_cache, cur_elt)->start;
7544 pixheight -= Dynarr_atp(w->line_start_cache, cur_elt)->height;
7546 /* Do not take into account the value of vertical_clip here.
7547 That is the responsibility of the calling functions. */
7548 if (pixheight < 0) {
7549 w->line_cache_validation_override--;
7550 if (-pixheight > point_line_height)
7551 /* We can't make the target line cover pixpos, so put it
7552 above pixpos. That way it will at least be visible. */
7559 while (cur_elt < 0) {
7561 int win_char_height;
7563 if (cur_pos <= BUF_BEGV(b)) {
7564 w->line_cache_validation_override--;
7568 win_char_height = window_char_height(w, 0);
7569 if (!win_char_height)
7570 win_char_height = 1;
7573 find_next_newline_no_quit(b, cur_pos,
7575 to = line_start_cache_end(w);
7576 update_line_start_cache(w, from, to, point, 0);
7578 cur_elt = point_in_line_start_cache(w, cur_pos, 2) - 1;
7579 assert(cur_elt >= -1);
7580 /* This used to be cur_elt>=0 under the assumption that if
7581 point is in the top line and not at BUF_BEGV, then
7582 setting the window_start to a newline before the start of
7583 the first line will always cause scrolling.
7585 However in my (jv) opinion this is wrong. That new line
7586 can be hidden in various ways: invisible extents, an
7587 explicit window-start not at a newline character etc.
7588 The existence of those are indeed known to create crashes
7589 on that assert. So we have no option but to continue the
7590 search if we found point at the top of the line_start_cache
7592 cur_pos = Dynarr_atp(w->line_start_cache, 0)->start;
7598 /* For window W, what does the starting position have to be so that
7599 the line containing point is on display line LINE. If LINE is
7600 positive it is considered to be the number of lines from the top of
7601 the window (0 is the top line). If it is negative the number is
7602 considered to be the number of lines from the bottom (-1 is the
7606 start_with_point_on_display_line(struct window *w, Bufpos point, int line)
7608 validate_line_start_cache(w);
7609 w->line_cache_validation_override++;
7612 int cur_elt = point_in_line_start_cache(w, point, line);
7614 if (cur_elt - line < 0)
7615 cur_elt = 0; /* Hit the top */
7619 w->line_cache_validation_override--;
7620 return Dynarr_atp(w->line_start_cache, cur_elt)->start;
7622 /* The calculated value of pixpos is correct for the bottom line
7623 or what we want when line is -1. Therefore we subtract one
7624 because we have already handled one line. */
7625 int new_line = -line - 1;
7626 int cur_elt = point_in_line_start_cache(w, point, new_line);
7627 int pixpos = WINDOW_TEXT_BOTTOM(w);
7628 Bufpos retval, search_point;
7630 /* If scroll_on_clipped_lines is false, the last "visible" line of
7631 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7632 If s_o_c_l is true, then we don't want to count a clipped
7633 line, so back up from the bottom by the height of the line
7634 containing point. */
7635 if (scroll_on_clipped_lines)
7637 Dynarr_atp(w->line_start_cache, cur_elt)->height;
7641 if (cur_elt + new_line >= Dynarr_length(w->line_start_cache)) {
7642 /* Hit the bottom of the buffer. */
7644 (cur_elt + new_line) -
7645 Dynarr_length(w->line_start_cache) + 1;
7649 XSETWINDOW(window, w);
7650 default_face_height_and_width(window, &defheight, 0);
7652 cur_elt = Dynarr_length(w->line_start_cache) - 1;
7654 pixpos -= (adjustment * defheight);
7655 if (pixpos < WINDOW_TEXT_TOP(w))
7656 pixpos = WINDOW_TEXT_TOP(w);
7658 cur_elt = cur_elt + new_line;
7660 search_point = Dynarr_atp(w->line_start_cache, cur_elt)->start;
7662 retval = start_with_line_at_pixpos(w, search_point, pixpos);
7663 w->line_cache_validation_override--;
7668 /* This is used to speed up vertical scrolling by caching the known
7669 buffer starting positions for display lines. This allows the
7670 scrolling routines to avoid costly calls to regenerate_window. If
7671 NO_REGEN is true then it will only add the values in the DESIRED
7672 display structs which are in the given range.
7674 Note also that the FROM/TO values are minimums. It is possible
7675 that this function will actually add information outside of the
7676 lines containing those positions. This can't hurt but it could
7679 #### We currently force the cache to have only 1 contiguous region.
7680 It might help to make the cache a dynarr of caches so that we can
7681 cover more areas. This might, however, turn out to be a lot of
7682 overhead for too little gain. */
7685 update_line_start_cache(struct window *w, Bufpos from, Bufpos to,
7686 Bufpos point, int no_regen)
7688 struct buffer *b = XBUFFER(w->buffer);
7689 line_start_cache_dynarr *cache = w->line_start_cache;
7690 Bufpos low_bound, high_bound;
7692 validate_line_start_cache(w);
7693 w->line_cache_validation_override++;
7695 if (from < BUF_BEGV(b))
7701 w->line_cache_validation_override--;
7705 if (Dynarr_length(cache)) {
7706 low_bound = line_start_cache_start(w);
7707 high_bound = line_start_cache_end(w);
7709 /* Check to see if the desired range is already in the cache. */
7710 if (from >= low_bound && to <= high_bound) {
7711 w->line_cache_validation_override--;
7715 /* Check to make sure that the desired range is adjacent to the
7716 current cache. If not, invalidate the cache. */
7717 if (to < low_bound || from > high_bound) {
7718 Dynarr_reset(cache);
7719 low_bound = high_bound = -1;
7722 low_bound = high_bound = -1;
7725 w->line_cache_last_updated = make_int(BUF_MODIFF(b));
7727 /* This could be integrated into the next two sections, but it is easier
7728 to follow what's going on by having it separate. */
7732 update_internal_cache_list(w, DESIRED_DISP);
7733 if (!Dynarr_length(internal_cache)) {
7734 w->line_cache_validation_override--;
7738 start = Dynarr_atp(internal_cache, 0)->start;
7740 Dynarr_atp(internal_cache,
7741 Dynarr_length(internal_cache) - 1)->end;
7743 /* We aren't allowed to generate additional information to fill in
7744 gaps, so if the DESIRED structs don't overlap the cache, reset the
7746 if (Dynarr_length(cache)) {
7747 if (end < low_bound || start > high_bound)
7748 Dynarr_reset(cache);
7750 /* #### What should really happen if what we are doing is
7751 extending a line (the last line)? */
7752 if (Dynarr_length(cache) == 1
7753 && Dynarr_length(internal_cache) == 1)
7754 Dynarr_reset(cache);
7757 if (!Dynarr_length(cache)) {
7758 Dynarr_add_many(cache, Dynarr_atp(internal_cache, 0),
7759 Dynarr_length(internal_cache));
7760 w->line_cache_validation_override--;
7764 /* An extra check just in case the calling function didn't pass in
7765 the bounds of the DESIRED structs in the first place. */
7766 if (start >= low_bound && end <= high_bound) {
7767 w->line_cache_validation_override--;
7771 /* At this point we know that the internal cache partially overlaps
7773 if (start < low_bound) {
7774 int ic_elt = Dynarr_length(internal_cache) - 1;
7775 while (ic_elt >= 0) {
7776 if (Dynarr_atp(internal_cache, ic_elt)->start <
7783 if (!(ic_elt >= 0)) {
7784 Dynarr_reset(cache);
7785 Dynarr_add_many(cache,
7786 Dynarr_atp(internal_cache, 0),
7787 Dynarr_length(internal_cache));
7788 w->line_cache_validation_override--;
7792 Dynarr_insert_many_at_start(cache,
7793 Dynarr_atp(internal_cache,
7797 if (end > high_bound) {
7800 while (ic_elt < Dynarr_length(internal_cache)) {
7801 if (Dynarr_atp(internal_cache, ic_elt)->start >
7808 if (!(ic_elt < Dynarr_length(internal_cache))) {
7809 Dynarr_reset(cache);
7810 Dynarr_add_many(cache,
7811 Dynarr_atp(internal_cache, 0),
7812 Dynarr_length(internal_cache));
7813 w->line_cache_validation_override--;
7817 Dynarr_add_many(cache,
7818 Dynarr_atp(internal_cache, ic_elt),
7819 Dynarr_length(internal_cache) - ic_elt);
7822 w->line_cache_validation_override--;
7826 if (!Dynarr_length(cache) || from < low_bound) {
7827 Bufpos startp = find_next_newline_no_quit(b, from, -1);
7829 int old_lb = low_bound;
7831 while (startp < old_lb || low_bound == -1) {
7835 regenerate_window(w, startp, point, CMOTION_DISP);
7836 update_internal_cache_list(w, CMOTION_DISP);
7838 /* If this assert is triggered then regenerate_window failed
7839 to layout a single line. This is not possible since we
7840 force at least a single line to be layout for CMOTION_DISP */
7841 assert(Dynarr_length(internal_cache));
7842 assert(startp == Dynarr_atp(internal_cache, 0)->start);
7844 ic_elt = Dynarr_length(internal_cache) - 1;
7845 if (low_bound != -1) {
7846 while (ic_elt >= 0) {
7847 if (Dynarr_atp(internal_cache, ic_elt)->
7854 assert(ic_elt >= 0);
7857 Dynarr_atp(internal_cache, ic_elt)->end + 1;
7860 * Handle invisible text properly:
7861 * If the last line we're inserting has the same end as the
7862 * line before which it will be added, merge the two lines.
7864 if (Dynarr_length(cache) &&
7865 Dynarr_atp(internal_cache, ic_elt)->end ==
7866 Dynarr_atp(cache, marker)->end) {
7867 Dynarr_atp(cache, marker)->start
7868 = Dynarr_atp(internal_cache, ic_elt)->start;
7869 Dynarr_atp(cache, marker)->height
7871 Dynarr_atp(internal_cache, ic_elt)->height;
7875 if (ic_elt >= 0) { /* we still have lines to add.. */
7876 Dynarr_insert_many(cache,
7877 Dynarr_atp(internal_cache,
7880 marker += (ic_elt + 1);
7883 if (startp < low_bound || low_bound == -1)
7885 startp = new_startp;
7886 if (startp > BUF_ZV(b)) {
7887 w->line_cache_validation_override--;
7893 assert(Dynarr_length(cache));
7894 assert(from >= low_bound);
7896 /* Readjust the high_bound to account for any changes made while
7897 correcting the low_bound. */
7898 high_bound = Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7900 if (to > high_bound) {
7902 Dynarr_atp(cache, Dynarr_length(cache) - 1)->end + 1;
7905 regenerate_window(w, startp, point, CMOTION_DISP);
7906 update_internal_cache_list(w, CMOTION_DISP);
7908 /* See comment above about regenerate_window failing. */
7909 assert(Dynarr_length(internal_cache));
7911 Dynarr_add_many(cache, Dynarr_atp(internal_cache, 0),
7912 Dynarr_length(internal_cache));
7914 Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7915 startp = high_bound + 1;
7917 while (to > high_bound);
7920 w->line_cache_validation_override--;
7921 assert(to <= high_bound);
7924 /* Given x and y coordinates in characters, relative to a window,
7925 return the pixel location corresponding to those coordinates. The
7926 pixel location returned is the center of the given character
7927 position. The pixel values are generated relative to the window,
7930 The modeline is considered to be part of the window. */
7933 glyph_to_pixel_translation(struct window *w, int char_x, int char_y,
7934 int *pix_x, int *pix_y)
7936 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
7937 int num_disp_lines, modeline;
7939 int defheight, defwidth;
7941 XSETWINDOW(window, w);
7942 default_face_height_and_width(window, &defheight, &defwidth);
7944 /* If we get a bogus value indicating somewhere above or to the left of
7945 the window, use the first window line or character position
7952 num_disp_lines = Dynarr_length(dla);
7954 if (num_disp_lines) {
7955 if (Dynarr_atp(dla, 0)->modeline) {
7961 /* First check if the y position intersects the display lines. */
7962 if (char_y < num_disp_lines) {
7963 struct display_line *dl = Dynarr_atp(dla, char_y + modeline);
7964 struct display_block *db =
7965 get_display_block_from_line(dl, TEXT);
7967 *pix_y = (dl->ypos - dl->ascent +
7968 ((unsigned int)(dl->ascent + dl->descent -
7971 if (char_x < Dynarr_length(db->runes)) {
7972 struct rune *rb = Dynarr_atp(db->runes, char_x);
7974 *pix_x = rb->xpos + (rb->width >> 1);
7976 int last_rune = Dynarr_length(db->runes) - 1;
7977 struct rune *rb = Dynarr_atp(db->runes, last_rune);
7979 char_x -= last_rune;
7981 *pix_x = rb->xpos + rb->width;
7982 *pix_x += ((char_x - 1) * defwidth);
7983 *pix_x += (defwidth >> 1);
7986 /* It didn't intersect, so extrapolate. #### For now, we include the
7987 modeline in this since we don't have true character positions in
7990 if (!Dynarr_length(w->face_cachels))
7991 reset_face_cachels(w);
7993 char_y -= num_disp_lines;
7995 if (Dynarr_length(dla)) {
7996 struct display_line *dl =
7997 Dynarr_atp(dla, Dynarr_length(dla) - 1);
7998 *pix_y = dl->ypos + dl->descent - dl->clip;
8000 *pix_y = WINDOW_TEXT_TOP(w);
8002 *pix_y += (char_y * defheight);
8003 *pix_y += (defheight >> 1);
8005 *pix_x = WINDOW_TEXT_LEFT(w);
8006 /* Don't adjust by one because this is still the unadjusted value. */
8007 *pix_x += (char_x * defwidth);
8008 *pix_x += (defwidth >> 1);
8011 if (*pix_x > w->pixel_left + w->pixel_width)
8012 *pix_x = w->pixel_left + w->pixel_width;
8013 if (*pix_y > w->pixel_top + w->pixel_height)
8014 *pix_y = w->pixel_top + w->pixel_height;
8016 *pix_x -= w->pixel_left;
8017 *pix_y -= w->pixel_top;
8020 /* Given a display line and a position, determine if there is a glyph
8021 there and return information about it if there is. */
8024 get_position_object(struct display_line *dl, Lisp_Object * obj1,
8025 Lisp_Object * obj2, int x_coord, int *low_x_coord,
8028 struct display_block *db;
8031 get_next_display_block(dl->bounds, dl->display_blocks, x_coord, 0);
8033 /* We use get_next_display_block to get the actual display block
8034 that would be displayed at x_coord. */
8036 if (block == NO_BLOCK)
8039 db = Dynarr_atp(dl->display_blocks, block);
8041 for (elt = 0; elt < Dynarr_length(db->runes); elt++) {
8042 struct rune *rb = Dynarr_atp(db->runes, elt);
8044 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) {
8045 if (rb->type == RUNE_DGLYPH) {
8046 *obj1 = rb->object.dglyph.glyph;
8047 *obj2 = rb->object.dglyph.extent;
8054 *low_x_coord = rb->xpos;
8056 *high_x_coord = rb->xpos + rb->width;
8063 #define UPDATE_CACHE_RETURN \
8065 d->pixel_to_glyph_cache.valid = 1; \
8066 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8067 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8068 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8069 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8070 d->pixel_to_glyph_cache.frame = f; \
8071 d->pixel_to_glyph_cache.col = *col; \
8072 d->pixel_to_glyph_cache.row = *row; \
8073 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8074 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8075 d->pixel_to_glyph_cache.w = *w; \
8076 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8077 d->pixel_to_glyph_cache.closest = *closest; \
8078 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8079 d->pixel_to_glyph_cache.obj1 = *obj1; \
8080 d->pixel_to_glyph_cache.obj2 = *obj2; \
8081 d->pixel_to_glyph_cache.retval = position; \
8082 RETURN_SANS_WARNINGS position; \
8085 /* Given x and y coordinates in pixels relative to a frame, return
8086 information about what is located under those coordinates.
8088 The return value will be one of:
8090 OVER_TOOLBAR: over one of the 4 frame toolbars
8091 OVER_MODELINE: over a modeline
8092 OVER_BORDER: over an internal border
8093 OVER_NOTHING: over the text area, but not over text
8094 OVER_OUTSIDE: outside of the frame border
8095 OVER_TEXT: over text in the text area
8101 -- nil if the coordinates are not over a glyph or a toolbar button.
8105 -- an extent, if the coordinates are over a glyph in the text area
8108 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8109 equivalent coordinates relative to the upper-left corner of the glyph.
8111 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8112 equivalent coordinates relative to the upper-left corner of the character.
8114 Otherwise, OBJ_X and OBJ_Y are undefined.
8118 pixel_to_glyph_translation(struct frame *f, int x_coord, int y_coord,
8119 int *col, int *row, int *obj_x, int *obj_y,
8120 struct window **w, Bufpos * bufpos,
8121 Bufpos * closest, Charcount * modeline_closest,
8122 Lisp_Object * obj1, Lisp_Object * obj2)
8125 struct pixel_to_glyph_translation_cache *cache;
8127 int frm_left, frm_right, frm_top, frm_bottom;
8128 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8129 int position = OVER_NOTHING;
8130 int device_check_failed = 0;
8131 display_line_dynarr *dla;
8133 /* This is a safety valve in case this got called with a frame in
8134 the middle of being deleted. */
8135 if (!DEVICEP(f->device) || !DEVICE_LIVE_P(XDEVICE(f->device))) {
8136 device_check_failed = 1;
8137 d = NULL, cache = NULL; /* Warning suppression */
8139 d = XDEVICE(f->device);
8140 cache = &d->pixel_to_glyph_cache;
8143 if (!device_check_failed
8145 && cache->frame == f
8146 && cache->low_x_coord <= x_coord
8147 && cache->high_x_coord > x_coord
8148 && cache->low_y_coord <= y_coord && cache->high_y_coord > y_coord) {
8151 *obj_x = cache->obj_x;
8152 *obj_y = cache->obj_y;
8154 *bufpos = cache->bufpos;
8155 *closest = cache->closest;
8156 *modeline_closest = cache->modeline_closest;
8157 *obj1 = cache->obj1;
8158 *obj2 = cache->obj2;
8160 return cache->retval;
8169 *modeline_closest = -1;
8173 low_x_coord = x_coord;
8174 high_x_coord = x_coord + 1;
8175 low_y_coord = y_coord;
8176 high_y_coord = y_coord + 1;
8179 if (device_check_failed)
8180 return OVER_NOTHING;
8182 frm_left = FRAME_LEFT_BORDER_END(f);
8183 frm_right = FRAME_RIGHT_BORDER_START(f);
8184 frm_top = FRAME_TOP_BORDER_END(f);
8185 frm_bottom = FRAME_BOTTOM_BORDER_START(f);
8187 /* Check if the mouse is outside of the text area actually used by
8189 if (y_coord < frm_top) {
8190 if (y_coord >= FRAME_TOP_BORDER_START(f)) {
8191 low_y_coord = FRAME_TOP_BORDER_START(f);
8192 high_y_coord = frm_top;
8193 position = OVER_BORDER;
8194 } else if (y_coord >= 0) {
8196 high_y_coord = FRAME_TOP_BORDER_START(f);
8197 position = OVER_TOOLBAR;
8199 low_y_coord = y_coord;
8201 position = OVER_OUTSIDE;
8203 } else if (y_coord >= frm_bottom) {
8204 if (y_coord < FRAME_BOTTOM_BORDER_END(f)) {
8205 low_y_coord = frm_bottom;
8206 high_y_coord = FRAME_BOTTOM_BORDER_END(f);
8207 position = OVER_BORDER;
8208 } else if (y_coord < FRAME_PIXHEIGHT(f)) {
8209 low_y_coord = FRAME_BOTTOM_BORDER_END(f);
8210 high_y_coord = FRAME_PIXHEIGHT(f);
8211 position = OVER_TOOLBAR;
8213 low_y_coord = FRAME_PIXHEIGHT(f);
8214 high_y_coord = y_coord;
8215 position = OVER_OUTSIDE;
8219 if (position != OVER_TOOLBAR && position != OVER_BORDER) {
8220 if (x_coord < frm_left) {
8221 if (x_coord >= FRAME_LEFT_BORDER_START(f)) {
8222 low_x_coord = FRAME_LEFT_BORDER_START(f);
8223 high_x_coord = frm_left;
8224 position = OVER_BORDER;
8225 } else if (x_coord >= 0) {
8227 high_x_coord = FRAME_LEFT_BORDER_START(f);
8228 position = OVER_TOOLBAR;
8230 low_x_coord = x_coord;
8232 position = OVER_OUTSIDE;
8234 } else if (x_coord >= frm_right) {
8235 if (x_coord < FRAME_RIGHT_BORDER_END(f)) {
8236 low_x_coord = frm_right;
8237 high_x_coord = FRAME_RIGHT_BORDER_END(f);
8238 position = OVER_BORDER;
8239 } else if (x_coord < FRAME_PIXWIDTH(f)) {
8240 low_x_coord = FRAME_RIGHT_BORDER_END(f);
8241 high_x_coord = FRAME_PIXWIDTH(f);
8242 position = OVER_TOOLBAR;
8244 low_x_coord = FRAME_PIXWIDTH(f);
8245 high_x_coord = x_coord;
8246 position = OVER_OUTSIDE;
8250 #ifdef HAVE_TOOLBARS
8251 if (position == OVER_TOOLBAR) {
8252 *obj1 = toolbar_button_at_pixpos(f, x_coord, y_coord);
8255 UPDATE_CACHE_RETURN;
8257 #endif /* HAVE_TOOLBARS */
8259 /* We still have to return the window the pointer is next to and its
8260 relative y position even if it is outside the x boundary. */
8261 if (x_coord < frm_left)
8263 else if (x_coord > frm_right)
8264 x_coord = frm_right;
8266 /* Same in reverse. */
8267 if (y_coord < frm_top)
8269 else if (y_coord > frm_bottom)
8270 y_coord = frm_bottom;
8272 /* Find what window the given coordinates are actually in. */
8273 window = f->root_window;
8274 *w = find_window_by_pixel_pos(x_coord, y_coord, window);
8276 /* If we didn't find a window, we're done. */
8278 UPDATE_CACHE_RETURN;
8279 } else if (position != OVER_NOTHING) {
8281 *modeline_closest = -1;
8283 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) {
8285 UPDATE_CACHE_RETURN;
8289 /* Check if the window is a minibuffer but isn't active. */
8290 if (MINI_WINDOW_P(*w) && !minibuf_level) {
8291 /* Must reset the window value since some callers will ignore
8292 the return value if it is set. */
8294 UPDATE_CACHE_RETURN;
8297 /* See if the point is over window vertical divider */
8298 if (window_needs_vertical_divider(*w)) {
8299 int div_x_high = WINDOW_RIGHT(*w);
8300 int div_x_low = div_x_high - window_divider_width(*w);
8301 int div_y_high = WINDOW_BOTTOM(*w);
8302 int div_y_low = WINDOW_TOP(*w);
8304 if (div_x_low < x_coord && x_coord <= div_x_high &&
8305 div_y_low < y_coord && y_coord <= div_y_high) {
8306 low_x_coord = div_x_low;
8307 high_x_coord = div_x_high;
8308 low_y_coord = div_y_low;
8309 high_y_coord = div_y_high;
8310 position = OVER_V_DIVIDER;
8311 UPDATE_CACHE_RETURN;
8315 dla = window_display_lines(*w, CURRENT_DISP);
8317 for (*row = 0; *row < Dynarr_length(dla); (*row)++) {
8318 int really_over_nothing = 0;
8319 struct display_line *dl = Dynarr_atp(dla, *row);
8321 if ((int)(dl->ypos - dl->ascent) <= y_coord
8322 && y_coord <= (int)(dl->ypos + dl->descent)) {
8323 int check_margin_glyphs = 0;
8324 struct display_block *db =
8325 get_display_block_from_line(dl, TEXT);
8326 struct rune *rb = 0;
8328 if (x_coord < dl->bounds.left_white
8329 || x_coord >= dl->bounds.right_white)
8330 check_margin_glyphs = 1;
8332 low_y_coord = dl->ypos - dl->ascent;
8333 high_y_coord = dl->ypos + dl->descent + 1;
8335 if (position == OVER_BORDER
8336 || position == OVER_OUTSIDE
8337 || check_margin_glyphs) {
8338 int x_check, left_bound;
8340 if (check_margin_glyphs) {
8342 left_bound = dl->bounds.left_white;
8344 x_check = high_x_coord;
8345 left_bound = frm_left;
8348 if (Dynarr_length(db->runes)) {
8349 if (x_check <= left_bound) {
8384 *modeline_closest += dl->offset;
8386 *closest += dl->offset;
8388 /* #### What should be here. */
8390 *modeline_closest = 0;
8395 if (check_margin_glyphs) {
8396 if (x_coord < dl->bounds.left_in
8397 || x_coord >= dl->bounds.right_in) {
8398 /* If we are over the outside margins then we
8399 know the loop over the text block isn't going
8400 to accomplish anything. So we go ahead and
8401 set what information we can right here and
8405 y_coord - (dl->ypos -
8407 get_position_object(dl, obj1,
8413 UPDATE_CACHE_RETURN;
8416 UPDATE_CACHE_RETURN;
8419 for (*col = 0; *col <= Dynarr_length(db->runes);
8422 (*col == Dynarr_length(db->runes));
8425 rb = Dynarr_atp(db->runes, *col);
8428 (rb->xpos <= x_coord
8429 && x_coord < rb->xpos + rb->width)) {
8432 rb = Dynarr_atp(db->runes,
8436 *bufpos = rb->bufpos + dl->offset;
8437 low_x_coord = rb->xpos;
8438 high_x_coord = rb->xpos + rb->width;
8440 if (rb->type == RUNE_DGLYPH) {
8443 /* Find the first character after the glyph. */
8480 /* In this case we failed to find a non-glyph
8481 character so we return the last position
8482 displayed on the line. */
8484 Dynarr_length(db->runes)) {
8496 really_over_nothing = 1;
8511 window_displayed_height(*w);
8513 if (position == OVER_NOTHING)
8517 if (rb->type == RUNE_DGLYPH) {
8524 } else if (rb->type ==
8533 UPDATE_CACHE_RETURN;
8535 || (rb->type == RUNE_CHAR
8536 && rb->object.chr.ch ==
8539 /* At this point we may have glyphs in the right
8541 if (check_margin_glyphs)
8542 get_position_object(dl,
8548 UPDATE_CACHE_RETURN;
8551 if (rb->type == RUNE_DGLYPH) {
8558 } else if (rb->type ==
8567 *obj_x = x_coord - rb->xpos;
8569 y_coord - (dl->ypos -
8572 /* At this point we may have glyphs in the left
8574 if (check_margin_glyphs)
8575 get_position_object(dl,
8582 if (position == OVER_NOTHING
8583 && !really_over_nothing)
8584 position = OVER_TEXT;
8586 UPDATE_CACHE_RETURN;
8593 *row = Dynarr_length(dla) - 1;
8594 if (FRAME_WIN_P(f)) {
8595 int bot_elt = Dynarr_length(dla) - 1;
8598 struct display_line *dl = Dynarr_atp(dla, bot_elt);
8599 int adj_area = y_coord - (dl->ypos + dl->descent);
8603 XSETWINDOW(lwin, *w);
8604 default_face_height_and_width(lwin, 0, &defheight);
8606 *row += (adj_area / defheight);
8610 /* #### This should be checked out some more to determine what
8611 should really be going on. */
8612 if (!MARKERP((*w)->start[CURRENT_DISP]))
8615 *closest = end_of_last_line_may_error(*w,
8616 marker_position((*w)->
8620 UPDATE_CACHE_RETURN;
8623 #undef UPDATE_CACHE_RETURN
8625 /***************************************************************************/
8627 /* Lisp functions */
8629 /***************************************************************************/
8631 DEFUN("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8632 Ensure that all minibuffers are correctly showing the echo area.
8636 Lisp_Object devcons, concons;
8638 DEVICE_LOOP_NO_BREAK(devcons, concons) {
8639 struct device *d = XDEVICE(XCAR(devcons));
8640 Lisp_Object frmcons;
8642 DEVICE_FRAME_LOOP(frmcons, d) {
8643 struct frame *f = XFRAME(XCAR(frmcons));
8645 if (FRAME_REPAINT_P(f) && FRAME_HAS_MINIBUF_P(f)) {
8646 Lisp_Object window = FRAME_MINIBUF_WINDOW(f);
8648 MAYBE_DEVMETH(d, frame_output_begin, (f));
8651 * If the frame size has changed, there may be random
8652 * chud on the screen left from previous messages
8653 * because redisplay_frame hasn't been called yet.
8654 * Clear the screen to get rid of the potential mess.
8656 if (f->echo_area_garbaged) {
8657 MAYBE_DEVMETH(d, clear_frame, (f));
8658 f->echo_area_garbaged = 0;
8660 redisplay_window(window, 0);
8661 MAYBE_DEVMETH(d, frame_output_end, (f));
8663 call_redisplay_end_triggers(XWINDOW(window), 0);
8671 static Lisp_Object restore_disable_preemption_value(Lisp_Object value)
8673 disable_preemption = XINT(value);
8677 DEFUN("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8678 Clear frame FRAME and output again what is supposed to appear on it.
8679 FRAME defaults to the selected frame if omitted.
8680 Normally, redisplay is preempted as normal if input arrives. However,
8681 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8682 input and is guaranteed to proceed to completion.
8684 (frame, no_preempt))
8686 struct frame *f = decode_frame(frame);
8687 int count = specpdl_depth();
8689 if (!NILP(no_preempt)) {
8690 record_unwind_protect(restore_disable_preemption_value,
8691 make_int(disable_preemption));
8692 disable_preemption++;
8696 redisplay_frame(f, 1);
8698 /* See the comment in Fredisplay_frame. */
8699 RESET_CHANGED_SET_FLAGS;
8701 return unbind_to(count, Qnil);
8704 DEFUN("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8705 Ensure that FRAME's contents are correctly displayed.
8706 This differs from `redraw-frame' in that it only redraws what needs to
8707 be updated, as opposed to unconditionally clearing and redrawing
8709 FRAME defaults to the selected frame if omitted.
8710 Normally, redisplay is preempted as normal if input arrives. However,
8711 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8712 input and is guaranteed to proceed to completion.
8714 (frame, no_preempt))
8716 struct frame *f = decode_frame(frame);
8717 int count = specpdl_depth();
8719 if (!NILP(no_preempt)) {
8720 record_unwind_protect(restore_disable_preemption_value,
8721 make_int(disable_preemption));
8722 disable_preemption++;
8725 redisplay_frame(f, 1);
8727 /* If we don't reset the global redisplay flags here, subsequent
8728 changes to the display will not get registered by redisplay
8729 because it thinks it already has registered changes. If you
8730 really knew what you were doing you could confuse redisplay by
8731 calling Fredisplay_frame while updating another frame. We assume
8732 that if you know what you are doing you will not be that
8734 RESET_CHANGED_SET_FLAGS;
8736 return unbind_to(count, Qnil);
8739 DEFUN("redraw-device", Fredraw_device, 0, 2, 0, /*
8740 Clear device DEVICE and output again what is supposed to appear on it.
8741 DEVICE defaults to the selected device if omitted.
8742 Normally, redisplay is preempted as normal if input arrives. However,
8743 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8744 input and is guaranteed to proceed to completion.
8746 (device, no_preempt))
8748 struct device *d = decode_device(device);
8749 Lisp_Object frmcons;
8750 int count = specpdl_depth();
8752 if (!NILP(no_preempt)) {
8753 record_unwind_protect(restore_disable_preemption_value,
8754 make_int(disable_preemption));
8755 disable_preemption++;
8758 DEVICE_FRAME_LOOP(frmcons, d) {
8759 XFRAME(XCAR(frmcons))->clear = 1;
8761 redisplay_device(d, 0);
8763 /* See the comment in Fredisplay_frame. */
8764 RESET_CHANGED_SET_FLAGS;
8766 return unbind_to(count, Qnil);
8769 DEFUN("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8770 Ensure that DEVICE's contents are correctly displayed.
8771 This differs from `redraw-device' in that it only redraws what needs to
8772 be updated, as opposed to unconditionally clearing and redrawing
8774 DEVICE defaults to the selected device if omitted.
8775 Normally, redisplay is preempted as normal if input arrives. However,
8776 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8777 input and is guaranteed to proceed to completion.
8779 (device, no_preempt))
8781 struct device *d = decode_device(device);
8782 int count = specpdl_depth();
8784 if (!NILP(no_preempt)) {
8785 record_unwind_protect(restore_disable_preemption_value,
8786 make_int(disable_preemption));
8787 disable_preemption++;
8790 redisplay_device(d, 0);
8792 /* See the comment in Fredisplay_frame. */
8793 RESET_CHANGED_SET_FLAGS;
8795 return unbind_to(count, Qnil);
8798 /* Big lie. Big lie. This will force all modelines to be updated
8799 regardless if the all flag is set or not. It remains in existence
8800 solely for backwards compatibility. */
8801 DEFUN("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8802 Force the modeline of the current buffer to be redisplayed.
8803 With optional non-nil ALL, force redisplay of all modelines.
8807 MARK_MODELINE_CHANGED;
8811 DEFUN("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8812 Force an immediate update of the cursor on FRAME.
8813 FRAME defaults to the selected frame if omitted.
8817 redisplay_redraw_cursor(decode_frame(frame), 1);
8821 /***************************************************************************/
8823 /* Lisp-variable change triggers */
8825 /***************************************************************************/
8828 margin_width_changed_in_frame(Lisp_Object specifier, struct frame *f,
8831 /* Nothing to be done? */
8835 redisplay_variable_changed(Lisp_Object sym, Lisp_Object * val,
8836 Lisp_Object in_object, int flags)
8838 /* #### clip_changed should really be renamed something like
8839 global_redisplay_change. */
8844 /* This is called if the built-in glyphs have their properties
8847 redisplay_glyph_changed(Lisp_Object glyph, Lisp_Object property,
8850 if (WINDOWP(locale)) {
8851 MARK_FRAME_GLYPHS_CHANGED(XFRAME
8852 (WINDOW_FRAME(XWINDOW(locale))));
8853 } else if (FRAMEP(locale)) {
8854 MARK_FRAME_GLYPHS_CHANGED(XFRAME(locale));
8855 } else if (DEVICEP(locale)) {
8856 Lisp_Object frmcons;
8857 DEVICE_FRAME_LOOP(frmcons, XDEVICE(locale))
8858 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8859 } else if (CONSOLEP(locale)) {
8860 Lisp_Object frmcons, devcons;
8861 CONSOLE_FRAME_LOOP_NO_BREAK(frmcons, devcons, XCONSOLE(locale))
8862 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8863 } else { /* global or buffer */
8865 Lisp_Object frmcons, devcons, concons;
8866 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
8867 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8872 text_cursor_visible_p_changed(Lisp_Object specifier, struct window *w,
8875 if (XFRAME(w->frame)->init_finished)
8876 Fforce_cursor_redisplay(w->frame);
8879 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
8881 /***************************************************************************/
8883 /* memory usage computation */
8885 /***************************************************************************/
8888 compute_rune_dynarr_usage(rune_dynarr * dyn, struct overhead_stats *ovstats)
8890 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8894 compute_display_block_dynarr_usage(display_block_dynarr * dyn,
8895 struct overhead_stats *ovstats)
8902 total = Dynarr_memory_usage(dyn, ovstats);
8903 for (i = 0; i < Dynarr_largest(dyn); i++)
8905 compute_rune_dynarr_usage(Dynarr_at(dyn, i).runes, ovstats);
8911 compute_glyph_block_dynarr_usage(glyph_block_dynarr * dyn,
8912 struct overhead_stats *ovstats)
8914 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8918 compute_display_line_dynarr_usage(display_line_dynarr * dyn,
8919 struct overhead_stats *ovstats)
8926 total = Dynarr_memory_usage(dyn, ovstats);
8927 for (i = 0; i < Dynarr_largest(dyn); i++) {
8928 struct display_line *dl = &Dynarr_at(dyn, i);
8930 compute_display_block_dynarr_usage(dl->display_blocks,
8933 compute_glyph_block_dynarr_usage(dl->left_glyphs, ovstats);
8935 compute_glyph_block_dynarr_usage(dl->right_glyphs, ovstats);
8942 compute_line_start_cache_dynarr_usage(line_start_cache_dynarr * dyn,
8943 struct overhead_stats *ovstats)
8945 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8948 #endif /* MEMORY_USAGE_STATS */
8950 /***************************************************************************/
8952 /* initialization */
8954 /***************************************************************************/
8956 void init_redisplay(void)
8958 disable_preemption = 0;
8959 preemption_count = 0;
8960 max_preempts = INIT_MAX_PREEMPTS;
8966 if (!cmotion_display_lines)
8967 cmotion_display_lines = Dynarr_new(display_line);
8968 if (!mode_spec_bufbyte_string)
8969 mode_spec_bufbyte_string = Dynarr_new(Bufbyte);
8970 if (!formatted_string_extent_dynarr)
8971 formatted_string_extent_dynarr = Dynarr_new(EXTENT);
8972 if (!formatted_string_extent_start_dynarr)
8973 formatted_string_extent_start_dynarr =
8974 Dynarr_new(Bytecount);
8975 if (!formatted_string_extent_end_dynarr)
8976 formatted_string_extent_end_dynarr =
8977 Dynarr_new(Bytecount);
8978 if (!internal_cache)
8979 internal_cache = Dynarr_new(line_start_cache);
8982 /* window system is nil when in -batch mode */
8983 if (!initialized || noninteractive)
8986 /* If the user wants to use a window system, we shouldn't bother
8987 initializing the terminal. This is especially important when the
8988 terminal is so dumb that emacs gives up before and doesn't bother
8989 using the window system.
8991 If the DISPLAY environment variable is set, try to use X, and die
8992 with an error message if that doesn't work. */
8994 #ifdef HAVE_X_WINDOWS
8995 if (!strcmp(display_use, "x")) {
8996 /* Some stuff checks this way early. */
8997 Vwindow_system = Qx;
8998 Vinitial_window_system = Qx;
9001 #endif /* HAVE_X_WINDOWS */
9004 if (!strcmp(display_use, "gtk")) {
9005 Vwindow_system = Qgtk;
9006 Vinitial_window_system = Qgtk;
9012 /* If no window system has been specified, try to use the terminal. */
9014 stderr_out("SXEmacs: standard input is not a tty\n");
9018 /* Look at the TERM variable */
9019 if (!getenv("TERM")) {
9021 ("Please set the environment variable TERM; see tset(1).\n");
9025 Vinitial_window_system = Qtty;
9027 #else /* not HAVE_TTY */
9028 /* No DISPLAY specified, and no TTY support. */
9029 stderr_out("SXEmacs: Cannot open display.\n\
9030 Please set the environmental variable DISPLAY to an appropriate value.\n");
9036 void syms_of_redisplay(void)
9038 defsymbol(&Qcursor_in_echo_area, "cursor-in-echo-area");
9039 #ifndef INHIBIT_REDISPLAY_HOOKS
9040 defsymbol(&Qpre_redisplay_hook, "pre-redisplay-hook");
9041 defsymbol(&Qpost_redisplay_hook, "post-redisplay-hook");
9042 #endif /* INHIBIT_REDISPLAY_HOOKS */
9043 defsymbol(&Qdisplay_warning_buffer, "display-warning-buffer");
9044 defsymbol(&Qbar_cursor, "bar-cursor");
9045 defsymbol(&Qredisplay_end_trigger_functions,
9046 "redisplay-end-trigger-functions");
9047 defsymbol(&Qtop_bottom, "top-bottom");
9048 defsymbol(&Qbuffer_list_changed_hook, "buffer-list-changed-hook");
9050 DEFSUBR(Fredisplay_echo_area);
9051 DEFSUBR(Fredraw_frame);
9052 DEFSUBR(Fredisplay_frame);
9053 DEFSUBR(Fredraw_device);
9054 DEFSUBR(Fredisplay_device);
9055 DEFSUBR(Fredraw_modeline);
9056 DEFSUBR(Fforce_cursor_redisplay);
9059 void vars_of_redisplay(void)
9063 staticpro(&last_arrow_position);
9064 staticpro(&last_arrow_string);
9065 last_arrow_position = Qnil;
9066 last_arrow_string = Qnil;
9069 /* #### Probably temporary */
9070 DEFVAR_INT("redisplay-cache-adjustment", &cache_adjustment /*
9071 \(Temporary) Setting this will impact the performance of the internal
9074 cache_adjustment = 2;
9076 DEFVAR_INT_MAGIC("pixel-vertical-clip-threshold", &vertical_clip /*
9077 Minimum pixel height for clipped bottom display line.
9078 A clipped line shorter than this won't be displayed.
9080 redisplay_variable_changed);
9083 DEFVAR_INT_MAGIC("pixel-horizontal-clip-threshold", &horizontal_clip /*
9084 Minimum visible area for clipped glyphs at right boundary.
9085 Clipped glyphs shorter than this won't be displayed.
9086 Only pixmap glyph instances are currently allowed to be clipped.
9088 redisplay_variable_changed);
9089 horizontal_clip = 5;
9091 DEFVAR_LISP("global-mode-string", &Vglobal_mode_string /*
9092 String displayed by modeline-format's "%m" specification.
9094 Vglobal_mode_string = Qnil;
9096 DEFVAR_LISP_MAGIC("overlay-arrow-position", &Voverlay_arrow_position /*
9097 Marker for where to display an arrow on top of the buffer text.
9098 This must be the beginning of a line in order to work.
9099 See also `overlay-arrow-string'.
9101 redisplay_variable_changed);
9102 Voverlay_arrow_position = Qnil;
9104 DEFVAR_LISP_MAGIC("overlay-arrow-string", &Voverlay_arrow_string /*
9105 String or glyph to display as an arrow. See also `overlay-arrow-position'.
9106 \(Note that despite the name of this variable, it can be set to a glyph as
9109 redisplay_variable_changed);
9110 Voverlay_arrow_string = Qnil;
9112 DEFVAR_INT("scroll-step", &scroll_step /*
9113 *The number of lines to try scrolling a window by when point moves out.
9114 If that fails to bring point back on frame, point is centered instead.
9115 If this is zero, point is always centered after it moves off screen.
9119 DEFVAR_INT("scroll-conservatively", &scroll_conservatively /*
9120 *Scroll up to this many lines, to bring point back on screen.
9122 scroll_conservatively = 0;
9124 DEFVAR_BOOL_MAGIC("truncate-partial-width-windows", &truncate_partial_width_windows /*
9125 *Non-nil means truncate lines in all windows less than full frame wide.
9127 redisplay_variable_changed);
9128 truncate_partial_width_windows = 1;
9130 DEFVAR_LISP("visible-bell", &Vvisible_bell /*
9131 *Non-nil substitutes a visual signal for the audible bell.
9133 Default behavior is to flash the whole screen. On some platforms,
9134 special effects are available using the following values:
9136 'display Flash the whole screen (ie, the default behavior).
9137 'top-bottom Flash only the top and bottom lines of the selected frame.
9139 When effects are unavailable on a platform, the visual bell is the
9140 default, whole screen. (Currently only X supports any special effects.)
9142 Vvisible_bell = Qnil;
9144 DEFVAR_BOOL("no-redraw-on-reenter", &no_redraw_on_reenter /*
9145 *Non-nil means no need to redraw entire frame after suspending.
9146 A non-nil value is useful if the terminal can automatically preserve
9147 Emacs's frame display when you reenter Emacs.
9148 It is up to you to set this variable if your terminal can do that.
9150 no_redraw_on_reenter = 0;
9152 DEFVAR_LISP("window-system", &Vwindow_system /*
9153 A symbol naming the window-system under which Emacs is running,
9154 such as `x', or nil if emacs is running on an ordinary terminal.
9156 Do not use this variable, except for GNU Emacs compatibility, as it
9157 gives wrong values in a multi-device environment. Use `console-type'
9160 Vwindow_system = Qnil;
9162 /* #### Temporary shit until window-system is eliminated. */
9163 DEFVAR_CONST_LISP("initial-window-system", &Vinitial_window_system /*
9166 Vinitial_window_system = Qnil;
9168 DEFVAR_BOOL("cursor-in-echo-area", &cursor_in_echo_area /*
9169 Non-nil means put cursor in minibuffer, at end of any message there.
9171 cursor_in_echo_area = 0;
9173 /* #### Shouldn't this be generalized as follows:
9175 if nil, use block cursor.
9176 if a number, use a bar cursor of that width.
9177 Otherwise, use a 1-pixel bar cursor.
9179 #### Or better yet, this variable should be trashed entirely
9180 (use a Lisp-magic variable to maintain compatibility)
9181 and a specifier `cursor-shape' added, which allows a block
9182 cursor, a bar cursor, a flashing block or bar cursor,
9183 maybe a caret cursor, etc. */
9185 DEFVAR_LISP("bar-cursor", &Vbar_cursor /*
9186 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9190 #ifndef INHIBIT_REDISPLAY_HOOKS
9191 xxDEFVAR_LISP("pre-redisplay-hook", &Vpre_redisplay_hook /*
9192 Function or functions to run before every redisplay.
9194 Vpre_redisplay_hook = Qnil;
9196 xxDEFVAR_LISP("post-redisplay-hook", &Vpost_redisplay_hook /*
9197 Function or functions to run after every redisplay.
9199 Vpost_redisplay_hook = Qnil;
9200 #endif /* INHIBIT_REDISPLAY_HOOKS */
9202 DEFVAR_LISP("buffer-list-changed-hook", &Vbuffer_list_changed_hook /*
9203 Function or functions to call when a frame's buffer list has changed.
9204 This is called during redisplay, before redisplaying each frame.
9205 Functions on this hook are called with one argument, the frame.
9207 Vbuffer_list_changed_hook = Qnil;
9209 DEFVAR_INT("display-warning-tick", &display_warning_tick /*
9210 Bump this to tell the C code to call `display-warning-buffer'
9211 at next redisplay. You should not normally change this; the function
9212 `display-warning' automatically does this at appropriate times.
9214 display_warning_tick = 0;
9216 DEFVAR_BOOL("inhibit-warning-display", &inhibit_warning_display /*
9217 Non-nil means inhibit display of warning messages.
9218 You should *bind* this, not set it. Any pending warning messages
9219 will be displayed when the binding no longer applies.
9221 /* reset to 0 by startup.el after the splash screen has displayed.
9222 This way, the warnings don't obliterate the splash screen. */
9223 inhibit_warning_display = 1;
9225 DEFVAR_LISP("window-size-change-functions", &Vwindow_size_change_functions /*
9226 Not currently implemented.
9227 Functions called before redisplay, if window sizes have changed.
9228 The value should be a list of functions that take one argument.
9229 Just before redisplay, for each frame, if any of its windows have changed
9230 size since the last redisplay, or have been split or deleted,
9231 all the functions in the list are called, with the frame as argument.
9233 Vwindow_size_change_functions = Qnil;
9235 DEFVAR_LISP("window-scroll-functions", &Vwindow_scroll_functions /*
9236 Not currently implemented.
9237 Functions to call before redisplaying a window with scrolling.
9238 Each function is called with two arguments, the window
9239 and its new display-start position. Note that the value of `window-end'
9240 is not valid when these functions are called.
9242 Vwindow_scroll_functions = Qnil;
9244 DEFVAR_LISP("redisplay-end-trigger-functions", &Vredisplay_end_trigger_functions /*
9245 See `set-window-redisplay-end-trigger'.
9247 Vredisplay_end_trigger_functions = Qnil;
9249 DEFVAR_BOOL("column-number-start-at-one", &column_number_start_at_one /*
9250 *Non-nil means column display number starts at 1.
9252 column_number_start_at_one = 0;
9255 void specifier_vars_of_redisplay(void)
9257 DEFVAR_SPECIFIER("left-margin-width", &Vleft_margin_width /*
9258 *Width of left margin.
9259 This is a specifier; use `set-specifier' to change it.
9261 Vleft_margin_width = Fmake_specifier(Qnatnum);
9262 set_specifier_fallback(Vleft_margin_width, list1(Fcons(Qnil, Qzero)));
9263 set_specifier_caching(Vleft_margin_width,
9264 offsetof(struct window, left_margin_width),
9265 some_window_value_changed,
9266 offsetof(struct frame, left_margin_width),
9267 margin_width_changed_in_frame, 0);
9269 DEFVAR_SPECIFIER("right-margin-width", &Vright_margin_width /*
9270 *Width of right margin.
9271 This is a specifier; use `set-specifier' to change it.
9273 Vright_margin_width = Fmake_specifier(Qnatnum);
9274 set_specifier_fallback(Vright_margin_width, list1(Fcons(Qnil, Qzero)));
9275 set_specifier_caching(Vright_margin_width,
9276 offsetof(struct window, right_margin_width),
9277 some_window_value_changed,
9278 offsetof(struct frame, right_margin_width),
9279 margin_width_changed_in_frame, 0);
9281 DEFVAR_SPECIFIER("minimum-line-ascent", &Vminimum_line_ascent /*
9282 *Minimum ascent height of lines.
9283 This is a specifier; use `set-specifier' to change it.
9285 Vminimum_line_ascent = Fmake_specifier(Qnatnum);
9286 set_specifier_fallback(Vminimum_line_ascent, list1(Fcons(Qnil, Qzero)));
9287 set_specifier_caching(Vminimum_line_ascent,
9288 offsetof(struct window, minimum_line_ascent),
9289 some_window_value_changed, 0, 0, 0);
9291 DEFVAR_SPECIFIER("minimum-line-descent", &Vminimum_line_descent /*
9292 *Minimum descent height of lines.
9293 This is a specifier; use `set-specifier' to change it.
9295 Vminimum_line_descent = Fmake_specifier(Qnatnum);
9296 set_specifier_fallback(Vminimum_line_descent,
9297 list1(Fcons(Qnil, Qzero)));
9298 set_specifier_caching(Vminimum_line_descent,
9299 offsetof(struct window, minimum_line_descent),
9300 some_window_value_changed, 0, 0, 0);
9302 DEFVAR_SPECIFIER("use-left-overflow", &Vuse_left_overflow /*
9303 *Non-nil means use the left outside margin as extra whitespace when
9304 displaying 'whitespace or 'inside-margin glyphs.
9305 This is a specifier; use `set-specifier' to change it.
9307 Vuse_left_overflow = Fmake_specifier(Qboolean);
9308 set_specifier_fallback(Vuse_left_overflow, list1(Fcons(Qnil, Qnil)));
9309 set_specifier_caching(Vuse_left_overflow,
9310 offsetof(struct window, use_left_overflow),
9311 some_window_value_changed, 0, 0, 0);
9313 DEFVAR_SPECIFIER("use-right-overflow", &Vuse_right_overflow /*
9314 *Non-nil means use the right outside margin as extra whitespace when
9315 displaying 'whitespace or 'inside-margin glyphs.
9316 This is a specifier; use `set-specifier' to change it.
9318 Vuse_right_overflow = Fmake_specifier(Qboolean);
9319 set_specifier_fallback(Vuse_right_overflow, list1(Fcons(Qnil, Qnil)));
9320 set_specifier_caching(Vuse_right_overflow,
9321 offsetof(struct window, use_right_overflow),
9322 some_window_value_changed, 0, 0, 0);
9324 DEFVAR_SPECIFIER("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9325 *Non-nil means the text cursor is visible (this is usually the case).
9326 This is a specifier; use `set-specifier' to change it.
9328 Vtext_cursor_visible_p = Fmake_specifier(Qboolean);
9329 set_specifier_fallback(Vtext_cursor_visible_p, list1(Fcons(Qnil, Qt)));
9330 set_specifier_caching(Vtext_cursor_visible_p,
9331 offsetof(struct window, text_cursor_visible_p),
9332 text_cursor_visible_p_changed, 0, 0, 0);