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+1);
1098 xstrncpy((char *)pb.data.p_string.str,
1099 (char *)pos, len+1);
1100 pb.data.p_string.len = len;
1102 Dynarr_add(prop, pb);
1108 /* #### Duplicate code from add_string_to_fstring_db_runes
1109 should we do more? */
1110 data->bytepos += pos - old_pos;
1116 /* Add a single rune of the specified width. The area covered by this
1117 rune will be displayed in the foreground color of the associated
1120 static prop_block_dynarr *add_blank_rune(pos_data * data, struct window *w,
1125 /* If data->start_col is not 0 then this call to add_blank_rune must have
1126 been to add it as a tab. */
1127 if (data->start_col) {
1128 /* assert (w != NULL) */
1129 prop_block_dynarr *retval;
1131 /* If we have still not fully scrolled horizontally, subtract
1132 the width of this tab and return. */
1133 if (char_tab_width < data->start_col) {
1134 data->start_col -= char_tab_width;
1136 } else if (char_tab_width == data->start_col)
1137 data->blank_width = 0;
1139 int spcwid = space_width(w);
1141 if (spcwid >= data->blank_width)
1142 data->blank_width = 0;
1144 data->blank_width -= spcwid;
1147 data->start_col = 0;
1148 retval = add_hscroll_rune(data);
1150 /* Could be caused by the handling of the hscroll rune. */
1151 if (retval != NULL || !data->blank_width)
1155 /* Blank runes are always calculated to fit. */
1156 assert(data->pixpos + data->blank_width <= data->max_pixpos);
1158 rb.findex = data->findex;
1159 rb.xpos = data->pixpos;
1160 rb.width = data->blank_width;
1161 if (data->bi_bufpos)
1163 bytind_to_bufpos(XBUFFER
1164 (WINDOW_BUFFER(XWINDOW(data->window))),
1167 /* #### and this is really correct too? */
1170 rb.type = RUNE_BLANK;
1172 if (data->cursor_type == CURSOR_ON) {
1173 if (data->bi_bufpos == data->bi_cursor_bufpos) {
1174 rb.cursor_type = CURSOR_ON;
1175 data->cursor_x = Dynarr_length(data->db->runes);
1177 rb.cursor_type = CURSOR_OFF;
1178 } else if (data->cursor_type == NEXT_CURSOR) {
1179 rb.cursor_type = CURSOR_ON;
1180 data->cursor_x = Dynarr_length(data->db->runes);
1181 data->cursor_type = NO_CURSOR;
1183 rb.cursor_type = CURSOR_OFF;
1185 Dynarr_add(data->db->runes, rb);
1186 data->pixpos += data->blank_width;
1191 static void add_blank_rune_noret(pos_data * data, struct window *w,
1194 prop_block_dynarr *prop = add_blank_rune(data,w,char_tab_width);
1195 if (prop && prop != ADD_FAILED )
1199 /* Add runes representing a character in octal. */
1201 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1203 if (add_failed || (add_failed = add_emchar_rune (data))) \
1205 struct prop_block pb; \
1207 prop = Dynarr_new (prop_block); \
1209 pb.type = PROP_CHAR; \
1210 pb.data.p_char.ch = data->ch; \
1211 pb.data.p_char.cursor_type = data->cursor_type; \
1212 Dynarr_add (prop, pb); \
1216 static prop_block_dynarr *add_octal_runes(pos_data * data)
1218 prop_block_dynarr *add_failed, *prop = 0;
1219 Emchar orig_char = data->ch;
1220 unsigned int orig_cursor_type = data->cursor_type;
1225 if (data->start_col)
1228 if (!data->start_col) {
1229 if (data->bi_start_col_enabled) {
1230 add_failed = add_hscroll_rune(data);
1232 struct glyph_block gb;
1233 struct window *w = XWINDOW(data->window);
1236 gb.glyph = Voctal_escape_glyph;
1238 add_glyph_rune(data, &gb, BEGIN_GLYPHS, 1,
1240 OCT_ESC_GLYPH_INDEX));
1244 /* We only propagate information if the glyph was partially
1249 data->cursor_type = IGNORE_CURSOR;
1251 if (data->ch >= 0x100) {
1252 /* If the character is an extended Mule character, it could have
1253 up to 19 bits. For the moment, we treat it as a seven-digit
1254 octal number. This is not that pretty, but whatever. */
1255 data->ch = (7 & (orig_char >> 18)) + '0';
1256 ADD_NEXT_OCTAL_RUNE_CHAR;
1258 data->ch = (7 & (orig_char >> 15)) + '0';
1259 ADD_NEXT_OCTAL_RUNE_CHAR;
1261 data->ch = (7 & (orig_char >> 12)) + '0';
1262 ADD_NEXT_OCTAL_RUNE_CHAR;
1264 data->ch = (7 & (orig_char >> 9)) + '0';
1265 ADD_NEXT_OCTAL_RUNE_CHAR;
1268 data->ch = (7 & (orig_char >> 6)) + '0';
1269 ADD_NEXT_OCTAL_RUNE_CHAR;
1271 data->ch = (7 & (orig_char >> 3)) + '0';
1272 ADD_NEXT_OCTAL_RUNE_CHAR;
1274 data->ch = (7 & orig_char) + '0';
1275 ADD_NEXT_OCTAL_RUNE_CHAR;
1279 data->cursor_type = orig_cursor_type;
1280 if (prop && prop != ADD_FAILED )
1285 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1287 /* Add runes representing a control character to a display block. */
1289 static prop_block_dynarr *add_control_char_runes(pos_data * data,
1292 if (!NILP(b->ctl_arrow)) {
1293 prop_block_dynarr *prop;
1294 Emchar orig_char = data->ch;
1295 unsigned int old_cursor_type = data->cursor_type;
1300 if (data->start_col)
1303 if (!data->start_col) {
1304 if (data->bi_start_col_enabled) {
1305 prop_block_dynarr *retval;
1307 retval = add_hscroll_rune(data);
1311 struct glyph_block gb;
1312 struct window *w = XWINDOW(data->window);
1315 gb.glyph = Vcontrol_arrow_glyph;
1317 /* We only propagate information if the glyph was partially
1319 prop = add_glyph_rune(data, &gb, BEGIN_GLYPHS, 1,
1320 GLYPH_CACHEL(w, CONTROL_GLYPH_INDEX));
1321 if ( prop != NULL ) {
1322 if ( prop != ADD_FAILED )
1329 if (orig_char == 0177)
1332 data->ch = orig_char ^ 0100;
1333 data->cursor_type = IGNORE_CURSOR;
1335 if (add_emchar_rune(data)) {
1336 struct prop_block pb;
1338 prop = Dynarr_new(prop_block);
1340 pb.type = PROP_CHAR;
1341 pb.data.p_char.ch = data->ch;
1342 pb.data.p_char.cursor_type = data->cursor_type;
1343 Dynarr_add(prop, pb);
1346 data->cursor_type = old_cursor_type;
1349 return add_octal_runes(data);
1353 static prop_block_dynarr *add_disp_table_entry_runes_1(pos_data * data,
1356 prop_block_dynarr *prop = NULL;
1358 if (STRINGP(entry)) {
1359 prop = add_bufbyte_string_runes(data,
1360 XSTRING_DATA(entry),
1361 XSTRING_LENGTH(entry), 0, 0);
1362 } else if (GLYPHP(entry)) {
1363 if (data->start_col)
1366 if (!data->start_col && data->bi_start_col_enabled) {
1367 prop = add_hscroll_rune(data);
1369 struct glyph_block gb;
1373 prop = add_glyph_rune(data, &gb, BEGIN_GLYPHS, 0, 0);
1375 } else if (CHAR_OR_CHAR_INTP(entry)) {
1376 data->ch = XCHAR_OR_CHAR_INT(entry);
1377 prop = add_emchar_rune(data);
1378 } else if (CONSP(entry)) {
1379 if (EQ(XCAR(entry), Qformat)
1380 && CONSP(XCDR(entry))
1381 && STRINGP(XCAR(XCDR(entry)))) {
1382 Lisp_Object format = XCAR(XCDR(entry));
1383 Bytind len = XSTRING_LENGTH(format);
1384 Bufbyte *src = XSTRING_DATA(format), *end = src + len;
1385 Bufbyte *result = alloca_array(Bufbyte, len);
1386 Bufbyte *dst = result;
1389 Emchar c = charptr_emchar(src);
1391 if (c != '%' || src == end) {
1392 dst += set_charptr_emchar(dst, c);
1394 c = charptr_emchar(src);
1398 dst += long_to_string_base
1399 ((char *)dst, data->ch, 16);
1402 dst += set_charptr_emchar(
1405 /* #### unimplemented */
1412 add_bufbyte_string_runes(data, result, dst - result,
1417 /* Else blow it off because someone added a bad entry and we don't
1418 have any safe way of signaling an error. */
1422 /* Given a display table entry, call the appropriate functions to
1423 display each element of the entry. */
1425 static prop_block_dynarr *add_disp_table_entry_runes(pos_data * data,
1428 prop_block_dynarr *prop = NULL;
1429 if (VECTORP(entry)) {
1430 Lisp_Vector *de = XVECTOR(entry);
1431 EMACS_INT len = vector_length(de);
1434 for (elt = 0; elt < len; elt++) {
1435 if (NILP(vector_data(de)[elt]))
1439 add_disp_table_entry_runes_1(data,
1442 /* Else blow it off because someone added a bad entry and we
1443 don't have any safe way of signaling an error. Hey, this
1444 comment sounds familiar. */
1446 /* #### Still need to add any remaining elements to the
1447 propagation information. */
1452 prop = add_disp_table_entry_runes_1(data, entry);
1456 /* Add runes which were propagated from the previous line. */
1458 static prop_block_dynarr *add_propagation_runes(prop_block_dynarr ** prop,
1461 /* #### Remember to handle start_col parameter of data when the rest of
1462 this is finished. */
1463 /* #### Chuck -- I've redone this function a bit. It looked like the
1464 case of not all the propagation blocks being added was not handled
1466 /* #### Chuck -- I also think the double indirection of PROP is kind
1467 of bogus. A cleaner solution is just to check for
1468 Dynarr_length (prop) > 0. */
1469 /* #### This function also doesn't even pay attention to ADD_FAILED!
1470 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1473 prop_block_dynarr *add_failed;
1474 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1475 unsigned int old_cursor_type = data->cursor_type;
1477 for (elt = 0; elt < Dynarr_length(*prop); elt++) {
1478 struct prop_block *pb = Dynarr_atp(*prop, elt);
1482 data->ch = pb->data.p_char.ch;
1483 data->bi_cursor_bufpos =
1484 pb->data.p_char.bi_cursor_bufpos;
1485 data->cursor_type = pb->data.p_char.cursor_type;
1486 add_failed = add_emchar_rune(data);
1489 goto oops_no_more_space;
1492 if (pb->data.p_string.str)
1493 xfree(pb->data.p_string.str);
1494 /* #### bogus bogus -- this doesn't do anything!
1495 Should probably call add_bufbyte_string_runes(),
1496 once that function is fixed. */
1498 case PROP_MINIBUF_PROMPT: {
1499 face_index old_findex = data->findex;
1500 Bytind bi_old_bufpos = data->bi_bufpos;
1502 data->findex = DEFAULT_INDEX;
1503 data->bi_bufpos = 0;
1504 data->cursor_type = NO_CURSOR;
1506 while (pb->data.p_string.len > 0) {
1508 charptr_emchar(pb->data.p_string.
1510 add_failed = add_emchar_rune(data);
1513 data->findex = old_findex;
1514 data->bi_bufpos = bi_old_bufpos;
1515 goto oops_no_more_space;
1517 /* Complicated equivalent of ptr++,
1520 pb->data.p_string.str;
1521 INC_CHARPTR(pb->data.p_string.
1523 pb->data.p_string.len -=
1524 pb->data.p_string.str -
1529 data->findex = old_findex;
1530 /* ##### FIXME FIXME FIXME -- Upon successful return
1531 from this function, data->bi_bufpos is automatically
1532 incremented. However, we don't want that to happen
1533 if we were adding the minibuffer prompt. */
1535 struct buffer *buf =
1536 XBUFFER(WINDOW_BUFFER
1537 (XWINDOW(data->window)));
1538 /* #### Chuck fix this shit or I'm gonna
1540 if (bi_old_bufpos > BI_BUF_BEGV(buf)) {
1545 /* #### is this correct?
1547 Does anyone care? Is this a cheesy
1550 BI_BUF_BEGV(buf) - 1;
1556 /* #### I think it's unnecessary and misleading to
1557 preserve the blank_width, as it implies that the
1558 value carries over from one rune to the next,
1560 int old_width = data->blank_width;
1561 face_index old_findex = data->findex;
1563 data->findex = pb->data.p_blank.findex;
1564 data->blank_width = pb->data.p_blank.width;
1565 data->bi_cursor_bufpos = 0;
1566 data->cursor_type = IGNORE_CURSOR;
1568 if (data->pixpos + data->blank_width >
1571 data->max_pixpos - data->pixpos;
1573 /* We pass a bogus value of char_tab_width. It
1574 shouldn't matter because unless something is really
1575 screwed up this call won't cause that arg to be
1577 add_failed = add_blank_rune(
1578 data, XWINDOW(data->window), 0);
1580 /* This can happen in the case where we have a tab which
1581 is wider than the window. */
1582 if (data->blank_width != pb->data.p_blank.width) {
1583 pb->data.p_blank.width -=
1585 add_failed = ADD_FAILED;
1588 data->findex = old_findex;
1589 data->blank_width = old_width;
1592 goto oops_no_more_space;
1604 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1605 data->cursor_type = old_cursor_type;
1606 if (elt < Dynarr_length(*prop)) {
1607 Dynarr_delete_many(*prop, 0, elt);
1615 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1616 the display block, but add all other types to the appropriate list
1617 of the display line. They will be added later by different
1620 static void add_glyph_rune_noret(pos_data * data,
1621 struct glyph_block *gb, int pos_type,
1623 struct glyph_cachel *cachel)
1625 prop_block_dynarr *prop = add_glyph_rune(data,gb,pos_type,allow_cursor,cachel);
1626 if (prop && prop != ADD_FAILED )
1630 static prop_block_dynarr *add_glyph_rune(pos_data * data,
1631 struct glyph_block *gb, int pos_type,
1633 struct glyph_cachel *cachel)
1635 struct window *w = XWINDOW(data->window);
1637 /* If window faces changed, and glyph instance is text, then
1638 glyph sizes might have changed too */
1639 invalidate_glyph_geometry_maybe(gb->glyph, w);
1641 /* This makes sure the glyph is in the cachels.
1643 #### We do this to make sure the glyph is in the glyph cachels,
1644 so that the dirty flag can be reset after redisplay has
1645 finished. We should do this some other way, maybe by iterating
1646 over the window cache of subwindows. */
1647 get_glyph_cachel_index(w, gb->glyph);
1649 /* A nil extent indicates a special glyph (ex. truncator). */
1650 if (NILP(gb->extent)
1651 || (pos_type == BEGIN_GLYPHS &&
1652 extent_begin_glyph_layout(XEXTENT(gb->extent)) == GL_TEXT)
1653 || (pos_type == END_GLYPHS &&
1654 extent_end_glyph_layout(XEXTENT(gb->extent)) == GL_TEXT)
1655 || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS) {
1659 int ascent, descent;
1660 Lisp_Object baseline;
1662 Lisp_Object instance;
1664 prop_block_dynarr *retval = 0;
1667 width = cachel->width;
1669 width = glyph_width(gb->glyph, data->window);
1674 if (data->start_col || data->start_col_xoffset) {
1675 int glyph_char_width = width / space_width(w);
1677 /* If we still have not fully scrolled horizontally after
1678 taking into account the width of the glyph, subtract its
1679 width and return. */
1680 if (glyph_char_width < data->start_col) {
1681 data->start_col -= glyph_char_width;
1683 } else if (glyph_char_width == data->start_col)
1686 xoffset = space_width(w) * data->start_col;
1689 /* #### Can this happen? */
1694 data->start_col = 0;
1695 retval = add_hscroll_rune(data);
1697 /* Could be caused by the handling of the hscroll rune. */
1698 if (retval != NULL || !width)
1703 if (data->pixpos + width > data->max_pixpos) {
1704 /* If this is the first object we are attempting to add to
1705 the line then we ignore the horizontal_clip threshold.
1706 Otherwise we will loop until the bottom of the window
1707 continually failing to add this glyph because it is wider
1708 than the window. We could alternatively just completely
1709 ignore the glyph and proceed from there but I think that
1710 this is a better solution.
1712 This does, however, create a different problem in that we
1713 can end up adding the object to every single line, never
1714 getting any further - for instance an extent with a long
1715 start-glyph that covers multitple following
1717 if (Dynarr_length(data->db->runes)
1718 && data->max_pixpos - data->pixpos <
1722 struct prop_block pb;
1724 /* We need to account for the width of the end-of-line
1725 glyph if there is nothing more in the line to display,
1726 since we will not display it in this instance. It seems
1727 kind of gross doing it here, but otherwise we have to
1728 search the runes in create_text_block(). */
1729 if (data->ch == '\n')
1731 data->end_glyph_width;
1732 width = data->max_pixpos - data->pixpos;
1733 /* Add the glyph we are displaying, but clipping, to the
1734 propagation data so that we don't try and do it
1736 retval = Dynarr_new(prop_block);
1737 pb.type = PROP_GLYPH;
1738 pb.data.p_glyph.glyph = gb->glyph;
1739 pb.data.p_glyph.width = width;
1740 Dynarr_add(retval, pb);
1745 ascent = cachel->ascent;
1746 descent = cachel->descent;
1748 ascent = glyph_ascent(gb->glyph, data->window);
1749 descent = glyph_descent(gb->glyph, data->window);
1752 baseline = glyph_baseline(gb->glyph, data->window);
1754 rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */
1756 if (glyph_contrib_p(gb->glyph, data->window)) {
1757 /* A pixmap that has not had a baseline explicitly set. Its
1758 contribution will be determined later. */
1759 if (NILP(baseline)) {
1760 int height = ascent + descent;
1761 data->need_baseline_computation = 1;
1762 data->max_pixmap_height =
1763 max(data->max_pixmap_height, height);
1766 /* A string so determine contribution normally. */
1767 else if (EQ(baseline, Qt)) {
1769 max(data->new_ascent, ascent);
1771 max(data->new_descent, descent);
1774 /* A pixmap with an explicitly set baseline. We determine the
1775 contribution here. */
1776 else if (INTP(baseline)) {
1777 int height = ascent + descent;
1778 int pix_ascent, pix_descent;
1780 pix_ascent = height * XINT(baseline) / 100;
1781 pix_descent = height - pix_ascent;
1784 max(data->new_ascent, pix_ascent);
1786 max(data->new_descent, pix_descent);
1787 data->max_pixmap_height =
1788 max(data->max_pixmap_height, height);
1790 rb.object.dglyph.descent = pix_descent;
1793 /* Otherwise something is screwed up. */
1798 face = glyph_face(gb->glyph, data->window);
1800 findex = data->findex;
1802 findex = get_builtin_face_cache_index(w, face);
1804 instance = glyph_image_instance(gb->glyph, data->window,
1806 if (TEXT_IMAGE_INSTANCEP(instance)) {
1807 Lisp_Object string =
1808 XIMAGE_INSTANCE_TEXT_STRING(instance);
1809 face_index orig_findex = data->findex;
1810 Bytind orig_bufpos = data->bi_bufpos;
1811 Bytind orig_start_col_enabled =
1812 data->bi_start_col_enabled;
1814 data->findex = findex;
1815 data->bi_start_col_enabled = 0;
1817 data->bi_bufpos = 0;
1819 prop_block_dynarr * tmp = NULL;
1820 tmp = add_bufbyte_string_runes(data,
1821 XSTRING_DATA(string),
1822 XSTRING_LENGTH(string),
1827 data->findex = orig_findex;
1828 data->bi_bufpos = orig_bufpos;
1829 data->bi_start_col_enabled = orig_start_col_enabled;
1834 rb.xpos = data->pixpos;
1836 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1837 if (data->bi_endpos)
1838 /* #### is this necessary at all? */
1839 rb.endpos = bytind_to_bufpos(XBUFFER(WINDOW_BUFFER(w)),
1843 rb.type = RUNE_DGLYPH;
1844 rb.object.dglyph.glyph = gb->glyph;
1845 rb.object.dglyph.extent = gb->extent;
1846 rb.object.dglyph.xoffset = xoffset;
1847 rb.object.dglyph.ascent = ascent;
1848 rb.object.dglyph.yoffset = 0; /* Until we know better, assume that it has
1849 a normal (textual) baseline. */
1852 rb.bufpos = bytind_to_bufpos(XBUFFER(WINDOW_BUFFER(w)),
1855 if (data->cursor_type == CURSOR_ON) {
1856 if (data->bi_bufpos == data->bi_cursor_bufpos) {
1857 rb.cursor_type = CURSOR_ON;
1859 Dynarr_length(data->db->runes);
1861 rb.cursor_type = CURSOR_OFF;
1862 } else if (data->cursor_type == NEXT_CURSOR) {
1863 rb.cursor_type = CURSOR_ON;
1864 data->cursor_x = Dynarr_length(data->db->runes);
1865 data->cursor_type = NO_CURSOR;
1866 } else if (data->cursor_type == IGNORE_CURSOR)
1867 rb.cursor_type = IGNORE_CURSOR;
1868 else if (data->cursor_type == NO_CURSOR)
1869 rb.cursor_type = NO_CURSOR;
1871 rb.cursor_type = CURSOR_OFF;
1873 rb.cursor_type = CURSOR_OFF;
1875 Dynarr_add(data->db->runes, rb);
1876 data->pixpos += width;
1880 if (!NILP(glyph_face(gb->glyph, data->window)))
1882 get_builtin_face_cache_index(w,
1883 glyph_face(gb->glyph,
1887 gb->findex = data->findex;
1889 if (pos_type == BEGIN_GLYPHS) {
1890 if (!data->dl->left_glyphs)
1891 data->dl->left_glyphs = Dynarr_new(glyph_block);
1892 Dynarr_add(data->dl->left_glyphs, *gb);
1894 } else if (pos_type == END_GLYPHS) {
1895 if (!data->dl->right_glyphs)
1896 data->dl->right_glyphs =
1897 Dynarr_new(glyph_block);
1898 Dynarr_add(data->dl->right_glyphs, *gb);
1901 abort(); /* there are no unknown types */
1907 /* Add all glyphs at position POS_TYPE that are contained in the given
1910 static prop_block_dynarr *add_glyph_runes(pos_data * data)
1912 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1913 why didn't you just modify add_glyph_rune in the first place? */
1915 glyph_block_dynarr *glyph_arr = (data->ef->glyphs);
1916 prop_block_dynarr *prop;
1918 for (elt = 0; elt < Dynarr_length(glyph_arr); elt++) {
1919 struct glyph_block *gb = Dynarr_atp(glyph_arr, elt);
1920 prop = add_glyph_rune(data, gb,
1921 gb->active ? END_GLYPHS : BEGIN_GLYPHS,
1925 /* #### Add some propagation information. */
1930 Dynarr_reset(glyph_arr);
1935 /* Given a position for a buffer in a window, ensure that the given
1936 display line DL accurately represents the text on a line starting
1937 at the given position.
1939 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1940 You must do appropriate conversion. */
1943 create_text_block(struct window *w, struct display_line *dl,
1944 Bytind bi_start_pos, prop_block_dynarr ** prop, int type)
1946 struct frame *f = XFRAME(w->frame);
1947 struct buffer *b = XBUFFER(w->buffer);
1948 struct device *d = XDEVICE(f->device);
1952 /* Don't display anything in the minibuffer if this window is not on
1953 a selected frame. We consider all other windows to be active
1954 minibuffers as it simplifies the coding. */
1955 int active_minibuffer = (!MINI_WINDOW_P(w) ||
1956 (f == device_selected_frame(d)) ||
1957 is_surrogate_for_selected_frame(f));
1959 int truncate_win = window_truncation_on(w);
1961 /* If the buffer's value of selective_display is an integer then
1962 only lines that start with less than selective_display columns of
1963 space will be displayed. If selective_display is t then all text
1964 after a ^M is invisible. */
1965 int selective = (INTP(b->selective_display)
1966 ? XINT(b->selective_display)
1967 : (!NILP(b->selective_display) ? -1 : 0));
1969 /* The variable ctl-arrow allows the user to specify what characters
1970 can actually be displayed and which octal should be used for.
1971 #### This variable should probably have some rethought done to
1974 #### It would also be really nice if you could specify that
1975 the characters come out in hex instead of in octal. Mule
1976 does that by adding a ctl-hexa variable similar to ctl-arrow,
1977 but that's bogus -- we need a more general solution. I
1978 think you need to extend the concept of display tables
1979 into a more general conversion mechanism. Ideally you
1980 could specify a Lisp function that converts characters,
1981 but this violates the Second Golden Rule and besides would
1982 make things way way way way slow.
1984 So instead, we extend the display-table concept, which was
1985 historically limited to 256-byte vectors, to one of the
1988 a) A 256-entry vector, for backward compatibility;
1989 b) char-table, mapping characters to values;
1990 c) range-table, mapping ranges of characters to values;
1991 d) a list of the above.
1993 The (d) option allows you to specify multiple display tables
1994 instead of just one. Each display table can specify conversions
1995 for some characters and leave others unchanged. The way the
1996 character gets displayed is determined by the first display table
1997 with a binding for that character. This way, you could call a
1998 function `enable-hex-display' that adds a hex display-table to
1999 the list of display tables for the current buffer.
2001 #### ...not yet implemented... Also, we extend the concept of
2002 "mapping" to include a printf-like spec. Thus you can make all
2003 extended characters show up as hex with a display table like
2006 #s(range-table data ((256 524288) (format "%x")))
2008 Since more than one display table is possible, you have
2009 great flexibility in mapping ranges of characters. */
2010 Emchar printable_min = (CHAR_OR_CHAR_INTP(b->ctl_arrow)
2011 ? XCHAR_OR_CHAR_INT(b->ctl_arrow)
2012 : ((EQ(b->ctl_arrow, Qt)
2013 || EQ(b->ctl_arrow, Qnil))
2016 Lisp_Object face_dt, window_dt;
2018 /* The text display block for this display line. */
2019 struct display_block *db = get_display_block_from_line(dl, TEXT);
2021 /* The first time through the main loop we need to force the glyph
2022 data to be updated. */
2025 /* Apparently the new extent_fragment_update returns an end position
2026 equal to the position passed in if there are no more runs to be
2028 int no_more_frags = 0;
2030 Lisp_Object synch_minibuffers_value =
2031 symbol_value_in_buffer(Qsynchronize_minibuffers, w->buffer);
2033 dl->used_prop_data = 0;
2035 dl->line_continuation = 0;
2038 data.ef = extent_fragment_new(w->buffer, f);
2040 /* These values are used by all of the rune addition routines. We add
2041 them to this structure for ease of passing. */
2043 XSETWINDOW(data.window, w);
2048 data.bi_bufpos = bi_start_pos;
2049 data.pixpos = dl->bounds.left_in;
2050 data.last_charset = Qunbound;
2051 data.last_findex = DEFAULT_INDEX;
2052 data.result_str = Qnil;
2054 /* Set the right boundary adjusting it to take into account any end
2055 glyph. Save the width of the end glyph for later use. */
2056 data.max_pixpos = dl->bounds.right_in;
2058 data.end_glyph_width = GLYPH_CACHEL_WIDTH(w, TRUN_GLYPH_INDEX);
2060 data.end_glyph_width = GLYPH_CACHEL_WIDTH(w, CONT_GLYPH_INDEX);
2061 data.max_pixpos -= data.end_glyph_width;
2063 if (cursor_in_echo_area && MINI_WINDOW_P(w) && echo_area_active(f)) {
2064 data.bi_cursor_bufpos = BI_BUF_ZV(b);
2065 data.cursor_type = CURSOR_ON;
2066 } else if (MINI_WINDOW_P(w) && !active_minibuffer)
2067 data.cursor_type = NO_CURSOR;
2068 else if (w == XWINDOW(FRAME_SELECTED_WINDOW(f)) &&
2069 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
2071 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))
2072 && f == XFRAME(DEVICE_SELECTED_FRAME(d))) {
2073 data.bi_cursor_bufpos = BI_BUF_PT(b);
2074 data.cursor_type = CURSOR_ON;
2075 } else if (w == XWINDOW(FRAME_SELECTED_WINDOW(f))) {
2076 data.bi_cursor_bufpos = bi_marker_position(w->pointm[type]);
2077 data.cursor_type = CURSOR_ON;
2079 data.cursor_type = NO_CURSOR;
2082 data.start_col = w->hscroll;
2083 data.start_col_xoffset = w->left_xoffset;
2084 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
2085 data.hscroll_glyph_width_adjust = 0;
2087 /* We regenerate the line from the very beginning. */
2088 Dynarr_reset(db->runes);
2090 /* Why is this less than or equal and not just less than? If the
2091 starting position is already equal to the maximum we can't add
2092 anything else, right? Wrong. We might still have a newline to
2093 add. A newline can use the room allocated for an end glyph since
2094 if we add it we know we aren't going to be adding any end
2097 /* #### Chuck -- I think this condition should be while (1).
2098 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
2099 and the begin-glyph ends exactly at the end of the window, the
2100 end-glyph and text might not be displayed. while (1) ensures
2101 that the loop terminates only when either (a) there is
2102 propagation data or (b) the end-of-line or end-of-buffer is hit.
2104 #### Also I think you need to ensure that the operation
2105 "add begin glyphs; add end glyphs; add text" is atomic and
2106 can't get interrupted in the middle. If you run off the end
2107 of the line during that operation, then you keep accumulating
2108 propagation data until you're done. Otherwise, if the (e.g.)
2109 there's a begin glyph at a particular position and attempting
2110 to display that glyph results in window-end being hit and
2111 propagation data being generated, then the character at that
2112 position won't be displayed.
2114 #### See also the comment after the end of this loop, below.
2116 while (data.pixpos <= data.max_pixpos
2117 && (active_minibuffer || !NILP(synch_minibuffers_value))) {
2118 /* #### This check probably should not be necessary. */
2119 if (data.bi_bufpos > BI_BUF_ZV(b)) {
2120 /* #### urk! More of this lossage! */
2125 /* If selective display was an integer and we aren't working on
2126 a continuation line then find the next line we are actually
2127 supposed to display. */
2128 if (selective > 0 && (data.bi_bufpos == BI_BUF_BEGV(b)
2129 || BUF_FETCH_CHAR(b,
2134 while (bi_spaces_at_point(b, data.bi_bufpos) >=
2137 bi_find_next_newline_no_quit(b,
2140 if (data.bi_bufpos >= BI_BUF_ZV(b)) {
2141 data.bi_bufpos = BI_BUF_ZV(b);
2147 /* Check for face changes. */
2149 || (!no_more_frags && data.bi_bufpos == data.ef->end)) {
2150 Lisp_Object last_glyph = Qnil;
2152 /* Deal with glyphs that we have already displayed. The
2153 theory is that if we end up with a PROP_GLYPH in the
2154 propagation data then we are clipping the glyph and there
2155 can be no propagation data before that point. The theory
2156 works because we always recalculate the extent-fragments
2157 for propagated data, we never actually propagate the
2158 fragments that still need to be displayed. */
2159 if (*prop && Dynarr_atp(*prop, 0)->type == PROP_GLYPH) {
2161 Dynarr_atp(*prop, 0)->data.p_glyph.glyph;
2165 /* Now compute the face and begin/end-glyph information. */
2167 /* Remember that the extent-fragment routines deal in Bytind's. */
2168 extent_fragment_update(w, data.ef, data.bi_bufpos,
2171 get_display_tables(w, data.findex, &face_dt,
2174 if (data.bi_bufpos == data.ef->end)
2179 /* Determine what is next to be displayed. We first handle any
2180 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2181 display then we determine what to do based on the character at the
2182 current buffer position. */
2184 /* If there are glyphs, add them to the line. These are
2185 the end glyphs for the previous run of text. We add
2186 them here rather than doing them at the end of handling
2187 the previous run so that glyphs at the beginning and
2188 end of a line are handled correctly. */
2189 if (Dynarr_length (data.ef->glyphs) > 0) {
2190 glyph_block_dynarr* tmpglyphs = 0;
2191 /* #### I think this is safe, but could be wrong. */
2192 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2194 *prop = add_glyph_runes (&data);
2195 tmpglyphs = data.ef->glyphs;
2199 /* If we just clipped a glyph and we are
2200 at the end of a line and there are more
2201 glyphs to display then do appropriate
2202 processing to not get a continuation
2204 if (*prop != ADD_FAILED
2205 && Dynarr_atp (*prop, 0)->type == PROP_GLYPH
2206 && data.ch == '\n') {
2207 /* If there are no more glyphs
2208 then do the normal processing.
2210 #### This doesn't actually work
2211 if the same glyph is present
2212 more than once in the block. To
2213 solve this we would have to
2214 carry the index around which
2215 might be problematic since the
2216 fragment is recalculated for
2218 if (EQ (Dynarr_end (tmpglyphs)->glyph,
2219 Dynarr_atp (*prop, 0)->data.p_glyph.glyph)) {
2220 Dynarr_free (*prop);
2224 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2225 add_emchar_rune (&data); /* discard prop data. */
2234 /* If the current position is covered by an invisible
2235 extent, do nothing (except maybe add some
2237 else if (data.ef->invisible) {
2238 /* #### Chuck, perhaps you could look at this code? I don't
2239 really know what I'm doing. */
2245 /* The extent fragment code only sets this when we should
2246 really display the ellipses. It makes sure the ellipses
2247 don't get displayed more than once in a row. */
2248 if (data.ef->invisible_ellipses) {
2249 struct glyph_block gb;
2251 data.ef->invisible_ellipses_already_displayed =
2253 data.ef->invisible_ellipses = 0;
2255 gb.glyph = Vinvisible_text_glyph;
2257 add_glyph_rune(&data, &gb, BEGIN_GLYPHS, 0,
2259 INVIS_GLYPH_INDEX));
2260 /* Perhaps they shouldn't propagate if the very next thing
2261 is to display a newline (for compatibility with
2262 selective-display-ellipses)? Maybe that's too
2268 /* If point is in an invisible region we place it on the
2269 next visible character. */
2270 if (data.cursor_type == CURSOR_ON
2271 && data.bi_bufpos == data.bi_cursor_bufpos) {
2272 data.cursor_type = NEXT_CURSOR;
2275 /* #### What if we we're dealing with a display table? */
2279 if (data.bi_bufpos == BI_BUF_ZV(b))
2282 INC_BYTIND(b, data.bi_bufpos);
2285 /* If there is propagation data, then it represents the current
2286 buffer position being displayed. Add them and advance the
2287 position counter. This might also add the minibuffer
2290 dl->used_prop_data = 1;
2291 *prop = add_propagation_runes(prop, &data);
2294 goto done; /* gee, a really narrow window */
2295 else if (data.bi_bufpos == BI_BUF_ZV(b))
2297 else if (data.bi_bufpos < BI_BUF_BEGV(b))
2298 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2299 data.bi_bufpos = BI_BUF_BEGV(b);
2301 INC_BYTIND(b, data.bi_bufpos);
2304 /* If at end-of-buffer, we've already processed begin and
2305 end-glyphs at this point and there's no text to process,
2307 else if (data.bi_bufpos == BI_BUF_ZV(b))
2311 Lisp_Object entry = Qnil;
2312 /* Get the character at the current buffer position. */
2313 data.ch = BI_BUF_FETCH_CHAR(b, data.bi_bufpos);
2314 if (!NILP(face_dt) || !NILP(window_dt))
2316 display_table_entry(data.ch, face_dt,
2319 /* If there is a display table entry for it, hand it off to
2320 add_disp_table_entry_runes and let it worry about it. */
2321 if (!NILP(entry) && !EQ(entry, make_char(data.ch))) {
2323 add_disp_table_entry_runes(&data, entry);
2329 /* Check if we have hit a newline character. If so, add a marker
2330 to the line and end this loop. */
2331 else if (data.ch == '\n') {
2332 /* We aren't going to be adding an end glyph so give its
2333 space back in order to make sure that the cursor can
2335 data.max_pixpos += data.end_glyph_width;
2338 && (bi_spaces_at_point
2339 (b, next_bytind(b, data.bi_bufpos))
2342 (b->selective_display_ellipses)) {
2343 struct glyph_block gb;
2347 Vinvisible_text_glyph;
2348 add_glyph_rune_noret(&data, &gb,
2351 INVIS_GLYPH_INDEX));
2353 /* Cheesy, cheesy, cheesy. We mark the end of the
2354 line with a special "character rune" whose width
2355 is the EOL cursor width and whose character is
2356 the non-printing character '\n'. */
2358 DEVMETH(d, eol_cursor_width,
2360 *prop = add_emchar_rune(&data);
2363 /* We need to set data.bi_bufpos to the start of the
2364 next visible region in order to make this line
2365 appear to contain all of the invisible area.
2366 Otherwise, the line cache won't work
2368 INC_BYTIND(b, data.bi_bufpos);
2369 while (bi_spaces_at_point
2371 data.bi_bufpos) >= selective) {
2373 bi_find_next_newline_no_quit
2374 (b, data.bi_bufpos, 1);
2375 if (data.bi_bufpos >=
2382 if (BI_BUF_FETCH_CHAR
2387 DEC_BYTIND(b, data.bi_bufpos);
2390 DEVMETH(d, eol_cursor_width, ());
2391 *prop = add_emchar_rune(&data);
2397 /* If the current character is ^M, and selective display is
2398 enabled, then add the invisible-text-glyph if
2399 selective-display-ellipses is set. In any case, this
2401 else if (data.ch == (('M' & 037)) && selective == -1) {
2402 Bytind bi_next_bufpos;
2404 /* Find the buffer position at the end of the line. */
2406 bi_find_next_newline_no_quit(b,
2409 if (BI_BUF_FETCH_CHAR
2410 (b, prev_bytind(b, bi_next_bufpos))
2412 DEC_BYTIND(b, bi_next_bufpos);
2414 /* If the cursor is somewhere in the elided text make
2415 sure that the cursor gets drawn appropriately. */
2416 if (data.cursor_type == CURSOR_ON
2417 && (data.bi_cursor_bufpos >= data.bi_bufpos
2418 && data.bi_cursor_bufpos <
2420 data.cursor_type = NEXT_CURSOR;
2423 /* We won't be adding a truncation or continuation glyph
2424 so give up the room allocated for them. */
2425 data.max_pixpos += data.end_glyph_width;
2427 if (!NILP(b->selective_display_ellipses)) {
2428 /* We don't propagate anything from the invisible
2429 text glyph if it fails to fit. This is
2431 struct glyph_block gb;
2434 gb.glyph = Vinvisible_text_glyph;
2435 add_glyph_rune(&data, &gb, BEGIN_GLYPHS,
2437 INVIS_GLYPH_INDEX));
2440 /* Set the buffer position to the end of the line. We
2441 need to do this before potentially adding a newline
2442 so that the cursor flag will get set correctly (if
2444 data.bi_bufpos = bi_next_bufpos;
2446 if (NILP(b->selective_display_ellipses)
2447 || data.bi_cursor_bufpos == bi_next_bufpos) {
2448 /* We have to at least add a newline character so
2449 that the cursor shows up properly. */
2452 DEVMETH(d, eol_cursor_width, ());
2453 data.findex = DEFAULT_INDEX;
2455 data.start_col_xoffset = 0;
2456 data.bi_start_col_enabled = 0;
2458 add_emchar_rune(&data);
2461 /* This had better be a newline but doing it this way
2462 we'll see obvious incorrect results if it isn't. No
2463 need to abort here. */
2464 data.ch = BI_BUF_FETCH_CHAR(b, data.bi_bufpos);
2469 /* If the current character is considered to be printable, then
2471 else if (data.ch >= printable_min) {
2472 *prop = add_emchar_rune(&data);
2477 /* If the current character is a tab, determine the next tab
2478 starting position and add a blank rune which extends from the
2479 current pixel position to that starting position. */
2480 else if (data.ch == '\t') {
2481 int tab_start_pixpos = data.pixpos;
2486 if (data.start_col > 1)
2489 (data.start_col - 1))
2490 + data.start_col_xoffset;
2493 next_tab_position(w, tab_start_pixpos,
2494 dl->bounds.left_in +
2496 hscroll_glyph_width_adjust);
2497 if (next_tab_start > data.max_pixpos) {
2499 next_tab_start - data.max_pixpos;
2500 next_tab_start = data.max_pixpos;
2502 data.blank_width = next_tab_start - data.pixpos;
2505 tab_start_pixpos) / space_width(w);
2508 add_blank_rune(&data, w, char_tab_width);
2510 /* add_blank_rune is only supposed to be called with
2511 sizes guaranteed to fit in the available space. */
2515 struct prop_block pb;
2516 *prop = Dynarr_new(prop_block);
2518 pb.type = PROP_BLANK;
2519 pb.data.p_blank.width = prop_width;
2520 pb.data.p_blank.findex = data.findex;
2521 Dynarr_add(*prop, pb);
2527 /* If character is a control character, pass it off to
2528 add_control_char_runes.
2530 The is_*() routines have undefined results on
2531 arguments outside of the range [-1, 255]. (This
2532 often bites people who carelessly use `char' instead
2533 of `unsigned char'.)
2535 else if (data.ch < 0x100 && iscntrl((Bufbyte) data.ch)) {
2536 *prop = add_control_char_runes(&data, b);
2542 /* If the character is above the ASCII range and we have not
2543 already handled it, then print it as an octal number. */
2544 else if (data.ch >= 0200) {
2545 *prop = add_octal_runes(&data);
2551 /* Assume the current character is considered to be printable,
2552 then just add it. */
2554 *prop = add_emchar_rune(&data);
2559 INC_BYTIND(b, data.bi_bufpos);
2565 /* Determine the starting point of the next line if we did not hit the
2566 end of the buffer. */
2567 if (data.bi_bufpos < BI_BUF_ZV(b)
2568 && (active_minibuffer || !NILP(synch_minibuffers_value))) {
2569 /* #### This check is not correct. If the line terminated
2570 due to a begin-glyph or end-glyph hitting window-end, then
2571 data.ch will not point to the character at data.bi_bufpos. If
2572 you make the two changes mentioned at the top of this loop,
2573 you should be able to say '(if (*prop))'. That should also
2574 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2577 /* The common case is that the line ended because we hit a newline.
2578 In that case, the next character is just the next buffer
2580 if (data.ch == '\n') {
2581 /* If data.start_col_enabled is still true, then the window is
2582 scrolled far enough so that nothing on this line is visible.
2583 We need to stick a truncation glyph at the beginning of the
2584 line in that case unless the line is completely blank. */
2585 if (data.bi_start_col_enabled) {
2586 if (data.cursor_type == CURSOR_ON) {
2587 if (data.bi_cursor_bufpos >=
2589 && data.bi_cursor_bufpos <=
2591 data.bi_cursor_bufpos =
2594 data.findex = DEFAULT_INDEX;
2596 data.bi_start_col_enabled = 0;
2598 if (data.bi_bufpos != bi_start_pos) {
2599 struct glyph_block gb;
2602 gb.glyph = Vhscroll_glyph;
2603 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS,
2605 HSCROLL_GLYPH_INDEX));
2607 /* This duplicates code down below to add a newline to
2608 the end of an otherwise empty line. */
2611 DEVMETH(d, eol_cursor_width, ());
2613 add_emchar_rune(&data);
2617 INC_BYTIND(b, data.bi_bufpos);
2620 /* Otherwise we have a buffer line which cannot fit on one display
2623 struct glyph_block gb;
2624 struct glyph_cachel *cachel;
2626 /* If the line is to be truncated then we actually have to look
2627 for the next newline. We also add the end-of-line glyph which
2628 we know will fit because we adjusted the right border before
2629 we starting laying out the line. */
2630 data.max_pixpos += data.end_glyph_width;
2631 data.findex = DEFAULT_INDEX;
2637 /* Now find the start of the next line. */
2639 bi_find_next_newline_no_quit(b,
2643 /* If the cursor is past the truncation line then we
2644 make it appear on the truncation glyph. If we've hit
2645 the end of the buffer then we also make the cursor
2646 appear unless eob is immediately preceded by a
2647 newline. In that case the cursor should actually
2648 appear on the next line. */
2649 if (data.cursor_type == CURSOR_ON
2650 && data.bi_cursor_bufpos >= data.bi_bufpos
2651 && (data.bi_cursor_bufpos < bi_pos ||
2652 (bi_pos == BI_BUF_ZV(b)
2653 && (bi_pos == BI_BUF_BEGV(b)
2656 (b, prev_bytind(b, bi_pos))
2658 data.bi_cursor_bufpos = bi_pos;
2660 data.cursor_type = NO_CURSOR;
2662 data.bi_bufpos = bi_pos;
2663 gb.glyph = Vtruncation_glyph;
2664 cachel = GLYPH_CACHEL(w, TRUN_GLYPH_INDEX);
2666 /* The cursor can never be on the continuation glyph. */
2667 data.cursor_type = NO_CURSOR;
2669 /* data.bi_bufpos is already at the start of the next line. */
2671 dl->line_continuation = 1;
2672 gb.glyph = Vcontinuation_glyph;
2673 cachel = GLYPH_CACHEL(w, CONT_GLYPH_INDEX);
2676 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS, 0, cachel);
2678 if (truncate_win && data.bi_bufpos == BI_BUF_ZV(b)
2679 && BI_BUF_FETCH_CHAR(b,
2683 /* #### Damn this losing shit. */
2686 } else if ((active_minibuffer || !NILP(synch_minibuffers_value))
2687 && (!echo_area_active(f) || data.bi_bufpos == BI_BUF_ZV(b))) {
2688 /* We need to add a marker to the end of the line since there is no
2689 newline character in order for the cursor to get drawn. We label
2690 it as a newline so that it gets handled correctly by the
2691 whitespace routines below. */
2694 data.blank_width = DEVMETH(d, eol_cursor_width, ());
2695 data.findex = DEFAULT_INDEX;
2697 data.start_col_xoffset = 0;
2698 data.bi_start_col_enabled = 0;
2700 data.max_pixpos += data.blank_width;
2701 add_emchar_rune(&data);
2702 data.max_pixpos -= data.blank_width;
2704 /* #### urk! Chuck, this shit is bad news. Going around
2705 manipulating invalid positions is guaranteed to result in
2706 trouble sooner or later. */
2707 data.bi_bufpos = BI_BUF_ZV(b) + 1;
2710 /* Calculate left whitespace boundary. */
2714 /* Whitespace past a newline is considered right whitespace. */
2715 while (elt < Dynarr_length(db->runes)) {
2716 struct rune *rb = Dynarr_atp(db->runes, elt);
2718 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2719 || rb->type == RUNE_BLANK) {
2720 dl->bounds.left_white += rb->width;
2723 elt = Dynarr_length(db->runes);
2727 /* Calculate right whitespace boundary. */
2729 int elt = Dynarr_length(db->runes) - 1;
2732 while (!done && elt >= 0) {
2733 struct rune *rb = Dynarr_atp(db->runes, elt);
2735 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2736 && isspace(rb->object.chr.ch))
2737 && !rb->type == RUNE_BLANK) {
2738 dl->bounds.right_white = rb->xpos + rb->width;
2746 /* The line is blank so everything is considered to be right
2749 dl->bounds.right_white = dl->bounds.left_in;
2752 /* Set the display blocks bounds. */
2753 db->start_pos = dl->bounds.left_in;
2754 if (Dynarr_length(db->runes)) {
2756 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
2758 db->end_pos = rb->xpos + rb->width;
2760 db->end_pos = dl->bounds.right_white;
2762 calculate_baseline(&data);
2764 dl->ascent = data.new_ascent;
2765 dl->descent = data.new_descent;
2768 unsigned short ascent =
2769 (unsigned short)XINT(w->minimum_line_ascent);
2771 if (dl->ascent < ascent)
2772 dl->ascent = ascent;
2775 unsigned short descent =
2776 (unsigned short)XINT(w->minimum_line_descent);
2778 if (dl->descent < descent)
2779 dl->descent = descent;
2782 calculate_yoffset(dl, db);
2784 dl->cursor_elt = data.cursor_x;
2785 /* #### lossage lossage lossage! Fix this shit! */
2786 if (data.bi_bufpos > BI_BUF_ZV(b))
2787 dl->end_bufpos = BUF_ZV(b);
2789 dl->end_bufpos = bytind_to_bufpos(b, data.bi_bufpos) - 1;
2791 data.dl->num_chars = column_at_point(b, dl->end_bufpos, 0);
2793 /* This doesn't correctly take into account tabs and control
2794 characters but if the window isn't being truncated then this
2795 value isn't going to end up being used anyhow. */
2796 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2798 /* #### handle horizontally scrolled line with text none of which
2799 was actually laid out. */
2801 /* #### handle any remainder of overlay arrow */
2803 if (*prop == ADD_FAILED)
2806 if (truncate_win && *prop) {
2811 extent_fragment_delete(data.ef);
2813 /* #### If we started at EOB, then make sure we return a value past
2814 it so that regenerate_window will exit properly. This is bogus.
2815 The main loop should get fixed so that it isn't necessary to call
2816 this function if we are already at EOB. */
2818 if (data.bi_bufpos == BI_BUF_ZV(b) && bi_start_pos == BI_BUF_ZV(b))
2819 return data.bi_bufpos + 1; /* Yuck! */
2821 return data.bi_bufpos;
2824 /* Display the overlay arrow at the beginning of the given line. */
2826 static int create_overlay_glyph_block(struct window *w, struct display_line *dl)
2828 struct frame *f = XFRAME(w->frame);
2829 struct device *d = XDEVICE(f->device);
2832 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2833 if (!STRINGP(Voverlay_arrow_string) && !GLYPHP(Voverlay_arrow_string))
2839 XSETWINDOW(data.window, w);
2840 data.db = get_display_block_from_line(dl, OVERWRITE);
2842 data.pixpos = dl->bounds.left_in;
2843 data.max_pixpos = dl->bounds.right_in;
2844 data.cursor_type = NO_CURSOR;
2846 data.findex = DEFAULT_INDEX;
2847 data.last_charset = Qunbound;
2848 data.last_findex = DEFAULT_INDEX;
2849 data.result_str = Qnil;
2852 Dynarr_reset(data.db->runes);
2854 if (STRINGP(Voverlay_arrow_string)) {
2855 add_bufbyte_string_runes
2857 XSTRING_DATA(Voverlay_arrow_string),
2858 XSTRING_LENGTH(Voverlay_arrow_string), 1, 0);
2859 } else if (GLYPHP(Voverlay_arrow_string)) {
2860 struct glyph_block gb;
2862 gb.glyph = Voverlay_arrow_string;
2864 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS, 0, 0);
2867 calculate_baseline(&data);
2869 dl->ascent = data.new_ascent;
2870 dl->descent = data.new_descent;
2872 data.db->start_pos = dl->bounds.left_in;
2873 data.db->end_pos = data.pixpos;
2875 calculate_yoffset(dl, data.db);
2877 return data.pixpos - dl->bounds.left_in;
2880 /* Add a type of glyph to a margin display block. */
2883 add_margin_runes(struct display_line *dl, struct display_block *db, int start,
2884 int count, enum glyph_layout layout, int side,
2887 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2888 ? dl->left_glyphs : dl->right_glyphs);
2891 struct window *w = XWINDOW(window);
2892 struct frame *f = XFRAME(w->frame);
2893 struct device *d = XDEVICE(f->device);
2898 data.window = window;
2901 data.pixpos = start;
2902 data.cursor_type = NO_CURSOR;
2904 data.last_charset = Qunbound;
2905 data.last_findex = DEFAULT_INDEX;
2906 data.result_str = Qnil;
2908 data.new_ascent = dl->ascent;
2909 data.new_descent = dl->descent;
2911 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2912 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS)) {
2914 elt = Dynarr_length(gbd) - 1;
2919 end = Dynarr_length(gbd);
2922 while (count && ((!reverse && elt < end) || (reverse && elt >= end))) {
2923 struct glyph_block *gb = Dynarr_atp(gbd, elt);
2925 if (NILP(gb->extent))
2926 abort(); /* these should have been handled in add_glyph_rune */
2929 ((side == LEFT_GLYPHS &&
2930 extent_begin_glyph_layout(XEXTENT(gb->extent)) == layout)
2931 || (side == RIGHT_GLYPHS &&
2932 extent_end_glyph_layout(XEXTENT(gb->extent)) ==
2934 data.findex = gb->findex;
2935 data.max_pixpos = data.pixpos + gb->width;
2936 add_glyph_rune_noret(&data, gb, side, 0, NULL);
2941 (reverse ? elt-- : elt++);
2944 calculate_baseline(&data);
2946 dl->ascent = data.new_ascent;
2947 dl->descent = data.new_descent;
2949 calculate_yoffset(dl, data.db);
2954 /* Add a blank to a margin display block. */
2957 add_margin_blank(struct display_line *dl, struct display_block *db,
2958 struct window *w, int xpos, int width, int side)
2962 rb.findex = (side == LEFT_GLYPHS
2963 ? get_builtin_face_cache_index(w, Vleft_margin_face)
2964 : get_builtin_face_cache_index(w, Vright_margin_face));
2969 rb.type = RUNE_BLANK;
2970 rb.cursor_type = CURSOR_OFF;
2972 Dynarr_add(db->runes, rb);
2975 /* Display glyphs in the left outside margin, left inside margin and
2976 left whitespace area. */
2979 create_left_glyph_block(struct window *w, struct display_line *dl,
2984 int use_overflow = (NILP(w->use_left_overflow) ? 0 : 1);
2986 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2987 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2988 int left_in_start = dl->bounds.left_in;
2989 int left_in_end = dl->bounds.left_in + overlay_width;
2991 struct display_block *odb, *idb;
2993 XSETWINDOW(window, w);
2995 /* We have to add the glyphs to the line in the order outside,
2996 inside, whitespace. However the precedence dictates that we
2997 determine how many will fit in the reverse order. */
2999 /* Determine how many whitespace glyphs we can display and where
3000 they should start. */
3001 white_in_start = dl->bounds.left_white;
3002 white_out_start = left_in_start;
3003 white_out_cnt = white_in_cnt = 0;
3006 while (elt < Dynarr_length(dl->left_glyphs)) {
3007 struct glyph_block *gb = Dynarr_atp(dl->left_glyphs, elt);
3009 if (NILP(gb->extent))
3010 abort(); /* these should have been handled in add_glyph_rune */
3012 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3016 width = glyph_width(gb->glyph, window);
3018 if (white_in_start - width >= left_in_end) {
3020 white_in_start -= width;
3023 } else if (use_overflow
3024 && (white_out_start - width >
3025 dl->bounds.left_out)) {
3027 white_out_start -= width;
3037 /* Determine how many inside margin glyphs we can display and where
3038 they should start. The inside margin glyphs get whatever space
3039 is left after the whitespace glyphs have been displayed. These
3040 are tricky to calculate since if we decide to use the overflow
3041 area we basically have to start over. So for these we build up a
3042 list of just the inside margin glyphs and manipulate it to
3043 determine the needed info. */
3045 glyph_block_dynarr *ib;
3046 int avail_in, avail_out;
3049 int used_in, used_out;
3052 used_in = used_out = 0;
3053 ib = Dynarr_new(glyph_block);
3054 while (elt < Dynarr_length(dl->left_glyphs)) {
3055 struct glyph_block *gb =
3056 Dynarr_atp(dl->left_glyphs, elt);
3058 if (NILP(gb->extent))
3059 abort(); /* these should have been handled in add_glyph_rune */
3061 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3063 gb->width = glyph_width(gb->glyph, window);
3064 used_in += gb->width;
3065 Dynarr_add(ib, *gb);
3074 avail_in = white_in_start - left_in_end;
3082 avail_out = white_out_start - dl->bounds.left_out;
3085 while (!done && marker < Dynarr_length(ib)) {
3086 int width = Dynarr_atp(ib, marker)->width;
3088 /* If everything now fits in the available inside margin
3089 space, we're done. */
3090 if (used_in <= avail_in)
3093 /* Otherwise see if we have room to move a glyph to the
3095 if (used_out + width <= avail_out) {
3106 /* At this point we now know that everything from marker on goes in
3107 the inside margin and everything before it goes in the outside
3108 margin. The stuff going into the outside margin is guaranteed
3109 to fit, but we may have to trim some stuff from the inside. */
3111 in_in_end = left_in_end;
3112 in_out_start = white_out_start;
3113 in_out_cnt = in_in_cnt = 0;
3117 while (elt < Dynarr_length(dl->left_glyphs)) {
3118 struct glyph_block *gb =
3119 Dynarr_atp(dl->left_glyphs, elt);
3121 if (NILP(gb->extent))
3122 abort(); /* these should have been handled in add_glyph_rune */
3124 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3126 int width = glyph_width(gb->glyph, window);
3130 in_out_start -= width;
3134 } else if (in_in_end + width < white_in_start) {
3147 /* Determine how many outside margin glyphs we can display. They
3148 always start at the left outside margin and can only use the
3149 outside margin space. */
3150 out_end = dl->bounds.left_out;
3154 while (elt < Dynarr_length(dl->left_glyphs)) {
3155 struct glyph_block *gb = Dynarr_atp(dl->left_glyphs, elt);
3157 if (NILP(gb->extent))
3158 abort(); /* these should have been handled in add_glyph_rune */
3160 if (extent_begin_glyph_layout(XEXTENT(gb->extent)) ==
3161 GL_OUTSIDE_MARGIN) {
3162 int width = glyph_width(gb->glyph, window);
3164 if (out_end + width <= in_out_start) {
3176 /* Now that we know where everything goes, we add the glyphs as
3177 runes to the appropriate display blocks. */
3178 if (out_cnt || in_out_cnt || white_out_cnt) {
3179 odb = get_display_block_from_line(dl, LEFT_OUTSIDE_MARGIN);
3180 odb->start_pos = dl->bounds.left_out;
3181 /* #### We should stop adding a blank to account for the space
3182 between the end of the glyphs and the margin and instead set
3183 this accordingly. */
3184 odb->end_pos = dl->bounds.left_in;
3185 Dynarr_reset(odb->runes);
3189 if (in_in_cnt || white_in_cnt) {
3190 idb = get_display_block_from_line(dl, LEFT_INSIDE_MARGIN);
3191 idb->start_pos = dl->bounds.left_in;
3192 /* #### See above comment for odb->end_pos */
3193 idb->end_pos = dl->bounds.left_white;
3194 Dynarr_reset(idb->runes);
3198 /* First add the outside margin glyphs. */
3201 add_margin_runes(dl, odb, dl->bounds.left_out, out_cnt,
3202 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3204 end_xpos = dl->bounds.left_out;
3206 /* There may be blank space between the outside margin glyphs and
3207 the inside margin glyphs. If so, add a blank. */
3208 if (in_out_cnt && (in_out_start - end_xpos)) {
3209 add_margin_blank(dl, odb, w, end_xpos, in_out_start - end_xpos,
3213 /* Next add the inside margin glyphs which are actually in the
3216 end_xpos = add_margin_runes(dl, odb, in_out_start, in_out_cnt,
3217 GL_INSIDE_MARGIN, LEFT_GLYPHS,
3221 /* If we didn't add any inside margin glyphs to the outside margin,
3222 but are adding whitespace glyphs, then we need to add a blank
3224 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos)) {
3225 add_margin_blank(dl, odb, w, end_xpos,
3226 white_out_start - end_xpos, LEFT_GLYPHS);
3229 /* Next add the whitespace margin glyphs which are actually in the
3231 if (white_out_cnt) {
3233 add_margin_runes(dl, odb, white_out_start, white_out_cnt,
3234 GL_WHITESPACE, LEFT_GLYPHS, window);
3237 /* We take care of clearing between the end of the glyphs and the
3238 start of the inside margin for lines which have glyphs. */
3239 if (odb && (left_in_start - end_xpos)) {
3240 add_margin_blank(dl, odb, w, end_xpos, left_in_start - end_xpos,
3244 /* Next add the inside margin glyphs which are actually in the
3247 end_xpos = add_margin_runes(dl, idb, left_in_end, in_in_cnt,
3248 GL_INSIDE_MARGIN, LEFT_GLYPHS,
3251 end_xpos = left_in_end;
3253 /* Make sure that the area between the end of the inside margin
3254 glyphs and the whitespace glyphs is cleared. */
3255 if (idb && (white_in_start - end_xpos > 0)) {
3256 add_margin_blank(dl, idb, w, end_xpos,
3257 white_in_start - end_xpos, LEFT_GLYPHS);
3260 /* Next add the whitespace margin glyphs which are actually in the
3263 add_margin_runes(dl, idb, white_in_start, white_in_cnt,
3264 GL_WHITESPACE, LEFT_GLYPHS, window);
3267 /* Whitespace glyphs always end right next to the text block so
3268 there is nothing we have to make sure is cleared after them. */
3271 /* Display glyphs in the right outside margin, right inside margin and
3272 right whitespace area. */
3274 static void create_right_glyph_block(struct window *w, struct display_line *dl)
3278 int use_overflow = (NILP(w->use_right_overflow) ? 0 : 1);
3280 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3281 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3283 struct display_block *odb, *idb;
3285 XSETWINDOW(window, w);
3287 /* We have to add the glyphs to the line in the order outside,
3288 inside, whitespace. However the precedence dictates that we
3289 determine how many will fit in the reverse order. */
3291 /* Determine how many whitespace glyphs we can display and where
3292 they should start. */
3293 white_in_end = dl->bounds.right_white;
3294 white_out_end = dl->bounds.right_in;
3295 white_out_cnt = white_in_cnt = 0;
3298 while (elt < Dynarr_length(dl->right_glyphs)) {
3299 struct glyph_block *gb = Dynarr_atp(dl->right_glyphs, elt);
3301 if (NILP(gb->extent))
3302 abort(); /* these should have been handled in add_glyph_rune */
3304 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3306 int width = glyph_width(gb->glyph, window);
3308 if (white_in_end + width <= dl->bounds.right_in) {
3310 white_in_end += width;
3313 } else if (use_overflow
3314 && (white_out_end + width <=
3315 dl->bounds.right_out)) {
3317 white_out_end += width;
3327 /* Determine how many inside margin glyphs we can display and where
3328 they should start. The inside margin glyphs get whatever space
3329 is left after the whitespace glyphs have been displayed. These
3330 are tricky to calculate since if we decide to use the overflow
3331 area we basically have to start over. So for these we build up a
3332 list of just the inside margin glyphs and manipulate it to
3333 determine the needed info. */
3335 glyph_block_dynarr *ib;
3336 int avail_in, avail_out;
3339 int used_in, used_out;
3342 used_in = used_out = 0;
3343 ib = Dynarr_new(glyph_block);
3344 while (elt < Dynarr_length(dl->right_glyphs)) {
3345 struct glyph_block *gb =
3346 Dynarr_atp(dl->right_glyphs, elt);
3348 if (NILP(gb->extent))
3349 abort(); /* these should have been handled in add_glyph_rune */
3351 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3353 gb->width = glyph_width(gb->glyph, window);
3354 used_in += gb->width;
3355 Dynarr_add(ib, *gb);
3364 avail_in = dl->bounds.right_in - white_in_end;
3369 avail_out = dl->bounds.right_out - white_out_end;
3372 while (!done && marker < Dynarr_length(ib)) {
3373 int width = Dynarr_atp(ib, marker)->width;
3375 /* If everything now fits in the available inside margin
3376 space, we're done. */
3377 if (used_in <= avail_in)
3380 /* Otherwise see if we have room to move a glyph to the
3382 if (used_out + width <= avail_out) {
3393 /* At this point we now know that everything from marker on goes in
3394 the inside margin and everything before it goes in the outside
3395 margin. The stuff going into the outside margin is guaranteed
3396 to fit, but we may have to trim some stuff from the inside. */
3398 in_in_start = dl->bounds.right_in;
3399 in_out_end = dl->bounds.right_in;
3400 in_out_cnt = in_in_cnt = 0;
3404 while (elt < Dynarr_length(dl->right_glyphs)) {
3405 struct glyph_block *gb =
3406 Dynarr_atp(dl->right_glyphs, elt);
3408 if (NILP(gb->extent))
3409 abort(); /* these should have been handled in add_glyph_rune */
3411 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3413 int width = glyph_width(gb->glyph, window);
3417 in_out_end += width;
3421 } else if (in_in_start - width >= white_in_end) {
3423 in_in_start -= width;
3434 /* Determine how many outside margin glyphs we can display. They
3435 always start at the right outside margin and can only use the
3436 outside margin space. */
3437 out_start = dl->bounds.right_out;
3441 while (elt < Dynarr_length(dl->right_glyphs)) {
3442 struct glyph_block *gb = Dynarr_atp(dl->right_glyphs, elt);
3444 if (NILP(gb->extent))
3445 abort(); /* these should have been handled in add_glyph_rune */
3447 if (extent_end_glyph_layout(XEXTENT(gb->extent)) ==
3448 GL_OUTSIDE_MARGIN) {
3449 int width = glyph_width(gb->glyph, window);
3451 if (out_start - width >= in_out_end) {
3463 /* Now that we now where everything goes, we add the glyphs as runes
3464 to the appropriate display blocks. */
3465 if (out_cnt || in_out_cnt || white_out_cnt) {
3466 odb = get_display_block_from_line(dl, RIGHT_OUTSIDE_MARGIN);
3467 /* #### See comments before odb->start_pos init in
3468 create_left_glyph_block */
3469 odb->start_pos = dl->bounds.right_in;
3470 odb->end_pos = dl->bounds.right_out;
3471 Dynarr_reset(odb->runes);
3475 if (in_in_cnt || white_in_cnt) {
3476 idb = get_display_block_from_line(dl, RIGHT_INSIDE_MARGIN);
3477 idb->start_pos = dl->bounds.right_white;
3478 /* #### See comments before odb->start_pos init in
3479 create_left_glyph_block */
3480 idb->end_pos = dl->bounds.right_in;
3481 Dynarr_reset(idb->runes);
3485 /* First add the whitespace margin glyphs which are actually in the
3488 end_xpos = add_margin_runes(dl, idb, dl->bounds.right_white,
3489 white_in_cnt, GL_WHITESPACE,
3490 RIGHT_GLYPHS, window);
3492 end_xpos = dl->bounds.right_white;
3494 /* Make sure that the area between the end of the whitespace glyphs
3495 and the inside margin glyphs is cleared. */
3496 if (in_in_cnt && (in_in_start - end_xpos)) {
3497 add_margin_blank(dl, idb, w, end_xpos, in_in_start - end_xpos,
3501 /* Next add the inside margin glyphs which are actually in the
3504 end_xpos = add_margin_runes(dl, idb, in_in_start, in_in_cnt,
3505 GL_INSIDE_MARGIN, RIGHT_GLYPHS,
3509 /* If we didn't add any inside margin glyphs then make sure the rest
3510 of the inside margin area gets cleared. */
3511 if (idb && (dl->bounds.right_in - end_xpos)) {
3512 add_margin_blank(dl, idb, w, end_xpos,
3513 dl->bounds.right_in - end_xpos, RIGHT_GLYPHS);
3516 /* Next add any whitespace glyphs in the outside margin. */
3517 if (white_out_cnt) {
3519 add_margin_runes(dl, odb, dl->bounds.right_in,
3520 white_out_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3523 end_xpos = dl->bounds.right_in;
3525 /* Next add any inside margin glyphs in the outside margin. */
3527 end_xpos = add_margin_runes(dl, odb, end_xpos, in_out_cnt,
3528 GL_INSIDE_MARGIN, RIGHT_GLYPHS,
3532 /* There may be space between any whitespace or inside margin glyphs
3533 in the outside margin and the actual outside margin glyphs. */
3534 if (odb && (out_start - end_xpos)) {
3535 add_margin_blank(dl, odb, w, end_xpos, out_start - end_xpos,
3539 /* Finally, add the outside margin glyphs. */
3541 add_margin_runes(dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3542 RIGHT_GLYPHS, window);
3546 /***************************************************************************/
3548 /* modeline routines */
3550 /***************************************************************************/
3552 /* This function is also used in frame.c by `generate_title_string' */
3554 generate_formatted_string_db(Lisp_Object format_str, Lisp_Object result_str,
3555 struct window *w, struct display_line *dl,
3556 struct display_block *db, face_index findex,
3557 int min_pixpos, int max_pixpos, int type)
3559 struct frame *f = XFRAME(w->frame);
3560 struct device *d = XDEVICE(f->device);
3564 Charcount offset = 0;
3570 data.findex = findex;
3571 data.pixpos = min_pixpos;
3572 data.max_pixpos = max_pixpos;
3573 data.cursor_type = NO_CURSOR;
3574 data.last_charset = Qunbound;
3575 data.last_findex = DEFAULT_INDEX;
3576 data.result_str = result_str;
3577 data.is_modeline = 1;
3579 XSETWINDOW(data.window, w);
3581 Dynarr_reset(formatted_string_extent_dynarr);
3582 Dynarr_reset(formatted_string_extent_start_dynarr);
3583 Dynarr_reset(formatted_string_extent_end_dynarr);
3585 /* result_str is nil when we're building a frame or icon title. Otherwise,
3586 we're building a modeline, so the offset starts at the modeline
3587 horizontal scrolling amount */
3588 if (!NILP(result_str))
3589 offset = w->modeline_hscroll;
3590 generate_fstring_runes(w, &data, 0, 0, -1, format_str, 0,
3591 max_pixpos - min_pixpos, findex, type, &offset,
3594 if (Dynarr_length(db->runes)) {
3596 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
3597 c_pixpos = rb->xpos + rb->width;
3599 c_pixpos = min_pixpos;
3601 /* If we don't reach the right side of the window, add a blank rune
3602 to make up the difference. This usually only occurs if the
3603 modeline face is using a proportional width font or a fixed width
3604 font of a different size from the default face font. */
3606 if (c_pixpos < max_pixpos) {
3607 data.pixpos = c_pixpos;
3608 data.blank_width = max_pixpos - data.pixpos;
3610 add_blank_rune(&data, NULL, 0);
3613 /* Now create the result string and frob the extents into it. */
3614 if (!NILP(result_str)) {
3618 struct buffer *buf = XBUFFER(WINDOW_BUFFER(w));
3620 in_modeline_generation = 1;
3622 detach_all_extents(result_str);
3623 resize_string(XSTRING(result_str), -1,
3624 data.bytepos - XSTRING_LENGTH(result_str));
3626 strdata = XSTRING_DATA(result_str);
3628 for (elt = 0, len = 0; elt < Dynarr_length(db->runes); elt++) {
3629 if (Dynarr_atp(db->runes, elt)->type == RUNE_CHAR) {
3630 len += (set_charptr_emchar
3631 (strdata + len, Dynarr_atp(db->runes,
3638 elt < Dynarr_length(formatted_string_extent_dynarr);
3640 Lisp_Object extent = Qnil;
3644 Dynarr_at(formatted_string_extent_dynarr,
3647 Fgethash(extent, buf->modeline_extent_table, Qnil);
3649 child = Fmake_extent(Qnil, Qnil, result_str);
3650 Fputhash(extent, child,
3651 buf->modeline_extent_table);
3653 Fset_extent_parent(child, extent);
3654 set_extent_endpoints
3656 Dynarr_at(formatted_string_extent_start_dynarr,
3658 Dynarr_at(formatted_string_extent_end_dynarr, elt),
3662 in_modeline_generation = 0;
3666 /* Ensure that the given display line DL accurately represents the
3667 modeline for the given window. */
3669 generate_modeline(struct window *w, struct display_line *dl, int type)
3671 struct buffer *b = XBUFFER(w->buffer);
3672 struct frame *f = XFRAME(w->frame);
3673 struct device *d = XDEVICE(f->device);
3675 /* Unlike display line and rune pointers, this one can't change underneath
3677 struct display_block *db = get_display_block_from_line(dl, TEXT);
3678 int max_pixpos, min_pixpos, ypos_adj;
3679 Lisp_Object font_inst;
3681 /* This will actually determine incorrect inside boundaries for the
3682 modeline since it ignores the margins. However being aware of this fact
3683 we never use those values anywhere so it doesn't matter. */
3684 dl->bounds = calculate_display_line_boundaries(w, 1);
3686 /* We are generating a modeline. */
3688 dl->cursor_elt = -1;
3690 /* Reset the runes on the modeline. */
3691 Dynarr_reset(db->runes);
3693 if (!WINDOW_HAS_MODELINE_P(w)) {
3696 /* If there is a horizontal scrollbar, don't add anything. */
3697 if (window_scrollbar_height(w))
3700 dl->ascent = DEVMETH(d, divider_height, ());
3702 /* The modeline is at the bottom of the gutters. */
3703 dl->ypos = WINDOW_BOTTOM(w);
3705 rb.findex = MODELINE_INDEX;
3706 rb.xpos = dl->bounds.left_out;
3707 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3710 rb.type = RUNE_HLINE;
3711 rb.object.hline.thickness = 1;
3712 rb.object.hline.yoffset = 0;
3713 rb.cursor_type = NO_CURSOR;
3715 if (!EQ(Qzero, w->modeline_shadow_thickness)
3716 && FRAME_WIN_P(f)) {
3717 int shadow_thickness = MODELINE_SHADOW_THICKNESS(w);
3719 dl->ypos -= shadow_thickness;
3720 rb.xpos += shadow_thickness;
3721 rb.width -= 2 * shadow_thickness;
3724 Dynarr_add(db->runes, rb);
3728 /* !!#### not right; needs to compute the max height of
3730 font_inst = WINDOW_FACE_CACHEL_FONT(w, MODELINE_INDEX, Vcharset_ascii);
3732 dl->ascent = XFONT_INSTANCE(font_inst)->ascent;
3733 dl->descent = XFONT_INSTANCE(font_inst)->descent;
3735 min_pixpos = dl->bounds.left_out;
3736 max_pixpos = dl->bounds.right_out;
3738 if (!EQ(Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P(f)) {
3739 int shadow_thickness = MODELINE_SHADOW_THICKNESS(w);
3741 ypos_adj = shadow_thickness;
3742 min_pixpos += shadow_thickness;
3743 max_pixpos -= shadow_thickness;
3747 generate_formatted_string_db(b->modeline_format,
3748 b->generated_modeline_string, w, dl, db,
3749 MODELINE_INDEX, min_pixpos, max_pixpos,
3752 /* The modeline is at the bottom of the gutters. We have to wait to
3753 set this until we've generated the modeline in order to account
3754 for any embedded faces. */
3755 dl->ypos = WINDOW_BOTTOM(w) - dl->descent - ypos_adj;
3759 add_string_to_fstring_db_runes(pos_data * data, const Bufbyte * str,
3760 Charcount pos, Charcount min_pos,
3763 /* This function has been Mule-ized. */
3765 const Bufbyte *cur_pos = str;
3766 struct display_block *db = data->db;
3768 data->blank_width = space_width(XWINDOW(data->window));
3769 while (Dynarr_length(db->runes) < pos)
3770 add_blank_rune_noret(data, NULL, 0);
3772 end = (Dynarr_length(db->runes) +
3773 bytecount_to_charcount(str, strlen((const char *)str)));
3775 end = min(max_pos, end);
3777 while (pos < end && *cur_pos) {
3778 const Bufbyte *old_cur_pos = cur_pos;
3781 data->ch = charptr_emchar(cur_pos);
3782 succeeded = (add_emchar_rune(data) != ADD_FAILED);
3783 INC_CHARPTR(cur_pos);
3786 data->modeline_charpos++;
3787 data->bytepos += cur_pos - old_cur_pos;
3791 while (Dynarr_length(db->runes) < min_pos &&
3792 (data->pixpos + data->blank_width <= data->max_pixpos))
3793 add_blank_rune_noret(data, NULL, 0);
3795 return Dynarr_length(db->runes);
3798 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3799 modeline extents. */
3801 add_glyph_to_fstring_db_runes(pos_data * data, Lisp_Object glyph,
3802 Charcount pos, Charcount min_pos,
3803 Charcount max_pos, Lisp_Object extent)
3805 /* This function has been Mule-ized. */
3807 struct display_block *db = data->db;
3808 struct glyph_block gb;
3810 data->blank_width = space_width(XWINDOW(data->window));
3811 while (Dynarr_length(db->runes) < pos)
3812 add_blank_rune_noret(data, NULL, 0);
3814 end = Dynarr_length(db->runes) + 1;
3816 end = min(max_pos, end);
3820 add_glyph_rune_noret(data, &gb, BEGIN_GLYPHS, 0, 0);
3823 while (Dynarr_length(db->runes) < pos &&
3824 (data->pixpos + data->blank_width <= data->max_pixpos))
3825 add_blank_rune_noret(data, NULL, 0);
3827 return Dynarr_length(db->runes);
3830 /* If max_pos is == -1, it is considered to be infinite. The same is
3831 true of max_pixsize. */
3832 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3833 if (Dynarr_length (data->db->runes)) \
3834 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3838 /* Note that this function does "positions" in terms of characters and
3839 not in terms of columns. This is necessary to make the formatting
3840 work correctly when proportional width fonts are used in the
3843 generate_fstring_runes(struct window *w, pos_data * data, Charcount pos,
3844 Charcount min_pos, Charcount max_pos,
3845 Lisp_Object elt, int depth, int max_pixsize,
3846 face_index findex, int type, Charcount * offset,
3847 Lisp_Object cur_ext)
3849 /* This function has been Mule-ized. */
3850 /* #### The other losing things in this function are:
3852 -- C zero-terminated-string lossage.
3853 -- Non-printable characters should be converted into something
3854 appropriate (e.g. ^F) instead of blindly being printed anyway.
3864 /* A string. Add to the display line and check for %-constructs
3867 Bufbyte *this = XSTRING_DATA(elt);
3869 while ((pos < max_pos || max_pos == -1) && *this) {
3870 Bufbyte *last = this;
3872 while (*this && *this != '%')
3876 /* No %-construct */
3878 bytecount_to_charcount(last, this - last);
3880 if (size <= *offset)
3886 *offset : min(pos + size - *offset,
3888 const Bufbyte *tmp_last =
3889 charptr_n_addr(last, *offset);
3892 add_string_to_fstring_db_runes(data,
3899 } else { /* *this == '%' */
3901 Charcount spec_width = 0;
3903 this++; /* skip over '%' */
3905 /* We can't allow -ve args due to the "%-" construct.
3906 * Argument specifies minwidth but not maxwidth
3907 * (maxwidth can be specified by
3908 * (<negative-number> . <stuff>) modeline elements)
3910 while (isdigit(*this)) {
3912 spec_width * 10 + (*this - '0');
3919 generate_fstring_runes(w, data, pos,
3922 Vglobal_mode_string,
3928 } else if (*this == '-') {
3929 Charcount num_to_add;
3931 if (max_pixsize < 0)
3933 else if (max_pos != -1)
3934 num_to_add = max_pos - pos;
3939 SET_CURRENT_MODE_CHARS_PIXSIZE;
3942 redisplay_text_width_string
3943 (w, findex, &ch, Qnil, 0,
3953 while (num_to_add--)
3955 add_string_to_fstring_db_runes
3956 (data, (const Bufbyte *)"-",
3958 } else if (*this != 0) {
3959 Emchar ch = charptr_emchar(this);
3963 decode_mode_spec(w, ch, type);
3966 Dynarr_atp(mode_spec_bufbyte_string,
3968 size = bytecount_to_charcount
3969 /* Skip the null character added by `decode_mode_spec' */
3972 (mode_spec_bufbyte_string)) - 1;
3974 if (size <= *offset)
3977 const Bufbyte *tmp_str =
3981 /* #### NOTE: I don't understand why a tmp_max is not
3982 computed and used here as in the plain string case
3985 add_string_to_fstring_db_runes
3986 (data, tmp_str, pos, pos,
3992 /* NOT this++. There could be any sort of character at
3993 the current position. */
3997 if (max_pixsize > 0) {
3999 SET_CURRENT_MODE_CHARS_PIXSIZE;
4001 if (cur_pixsize >= max_pixsize)
4005 } else if (SYMBOLP(elt)) {
4006 /* A symbol: process the value of the symbol recursively
4007 as if it appeared here directly. */
4008 Lisp_Object tem = symbol_value_in_buffer(elt, w->buffer);
4010 if (!UNBOUNDP(tem)) {
4011 /* If value is a string, output that string literally:
4012 don't check for % within it. */
4014 Bufbyte *str = XSTRING_DATA(tem);
4015 Charcount size = XSTRING_CHAR_LENGTH(tem);
4017 if (size <= *offset)
4020 const Bufbyte *tmp_str =
4021 charptr_n_addr(str, *offset);
4023 /* #### NOTE: I don't understand why a tmp_max is not
4024 computed and used here as in the plain string case
4027 add_string_to_fstring_db_runes(data,
4035 /* Give up right away for nil or t. */
4036 else if (!EQ(tem, elt)) {
4041 } else if (GENERIC_SPECIFIERP(elt)) {
4042 Lisp_Object window, tem;
4043 XSETWINDOW(window, w);
4044 tem = specifier_instance_no_quit(elt, Qunbound, window,
4045 ERROR_ME_NOT, 0, Qzero);
4046 if (!UNBOUNDP(tem)) {
4050 } else if (CONSP(elt)) {
4051 /* A cons cell: four distinct cases.
4052 * - If first element is a string or a cons, process all the elements
4053 * and effectively concatenate them.
4054 * - If first element is a negative number, truncate displaying cdr to
4055 * at most that many characters. If positive, pad (with spaces)
4056 * to at least that many characters.
4057 * - If first element is another symbol, process the cadr or caddr
4058 * recursively according to whether the symbol's value is non-nil or
4060 * - If first element is an extent, process the cdr recursively
4061 * and handle the extent's face.
4064 Lisp_Object car, tem;
4072 tem = symbol_value_in_buffer(car, w->buffer);
4073 /* elt is now the cdr, and we know it is a cons cell.
4074 Use its car if CAR has a non-nil value. */
4075 if (!UNBOUNDP(tem)) {
4081 /* Symbol's value is nil (or symbol is unbound)
4082 * Get the cddr of the original list
4083 * and if possible find the caddr and use that.
4087 else if (!CONSP(elt))
4093 } else if (INTP(car)) {
4094 Charcount lim = XINT(car);
4099 /* Negative int means reduce maximum width.
4100 * DO NOT change MIN_PIXPOS here!
4101 * (20 -10 . foo) should truncate foo to 10 col
4102 * and then pad to 20.
4105 max_pos = pos - lim;
4107 max_pos = min(max_pos, pos - lim);
4108 } else if (lim > 0) {
4109 /* Padding specified. Don't let it be more than
4113 if (max_pos != -1 && lim > max_pos)
4115 /* If that's more padding than already wanted, queue it.
4116 * But don't reduce padding already specified even if
4117 * that is beyond the current truncation point.
4123 } else if (STRINGP(car) || CONSP(car)) {
4126 /* LIMIT is to protect against circular lists. */
4127 while (CONSP(elt) && --limit > 0
4128 && (pos < max_pos || max_pos == -1)) {
4130 generate_fstring_runes(w, data, pos, pos,
4133 findex, type, offset,
4137 } else if (EXTENTP(car)) {
4138 struct extent *ext = XEXTENT(car);
4140 if (EXTENT_LIVE_P(ext)) {
4141 face_index old_findex = data->findex;
4143 Lisp_Object font_inst;
4144 face_index new_findex;
4145 Bytecount start = data->bytepos;
4147 face = extent_face(ext);
4149 /* #### needs to merge faces, sigh */
4150 /* #### needs to handle list of faces */
4152 get_builtin_face_cache_index(w,
4154 /* !!#### not right; needs to compute the max height of
4157 WINDOW_FACE_CACHEL_FONT(w,
4161 data->dl->ascent = max(data->dl->ascent,
4166 max(data->dl->descent,
4167 XFONT_INSTANCE(font_inst)->
4170 new_findex = old_findex;
4172 data->findex = new_findex;
4174 generate_fstring_runes(w, data, pos, pos,
4180 data->findex = old_findex;
4181 Dynarr_add(formatted_string_extent_dynarr, ext);
4182 Dynarr_add(formatted_string_extent_start_dynarr,
4184 Dynarr_add(formatted_string_extent_end_dynarr,
4188 } else if (GLYPHP(elt)) {
4189 /* Glyphs are considered as one character with respect to the modeline
4190 horizontal scrolling facility. -- dv */
4195 add_glyph_to_fstring_db_runes(data, elt, pos, pos,
4200 char *str = GETTEXT("*invalid*");
4201 Charcount size = (Charcount) strlen(str); /* is this ok ?? -- dv */
4203 if (size <= *offset)
4206 const Bufbyte *tmp_str =
4207 charptr_n_addr((const Bufbyte *)str,
4210 /* #### NOTE: I don't understand why a tmp_max is not computed and
4211 used here as in the plain string case above. -- dv */
4213 add_string_to_fstring_db_runes(data,
4222 if (min_pos > pos) {
4223 add_string_to_fstring_db_runes(data, (const Bufbyte *)"", pos,
4230 /* Update just the modeline. Assumes the desired display structs. If
4231 they do not have a modeline block, it does nothing. */
4232 static void regenerate_modeline(struct window *w)
4234 display_line_dynarr *dla = window_display_lines(w, DESIRED_DISP);
4236 if (!Dynarr_length(dla) || !Dynarr_atp(dla, 0)->modeline)
4239 generate_modeline(w, Dynarr_atp(dla, 0), DESIRED_DISP);
4240 redisplay_update_line(w, 0, 0, 0);
4244 /* Make sure that modeline display line is present in the given
4245 display structs if the window has a modeline and update that
4246 line. Returns true if a modeline was needed. */
4247 static int ensure_modeline_generated(struct window *w, int type)
4251 /* minibuffer windows don't have modelines */
4252 if (MINI_WINDOW_P(w))
4254 /* windows which haven't had it turned off do */
4255 else if (WINDOW_HAS_MODELINE_P(w))
4257 /* windows which have it turned off don't have a divider if there is
4258 a horizontal scrollbar */
4259 else if (window_scrollbar_height(w))
4261 /* and in this case there is none */
4265 if (need_modeline) {
4266 display_line_dynarr *dla;
4268 dla = window_display_lines(w, type);
4270 /* We don't care if there is a display line which is not
4271 currently a modeline because it is definitely going to become
4272 one if we have gotten to this point. */
4273 if (Dynarr_length(dla) == 0) {
4274 if (Dynarr_largest(dla) > 0) {
4275 struct display_line *mlp = Dynarr_atp(dla, 0);
4276 Dynarr_add(dla, *mlp);
4278 struct display_line modeline;
4280 Dynarr_add(dla, modeline);
4284 /* If we're adding a new place marker go ahead and generate the
4285 modeline so that it is available for use by
4286 window_modeline_height. */
4287 generate_modeline(w, Dynarr_atp(dla, 0), type);
4290 return need_modeline;
4293 /* #### Kludge or not a kludge. I tend towards the former. */
4294 int real_current_modeline_height(struct window *w)
4296 Fset_marker(w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4297 Fset_marker(w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP],
4300 if (ensure_modeline_generated(w, CMOTION_DISP)) {
4301 display_line_dynarr *dla =
4302 window_display_lines(w, CMOTION_DISP);
4304 if (Dynarr_length(dla)) {
4305 if (Dynarr_atp(dla, 0)->modeline)
4306 return (Dynarr_atp(dla, 0)->ascent +
4307 Dynarr_atp(dla, 0)->descent);
4313 /***************************************************************************/
4315 /* displayable string routines */
4317 /***************************************************************************/
4319 /* Given a position for a string in a window, ensure that the given
4320 display line DL accurately represents the text on a line starting
4321 at the given position.
4323 Yes, this is duplicating the code of create_text_block, but it
4324 looked just too hard to change create_text_block to handle strings
4325 *and* buffers. We already make a distinction between the two
4326 elsewhere in the code so I think unifying them would require a
4327 complete MULE rewrite. Besides, the other distinction is that these
4328 functions cover text that the user *cannot edit* so we can remove
4329 everything to do with cursors, minibuffers etc. Eventually the
4330 modeline routines should be modified to use this code as it copes
4331 with many more types of display situation. */
4334 create_string_text_block(struct window *w, Lisp_Object disp_string,
4335 struct display_line *dl,
4337 prop_block_dynarr ** prop, face_index default_face)
4339 struct frame *f = XFRAME(w->frame);
4340 /* Note that a lot of the buffer controlled stuff has been left in
4341 because you might well want to make use of it (selective display
4342 etc), its just the buffer text that we do not use. However, it
4343 seems to be possible for buffer to be nil sometimes so protect
4344 against this case. */
4345 struct buffer *b = BUFFERP(w->buffer) ? XBUFFER(w->buffer) : 0;
4346 struct device *d = XDEVICE(f->device);
4347 Lisp_String *s = XSTRING(disp_string);
4349 /* we're working with these a lot so precalculate them */
4350 Bytecount slen = XSTRING_LENGTH(disp_string);
4351 Bytecount bi_string_zv = slen;
4352 Bytind bi_start_pos = charcount_to_bytecount(string_data(s), start_pos);
4356 int truncate_win = b ? window_truncation_on(w) : 0;
4358 /* We're going to ditch selective display for static text, it's an
4359 FSF thing and invisible extents are the way to go here.
4360 Implementing it also relies on a number of buffer-specific
4361 functions that we don't have the luxury of being able to use
4364 /* The variable ctl-arrow allows the user to specify what characters
4365 can actually be displayed and which octal should be used for.
4366 #### This variable should probably have some rethought done to
4369 #### It would also be really nice if you could specify that
4370 the characters come out in hex instead of in octal. Mule
4371 does that by adding a ctl-hexa variable similar to ctl-arrow,
4372 but that's bogus -- we need a more general solution. I
4373 think you need to extend the concept of display tables
4374 into a more general conversion mechanism. Ideally you
4375 could specify a Lisp function that converts characters,
4376 but this violates the Second Golden Rule and besides would
4377 make things way way way way slow.
4379 So instead, we extend the display-table concept, which was
4380 historically limited to 256-byte vectors, to one of the
4383 a) A 256-entry vector, for backward compatibility;
4384 b) char-table, mapping characters to values;
4385 c) range-table, mapping ranges of characters to values;
4386 d) a list of the above.
4388 The (d) option allows you to specify multiple display tables
4389 instead of just one. Each display table can specify conversions
4390 for some characters and leave others unchanged. The way the
4391 character gets displayed is determined by the first display table
4392 with a binding for that character. This way, you could call a
4393 function `enable-hex-display' that adds a hex display-table to
4394 the list of display tables for the current buffer.
4396 #### ...not yet implemented... Also, we extend the concept of
4397 "mapping" to include a printf-like spec. Thus you can make all
4398 extended characters show up as hex with a display table like
4401 #s(range-table data ((256 524288) (format "%x")))
4403 Since more than one display table is possible, you have
4404 great flexibility in mapping ranges of characters. */
4405 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP(b->ctl_arrow)
4406 ? XCHAR_OR_CHAR_INT(b->ctl_arrow)
4407 : ((EQ(b->ctl_arrow, Qt)
4408 || EQ(b->ctl_arrow, Qnil))
4409 ? 255 : 160)) : 255;
4411 Lisp_Object face_dt, window_dt;
4413 /* The text display block for this display line. */
4414 struct display_block *db = get_display_block_from_line(dl, TEXT);
4416 /* The first time through the main loop we need to force the glyph
4417 data to be updated. */
4420 /* Apparently the new extent_fragment_update returns an end position
4421 equal to the position passed in if there are no more runs to be
4423 int no_more_frags = 0;
4425 dl->used_prop_data = 0;
4427 dl->line_continuation = 0;
4429 /* set up faces to use for clearing areas, used by
4430 output_display_line */
4431 dl->default_findex = default_face;
4433 dl->left_margin_findex = default_face;
4434 dl->right_margin_findex = default_face;
4436 dl->left_margin_findex =
4437 get_builtin_face_cache_index(w, Vleft_margin_face);
4438 dl->right_margin_findex =
4439 get_builtin_face_cache_index(w, Vright_margin_face);
4443 data.ef = extent_fragment_new(disp_string, f);
4445 /* These values are used by all of the rune addition routines. We add
4446 them to this structure for ease of passing. */
4448 XSETWINDOW(data.window, w);
4452 data.bi_bufpos = bi_start_pos;
4453 data.pixpos = dl->bounds.left_in;
4454 data.last_charset = Qunbound;
4455 data.last_findex = default_face;
4456 data.result_str = Qnil;
4457 data.string = disp_string;
4459 /* Set the right boundary adjusting it to take into account any end
4460 glyph. Save the width of the end glyph for later use. */
4461 data.max_pixpos = dl->bounds.right_in;
4462 data.max_pixpos -= data.end_glyph_width;
4464 data.cursor_type = NO_CURSOR;
4468 /* I don't think we want this, string areas should not scroll with
4470 data.start_col = w->hscroll;
4471 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4473 data.bi_start_col_enabled = 0;
4474 data.hscroll_glyph_width_adjust = 0;
4476 /* We regenerate the line from the very beginning. */
4477 Dynarr_reset(db->runes);
4479 /* Why is this less than or equal and not just less than? If the
4480 starting position is already equal to the maximum we can't add
4481 anything else, right? Wrong. We might still have a newline to
4482 add. A newline can use the room allocated for an end glyph since
4483 if we add it we know we aren't going to be adding any end
4486 /* #### Chuck -- I think this condition should be while (1).
4487 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4488 and the begin-glyph ends exactly at the end of the window, the
4489 end-glyph and text might not be displayed. while (1) ensures
4490 that the loop terminates only when either (a) there is
4491 propagation data or (b) the end-of-line or end-of-buffer is hit.
4493 #### Also I think you need to ensure that the operation
4494 "add begin glyphs; add end glyphs; add text" is atomic and
4495 can't get interrupted in the middle. If you run off the end
4496 of the line during that operation, then you keep accumulating
4497 propagation data until you're done. Otherwise, if the (e.g.)
4498 there's a begin glyph at a particular position and attempting
4499 to display that glyph results in window-end being hit and
4500 propagation data being generated, then the character at that
4501 position won't be displayed.
4503 #### See also the comment after the end of this loop, below.
4505 while (data.pixpos <= data.max_pixpos) {
4506 /* #### This check probably should not be necessary. */
4507 if (data.bi_bufpos > bi_string_zv) {
4508 /* #### urk! More of this lossage! */
4513 /* Check for face changes. */
4515 || (!no_more_frags && data.bi_bufpos == data.ef->end)) {
4516 Lisp_Object last_glyph = Qnil;
4517 /* Deal with clipped glyphs that we have already displayed. */
4518 if (*prop && Dynarr_atp(*prop, 0)->type == PROP_GLYPH) {
4520 Dynarr_atp(*prop, 0)->data.p_glyph.glyph;
4524 /* Now compute the face and begin/end-glyph information. */
4526 /* Remember that the extent-fragment routines deal in Bytind's. */
4527 extent_fragment_update(w, data.ef, data.bi_bufpos,
4529 /* This is somewhat cheesy but the alternative is to
4530 propagate default_face into extent_fragment_update. */
4531 if (data.findex == DEFAULT_INDEX)
4532 data.findex = default_face;
4534 get_display_tables(w, data.findex, &face_dt,
4537 if (data.bi_bufpos == data.ef->end)
4542 /* Determine what is next to be displayed. We first handle any
4543 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4544 display then we determine what to do based on the character at the
4545 current buffer position. */
4547 /* If there are glyphs, add them to the line. We add the end
4548 glyphs for the previous run of text here rather than doing
4549 them at the end of handling the previous run so that glyphs
4550 at the beginning and end of a line are handled correctly. */
4551 if (Dynarr_length(data.ef->glyphs) > 0) {
4552 data.ch = string_char(s, data.bi_bufpos);
4553 *prop = add_glyph_runes(&data);
4559 /* If the current position is covered by an invisible extent, do
4560 nothing (except maybe add some ellipses). */
4561 else if (data.ef->invisible) {
4562 /* #### Chuck, perhaps you could look at this code? I don't
4563 really know what I'm doing. */
4569 /* The extent fragment code only sets this when we should
4570 really display the ellipses. It makes sure the ellipses
4571 don't get displayed more than once in a row. */
4572 if (data.ef->invisible_ellipses) {
4573 struct glyph_block gb;
4575 data.ef->invisible_ellipses_already_displayed =
4577 data.ef->invisible_ellipses = 0;
4579 gb.glyph = Vinvisible_text_glyph;
4581 add_glyph_rune(&data, &gb, BEGIN_GLYPHS, 0,
4583 INVIS_GLYPH_INDEX));
4584 /* Perhaps they shouldn't propagate if the very next thing
4585 is to display a newline (for compatibility with
4586 selective-display-ellipses)? Maybe that's too
4592 /* #### What if we're dealing with a display table? */
4596 if (data.bi_bufpos == bi_string_zv)
4599 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4602 /* If there is propagation data, then it represents the current
4603 buffer position being displayed. Add them and advance the
4604 position counter. This might also add the minibuffer
4607 dl->used_prop_data = 1;
4608 *prop = add_propagation_runes(prop, &data);
4611 goto done; /* gee, a really narrow window */
4612 else if (data.bi_bufpos == bi_string_zv)
4614 else if (data.bi_bufpos < 0)
4615 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4618 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4621 /* If at end-of-buffer, we've already processed begin and
4622 end-glyphs at this point and there's no text to process,
4624 else if (data.bi_bufpos == bi_string_zv)
4628 Lisp_Object entry = Qnil;
4629 /* Get the character at the current buffer position. */
4630 data.ch = string_char(s, data.bi_bufpos);
4631 if (!NILP(face_dt) || !NILP(window_dt))
4633 display_table_entry(data.ch, face_dt,
4636 /* If there is a display table entry for it, hand it off to
4637 add_disp_table_entry_runes and let it worry about it. */
4638 if (!NILP(entry) && !EQ(entry, make_char(data.ch))) {
4640 add_disp_table_entry_runes(&data, entry);
4646 /* Check if we have hit a newline character. If so, add a marker
4647 to the line and end this loop. */
4648 else if (data.ch == '\n') {
4649 /* We aren't going to be adding an end glyph so give its
4650 space back in order to make sure that the cursor can
4652 data.max_pixpos += data.end_glyph_width;
4656 /* If the current character is considered to be printable, then
4658 else if (data.ch >= printable_min) {
4659 *prop = add_emchar_rune(&data);
4664 /* If the current character is a tab, determine the next tab
4665 starting position and add a blank rune which extends from the
4666 current pixel position to that starting position. */
4667 else if (data.ch == '\t') {
4668 int tab_start_pixpos = data.pixpos;
4673 if (data.start_col > 1)
4676 (data.start_col - 1));
4679 next_tab_position(w, tab_start_pixpos,
4680 dl->bounds.left_in +
4682 hscroll_glyph_width_adjust);
4683 if (next_tab_start > data.max_pixpos) {
4685 next_tab_start - data.max_pixpos;
4686 next_tab_start = data.max_pixpos;
4688 data.blank_width = next_tab_start - data.pixpos;
4691 tab_start_pixpos) / space_width(w);
4694 add_blank_rune(&data, w, char_tab_width);
4696 /* add_blank_rune is only supposed to be called with
4697 sizes guaranteed to fit in the available space. */
4701 struct prop_block pb;
4702 *prop = Dynarr_new(prop_block);
4704 pb.type = PROP_BLANK;
4705 pb.data.p_blank.width = prop_width;
4706 pb.data.p_blank.findex = data.findex;
4707 Dynarr_add(*prop, pb);
4713 /* If character is a control character, pass it off to
4714 add_control_char_runes.
4716 The is_*() routines have undefined results on
4717 arguments outside of the range [-1, 255]. (This
4718 often bites people who carelessly use `char' instead
4719 of `unsigned char'.)
4721 else if (data.ch < 0x100 && iscntrl((Bufbyte) data.ch)) {
4722 *prop = add_control_char_runes(&data, b);
4728 /* If the character is above the ASCII range and we have not
4729 already handled it, then print it as an octal number. */
4730 else if (data.ch >= 0200) {
4731 *prop = add_octal_runes(&data);
4737 /* Assume the current character is considered to be printable,
4738 then just add it. */
4740 *prop = add_emchar_rune(&data);
4745 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4751 /* Determine the starting point of the next line if we did not hit the
4752 end of the buffer. */
4753 if (data.bi_bufpos < bi_string_zv) {
4754 /* #### This check is not correct. If the line terminated
4755 due to a begin-glyph or end-glyph hitting window-end, then
4756 data.ch will not point to the character at data.bi_bufpos. If
4757 you make the two changes mentioned at the top of this loop,
4758 you should be able to say '(if (*prop))'. That should also
4759 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4762 /* The common case is that the line ended because we hit a newline.
4763 In that case, the next character is just the next buffer
4765 if (data.ch == '\n') {
4766 INC_CHARBYTIND(string_data(s), data.bi_bufpos);
4769 /* Otherwise we have a buffer line which cannot fit on one display
4772 struct glyph_block gb;
4773 struct glyph_cachel *cachel;
4775 /* If the line is to be truncated then we actually have to look
4776 for the next newline. We also add the end-of-line glyph which
4777 we know will fit because we adjusted the right border before
4778 we starting laying out the line. */
4779 data.max_pixpos += data.end_glyph_width;
4780 data.findex = default_face;
4786 /* Now find the start of the next line. */
4788 bi_find_next_emchar_in_string(s, '\n',
4792 data.cursor_type = NO_CURSOR;
4793 data.bi_bufpos = bi_pos;
4794 gb.glyph = Vtruncation_glyph;
4795 cachel = GLYPH_CACHEL(w, TRUN_GLYPH_INDEX);
4797 /* The cursor can never be on the continuation glyph. */
4798 data.cursor_type = NO_CURSOR;
4800 /* data.bi_bufpos is already at the start of the next line. */
4802 dl->line_continuation = 1;
4803 gb.glyph = Vcontinuation_glyph;
4804 cachel = GLYPH_CACHEL(w, CONT_GLYPH_INDEX);
4807 if (data.end_glyph_width)
4808 add_glyph_rune_noret(&data, &gb, BEGIN_GLYPHS, 0,
4811 if (truncate_win && data.bi_bufpos == bi_string_zv) {
4812 const Bufbyte *endb =
4813 charptr_n_addr(string_data(s),
4816 if (charptr_emchar(endb) != '\n') {
4817 /* #### Damn this losing shit. */
4822 } else if (data.bi_bufpos == bi_string_zv) {
4823 /* create_text_block () adds a bogus \n marker here which screws
4824 up subwindow display. Since we never have a cursor in the
4825 gutter we can safely ignore it. */
4827 /* Calculate left whitespace boundary. */
4831 /* Whitespace past a newline is considered right whitespace. */
4832 while (elt < Dynarr_length(db->runes)) {
4833 struct rune *rb = Dynarr_atp(db->runes, elt);
4835 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4836 || rb->type == RUNE_BLANK) {
4837 dl->bounds.left_white += rb->width;
4840 elt = Dynarr_length(db->runes);
4844 /* Calculate right whitespace boundary. */
4846 int elt = Dynarr_length(db->runes) - 1;
4849 while (!done && elt >= 0) {
4850 struct rune *rb = Dynarr_atp(db->runes, elt);
4852 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4853 && isspace(rb->object.chr.ch))
4854 && !rb->type == RUNE_BLANK) {
4855 dl->bounds.right_white = rb->xpos + rb->width;
4863 /* The line is blank so everything is considered to be right
4866 dl->bounds.right_white = dl->bounds.left_in;
4869 /* Set the display blocks bounds. */
4870 db->start_pos = dl->bounds.left_in;
4871 if (Dynarr_length(db->runes)) {
4873 Dynarr_atp(db->runes, Dynarr_length(db->runes) - 1);
4875 db->end_pos = rb->xpos + rb->width;
4877 db->end_pos = dl->bounds.right_white;
4879 calculate_baseline(&data);
4881 dl->ascent = data.new_ascent;
4882 dl->descent = data.new_descent;
4885 unsigned short ascent =
4886 (unsigned short)XINT(w->minimum_line_ascent);
4888 if (dl->ascent < ascent)
4889 dl->ascent = ascent;
4892 unsigned short descent =
4893 (unsigned short)XINT(w->minimum_line_descent);
4895 if (dl->descent < descent)
4896 dl->descent = descent;
4899 calculate_yoffset(dl, db);
4901 dl->cursor_elt = data.cursor_x;
4902 /* #### lossage lossage lossage! Fix this shit! */
4903 if (data.bi_bufpos > bi_string_zv)
4905 buffer_or_string_bytind_to_bufpos(disp_string,
4909 buffer_or_string_bytind_to_bufpos(disp_string,
4910 data.bi_bufpos) - 1;
4912 data.dl->num_chars =
4913 string_column_at_point(s, dl->end_bufpos,
4914 b ? XINT(b->tab_width) : 8);
4916 /* This doesn't correctly take into account tabs and control
4917 characters but if the window isn't being truncated then this
4918 value isn't going to end up being used anyhow. */
4919 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4921 /* #### handle horizontally scrolled line with text none of which
4922 was actually laid out. */
4924 /* #### handle any remainder of overlay arrow */
4926 if (*prop == ADD_FAILED)
4929 if (truncate_win && *prop) {
4934 extent_fragment_delete(data.ef);
4936 /* #### If we started at EOB, then make sure we return a value past
4937 it so that regenerate_window will exit properly. This is bogus.
4938 The main loop should get fixed so that it isn't necessary to call
4939 this function if we are already at EOB. */
4941 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4942 return bytecount_to_charcount(string_data(s), data.bi_bufpos) + 1; /* Yuck! */
4944 return bytecount_to_charcount(string_data(s), data.bi_bufpos);
4947 /* Given a display line and a starting position, ensure that the
4948 contents of the display line accurately represent the visual
4949 representation of the buffer contents starting from the given
4950 position when displayed in the given window. The display line ends
4951 when the contents of the line reach the right boundary of the given
4954 This is very similar to generate_display_line but with the same
4955 limitations as create_string_text_block. I have taken the liberty
4956 of fixing the bytind stuff though.*/
4959 generate_string_display_line(struct window *w, Lisp_Object disp_string,
4960 struct display_line *dl,
4962 prop_block_dynarr ** prop, face_index default_face)
4966 /* you must set bounds before calling this. */
4968 /* Reset what this line is using. */
4969 if (dl->display_blocks)
4970 Dynarr_reset(dl->display_blocks);
4971 if (dl->left_glyphs) {
4972 Dynarr_free(dl->left_glyphs);
4973 dl->left_glyphs = 0;
4975 if (dl->right_glyphs) {
4976 Dynarr_free(dl->right_glyphs);
4977 dl->right_glyphs = 0;
4980 /* We aren't generating a modeline at the moment. */
4983 /* Create a display block for the text region of the line. */
4984 ret_bufpos = create_string_text_block(w, disp_string, dl, start_pos,
4985 prop, default_face);
4986 dl->bufpos = start_pos;
4987 if (dl->end_bufpos < dl->bufpos)
4988 dl->end_bufpos = dl->bufpos;
4990 /* If there are left glyphs associated with any character in the
4991 text block, then create a display block to handle them. */
4992 if (dl->left_glyphs != NULL && Dynarr_length(dl->left_glyphs))
4993 create_left_glyph_block(w, dl, 0);
4995 /* If there are right glyphs associated with any character in the
4996 text block, then create a display block to handle them. */
4997 if (dl->right_glyphs != NULL && Dynarr_length(dl->right_glyphs))
4998 create_right_glyph_block(w, dl);
5003 /* This is ripped off from regenerate_window. All we want to do is
5004 loop through elements in the string creating display lines until we
5005 have covered the provided area. Simple really. */
5007 generate_displayable_area(struct window *w, Lisp_Object disp_string,
5008 int xpos, int ypos, int width, int height,
5009 display_line_dynarr * dla,
5010 Bufpos start_pos, face_index default_face)
5012 int yend = ypos + height;
5015 prop_block_dynarr *prop = 0;
5016 layout_bounds bounds;
5020 /* if there's nothing to do then do nothing. code after this assumes
5021 there is something to do. */
5022 if (NILP(disp_string))
5025 s_zv = XSTRING_CHAR_LENGTH(disp_string);
5027 bounds.left_out = xpos;
5028 bounds.right_out = xpos + width;
5029 /* The inner boundaries mark where the glyph margins are located. */
5030 bounds.left_in = bounds.left_out + window_left_margin_width(w);
5031 bounds.right_in = bounds.right_out - window_right_margin_width(w);
5032 /* We cannot fully calculate the whitespace boundaries as they
5033 depend on the contents of the line being displayed. */
5034 bounds.left_white = bounds.left_in;
5035 bounds.right_white = bounds.right_in;
5037 while (ypos < yend) {
5038 struct display_line dl;
5039 struct display_line *dlp;
5043 if (Dynarr_length(dla) < Dynarr_largest(dla)) {
5044 dlp = Dynarr_atp(dla, Dynarr_length(dla));
5053 dlp->bounds = bounds;
5056 generate_string_display_line(w, disp_string, dlp, start_pos,
5057 &prop, default_face);
5058 /* we need to make sure that we continue along the line if there
5059 is more left to display otherwise we just end up redisplaying
5060 the same chunk over and over again. */
5061 if (next_pos == start_pos && next_pos < s_zv)
5064 start_pos = next_pos;
5066 dlp->ypos = ypos + dlp->ascent;
5067 ypos = dlp->ypos + dlp->descent;
5070 int visible_height = dlp->ascent + dlp->descent;
5072 dlp->clip = (ypos - yend);
5073 visible_height -= dlp->clip;
5075 if (visible_height < VERTICAL_CLIP(w, 1)) {
5077 free_display_line(dlp);
5083 Dynarr_add(dla, *dlp);
5085 /* #### This type of check needs to be done down in the
5086 generate_display_line call. */
5087 if (start_pos >= s_zv)
5095 /***************************************************************************/
5097 /* window-regeneration routines */
5099 /***************************************************************************/
5101 /* For a given window and starting position in the buffer it contains,
5102 ensure that the TYPE display lines accurately represent the
5103 presentation of the window. We pass the buffer instead of getting
5104 it from the window since redisplay_window may have temporarily
5105 changed it to the echo area buffer. */
5108 regenerate_window(struct window *w, Bufpos start_pos, Bufpos point, int type)
5110 struct frame *f = XFRAME(w->frame);
5111 struct buffer *b = XBUFFER(w->buffer);
5112 int ypos = WINDOW_TEXT_TOP(w);
5113 int yend; /* set farther down */
5114 int yclip = WINDOW_TEXT_TOP_CLIP(w);
5117 prop_block_dynarr *prop;
5118 layout_bounds bounds;
5119 display_line_dynarr *dla;
5122 /* The lines had better exist by this point. */
5123 if (!(dla = window_display_lines(w, type))) {
5128 w->max_line_len = 0;
5130 /* Normally these get updated in redisplay_window but it is possible
5131 for this function to get called from some other points where that
5132 update may not have occurred. This acts as a safety check. */
5133 if (!Dynarr_length(w->face_cachels))
5134 reset_face_cachels(w);
5135 if (!Dynarr_length(w->glyph_cachels))
5136 reset_glyph_cachels(w);
5138 Fset_marker(w->start[type], make_int(start_pos), w->buffer);
5139 Fset_marker(w->pointm[type], make_int(point), w->buffer);
5140 w->last_point_x[type] = -1;
5141 w->last_point_y[type] = -1;
5143 /* Make sure a modeline is in the structs if needed. */
5144 need_modeline = ensure_modeline_generated(w, type);
5146 /* Wait until here to set this so that the structs have a modeline
5147 generated in the case where one didn't exist. */
5148 yend = WINDOW_TEXT_BOTTOM(w);
5150 bounds = calculate_display_line_boundaries(w, 0);
5152 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5153 if (MINI_WINDOW_P(w)
5154 && (!NILP(Vminibuf_prompt) || !NILP(Vminibuf_preprompt))
5155 && !echo_area_active(f)
5156 && start_pos == BUF_BEGV(b)) {
5157 struct prop_block pb;
5159 prop = Dynarr_new(prop_block);
5161 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5162 pb.type = PROP_MINIBUF_PROMPT;
5163 pb.data.p_string.str = XSTRING_DATA(string);
5164 pb.data.p_string.len = XSTRING_LENGTH(string);
5165 Dynarr_add(prop, pb);
5169 /* When we are computing things for scrolling purposes, make
5170 sure at least one line is always generated */
5171 force = (type == CMOTION_DISP);
5173 /* Make sure this is set always */
5174 /* Note the conversion at end */
5175 w->window_end_pos[type] = start_pos;
5176 while (ypos < yend || force) {
5177 struct display_line dl;
5178 struct display_line *dlp;
5181 if (Dynarr_length(dla) < Dynarr_largest(dla)) {
5182 dlp = Dynarr_atp(dla, Dynarr_length(dla));
5191 dlp->bounds = bounds;
5194 generate_display_line(w, dlp, 1, start_pos, &prop, type);
5196 if (yclip > dlp->ascent) {
5197 /* this should never happen, but if it does just display the
5202 dlp->ypos = (ypos + dlp->ascent) - yclip;
5203 ypos = dlp->ypos + dlp->descent;
5205 /* See if we've been asked to start midway through a line, for
5206 partial display line scrolling. */
5208 dlp->top_clip = yclip;
5214 int visible_height = dlp->ascent + dlp->descent;
5216 dlp->clip = (ypos - yend);
5217 /* Although this seems strange we could have a single very
5218 tall line visible for which we need to account for both
5219 the top clip and the bottom clip. */
5220 visible_height -= (dlp->clip + dlp->top_clip);
5222 if (visible_height < VERTICAL_CLIP(w, 1) && !force) {
5224 free_display_line(dlp);
5230 if (dlp->cursor_elt != -1) {
5231 /* #### This check is steaming crap. Have to get things
5232 fixed so when create_text_block hits EOB, we're done,
5234 if (w->last_point_x[type] == -1) {
5235 w->last_point_x[type] = dlp->cursor_elt;
5236 w->last_point_y[type] = Dynarr_length(dla);
5238 /* #### This means that we've added a cursor at EOB
5239 twice. Yuck oh yuck. */
5240 struct display_block *db =
5241 get_display_block_from_line(dlp, TEXT);
5243 Dynarr_atp(db->runes,
5244 dlp->cursor_elt)->cursor_type =
5246 dlp->cursor_elt = -1;
5250 if (dlp->num_chars > w->max_line_len)
5251 w->max_line_len = dlp->num_chars;
5253 Dynarr_add(dla, *dlp);
5255 /* #### This isn't right, but it is close enough for now. */
5256 w->window_end_pos[type] = start_pos;
5258 /* #### This type of check needs to be done down in the
5259 generate_display_line call. */
5260 if (start_pos > BUF_ZV(b))
5269 /* #### More not quite right, but close enough. */
5270 /* Ben sez: apparently window_end_pos[] is measured
5271 as the number of characters between the window end and the
5272 end of the buffer? This seems rather weirdo. What's
5273 the justification for this?
5275 JV sez: Because BUF_Z (b) would be a good initial value, however
5276 that can change. This representation allows initalizing with 0.
5278 w->window_end_pos[type] = BUF_Z(b) - w->window_end_pos[type];
5280 if (need_modeline) {
5281 /* We know that this is the right thing to use because we put it
5282 there when we first started working in this function. */
5283 generate_modeline(w, Dynarr_atp(dla, 0), type);
5287 #define REGEN_INC_FIND_START_END \
5289 /* Determine start and end of lines. */ \
5290 if (!Dynarr_length (cdla)) \
5294 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5298 else if (!Dynarr_atp (cdla, 0)->modeline \
5299 && !Dynarr_atp (ddla, 0)->modeline) \
5304 abort (); /* structs differ */ \
5306 dla_end = Dynarr_length (cdla) - 1; \
5309 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5310 + Dynarr_atp (cdla, dla_start)->offset); \
5311 /* If this isn't true, then startp has changed and we need to do a \
5313 if (startp != start_pos) \
5316 /* Point is outside the visible region so give up. */ \
5317 if (pointm < start_pos) \
5322 /* This attempts to incrementally update the display structures. It
5323 returns a boolean indicating success or failure. This function is
5324 very similar to regenerate_window_incrementally and is in fact only
5325 called from that function. However, because of the nature of the
5326 changes it deals with it sometimes makes different assumptions
5327 which can lead to success which are much more difficult to make
5328 when dealing with buffer changes. */
5331 regenerate_window_extents_only_changed(struct window *w, Bufpos startp,
5333 Charcount beg_unchanged,
5334 Charcount end_unchanged)
5336 struct buffer *b = XBUFFER(w->buffer);
5337 display_line_dynarr *cdla = window_display_lines(w, CURRENT_DISP);
5338 display_line_dynarr *ddla = window_display_lines(w, DESIRED_DISP);
5342 int first_line, last_line;
5344 /* Don't define this in the loop where it is used because we
5345 definitely want its value to survive between passes. */
5346 prop_block_dynarr *prop = NULL;
5348 /* If we don't have any buffer change recorded but the modiff flag has
5349 been incremented, then fail. I'm not sure of the exact circumstances
5350 under which this can happen, but I believe that it is probably a
5351 reasonable happening. */
5352 if (!point_visible(w, pointm, CURRENT_DISP)
5353 || XINT(w->last_modified[CURRENT_DISP]) < BUF_MODIFF(b))
5356 /* If the cursor is moved we attempt to update it. If we succeed we
5357 go ahead and proceed with the optimization attempt. */
5358 if (!EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5359 || pointm != marker_position(w->last_point[CURRENT_DISP])) {
5360 struct frame *f = XFRAME(w->frame);
5361 struct device *d = XDEVICE(f->device);
5362 struct frame *sel_f = device_selected_frame(d);
5365 if (w->last_point_x[CURRENT_DISP] != -1
5366 && w->last_point_y[CURRENT_DISP] != -1) {
5368 if (redisplay_move_cursor(w, pointm, WINDOW_TTY_P(w))) {
5369 /* Always regenerate the modeline in case it is
5370 displaying the current line or column. */
5371 regenerate_modeline(w);
5374 } else if (w != XWINDOW(FRAME_SELECTED_WINDOW(sel_f))) {
5375 if (f->modeline_changed)
5376 regenerate_modeline(w);
5384 if (beg_unchanged == -1 && end_unchanged == -1)
5387 /* assert: There are no buffer modifications or they are all below the
5388 visible region. We assume that regenerate_window_incrementally has
5389 not called us unless this is true. */
5391 REGEN_INC_FIND_START_END;
5393 /* If the changed are starts before the visible area, give up. */
5394 if (beg_unchanged < startp)
5397 /* Find what display line the extent changes first affect. */
5399 while (line <= dla_end) {
5400 struct display_line *dl = Dynarr_atp(cdla, line);
5401 Bufpos lstart = dl->bufpos + dl->offset;
5402 Bufpos lend = dl->end_bufpos + dl->offset;
5404 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5410 /* If the changes are below the visible area then if point hasn't
5411 moved return success otherwise fail in order to be safe. */
5412 if (line > dla_end) {
5413 if (EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5414 && pointm == marker_position(w->last_point[CURRENT_DISP]))
5420 /* At this point we know what line the changes first affect. We now
5421 begin redrawing lines as long as we are still in the affected
5422 region and the line's size and positioning don't change.
5423 Otherwise we fail. If we fail we will have altered the desired
5424 structs which could lead to an assertion failure. However, if we
5425 fail the next thing that is going to happen is a full regen so we
5426 will actually end up being safe. */
5427 w->last_modified[DESIRED_DISP] = make_int(BUF_MODIFF(b));
5428 w->last_facechange[DESIRED_DISP] = make_int(BUF_FACECHANGE(b));
5429 Fset_marker(w->last_start[DESIRED_DISP], make_int(startp), w->buffer);
5430 Fset_marker(w->last_point[DESIRED_DISP], make_int(pointm), w->buffer);
5432 first_line = last_line = line;
5433 while (line <= dla_end) {
5434 Bufpos old_start, old_end, new_start;
5435 struct display_line *cdl = Dynarr_atp(cdla, line);
5436 struct display_line *ddl = Dynarr_atp(ddla, line);
5437 struct display_block *db;
5440 assert(cdl->bufpos == ddl->bufpos);
5441 assert(cdl->end_bufpos == ddl->end_bufpos);
5442 assert(cdl->offset == ddl->offset);
5444 db = get_display_block_from_line(ddl, TEXT);
5445 initial_size = Dynarr_length(db->runes);
5446 old_start = ddl->bufpos + ddl->offset;
5447 old_end = ddl->end_bufpos + ddl->offset;
5449 /* If this is the first line being updated and it used
5450 propagation data, fail. Otherwise we'll be okay because
5451 we'll have the necessary propagation data. */
5452 if (line == first_line && ddl->used_prop_data)
5456 generate_display_line(w, ddl, 0, ddl->bufpos + ddl->offset,
5457 &prop, DESIRED_DISP);
5458 (void)new_start; // Silence set-not-read warning.
5462 /* #### If there is propagated stuff the fail. We could
5463 probably actually deal with this if the line had propagated
5464 information when originally created by a full
5471 /* If any line position parameters have changed or a
5472 cursor has disappeared or disappeared, fail. */
5473 db = get_display_block_from_line(ddl, TEXT);
5474 if (cdl->ypos != ddl->ypos
5475 || cdl->ascent != ddl->ascent
5476 || cdl->descent != ddl->descent
5477 || cdl->top_clip != ddl->top_clip
5478 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5479 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5480 || old_start != ddl->bufpos
5481 || old_end != ddl->end_bufpos
5482 || initial_size != Dynarr_length(db->runes)) {
5486 if (ddl->cursor_elt != -1) {
5487 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5488 w->last_point_y[DESIRED_DISP] = line;
5493 /* If the extent changes end on the line we just updated then
5494 we're done. Otherwise go on to the next line. */
5495 if (end_unchanged <= ddl->end_bufpos)
5501 redisplay_update_line(w, first_line, last_line, 1);
5505 /* Attempt to update the display data structures based on knowledge of
5506 the changed region in the buffer. Returns a boolean indicating
5507 success or failure. If this function returns a failure then a
5508 regenerate_window _must_ be performed next in order to maintain
5509 invariants located here. */
5512 regenerate_window_incrementally(struct window *w, Bufpos startp, Bufpos pointm)
5514 struct buffer *b = XBUFFER(w->buffer);
5515 display_line_dynarr *cdla = window_display_lines(w, CURRENT_DISP);
5516 display_line_dynarr *ddla = window_display_lines(w, DESIRED_DISP);
5517 Charcount beg_unchanged, end_unchanged;
5518 Charcount extent_beg_unchanged, extent_end_unchanged;
5524 /* If this function is called, the current and desired structures
5525 had better be identical. If they are not, then that is a bug. */
5526 assert(Dynarr_length(cdla) == Dynarr_length(ddla));
5528 /* We don't handle minibuffer windows yet. The minibuffer prompt
5530 if (MINI_WINDOW_P(w))
5533 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED(b);
5534 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED(b) == -1
5535 ? -1 : BUF_Z(b) - BUF_EXTENT_END_UNCHANGED(b));
5537 /* If nothing has changed in the buffer, then make sure point is ok
5539 if (BUF_BEGIN_UNCHANGED(b) == -1 && BUF_END_UNCHANGED(b) == -1)
5540 return regenerate_window_extents_only_changed(w, startp, pointm,
5541 extent_beg_unchanged,
5542 extent_end_unchanged);
5544 /* We can't deal with deleted newlines. */
5545 if (BUF_NEWLINE_WAS_DELETED(b))
5548 beg_unchanged = BUF_BEGIN_UNCHANGED(b);
5549 end_unchanged = (BUF_END_UNCHANGED(b) == -1
5550 ? -1 : BUF_Z(b) - BUF_END_UNCHANGED(b));
5552 REGEN_INC_FIND_START_END;
5554 /* If the changed area starts before the visible area, give up. */
5555 if (beg_unchanged < startp)
5558 /* Find what display line the buffer changes first affect. */
5560 while (line <= dla_end) {
5561 struct display_line *dl = Dynarr_atp(cdla, line);
5562 Bufpos lstart = dl->bufpos + dl->offset;
5563 Bufpos lend = dl->end_bufpos + dl->offset;
5565 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5571 /* If the changes are below the visible area then if point hasn't
5572 moved return success otherwise fail in order to be safe. */
5574 return regenerate_window_extents_only_changed(w, startp, pointm,
5575 extent_beg_unchanged,
5576 extent_end_unchanged);
5578 /* At this point we know what line the changes first affect. We
5579 now redraw that line. If the changes are contained within it
5580 we are going to succeed and can update just that one line.
5581 Otherwise we fail. If we fail we will have altered the desired
5582 structs which could lead to an assertion failure. However, if
5583 we fail the next thing that is going to happen is a full regen
5584 so we will actually end up being safe. */
5587 prop_block_dynarr *prop = NULL;
5588 struct display_line *cdl = Dynarr_atp(cdla, line);
5589 struct display_line *ddl = Dynarr_atp(ddla, line);
5591 assert(cdl->bufpos == ddl->bufpos);
5592 assert(cdl->end_bufpos == ddl->end_bufpos);
5593 assert(cdl->offset == ddl->offset);
5595 /* If the line continues to next display line, fail. */
5596 if (ddl->line_continuation)
5599 /* If the line was generated using propagation data, fail. */
5600 if (ddl->used_prop_data)
5604 generate_display_line(w, ddl, 0, ddl->bufpos + ddl->offset,
5605 &prop, DESIRED_DISP);
5606 (void)new_start; // Silence set-not-read warning.
5610 /* If there is propagated stuff then it is pretty much a
5611 guarantee that more than just the one line is affected. */
5617 /* If the line continues to next display line, fail. */
5618 if (ddl->line_continuation)
5621 /* If any line position parameters have changed or a
5622 cursor has disappeared or disappeared, fail. */
5623 if (cdl->ypos != ddl->ypos
5624 || cdl->ascent != ddl->ascent
5625 || cdl->descent != ddl->descent
5626 || cdl->top_clip != ddl->top_clip
5627 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5628 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) {
5632 /* If the changed area also ends on this line, then we may be in
5633 business. Update everything and return success. */
5634 if (end_unchanged >= ddl->bufpos
5635 && end_unchanged <= ddl->end_bufpos) {
5636 w->last_modified[DESIRED_DISP] =
5637 make_int(BUF_MODIFF(b));
5638 w->last_facechange[DESIRED_DISP] =
5639 make_int(BUF_FACECHANGE(b));
5640 Fset_marker(w->last_start[DESIRED_DISP],
5641 make_int(startp), w->buffer);
5642 Fset_marker(w->last_point[DESIRED_DISP],
5643 make_int(pointm), w->buffer);
5645 if (ddl->cursor_elt != -1) {
5646 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5647 w->last_point_y[DESIRED_DISP] = line;
5650 redisplay_update_line(w, line, line, 1);
5651 regenerate_modeline(w);
5653 /* #### For now we just flush the cache until this has been
5654 tested. After that is done, this should correct the
5656 Dynarr_reset(w->line_start_cache);
5658 /* Adjust the extent changed boundaries to remove any
5659 overlap with the buffer changes since we've just
5660 successfully updated that area. */
5661 if (extent_beg_unchanged != -1
5662 && extent_beg_unchanged >= beg_unchanged
5663 && extent_beg_unchanged < end_unchanged)
5664 extent_beg_unchanged = end_unchanged;
5666 if (extent_end_unchanged != -1
5667 && extent_end_unchanged >= beg_unchanged
5668 && extent_end_unchanged < end_unchanged)
5669 extent_end_unchanged = beg_unchanged - 1;
5671 if (extent_end_unchanged <= extent_beg_unchanged)
5672 extent_beg_unchanged = extent_end_unchanged =
5675 /* This could lead to odd results if it fails, but since the
5676 buffer changes update succeeded this probably will to.
5677 We already know that the extent changes start at or after
5678 the line because we checked before entering the loop. */
5679 if (extent_beg_unchanged != -1
5680 && extent_end_unchanged != -1
5681 && ((extent_beg_unchanged < ddl->bufpos)
5682 || (extent_end_unchanged > ddl->end_bufpos)))
5683 return regenerate_window_extents_only_changed(w,
5686 extent_beg_unchanged,
5687 extent_end_unchanged);
5697 /* Given a window and a point, update the given display lines such
5698 that point is displayed in the middle of the window.
5699 Return the window's new start position. */
5702 regenerate_window_point_center(struct window *w, Bufpos point, int type)
5706 /* We need to make sure that the modeline is generated so that the
5707 window height can be calculated correctly. */
5708 ensure_modeline_generated(w, type);
5710 startp = start_with_line_at_pixpos(w, point, window_half_pixpos(w));
5711 regenerate_window(w, startp, point, type);
5712 Fset_marker(w->start[type], make_int(startp), w->buffer);
5717 /* Given a window and a set of display lines, return a boolean
5718 indicating whether the given point is contained within. */
5720 static int point_visible(struct window *w, Bufpos point, int type)
5722 struct buffer *b = XBUFFER(w->buffer);
5723 display_line_dynarr *dla = window_display_lines(w, type);
5726 if (Dynarr_length(dla) && Dynarr_atp(dla, 0)->modeline)
5731 if (Dynarr_length(dla) > first_line) {
5733 struct display_line *dl = Dynarr_atp(dla, first_line);
5736 end = BUF_Z(b) - w->window_end_pos[type] - 1;
5738 if (point >= start && point <= end) {
5739 if (!MINI_WINDOW_P(w) && scroll_on_clipped_lines) {
5740 dl = Dynarr_atp(dla, Dynarr_length(dla) - 1);
5742 if (point >= (dl->bufpos + dl->offset)
5743 && point <= (dl->end_bufpos + dl->offset))
5755 /* Return pixel position the middle of the window, not including the
5756 modeline and any potential horizontal scrollbar. */
5758 int window_half_pixpos(struct window *w)
5760 return WINDOW_TEXT_TOP(w) + (WINDOW_TEXT_HEIGHT(w) >> 1);
5763 /* Return the display line which is currently in the middle of the
5764 window W for display lines TYPE. */
5766 int line_at_center(struct window *w, int type, Bufpos start, Bufpos point)
5768 display_line_dynarr *dla;
5771 int first_elt = (MINI_WINDOW_P(w) ? 0 : 1);
5773 if (type == CMOTION_DISP)
5774 regenerate_window(w, start, point, type);
5776 dla = window_display_lines(w, type);
5777 half = window_half_pixpos(w);
5779 for (elt = first_elt; elt < Dynarr_length(dla); elt++) {
5780 struct display_line *dl = Dynarr_atp(dla, elt);
5781 int line_bot = dl->ypos + dl->descent;
5783 if (line_bot > half)
5787 /* We may not have a line at the middle if the end of the buffer is
5792 /* Return a value for point that would place it at the beginning of
5793 the line which is in the middle of the window. */
5795 Bufpos point_at_center(struct window * w, int type, Bufpos start, Bufpos point)
5797 /* line_at_center will regenerate the display structures, if necessary. */
5798 int line = line_at_center(w, type, start, point);
5801 return BUF_ZV(XBUFFER(w->buffer));
5803 display_line_dynarr *dla = window_display_lines(w, type);
5804 struct display_line *dl = Dynarr_atp(dla, line);
5810 /* For a given window, ensure that the current visual representation
5813 static void redisplay_window(Lisp_Object window, int skip_selected)
5815 struct window *w = XWINDOW(window);
5816 struct frame *f = XFRAME(w->frame);
5817 struct device *d = XDEVICE(f->device);
5818 Lisp_Object old_buffer = w->buffer;
5819 Lisp_Object the_buffer = w->buffer;
5821 int echo_active = 0;
5826 int selected_in_its_frame;
5827 int selected_globally;
5828 int skip_output = 0;
5829 int truncation_changed;
5830 int inactive_minibuffer =
5831 (MINI_WINDOW_P(w) &&
5832 (f != device_selected_frame(d)) &&
5833 !is_surrogate_for_selected_frame(f));
5835 /* #### In the new world this function actually does a bunch of
5836 optimizations such as buffer-based scrolling, but none of that is
5839 /* If this is a combination window, do its children; that's all.
5840 The selected window is always a leaf so we don't check for
5841 skip_selected here. */
5842 if (!NILP(w->vchild)) {
5843 redisplay_windows(w->vchild, skip_selected);
5846 if (!NILP(w->hchild)) {
5847 redisplay_windows(w->hchild, skip_selected);
5851 /* Is this window the selected window on its frame? */
5852 selected_in_its_frame = (w == XWINDOW(FRAME_SELECTED_WINDOW(f)));
5854 selected_in_its_frame &&
5855 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5856 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d
5857 && XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5858 if (skip_selected && selected_in_its_frame)
5861 /* It is possible that the window is not fully initialized yet. */
5862 if (NILP(w->buffer))
5865 if (MINI_WINDOW_P(w) && echo_area_active(f)) {
5866 w->buffer = the_buffer = Vecho_area_buffer;
5870 b = XBUFFER(w->buffer);
5873 old_pointm = selected_globally ? BUF_PT(b)
5874 : marker_position(w->pointm[CURRENT_DISP]);
5877 if (selected_globally) {
5880 pointm = marker_position(w->pointm[CURRENT_DISP]);
5882 if (pointm < BUF_BEGV(b))
5883 pointm = BUF_BEGV(b);
5884 else if (pointm > BUF_ZV(b))
5888 Fset_marker(w->pointm[DESIRED_DISP], make_int(pointm), the_buffer);
5890 /* If the buffer has changed we have to invalidate all of our face
5892 if ((!echo_active && b != window_display_buffer(w))
5893 || !Dynarr_length(w->face_cachels)
5894 || f->faces_changed)
5895 reset_face_cachels(w);
5897 mark_face_cachels_as_not_updated(w);
5899 /* Ditto the glyph cache elements, although we do *not* invalidate
5900 the cache purely because glyphs have changed - this is now
5901 handled by the dirty flag. */
5902 if ((!echo_active && b != window_display_buffer(w))
5903 || !Dynarr_length(w->glyph_cachels) || f->faces_changed)
5904 reset_glyph_cachels(w);
5906 mark_glyph_cachels_as_not_updated(w);
5908 /* If the marker's buffer is not the window's buffer, then we need
5909 to find a new starting position. */
5910 if (!MINI_WINDOW_P(w)
5911 && !EQ(Fmarker_buffer(w->start[CURRENT_DISP]), w->buffer)) {
5913 regenerate_window_point_center(w, pointm, DESIRED_DISP);
5915 goto regeneration_done;
5919 old_startp = marker_position(w->start[CURRENT_DISP]);
5922 startp = marker_position(w->start[CURRENT_DISP]);
5923 if (startp < BUF_BEGV(b))
5924 startp = BUF_BEGV(b);
5925 else if (startp > BUF_ZV(b))
5928 Fset_marker(w->start[DESIRED_DISP], make_int(startp), the_buffer);
5930 truncation_changed = (find_window_mirror(w)->truncate_win !=
5931 window_truncation_on(w));
5933 /* If w->force_start is set, then some function set w->start and we
5934 should display from there and change point, if necessary, to
5935 ensure that it is visible. */
5936 if (w->force_start || inactive_minibuffer) {
5938 w->last_modified[DESIRED_DISP] = Qzero;
5939 w->last_facechange[DESIRED_DISP] = Qzero;
5941 regenerate_window(w, startp, pointm, DESIRED_DISP);
5943 if (!point_visible(w, pointm, DESIRED_DISP)
5944 && !inactive_minibuffer) {
5945 pointm = point_at_center(w, DESIRED_DISP, 0, 0);
5947 if (selected_globally)
5948 BUF_SET_PT(b, pointm);
5950 Fset_marker(w->pointm[DESIRED_DISP], make_int(pointm),
5953 /* #### BUFU amounts of overkill just to get the cursor
5954 location marked properly. FIX ME FIX ME FIX ME */
5955 regenerate_window(w, startp, pointm, DESIRED_DISP);
5958 goto regeneration_done;
5961 /* If nothing has changed since the last redisplay, then we just
5962 need to make sure that point is still visible. */
5963 if (XINT(w->last_modified[CURRENT_DISP]) >= BUF_MODIFF(b)
5964 && XINT(w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE(b)
5966 /* This check is to make sure we restore the minibuffer after a
5967 temporary change to the echo area. */
5968 && !(MINI_WINDOW_P(w) && f->buffers_changed)
5969 && !f->frame_changed && !truncation_changed
5970 /* check whether start is really at the beginning of a line GE */
5971 && (!w->start_at_line_beg || beginning_of_line_p(b, startp))
5973 /* Check if the cursor has actually moved. */
5974 if (EQ(Fmarker_buffer(w->last_point[CURRENT_DISP]), w->buffer)
5975 && pointm == marker_position(w->last_point[CURRENT_DISP])
5976 && selected_globally
5977 && !w->windows_changed
5979 && !f->extents_changed
5980 && !f->faces_changed
5981 && !f->glyphs_changed && !f->subwindows_changed
5982 /* && !f->subwindows_state_changed */
5983 && !f->point_changed && !f->windows_structure_changed) {
5984 /* If not, we're done. */
5985 if (f->modeline_changed)
5986 regenerate_modeline(w);
5989 goto regeneration_done;
5991 /* If the new point is visible in the redisplay structures,
5992 then let the output update routines handle it, otherwise
5993 do things the hard way. */
5994 if (!w->windows_changed
5996 && !f->extents_changed
5997 && !f->faces_changed
5998 && !f->glyphs_changed && !f->subwindows_changed
5999 /* && !f->subwindows_state_changed */
6000 && !f->windows_structure_changed) {
6001 if (point_visible(w, pointm, CURRENT_DISP)
6002 && w->last_point_x[CURRENT_DISP] != -1
6003 && w->last_point_y[CURRENT_DISP] != -1) {
6004 if (redisplay_move_cursor
6005 (w, pointm, FRAME_TTY_P(f))) {
6006 /* Always regenerate in case it is displaying
6007 the current line or column. */
6008 regenerate_modeline(w);
6011 goto regeneration_done;
6013 } else if (!selected_in_its_frame
6014 && !f->point_changed) {
6015 if (f->modeline_changed)
6016 regenerate_modeline(w);
6019 goto regeneration_done;
6023 /* If we weren't able to take the shortcut method, then use
6024 the brute force method. */
6025 regenerate_window(w, startp, pointm, DESIRED_DISP);
6027 if (point_visible(w, pointm, DESIRED_DISP))
6028 goto regeneration_done;
6032 /* Check if the starting point is no longer at the beginning of a
6033 line, in which case find a new starting point. We also recenter
6034 if our start position is equal to point-max. Otherwise we'll end
6035 up with a blank window. */
6036 else if (((w->start_at_line_beg || MINI_WINDOW_P(w))
6037 && !(startp == BUF_BEGV(b)
6038 || BUF_FETCH_CHAR(b, startp - 1) == '\n'))
6039 || (pointm == startp &&
6040 EQ(Fmarker_buffer(w->last_start[CURRENT_DISP]), w->buffer)
6041 && startp < marker_position(w->last_start[CURRENT_DISP]))
6042 || (startp == BUF_ZV(b))) {
6044 regenerate_window_point_center(w, pointm, DESIRED_DISP);
6046 goto regeneration_done;
6048 /* See if we can update the data structures locally based on
6049 knowledge of what changed in the buffer. */
6050 else if (!w->windows_changed
6052 && !f->faces_changed
6053 && !f->glyphs_changed && !f->subwindows_changed
6054 /* && !f->subwindows_state_changed */
6055 && !f->windows_structure_changed
6056 && !f->frame_changed
6057 && !truncation_changed
6059 && regenerate_window_incrementally(w, startp, pointm)) {
6060 if (f->modeline_changed
6061 || XINT(w->last_modified[CURRENT_DISP]) < BUF_MODIFF(b)
6062 || XINT(w->last_facechange[CURRENT_DISP]) <
6064 regenerate_modeline(w);
6067 goto regeneration_done;
6069 /* #### This is where a check for structure based scrolling would go. */
6070 /* If all else fails, try just regenerating and see what happens. */
6072 regenerate_window(w, startp, pointm, DESIRED_DISP);
6074 if (point_visible(w, pointm, DESIRED_DISP))
6075 goto regeneration_done;
6078 /* We still haven't gotten the window regenerated with point
6079 visible. Next we try scrolling a little and see if point comes
6080 back onto the screen. */
6081 if (scroll_step > 0) {
6082 int scrolled = scroll_conservatively;
6083 for (; scrolled >= 0; scrolled -= scroll_step) {
6084 startp = vmotion(w, startp,
6086 startp) ? -scroll_step : scroll_step,
6088 regenerate_window(w, startp, pointm, DESIRED_DISP);
6090 if (point_visible(w, pointm, DESIRED_DISP))
6091 goto regeneration_done;
6095 /* We still haven't managed to get the screen drawn with point on
6096 the screen, so just center it and be done with it. */
6097 startp = regenerate_window_point_center(w, pointm, DESIRED_DISP);
6101 /* If the window's frame is changed then reset the current display
6102 lines in order to force a full repaint. */
6103 if (f->frame_changed) {
6104 display_line_dynarr *cla =
6105 window_display_lines(w, CURRENT_DISP);
6110 /* Must do this before calling redisplay_output_window because it
6111 sets some markers on the window. */
6113 w->buffer = old_buffer;
6114 Fset_marker(w->pointm[DESIRED_DISP], make_int(old_pointm),
6116 Fset_marker(w->start[DESIRED_DISP], make_int(old_startp),
6120 /* These also have to be set before calling redisplay_output_window
6121 since it sets the CURRENT_DISP values based on them. */
6122 w->last_modified[DESIRED_DISP] = make_int(BUF_MODIFF(b));
6123 w->last_facechange[DESIRED_DISP] = make_int(BUF_FACECHANGE(b));
6124 Fset_marker(w->last_start[DESIRED_DISP], make_int(startp), w->buffer);
6125 Fset_marker(w->last_point[DESIRED_DISP], make_int(pointm), w->buffer);
6128 Bufpos start = marker_position(w->start[DESIRED_DISP]);
6129 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1 ? BUF_ZV(b)
6130 : BUF_Z(b) - w->window_end_pos[DESIRED_DISP] - 1);
6131 /* Don't pollute the cache if not sure if we are correct */
6132 if (w->start_at_line_beg)
6133 update_line_start_cache(w, start, end, pointm, 1);
6134 redisplay_output_window(w);
6136 * If we just displayed the echo area, the line start cache is
6137 * no longer valid, because the minibuffer window is associated
6138 * with the window now.
6141 w->line_cache_last_updated = make_int(-1);
6144 /* #### This should be dependent on face changes and will need to be
6145 somewhere else once tty updates occur on a per-frame basis. */
6146 mark_face_cachels_as_clean(w);
6148 /* The glyph cachels only get dirty if someone changed something.
6149 Since redisplay has now effectively ended we can reset the dirty
6150 flag since everything must be up-to-date. */
6152 mark_glyph_cachels_as_clean(w);
6154 w->windows_changed = 0;
6157 /* Call buffer_reset_changes for all buffers present in any window
6158 currently visible in all frames on all devices. #### There has to
6159 be a better way to do this. */
6161 static int reset_buffer_changes_mapfun(struct window *w, void *ignored_closure)
6163 buffer_reset_changes(XBUFFER(w->buffer));
6167 static void reset_buffer_changes(void)
6169 Lisp_Object frmcons, devcons, concons;
6171 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
6172 struct frame *f = XFRAME(XCAR(frmcons));
6174 if (FRAME_REPAINT_P(f))
6175 map_windows(f, reset_buffer_changes_mapfun, 0);
6179 /* Ensure that all windows underneath the given window in the window
6180 hierarchy are correctly displayed. */
6182 static void redisplay_windows(Lisp_Object window, int skip_selected)
6184 for (; !NILP(window); window = XWINDOW(window)->next) {
6185 redisplay_window(window, skip_selected);
6189 static int call_redisplay_end_triggers(struct window *w, void *closure)
6191 Bufpos lrpos = w->last_redisplay_pos;
6192 w->last_redisplay_pos = 0;
6193 if (!NILP(w->buffer)
6194 && !NILP(w->redisplay_end_trigger)
6198 if (MARKERP(w->redisplay_end_trigger)
6199 && XMARKER(w->redisplay_end_trigger)->buffer != 0)
6200 pos = marker_position(w->redisplay_end_trigger);
6201 else if (INTP(w->redisplay_end_trigger))
6202 pos = XINT(w->redisplay_end_trigger);
6204 w->redisplay_end_trigger = Qnil;
6210 XSETWINDOW(window, w);
6211 va_run_hook_with_args_in_buffer(XBUFFER(w->buffer),
6212 Qredisplay_end_trigger_functions,
6215 redisplay_end_trigger);
6216 w->redisplay_end_trigger = Qnil;
6223 /* Ensure that all windows on the given frame are correctly displayed. */
6225 int redisplay_frame(struct frame *f, int preemption_check)
6227 struct device *d = XDEVICE(f->device);
6229 if (preemption_check
6230 && !DEVICE_IMPL_FLAG(d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) {
6231 /* The preemption check itself takes a lot of time,
6232 so normally don't do it here. We do it if called
6233 from Lisp, though (`redisplay-frame'). */
6236 REDISPLAY_PREEMPTION_CHECK;
6241 if (!internal_equal(f->old_buffer_alist, f->buffer_alist, 0)) {
6244 f->old_buffer_alist = Freplace_list(f->old_buffer_alist,
6246 XSETFRAME(frame, f);
6247 va_run_hook_with_args(Qbuffer_list_changed_hook, 1, frame);
6250 /* Before we put a hold on frame size changes, attempt to process
6251 any which are already pending. */
6252 if (f->size_change_pending)
6253 change_frame_size(f, f->new_height, f->new_width, 0);
6255 /* If frame size might need to be changed, due to changed size
6256 of toolbars, scrollbars etc, change it now */
6257 if (f->size_slipped) {
6258 adjust_frame_size(f);
6259 assert(!f->size_slipped);
6262 /* The menubar, toolbar, and icon updates must be done before
6263 hold_frame_size_changes is called and we are officially
6264 'in_display'. They may eval lisp code which may call Fsignal.
6265 If in_display is set Fsignal will abort. */
6267 #ifdef HAVE_MENUBARS
6268 /* Update the menubar. It is done first since it could change
6269 the menubar's visibility. This way we avoid having flashing
6270 caused by an Expose event generated by the visibility change
6272 update_frame_menubars(f);
6273 #endif /* HAVE_MENUBARS */
6274 #ifdef HAVE_TOOLBARS
6275 /* Update the toolbars geometry. We don't update the toolbars
6276 themselves at this point since the space they are trying to
6277 occupy may currently by occupied by gutter elements. Instead we
6278 update the geometry, then update the gutter geometry, then update
6279 the gutters - which will cause mapped windows to be repositioned
6280 - and finally update the toolbars. */
6281 update_frame_toolbars_geometry(f);
6282 #endif /* HAVE_TOOLBARS */
6283 /* Gutter update proper has to be done inside display when no frame
6284 size changes can occur, thus we separately update the gutter
6285 geometry here if it needs it. */
6286 update_frame_gutter_geometry(f);
6288 /* If we clear the frame we have to force its contents to be redrawn. */
6290 f->frame_changed = 1;
6292 /* Invalidate the subwindow caches. We use subwindows_changed here
6293 to cause subwindows to get instantiated. This is because
6294 subwindows_state_changed is less strict - dealing with things
6295 like the clicked state of button. We have to do this before
6296 redisplaying the gutters as subwindows get unmapped in the
6298 if (f->frame_changed)
6299 reset_frame_subwindow_instance_cache(f);
6301 if (f->frame_changed || f->subwindows_changed) {
6302 /* we have to do this so the gutter gets regenerated. */
6303 reset_gutter_display_lines(f);
6306 hold_frame_size_changes();
6308 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6309 /* Within this section, we are defenseless and assume that the
6310 following cannot happen:
6312 1) garbage collection
6313 2) Lisp code evaluation
6314 3) frame size changes
6316 We ensure (3) by calling hold_frame_size_changes(), which
6317 will cause any pending frame size changes to get put on hold
6318 till after the end of the critical section. (1) follows
6319 automatically if (2) is met. #### Unfortunately, there are
6320 some places where Lisp code can be called within this section.
6321 We need to remove them.
6323 If Fsignal() is called during this critical section, we
6326 If garbage collection is called during this critical section,
6327 we simply return. #### We should abort instead.
6329 #### If a frame-size change does occur we should probably
6330 actually be preempting redisplay. */
6332 MAYBE_DEVMETH(d, frame_output_begin, (f));
6334 /* Erase the frame before outputting its contents. */
6336 MAYBE_DEVMETH(d, clear_frame, (f));
6339 /* We can now update the gutters, safe in the knowledge that our
6340 efforts won't get undone. */
6342 /* This can call lisp, but redisplay is protected by binding
6343 inhibit_quit. More importantly the code involving display lines
6344 *assumes* that GC will not happen and so does not GCPRO
6345 anything. Since we use this code the whole time with the gutters
6346 we cannot allow GC to happen when manipulating the gutters. */
6347 update_frame_gutters(f);
6349 /* Do the selected window first. */
6350 redisplay_window(FRAME_SELECTED_WINDOW(f), 0);
6352 /* Then do the rest. */
6353 redisplay_windows(f->root_window, 1);
6355 MAYBE_DEVMETH(d, frame_output_end, (f));
6357 update_frame_title(f);
6359 #ifdef HAVE_TOOLBARS
6360 /* Finally update the toolbars. It seems its possible to get in a
6361 cycle between updating the gutter and the toolbars. Basically we
6362 want to end up with both being up-to-date and this doesn't seem
6363 possible in a single pass. */
6364 update_frame_toolbars(f);
6365 #endif /* HAVE_TOOLBARS */
6367 CLASS_RESET_CHANGED_FLAGS(f);
6368 f->window_face_cache_reset = 0;
6369 f->echo_area_garbaged = 0;
6372 if (!f->size_change_pending)
6373 f->size_changed = 0;
6375 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6377 /* Allow frame size changes to occur again.
6379 #### what happens if changes to other frames happen? */
6380 unhold_one_frame_size_changes(f);
6382 map_windows(f, call_redisplay_end_triggers, 0);
6386 /* Ensure that all frames on the given device are correctly displayed.
6387 If AUTOMATIC is non-zero, and the device implementation indicates
6388 no automatic redisplay, as printers do, then the device is not
6389 redisplayed. AUTOMATIC is set to zero when called from lisp
6390 functions (redraw-device) and (redisplay-device), and to non-zero
6391 when called from "lazy" redisplay();
6394 static int redisplay_device(struct device *d, int automatic)
6396 Lisp_Object frame, frmcons;
6397 int size_change_failed = 0;
6400 if (automatic && DEVICE_IMPL_FLAG(d, XDEVIMPF_NO_AUTO_REDISPLAY))
6403 if (DEVICE_STREAM_P(d)) /* nothing to do */
6406 /* It is possible that redisplay has been called before the
6407 device is fully initialized, or that the console implementation
6408 allows frameless devices. If so then continue with the next
6410 if (NILP(DEVICE_SELECTED_FRAME(d)))
6413 if (!DEVICE_IMPL_FLAG(d, XDEVIMPF_DONT_PREEMPT_REDISPLAY)) {
6415 REDISPLAY_PREEMPTION_CHECK;
6420 /* Always do the selected frame first. */
6421 frame = DEVICE_SELECTED_FRAME(d);
6425 if (f->icon_changed || f->windows_changed)
6426 update_frame_icon(f);
6428 if (FRAME_REPAINT_P(f)) {
6429 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) {
6430 int preempted = redisplay_frame(f, 0);
6435 /* If the frame redisplay did not get preempted, then this flag
6436 should have gotten set to 0. It might be possible for that
6437 not to happen if a size change event were to occur at an odd
6438 time. To make sure we don't miss anything we simply don't
6439 reset the top level flags until the condition ends up being
6440 in the right state. */
6441 if (f->size_changed)
6442 size_change_failed = 1;
6445 DEVICE_FRAME_LOOP(frmcons, d) {
6446 f = XFRAME(XCAR(frmcons));
6448 if (f == XFRAME(DEVICE_SELECTED_FRAME(d)))
6451 if (f->icon_changed || f->windows_changed)
6452 update_frame_icon(f);
6454 if (FRAME_REPAINT_P(f)) {
6455 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) {
6456 int preempted = redisplay_frame(f, 0);
6461 if (f->size_change_pending)
6462 size_change_failed = 1;
6466 /* If we get here then we redisplayed all of our frames without
6467 getting preempted so mark ourselves as clean. */
6468 CLASS_RESET_CHANGED_FLAGS(d);
6470 if (!size_change_failed)
6471 d->size_changed = 0;
6476 static Lisp_Object restore_profiling_redisplay_flag(Lisp_Object val)
6478 profiling_redisplay_flag = XINT(val);
6482 /* Ensure that all windows on all frames on all devices are displaying
6483 the current contents of their respective buffers. */
6485 static void redisplay_without_hooks(void)
6487 Lisp_Object devcons, concons;
6488 int size_change_failed = 0;
6489 int count = specpdl_depth();
6491 if (profiling_active) {
6492 record_unwind_protect(restore_profiling_redisplay_flag,
6493 make_int(profiling_redisplay_flag));
6494 profiling_redisplay_flag = 1;
6497 if (asynch_device_change_pending)
6498 handle_asynch_device_change();
6500 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6501 !disable_preemption && preemption_count < max_preempts)
6504 DEVICE_LOOP_NO_BREAK(devcons, concons) {
6505 struct device *d = XDEVICE(XCAR(devcons));
6508 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(d)) {
6509 preempted = redisplay_device(d, 1);
6513 RESET_CHANGED_SET_FLAGS;
6517 /* See comment in redisplay_device. */
6518 if (d->size_changed)
6519 size_change_failed = 1;
6522 preemption_count = 0;
6524 /* Mark redisplay as accurate */
6525 GLOBAL_RESET_CHANGED_FLAGS;
6526 RESET_CHANGED_SET_FLAGS;
6528 if (faces_changed) {
6529 mark_all_faces_as_clean();
6533 if (!size_change_failed)
6536 reset_buffer_changes();
6539 unbind_to(count, Qnil);
6542 void redisplay(void)
6544 if (last_display_warning_tick != display_warning_tick &&
6545 !inhibit_warning_display) {
6546 /* If an error occurs during this function, oh well.
6547 If we report another warning, we could get stuck in an
6548 infinite loop reporting warnings. */
6549 call0_trapping_errors(0, Qdisplay_warning_buffer);
6550 last_display_warning_tick = display_warning_tick;
6552 /* The run_hook_trapping_errors functions are smart enough not
6553 to do any evalling if the hook function is empty, so there
6554 should not be any significant time loss. All places in the
6555 C code that call redisplay() are prepared to handle GCing,
6556 so we should be OK. */
6557 #ifndef INHIBIT_REDISPLAY_HOOKS
6558 run_hook_trapping_errors("Error in pre-redisplay-hook",
6559 Qpre_redisplay_hook);
6560 #endif /* INHIBIT_REDISPLAY_HOOKS */
6562 redisplay_without_hooks();
6564 #ifndef INHIBIT_REDISPLAY_HOOKS
6565 run_hook_trapping_errors("Error in post-redisplay-hook",
6566 Qpost_redisplay_hook);
6567 #endif /* INHIBIT_REDISPLAY_HOOKS */
6570 static char window_line_number_buf[32];
6572 /* Efficiently determine the window line number, and return a pointer
6573 to its printed representation. Do this regardless of whether
6574 line-number-mode is on. The first line in the buffer is counted as
6575 1. If narrowing is in effect, the lines are counted from the
6576 beginning of the visible portion of the buffer. */
6577 static char *window_line_number(struct window *w, int type)
6579 struct device *d = XDEVICE(XFRAME(w->frame)->device);
6580 struct buffer *b = XBUFFER(w->buffer);
6581 /* Be careful in the order of these tests. The first clause will
6582 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6583 This can occur when the frame title is computed really early */
6585 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6586 (w == XWINDOW(FRAME_SELECTED_WINDOW(device_selected_frame(d)))) &&
6587 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6588 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) ==
6591 : marker_position(w->pointm[type]));
6594 line = buffer_line_number(b, pos, 1);
6596 long_to_string(window_line_number_buf, line + 1, sizeof(window_line_number_buf));
6598 return window_line_number_buf;
6601 /* Given a character representing an object in a modeline
6602 specification, return a string (stored into the global array
6603 `mode_spec_bufbyte_string') with the information that object
6606 This function is largely unchanged from previous versions of the
6609 Warning! This code is also used for frame titles and can be called
6610 very early in the device/frame update process! JV
6613 static void decode_mode_spec(struct window *w, Emchar spec, int type)
6615 Lisp_Object obj = Qnil;
6616 const char *str = NULL;
6617 struct buffer *b = XBUFFER(w->buffer);
6619 Dynarr_reset(mode_spec_bufbyte_string);
6622 /* print buffer name */
6627 /* print visited file name */
6632 /* print the current column */
6634 Lisp_Object tmp = Fselected_window(Qnil);
6635 Bufpos pt = (w == XWINDOW(tmp))
6637 : marker_position(w->pointm[type]);
6639 column_at_point(b, pt,
6640 1) + !!column_number_start_at_one;
6641 char buf[sizeof(long)*3+1];
6643 long_to_string(buf, col, sizeof(buf));
6645 Dynarr_add_many(mode_spec_bufbyte_string,
6646 (const Bufbyte *)buf, strlen(buf));
6648 goto decode_mode_spec_done;
6650 /* print the file coding system */
6653 Lisp_Object codesys = b->buffer_file_coding_system;
6654 /* Be very careful here not to get an error. */
6655 if (NILP(codesys) || SYMBOLP(codesys)
6656 || CODING_SYSTEMP(codesys)) {
6657 codesys = Ffind_coding_system(codesys);
6658 if (CODING_SYSTEMP(codesys))
6659 obj = XCODING_SYSTEM_MNEMONIC(codesys);
6661 #endif /* FILE_CODING */
6665 /* print the current line number */
6667 str = window_line_number(w, type);
6670 /* print value of mode-name (obsolete) */
6675 /* print hyphen and frame number, if != 1 */
6678 struct frame *f = XFRAME(w->frame);
6679 if (FRAME_TTY_P(f) && f->order_count > 1
6680 && f->order_count <= 99999999) {
6681 /* Naughty, naughty */
6682 const size_t order_strmax = sizeof(f->order_count)*3+2;
6683 char *writable_str = alloca_array(char, order_strmax);
6684 int n = snprintf(writable_str, order_strmax, "-%d", f->order_count);
6685 assert(n>=0 && (size_t)n < order_strmax);
6688 #endif /* HAVE_TTY */
6692 /* print Narrow if appropriate */
6694 if (BUF_BEGV(b) > BUF_BEG(b)
6695 || BUF_ZV(b) < BUF_Z(b))
6699 /* print %, * or hyphen, if buffer is read-only, modified or
6702 str = (!NILP(b->read_only)
6703 ? "%" : ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6707 /* print * or hyphen -- XEmacs change to allow a buffer to be
6708 read-only but still indicate whether it is modified. */
6710 str = ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6711 ? "*" : (!NILP(b->read_only)
6715 /* #### defined in 19.29 decode_mode_spec, but not in
6716 modeline-format doc string. */
6717 /* This differs from %* in that it ignores read-only-ness. */
6719 str = ((BUF_MODIFF(b) > BUF_SAVE_MODIFF(b))
6723 /* print process status */
6725 obj = Fget_buffer_process(w->buffer);
6727 str = GETTEXT("no process");
6729 obj = Fsymbol_name(Fprocess_status(obj));
6732 /* Print name of selected frame. */
6734 obj = XFRAME(w->frame)->name;
6737 /* indicate TEXT or BINARY */
6739 /* #### NT does not use this any more. Now what? */
6743 /* print percent of buffer above top of window, or Top, Bot or
6746 Bufpos pos = marker_position(w->start[type]);
6748 /* This had better be while the desired lines are being done. */
6749 if (w->window_end_pos[type] <= BUF_Z(b) - BUF_ZV(b)) {
6750 if (pos <= BUF_BEGV(b))
6754 } else if (pos <= BUF_BEGV(b)) {
6757 /* This hard limit is ok since the string it will hold
6758 has a fixed maximum length of 3. But just to be
6760 char buf[sizeof(long)*3+4];
6762 Charcount chars = pos - BUF_BEGV(b);
6763 Charcount total = BUF_ZV(b) - BUF_BEGV(b);
6765 /* Avoid overflow on big buffers */
6766 int percent = total > LONG_MAX / 200 ?
6767 (chars + total / 200) / (total / 100) :
6768 (chars * 100 + total / 2) / total;
6770 /* We can't normally display a 3-digit number, so get us
6771 a 2-digit number that is close. */
6775 n = snprintf(buf, sizeof(buf), "%d%%", percent);
6776 assert(n>=0 && (size_t)n < sizeof(buf));
6777 Dynarr_add_many(mode_spec_bufbyte_string,
6778 (Bufbyte *) buf, strlen(buf));
6780 goto decode_mode_spec_done;
6785 /* print percent of buffer above bottom of window, perhaps plus
6786 Top, or print Bottom or All */
6788 Bufpos toppos = marker_position(w->start[type]);
6789 Bufpos botpos = BUF_Z(b) - w->window_end_pos[type];
6791 /* botpos is only accurate as of the last redisplay, so we can
6792 only treat it as a hint. In particular, after erase-buffer,
6793 botpos may be negative. */
6794 if (botpos < toppos)
6797 if (botpos >= BUF_ZV(b)) {
6798 if (toppos <= BUF_BEGV(b))
6803 /* This hard limit is ok since the string it will hold
6804 has a fixed maximum length of around 6. But just to
6806 char buf[sizeof(long)*3+6];
6808 Charcount chars = botpos - BUF_BEGV(b);
6809 Charcount total = BUF_ZV(b) - BUF_BEGV(b);
6811 /* Avoid overflow on big buffers */
6812 int percent = total > LONG_MAX / 200 ?
6813 (chars + total / 200) / (total / 100) :
6814 (chars * 100 + total / 2) / max(total, 1);
6816 /* We can't normally display a 3-digit number, so get us
6817 a 2-digit number that is close. */
6821 if (toppos <= BUF_BEGV(b))
6822 n = snprintf(buf, sizeof(buf), "Top%d%%", percent);
6824 n = snprintf(buf, sizeof(buf), "%d%%", percent);
6825 assert(n>=0 && (size_t)n < sizeof(buf));
6826 Dynarr_add_many(mode_spec_bufbyte_string,
6827 (Bufbyte *) buf, strlen(buf));
6829 goto decode_mode_spec_done;
6839 /* print one [ for each recursive editing level. */
6843 if (command_loop_level > 5) {
6848 for (i = 0; i < command_loop_level; i++)
6849 Dynarr_add(mode_spec_bufbyte_string, '[');
6851 goto decode_mode_spec_done;
6854 /* print one ] for each recursive editing level. */
6858 if (command_loop_level > 5) {
6863 for (i = 0; i < command_loop_level; i++)
6864 Dynarr_add(mode_spec_bufbyte_string, ']');
6866 goto decode_mode_spec_done;
6869 /* print infinitely many dashes -- handle at top level now */
6878 Dynarr_add_many(mode_spec_bufbyte_string,
6879 XSTRING_DATA(obj), XSTRING_LENGTH(obj));
6881 Dynarr_add_many(mode_spec_bufbyte_string,
6882 (const Bufbyte*)str, strlen(str));
6885 decode_mode_spec_done:
6886 Dynarr_add(mode_spec_bufbyte_string, '\0');
6890 /* Given a display line, free all of its data structures. */
6892 static void free_display_line(struct display_line *dl)
6896 if (dl->display_blocks) {
6897 for (block = 0; block < Dynarr_largest(dl->display_blocks);
6899 struct display_block *db =
6900 Dynarr_atp(dl->display_blocks, block);
6902 Dynarr_free(db->runes);
6905 Dynarr_free(dl->display_blocks);
6906 dl->display_blocks = NULL;
6909 if (dl->left_glyphs) {
6910 Dynarr_free(dl->left_glyphs);
6911 dl->left_glyphs = NULL;
6914 if (dl->right_glyphs) {
6915 Dynarr_free(dl->right_glyphs);
6916 dl->right_glyphs = NULL;
6920 /* Given an array of display lines, free them and all data structures
6921 contained within them. */
6923 void free_display_lines(display_line_dynarr * dla)
6927 for (line = 0; line < Dynarr_largest(dla); line++) {
6928 free_display_line(Dynarr_atp(dla, line));
6934 /* Call internal free routine for each set of display lines. */
6936 void free_display_structs(struct window_mirror *mir)
6938 if (mir->current_display_lines) {
6939 free_display_lines(mir->current_display_lines);
6940 mir->current_display_lines = 0;
6943 if (mir->desired_display_lines) {
6944 free_display_lines(mir->desired_display_lines);
6945 mir->desired_display_lines = 0;
6949 static void mark_glyph_block_dynarr(glyph_block_dynarr * gba)
6952 glyph_block *gb = Dynarr_atp(gba, 0);
6953 glyph_block *gb_last = Dynarr_atp(gba, Dynarr_length(gba));
6955 for (; gb < gb_last; gb++) {
6956 if (!NILP(gb->glyph))
6957 mark_object(gb->glyph);
6958 if (!NILP(gb->extent))
6959 mark_object(gb->extent);
6964 /* See the comment in image_instantiate_cache_result as to why marking
6965 the glyph will also mark the image_instance. */
6966 void mark_redisplay_structs(display_line_dynarr * dla)
6968 display_line *dl = Dynarr_atp(dla, 0);
6969 display_line *dl_last = Dynarr_atp(dla, Dynarr_length(dla));
6971 for (; dl < dl_last; dl++) {
6972 display_block_dynarr *dba = dl->display_blocks;
6973 display_block *db = Dynarr_atp(dba, 0);
6974 display_block *db_last = Dynarr_atp(dba, Dynarr_length(dba));
6976 for (; db < db_last; db++) {
6977 rune_dynarr *ra = db->runes;
6978 rune *r = Dynarr_atp(ra, 0);
6979 rune *r_last = Dynarr_atp(ra, Dynarr_length(ra));
6981 for (; r < r_last; r++) {
6982 if (r->type == RUNE_DGLYPH) {
6983 if (!NILP(r->object.dglyph.glyph))
6984 mark_object(r->object.dglyph.
6986 if (!NILP(r->object.dglyph.extent))
6987 mark_object(r->object.dglyph.
6993 mark_glyph_block_dynarr(dl->left_glyphs);
6994 mark_glyph_block_dynarr(dl->right_glyphs);
6998 static void mark_window_mirror(struct window_mirror *mir)
7000 mark_redisplay_structs(mir->current_display_lines);
7001 mark_redisplay_structs(mir->desired_display_lines);
7004 mark_window_mirror(mir->next);
7007 mark_window_mirror(mir->hchild);
7008 else if (mir->vchild)
7009 mark_window_mirror(mir->vchild);
7012 void mark_redisplay(void)
7014 Lisp_Object frmcons, devcons, concons;
7016 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) {
7017 struct frame *f = XFRAME(XCAR(frmcons));
7018 mark_window_mirror(f->root_mirror);
7023 /*****************************************************************************
7024 Line Start Cache Description and Rationale
7026 The traditional scrolling code in Emacs breaks in a variable height world.
7027 It depends on the key assumption that the number of lines that can be
7028 displayed at any given time is fixed. This led to a complete separation
7029 of the scrolling code from the redisplay code. In order to fully support
7030 variable height lines, the scrolling code must actually be tightly
7031 integrated with redisplay. Only redisplay can determine how many lines
7032 will be displayed on a screen for any given starting point.
7034 What is ideally wanted is a complete list of the starting buffer position
7035 for every possible display line of a buffer along with the height of that
7036 display line. Maintaining such a full list would be very expensive. We
7037 settle for having it include information for all areas which we happen to
7038 generate anyhow (i.e. the region currently being displayed) and for those
7039 areas we need to work with.
7041 In order to ensure that the cache accurately represents what redisplay
7042 would actually show, it is necessary to invalidate it in many situations.
7043 If the buffer changes, the starting positions may no longer be correct.
7044 If a face or an extent has changed then the line heights may have altered.
7045 These events happen frequently enough that the cache can end up being
7046 constantly disabled. With this potentially constant invalidation when is
7047 the cache ever useful?
7049 Even if the cache is invalidated before every single usage, it is
7050 necessary. Scrolling often requires knowledge about display lines which
7051 are actually above or below the visible region. The cache provides a
7052 convenient light-weight method of storing this information for multiple
7053 display regions. This knowledge is necessary for the scrolling code to
7054 always obey the First Golden Rule of Redisplay.
7056 If the cache already contains all of the information that the scrolling
7057 routines happen to need so that it doesn't have to go generate it, then we
7058 are able to obey the Third Golden Rule of Redisplay. The first thing we
7059 do to help out the cache is to always add the displayed region. This
7060 region had to be generated anyway, so the cache ends up getting the
7061 information basically for free. In those cases where a user is simply
7062 scrolling around viewing a buffer there is a high probability that this is
7063 sufficient to always provide the needed information. The second thing we
7064 can do is be smart about invalidating the cache.
7066 TODO -- Be smart about invalidating the cache. Potential places:
7068 + Insertions at end-of-line which don't cause line-wraps do not alter the
7069 starting positions of any display lines. These types of buffer
7070 modifications should not invalidate the cache. This is actually a large
7071 optimization for redisplay speed as well.
7073 + Buffer modifications frequently only affect the display of lines at and
7074 below where they occur. In these situations we should only invalidate
7075 the part of the cache starting at where the modification occurs.
7077 In case you're wondering, the Second Golden Rule of Redisplay is not
7079 ****************************************************************************/
7081 /* This will get used quite a bit so we don't want to be constantly
7082 allocating and freeing it. */
7083 static line_start_cache_dynarr *internal_cache;
7085 /* Makes internal_cache represent the TYPE display structs and only
7086 the TYPE display structs. */
7088 static void update_internal_cache_list(struct window *w, int type)
7091 display_line_dynarr *dla = window_display_lines(w, type);
7093 Dynarr_reset(internal_cache);
7094 for (line = 0; line < Dynarr_length(dla); line++) {
7095 struct display_line *dl = Dynarr_atp(dla, line);
7100 struct line_start_cache lsc;
7102 lsc.start = dl->bufpos;
7103 lsc.end = dl->end_bufpos;
7104 lsc.height = dl->ascent + dl->descent;
7106 Dynarr_add(internal_cache, lsc);
7111 /* Reset the line cache if necessary. This should be run at the
7112 beginning of any function which access the cache. */
7114 static void validate_line_start_cache(struct window *w)
7116 struct buffer *b = XBUFFER(w->buffer);
7117 struct frame *f = XFRAME(w->frame);
7119 if (!w->line_cache_validation_override) {
7120 /* f->extents_changed used to be in here because extent face and
7121 size changes can cause text shifting. However, the extent
7122 covering the region is constantly having its face set and
7123 priority altered by the mouse code. This means that the line
7124 start cache is constantly being invalidated. This is bad
7125 since the mouse code also triggers heavy usage of the cache.
7126 Since it is an unlikely that f->extents being changed
7127 indicates that the cache really needs to be updated and if it
7128 does redisplay will catch it pretty quickly we no longer
7129 invalidate the cache if it is set. This greatly speeds up
7130 dragging out regions with the mouse. */
7131 if (XINT(w->line_cache_last_updated) < BUF_MODIFF(b)
7132 || f->faces_changed || f->clip_changed) {
7133 Dynarr_reset(w->line_start_cache);
7138 /* Return the very first buffer position contained in the given
7139 window's cache, or -1 if the cache is empty. Assumes that the
7142 static Bufpos line_start_cache_start(struct window *w)
7144 line_start_cache_dynarr *cache = w->line_start_cache;
7146 if (!Dynarr_length(cache))
7149 return Dynarr_atp(cache, 0)->start;
7152 /* Return the very last buffer position contained in the given
7153 window's cache, or -1 if the cache is empty. Assumes that the
7156 static Bufpos line_start_cache_end(struct window *w)
7158 line_start_cache_dynarr *cache = w->line_start_cache;
7160 if (!Dynarr_length(cache))
7163 return Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7166 /* Return the index of the line POINT is contained within in window
7167 W's line start cache. It will enlarge the cache or move the cache
7168 window in order to have POINT be present in the cache. MIN_PAST is
7169 a guarantee of the number of entries in the cache present on either
7170 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7171 then it will be treated as 0, but the cache window will not be
7172 allowed to shift. Returns -1 if POINT cannot be found in the cache
7175 int point_in_line_start_cache(struct window *w, Bufpos point, int min_past)
7177 struct buffer *b = XBUFFER(w->buffer);
7178 line_start_cache_dynarr *cache = w->line_start_cache;
7179 unsigned int top, bottom;
7182 validate_line_start_cache(w);
7183 w->line_cache_validation_override++;
7185 /* Let functions pass in negative values, but we still treat -1
7187 /* #### bogosity alert */
7188 if (min_past < 0 && min_past != -1)
7189 min_past = -min_past;
7191 if (!Dynarr_length(cache) || line_start_cache_start(w) > point
7192 || line_start_cache_end(w) < point) {
7194 int win_char_height = window_char_height(w, 1);
7196 /* Occasionally we get here with a 0 height
7197 window. find_next_newline_no_quit will abort if we pass it a
7198 count of 0 so handle that case. */
7199 if (!win_char_height)
7200 win_char_height = 1;
7202 if (!Dynarr_length(cache)) {
7203 Bufpos from = find_next_newline_no_quit(b, point, -1);
7205 find_next_newline_no_quit(b, from, win_char_height);
7207 update_line_start_cache(w, from, to, point, 0);
7209 if (!Dynarr_length(cache)) {
7210 w->line_cache_validation_override--;
7215 assert(Dynarr_length(cache));
7218 while (line_start_cache_start(w) > point
7219 && (loop < cache_adjustment || min_past == -1)) {
7222 from = line_start_cache_start(w);
7223 if (from <= BUF_BEGV(b))
7227 find_next_newline_no_quit(b, from,
7229 to = line_start_cache_end(w);
7231 update_line_start_cache(w, from, to, point, 0);
7235 if (line_start_cache_start(w) > point) {
7238 from = find_next_newline_no_quit(b, point, -1);
7239 if (from >= BUF_ZV(b)) {
7240 to = find_next_newline_no_quit(b, from,
7245 to = find_next_newline_no_quit(b, from,
7248 update_line_start_cache(w, from, to, point, 0);
7252 while (line_start_cache_end(w) < point
7253 && (loop < cache_adjustment || min_past == -1)) {
7256 to = line_start_cache_end(w);
7257 if (to >= BUF_ZV(b))
7260 from = line_start_cache_end(w);
7261 to = find_next_newline_no_quit(b, from,
7264 update_line_start_cache(w, from, to, point, 0);
7268 if (line_start_cache_end(w) < point) {
7271 from = find_next_newline_no_quit(b, point, -1);
7272 if (from >= BUF_ZV(b)) {
7273 to = find_next_newline_no_quit(b, from,
7278 to = find_next_newline_no_quit(b, from,
7281 update_line_start_cache(w, from, to, point, 0);
7285 assert(Dynarr_length(cache));
7290 /* This could happen if the buffer is narrowed. */
7291 if (line_start_cache_start(w) > point
7292 || line_start_cache_end(w) < point) {
7293 w->line_cache_validation_override--;
7299 top = Dynarr_length(cache) - 1;
7306 pos = (bottom + top + 1) >> 1;
7307 start = Dynarr_atp(cache, pos)->start;
7308 end = Dynarr_atp(cache, pos)->end;
7310 if (point >= start && point <= end) {
7312 && line_start_cache_start(w) > BUF_BEGV(b)) {
7314 find_next_newline_no_quit(b,
7315 line_start_cache_start
7318 Bufpos to = line_start_cache_end(w);
7320 update_line_start_cache(w, from, to, point, 0);
7321 goto find_point_loop;
7322 } else if ((Dynarr_length(cache) - pos - 1) < min_past
7323 && line_start_cache_end(w) < BUF_ZV(b)) {
7324 Bufpos from = line_start_cache_end(w);
7325 Bufpos to = find_next_newline_no_quit(b, from,
7331 update_line_start_cache(w, from, to, point, 0);
7332 goto find_point_loop;
7334 w->line_cache_validation_override--;
7337 } else if (point > end)
7339 else if (point < start)
7344 new_pos = (bottom + top + 1) >> 1;
7345 if (pos == new_pos) {
7346 w->line_cache_validation_override--;
7352 /* Return a boolean indicating if POINT would be visible in window W
7353 if display of the window was to begin at STARTP. */
7355 int point_would_be_visible(struct window *w, Bufpos startp, Bufpos point)
7357 struct buffer *b = XBUFFER(w->buffer);
7358 int pixpos = -WINDOW_TEXT_TOP_CLIP(w);
7359 int bottom = WINDOW_TEXT_HEIGHT(w);
7362 /* If point is before the intended start it obviously can't be visible. */
7366 /* If point or start are not in the accessible buffer range, then
7368 if (startp < BUF_BEGV(b) || startp > BUF_ZV(b)
7369 || point < BUF_BEGV(b) || point > BUF_ZV(b))
7372 validate_line_start_cache(w);
7373 w->line_cache_validation_override++;
7375 start_elt = point_in_line_start_cache(w, startp, 0);
7376 if (start_elt == -1) {
7377 w->line_cache_validation_override--;
7381 assert(line_start_cache_start(w) <= startp
7382 && line_start_cache_end(w) >= startp);
7387 /* Expand the cache if necessary. */
7388 if (start_elt == Dynarr_length(w->line_start_cache)) {
7390 Dynarr_atp(w->line_start_cache,
7391 start_elt - 1)->start;
7393 start_elt = point_in_line_start_cache(w, old_startp,
7397 /* We've already actually processed old_startp, so increment
7401 /* If this happens we didn't add any extra elements. Bummer. */
7402 if (start_elt == Dynarr_length(w->line_start_cache)) {
7403 w->line_cache_validation_override--;
7408 height = Dynarr_atp(w->line_start_cache, start_elt)->height;
7410 if (pixpos + height > bottom) {
7411 if (bottom - pixpos < VERTICAL_CLIP(w, 0)) {
7412 w->line_cache_validation_override--;
7418 if (point <= Dynarr_atp(w->line_start_cache, start_elt)->end) {
7419 w->line_cache_validation_override--;
7427 /* For the given window W, if display starts at STARTP, what will be
7428 the buffer position at the beginning or end of the last line
7429 displayed. The end of the last line is also know as the window end
7432 WARNING: It is possible that redisplay failed to layout any lines for the
7433 windows. Under normal circumstances this is rare. However it seems that it
7434 does occur in the following situation: A mouse event has come in and we
7435 need to compute its location in a window. That code (in
7436 pixel_to_glyph_translation) already can handle 0 as an error return value.
7438 #### With a little work this could probably be reworked as just a
7439 call to start_with_line_at_pixpos. */
7442 start_end_of_last_line(struct window *w, Bufpos startp, int end, int may_error)
7444 struct buffer *b = XBUFFER(w->buffer);
7445 line_start_cache_dynarr *cache = w->line_start_cache;
7447 int bottom = WINDOW_TEXT_HEIGHT(w);
7451 validate_line_start_cache(w);
7452 w->line_cache_validation_override++;
7454 if (startp < BUF_BEGV(b))
7455 startp = BUF_BEGV(b);
7456 else if (startp > BUF_ZV(b))
7460 start_elt = point_in_line_start_cache(w, cur_start, 0);
7461 if (start_elt == -1)
7462 return may_error ? 0 : startp;
7465 int height = Dynarr_atp(cache, start_elt)->height;
7467 cur_start = Dynarr_atp(cache, start_elt)->start;
7469 if (pixpos + height > bottom) {
7470 /* Adjust for any possible clip. */
7471 if (bottom - pixpos < VERTICAL_CLIP(w, 0))
7474 if (start_elt < 0) {
7475 w->line_cache_validation_override--;
7481 w->line_cache_validation_override--;
7483 return Dynarr_atp(cache,
7486 return Dynarr_atp(cache,
7493 if (start_elt == Dynarr_length(cache)) {
7494 Bufpos from = line_start_cache_end(w);
7495 int win_char_height = window_char_height(w, 0);
7496 Bufpos to = find_next_newline_no_quit(b, from,
7501 /* We've hit the end of the bottom so that's what it is. */
7502 if (from >= BUF_ZV(b)) {
7503 w->line_cache_validation_override--;
7507 update_line_start_cache(w, from, to, BUF_PT(b), 0);
7509 /* Updating the cache invalidates any current indexes. */
7511 point_in_line_start_cache(w, cur_start, -1) + 1;
7516 /* For the given window W, if display starts at STARTP, what will be
7517 the buffer position at the beginning of the last line displayed. */
7519 Bufpos start_of_last_line(struct window * w, Bufpos startp)
7521 return start_end_of_last_line(w, startp, 0, 0);
7524 /* For the given window W, if display starts at STARTP, what will be
7525 the buffer position at the end of the last line displayed. This is
7526 also know as the window end position. */
7528 Bufpos end_of_last_line(struct window * w, Bufpos startp)
7530 return start_end_of_last_line(w, startp, 1, 0);
7533 static Bufpos end_of_last_line_may_error(struct window *w, Bufpos startp)
7535 return start_end_of_last_line(w, startp, 1, 1);
7538 /* For window W, what does the starting position have to be so that
7539 the line containing POINT will cover pixel position PIXPOS. */
7541 Bufpos start_with_line_at_pixpos(struct window * w, Bufpos point, int pixpos)
7543 struct buffer *b = XBUFFER(w->buffer);
7545 Bufpos cur_pos, prev_pos = point;
7546 int point_line_height;
7547 int pixheight = pixpos - WINDOW_TEXT_TOP(w);
7549 validate_line_start_cache(w);
7550 w->line_cache_validation_override++;
7552 cur_elt = point_in_line_start_cache(w, point, 0);
7553 /* #### See comment in update_line_start_cache about big minibuffers. */
7555 w->line_cache_validation_override--;
7559 point_line_height = Dynarr_atp(w->line_start_cache, cur_elt)->height;
7562 cur_pos = Dynarr_atp(w->line_start_cache, cur_elt)->start;
7564 pixheight -= Dynarr_atp(w->line_start_cache, cur_elt)->height;
7566 /* Do not take into account the value of vertical_clip here.
7567 That is the responsibility of the calling functions. */
7568 if (pixheight < 0) {
7569 w->line_cache_validation_override--;
7570 if (-pixheight > point_line_height)
7571 /* We can't make the target line cover pixpos, so put it
7572 above pixpos. That way it will at least be visible. */
7579 while (cur_elt < 0) {
7581 int win_char_height;
7583 if (cur_pos <= BUF_BEGV(b)) {
7584 w->line_cache_validation_override--;
7588 win_char_height = window_char_height(w, 0);
7589 if (!win_char_height)
7590 win_char_height = 1;
7593 find_next_newline_no_quit(b, cur_pos,
7595 to = line_start_cache_end(w);
7596 update_line_start_cache(w, from, to, point, 0);
7598 cur_elt = point_in_line_start_cache(w, cur_pos, 2) - 1;
7599 assert(cur_elt >= -1);
7600 /* This used to be cur_elt>=0 under the assumption that if
7601 point is in the top line and not at BUF_BEGV, then
7602 setting the window_start to a newline before the start of
7603 the first line will always cause scrolling.
7605 However in my (jv) opinion this is wrong. That new line
7606 can be hidden in various ways: invisible extents, an
7607 explicit window-start not at a newline character etc.
7608 The existence of those are indeed known to create crashes
7609 on that assert. So we have no option but to continue the
7610 search if we found point at the top of the line_start_cache
7612 cur_pos = Dynarr_atp(w->line_start_cache, 0)->start;
7618 /* For window W, what does the starting position have to be so that
7619 the line containing point is on display line LINE. If LINE is
7620 positive it is considered to be the number of lines from the top of
7621 the window (0 is the top line). If it is negative the number is
7622 considered to be the number of lines from the bottom (-1 is the
7626 start_with_point_on_display_line(struct window *w, Bufpos point, int line)
7628 validate_line_start_cache(w);
7629 w->line_cache_validation_override++;
7632 int cur_elt = point_in_line_start_cache(w, point, line);
7634 if (cur_elt - line < 0)
7635 cur_elt = 0; /* Hit the top */
7639 w->line_cache_validation_override--;
7640 return Dynarr_atp(w->line_start_cache, cur_elt)->start;
7642 /* The calculated value of pixpos is correct for the bottom line
7643 or what we want when line is -1. Therefore we subtract one
7644 because we have already handled one line. */
7645 int new_line = -line - 1;
7646 int cur_elt = point_in_line_start_cache(w, point, new_line);
7647 int pixpos = WINDOW_TEXT_BOTTOM(w);
7648 Bufpos retval, search_point;
7650 /* If scroll_on_clipped_lines is false, the last "visible" line of
7651 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7652 If s_o_c_l is true, then we don't want to count a clipped
7653 line, so back up from the bottom by the height of the line
7654 containing point. */
7655 if (scroll_on_clipped_lines)
7657 Dynarr_atp(w->line_start_cache, cur_elt)->height;
7661 if (cur_elt + new_line >= Dynarr_length(w->line_start_cache)) {
7662 /* Hit the bottom of the buffer. */
7664 (cur_elt + new_line) -
7665 Dynarr_length(w->line_start_cache) + 1;
7669 XSETWINDOW(window, w);
7670 default_face_height_and_width(window, &defheight, 0);
7672 cur_elt = Dynarr_length(w->line_start_cache) - 1;
7674 pixpos -= (adjustment * defheight);
7675 if (pixpos < WINDOW_TEXT_TOP(w))
7676 pixpos = WINDOW_TEXT_TOP(w);
7678 cur_elt = cur_elt + new_line;
7680 search_point = Dynarr_atp(w->line_start_cache, cur_elt)->start;
7682 retval = start_with_line_at_pixpos(w, search_point, pixpos);
7683 w->line_cache_validation_override--;
7688 /* This is used to speed up vertical scrolling by caching the known
7689 buffer starting positions for display lines. This allows the
7690 scrolling routines to avoid costly calls to regenerate_window. If
7691 NO_REGEN is true then it will only add the values in the DESIRED
7692 display structs which are in the given range.
7694 Note also that the FROM/TO values are minimums. It is possible
7695 that this function will actually add information outside of the
7696 lines containing those positions. This can't hurt but it could
7699 #### We currently force the cache to have only 1 contiguous region.
7700 It might help to make the cache a dynarr of caches so that we can
7701 cover more areas. This might, however, turn out to be a lot of
7702 overhead for too little gain. */
7705 update_line_start_cache(struct window *w, Bufpos from, Bufpos to,
7706 Bufpos point, int no_regen)
7708 struct buffer *b = XBUFFER(w->buffer);
7709 line_start_cache_dynarr *cache = w->line_start_cache;
7710 Bufpos low_bound, high_bound;
7712 validate_line_start_cache(w);
7713 w->line_cache_validation_override++;
7715 if (from < BUF_BEGV(b))
7721 w->line_cache_validation_override--;
7725 if (Dynarr_length(cache)) {
7726 low_bound = line_start_cache_start(w);
7727 high_bound = line_start_cache_end(w);
7729 /* Check to see if the desired range is already in the cache. */
7730 if (from >= low_bound && to <= high_bound) {
7731 w->line_cache_validation_override--;
7735 /* Check to make sure that the desired range is adjacent to the
7736 current cache. If not, invalidate the cache. */
7737 if (to < low_bound || from > high_bound) {
7738 Dynarr_reset(cache);
7739 low_bound = high_bound = -1;
7742 low_bound = high_bound = -1;
7745 w->line_cache_last_updated = make_int(BUF_MODIFF(b));
7747 /* This could be integrated into the next two sections, but it is easier
7748 to follow what's going on by having it separate. */
7752 update_internal_cache_list(w, DESIRED_DISP);
7753 if (!Dynarr_length(internal_cache)) {
7754 w->line_cache_validation_override--;
7758 start = Dynarr_atp(internal_cache, 0)->start;
7760 Dynarr_atp(internal_cache,
7761 Dynarr_length(internal_cache) - 1)->end;
7763 /* We aren't allowed to generate additional information to fill in
7764 gaps, so if the DESIRED structs don't overlap the cache, reset the
7766 if (Dynarr_length(cache)) {
7767 if (end < low_bound || start > high_bound)
7768 Dynarr_reset(cache);
7770 /* #### What should really happen if what we are doing is
7771 extending a line (the last line)? */
7772 if (Dynarr_length(cache) == 1
7773 && Dynarr_length(internal_cache) == 1)
7774 Dynarr_reset(cache);
7777 if (!Dynarr_length(cache)) {
7778 Dynarr_add_many(cache, Dynarr_atp(internal_cache, 0),
7779 Dynarr_length(internal_cache));
7780 w->line_cache_validation_override--;
7784 /* An extra check just in case the calling function didn't pass in
7785 the bounds of the DESIRED structs in the first place. */
7786 if (start >= low_bound && end <= high_bound) {
7787 w->line_cache_validation_override--;
7791 /* At this point we know that the internal cache partially overlaps
7793 if (start < low_bound) {
7794 int ic_elt = Dynarr_length(internal_cache) - 1;
7795 while (ic_elt >= 0) {
7796 if (Dynarr_atp(internal_cache, ic_elt)->start <
7803 if (!(ic_elt >= 0)) {
7804 Dynarr_reset(cache);
7805 Dynarr_add_many(cache,
7806 Dynarr_atp(internal_cache, 0),
7807 Dynarr_length(internal_cache));
7808 w->line_cache_validation_override--;
7812 Dynarr_insert_many_at_start(cache,
7813 Dynarr_atp(internal_cache,
7817 if (end > high_bound) {
7820 while (ic_elt < Dynarr_length(internal_cache)) {
7821 if (Dynarr_atp(internal_cache, ic_elt)->start >
7828 if (!(ic_elt < Dynarr_length(internal_cache))) {
7829 Dynarr_reset(cache);
7830 Dynarr_add_many(cache,
7831 Dynarr_atp(internal_cache, 0),
7832 Dynarr_length(internal_cache));
7833 w->line_cache_validation_override--;
7837 Dynarr_add_many(cache,
7838 Dynarr_atp(internal_cache, ic_elt),
7839 Dynarr_length(internal_cache) - ic_elt);
7842 w->line_cache_validation_override--;
7846 if (!Dynarr_length(cache) || from < low_bound) {
7847 Bufpos startp = find_next_newline_no_quit(b, from, -1);
7849 int old_lb = low_bound;
7851 while (startp < old_lb || low_bound == -1) {
7855 regenerate_window(w, startp, point, CMOTION_DISP);
7856 update_internal_cache_list(w, CMOTION_DISP);
7858 /* If this assert is triggered then regenerate_window failed
7859 to layout a single line. This is not possible since we
7860 force at least a single line to be layout for CMOTION_DISP */
7861 assert(Dynarr_length(internal_cache));
7862 assert(startp == Dynarr_atp(internal_cache, 0)->start);
7864 ic_elt = Dynarr_length(internal_cache) - 1;
7865 if (low_bound != -1) {
7866 while (ic_elt >= 0) {
7867 if (Dynarr_atp(internal_cache, ic_elt)->
7874 assert(ic_elt >= 0);
7877 Dynarr_atp(internal_cache, ic_elt)->end + 1;
7880 * Handle invisible text properly:
7881 * If the last line we're inserting has the same end as the
7882 * line before which it will be added, merge the two lines.
7884 if (Dynarr_length(cache) &&
7885 Dynarr_atp(internal_cache, ic_elt)->end ==
7886 Dynarr_atp(cache, marker)->end) {
7887 Dynarr_atp(cache, marker)->start
7888 = Dynarr_atp(internal_cache, ic_elt)->start;
7889 Dynarr_atp(cache, marker)->height
7891 Dynarr_atp(internal_cache, ic_elt)->height;
7895 if (ic_elt >= 0) { /* we still have lines to add.. */
7896 Dynarr_insert_many(cache,
7897 Dynarr_atp(internal_cache,
7900 marker += (ic_elt + 1);
7903 if (startp < low_bound || low_bound == -1)
7905 startp = new_startp;
7906 if (startp > BUF_ZV(b)) {
7907 w->line_cache_validation_override--;
7913 assert(Dynarr_length(cache));
7914 assert(from >= low_bound);
7916 /* Readjust the high_bound to account for any changes made while
7917 correcting the low_bound. */
7918 high_bound = Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7920 if (to > high_bound) {
7922 Dynarr_atp(cache, Dynarr_length(cache) - 1)->end + 1;
7925 regenerate_window(w, startp, point, CMOTION_DISP);
7926 update_internal_cache_list(w, CMOTION_DISP);
7928 /* See comment above about regenerate_window failing. */
7929 assert(Dynarr_length(internal_cache));
7931 Dynarr_add_many(cache, Dynarr_atp(internal_cache, 0),
7932 Dynarr_length(internal_cache));
7934 Dynarr_atp(cache, Dynarr_length(cache) - 1)->end;
7935 startp = high_bound + 1;
7937 while (to > high_bound);
7940 w->line_cache_validation_override--;
7941 assert(to <= high_bound);
7944 /* Given x and y coordinates in characters, relative to a window,
7945 return the pixel location corresponding to those coordinates. The
7946 pixel location returned is the center of the given character
7947 position. The pixel values are generated relative to the window,
7950 The modeline is considered to be part of the window. */
7953 glyph_to_pixel_translation(struct window *w, int char_x, int char_y,
7954 int *pix_x, int *pix_y)
7956 display_line_dynarr *dla = window_display_lines(w, CURRENT_DISP);
7957 int num_disp_lines, modeline;
7959 int defheight, defwidth;
7961 XSETWINDOW(window, w);
7962 default_face_height_and_width(window, &defheight, &defwidth);
7964 /* If we get a bogus value indicating somewhere above or to the left of
7965 the window, use the first window line or character position
7972 num_disp_lines = Dynarr_length(dla);
7974 if (num_disp_lines) {
7975 if (Dynarr_atp(dla, 0)->modeline) {
7981 /* First check if the y position intersects the display lines. */
7982 if (char_y < num_disp_lines) {
7983 struct display_line *dl = Dynarr_atp(dla, char_y + modeline);
7984 struct display_block *db =
7985 get_display_block_from_line(dl, TEXT);
7987 *pix_y = (dl->ypos - dl->ascent +
7988 ((unsigned int)(dl->ascent + dl->descent -
7991 if (char_x < Dynarr_length(db->runes)) {
7992 struct rune *rb = Dynarr_atp(db->runes, char_x);
7994 *pix_x = rb->xpos + (rb->width >> 1);
7996 int last_rune = Dynarr_length(db->runes) - 1;
7997 struct rune *rb = Dynarr_atp(db->runes, last_rune);
7999 char_x -= last_rune;
8001 *pix_x = rb->xpos + rb->width;
8002 *pix_x += ((char_x - 1) * defwidth);
8003 *pix_x += (defwidth >> 1);
8006 /* It didn't intersect, so extrapolate. #### For now, we include the
8007 modeline in this since we don't have true character positions in
8010 if (!Dynarr_length(w->face_cachels))
8011 reset_face_cachels(w);
8013 char_y -= num_disp_lines;
8015 if (Dynarr_length(dla)) {
8016 struct display_line *dl =
8017 Dynarr_atp(dla, Dynarr_length(dla) - 1);
8018 *pix_y = dl->ypos + dl->descent - dl->clip;
8020 *pix_y = WINDOW_TEXT_TOP(w);
8022 *pix_y += (char_y * defheight);
8023 *pix_y += (defheight >> 1);
8025 *pix_x = WINDOW_TEXT_LEFT(w);
8026 /* Don't adjust by one because this is still the unadjusted value. */
8027 *pix_x += (char_x * defwidth);
8028 *pix_x += (defwidth >> 1);
8031 if (*pix_x > w->pixel_left + w->pixel_width)
8032 *pix_x = w->pixel_left + w->pixel_width;
8033 if (*pix_y > w->pixel_top + w->pixel_height)
8034 *pix_y = w->pixel_top + w->pixel_height;
8036 *pix_x -= w->pixel_left;
8037 *pix_y -= w->pixel_top;
8040 /* Given a display line and a position, determine if there is a glyph
8041 there and return information about it if there is. */
8044 get_position_object(struct display_line *dl, Lisp_Object * obj1,
8045 Lisp_Object * obj2, int x_coord, int *low_x_coord,
8048 struct display_block *db;
8051 get_next_display_block(dl->bounds, dl->display_blocks, x_coord, 0);
8053 /* We use get_next_display_block to get the actual display block
8054 that would be displayed at x_coord. */
8056 if (block == NO_BLOCK)
8059 db = Dynarr_atp(dl->display_blocks, block);
8061 for (elt = 0; elt < Dynarr_length(db->runes); elt++) {
8062 struct rune *rb = Dynarr_atp(db->runes, elt);
8064 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width)) {
8065 if (rb->type == RUNE_DGLYPH) {
8066 *obj1 = rb->object.dglyph.glyph;
8067 *obj2 = rb->object.dglyph.extent;
8074 *low_x_coord = rb->xpos;
8076 *high_x_coord = rb->xpos + rb->width;
8083 #define UPDATE_CACHE_RETURN \
8085 d->pixel_to_glyph_cache.valid = 1; \
8086 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8087 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8088 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8089 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8090 d->pixel_to_glyph_cache.frame = f; \
8091 d->pixel_to_glyph_cache.col = *col; \
8092 d->pixel_to_glyph_cache.row = *row; \
8093 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8094 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8095 d->pixel_to_glyph_cache.w = *w; \
8096 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8097 d->pixel_to_glyph_cache.closest = *closest; \
8098 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8099 d->pixel_to_glyph_cache.obj1 = *obj1; \
8100 d->pixel_to_glyph_cache.obj2 = *obj2; \
8101 d->pixel_to_glyph_cache.retval = position; \
8102 RETURN_SANS_WARNINGS position; \
8105 /* Given x and y coordinates in pixels relative to a frame, return
8106 information about what is located under those coordinates.
8108 The return value will be one of:
8110 OVER_TOOLBAR: over one of the 4 frame toolbars
8111 OVER_MODELINE: over a modeline
8112 OVER_BORDER: over an internal border
8113 OVER_NOTHING: over the text area, but not over text
8114 OVER_OUTSIDE: outside of the frame border
8115 OVER_TEXT: over text in the text area
8121 -- nil if the coordinates are not over a glyph or a toolbar button.
8125 -- an extent, if the coordinates are over a glyph in the text area
8128 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8129 equivalent coordinates relative to the upper-left corner of the glyph.
8131 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8132 equivalent coordinates relative to the upper-left corner of the character.
8134 Otherwise, OBJ_X and OBJ_Y are undefined.
8138 pixel_to_glyph_translation(struct frame *f, int x_coord, int y_coord,
8139 int *col, int *row, int *obj_x, int *obj_y,
8140 struct window **w, Bufpos * bufpos,
8141 Bufpos * closest, Charcount * modeline_closest,
8142 Lisp_Object * obj1, Lisp_Object * obj2)
8145 struct pixel_to_glyph_translation_cache *cache;
8147 int frm_left, frm_right, frm_top, frm_bottom;
8148 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8149 int position = OVER_NOTHING;
8150 int device_check_failed = 0;
8151 display_line_dynarr *dla;
8153 /* This is a safety valve in case this got called with a frame in
8154 the middle of being deleted. */
8155 if (!DEVICEP(f->device) || !DEVICE_LIVE_P(XDEVICE(f->device))) {
8156 device_check_failed = 1;
8157 d = NULL, cache = NULL; /* Warning suppression */
8159 d = XDEVICE(f->device);
8160 cache = &d->pixel_to_glyph_cache;
8163 if (!device_check_failed
8165 && cache->frame == f
8166 && cache->low_x_coord <= x_coord
8167 && cache->high_x_coord > x_coord
8168 && cache->low_y_coord <= y_coord && cache->high_y_coord > y_coord) {
8171 *obj_x = cache->obj_x;
8172 *obj_y = cache->obj_y;
8174 *bufpos = cache->bufpos;
8175 *closest = cache->closest;
8176 *modeline_closest = cache->modeline_closest;
8177 *obj1 = cache->obj1;
8178 *obj2 = cache->obj2;
8180 return cache->retval;
8189 *modeline_closest = -1;
8193 low_x_coord = x_coord;
8194 high_x_coord = x_coord + 1;
8195 low_y_coord = y_coord;
8196 high_y_coord = y_coord + 1;
8199 if (device_check_failed)
8200 return OVER_NOTHING;
8202 frm_left = FRAME_LEFT_BORDER_END(f);
8203 frm_right = FRAME_RIGHT_BORDER_START(f);
8204 frm_top = FRAME_TOP_BORDER_END(f);
8205 frm_bottom = FRAME_BOTTOM_BORDER_START(f);
8207 /* Check if the mouse is outside of the text area actually used by
8209 if (y_coord < frm_top) {
8210 if (y_coord >= FRAME_TOP_BORDER_START(f)) {
8211 low_y_coord = FRAME_TOP_BORDER_START(f);
8212 high_y_coord = frm_top;
8213 position = OVER_BORDER;
8214 } else if (y_coord >= 0) {
8216 high_y_coord = FRAME_TOP_BORDER_START(f);
8217 position = OVER_TOOLBAR;
8219 low_y_coord = y_coord;
8221 position = OVER_OUTSIDE;
8223 } else if (y_coord >= frm_bottom) {
8224 if (y_coord < FRAME_BOTTOM_BORDER_END(f)) {
8225 low_y_coord = frm_bottom;
8226 high_y_coord = FRAME_BOTTOM_BORDER_END(f);
8227 position = OVER_BORDER;
8228 } else if (y_coord < FRAME_PIXHEIGHT(f)) {
8229 low_y_coord = FRAME_BOTTOM_BORDER_END(f);
8230 high_y_coord = FRAME_PIXHEIGHT(f);
8231 position = OVER_TOOLBAR;
8233 low_y_coord = FRAME_PIXHEIGHT(f);
8234 high_y_coord = y_coord;
8235 position = OVER_OUTSIDE;
8239 if (position != OVER_TOOLBAR && position != OVER_BORDER) {
8240 if (x_coord < frm_left) {
8241 if (x_coord >= FRAME_LEFT_BORDER_START(f)) {
8242 low_x_coord = FRAME_LEFT_BORDER_START(f);
8243 high_x_coord = frm_left;
8244 position = OVER_BORDER;
8245 } else if (x_coord >= 0) {
8247 high_x_coord = FRAME_LEFT_BORDER_START(f);
8248 position = OVER_TOOLBAR;
8250 low_x_coord = x_coord;
8252 position = OVER_OUTSIDE;
8254 } else if (x_coord >= frm_right) {
8255 if (x_coord < FRAME_RIGHT_BORDER_END(f)) {
8256 low_x_coord = frm_right;
8257 high_x_coord = FRAME_RIGHT_BORDER_END(f);
8258 position = OVER_BORDER;
8259 } else if (x_coord < FRAME_PIXWIDTH(f)) {
8260 low_x_coord = FRAME_RIGHT_BORDER_END(f);
8261 high_x_coord = FRAME_PIXWIDTH(f);
8262 position = OVER_TOOLBAR;
8264 low_x_coord = FRAME_PIXWIDTH(f);
8265 high_x_coord = x_coord;
8266 position = OVER_OUTSIDE;
8270 #ifdef HAVE_TOOLBARS
8271 if (position == OVER_TOOLBAR) {
8272 *obj1 = toolbar_button_at_pixpos(f, x_coord, y_coord);
8275 UPDATE_CACHE_RETURN;
8277 #endif /* HAVE_TOOLBARS */
8279 /* We still have to return the window the pointer is next to and its
8280 relative y position even if it is outside the x boundary. */
8281 if (x_coord < frm_left)
8283 else if (x_coord > frm_right)
8284 x_coord = frm_right;
8286 /* Same in reverse. */
8287 if (y_coord < frm_top)
8289 else if (y_coord > frm_bottom)
8290 y_coord = frm_bottom;
8292 /* Find what window the given coordinates are actually in. */
8293 window = f->root_window;
8294 *w = find_window_by_pixel_pos(x_coord, y_coord, window);
8296 /* If we didn't find a window, we're done. */
8298 UPDATE_CACHE_RETURN;
8299 } else if (position != OVER_NOTHING) {
8301 *modeline_closest = -1;
8303 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom) {
8305 UPDATE_CACHE_RETURN;
8309 /* Check if the window is a minibuffer but isn't active. */
8310 if (MINI_WINDOW_P(*w) && !minibuf_level) {
8311 /* Must reset the window value since some callers will ignore
8312 the return value if it is set. */
8314 UPDATE_CACHE_RETURN;
8317 /* See if the point is over window vertical divider */
8318 if (window_needs_vertical_divider(*w)) {
8319 int div_x_high = WINDOW_RIGHT(*w);
8320 int div_x_low = div_x_high - window_divider_width(*w);
8321 int div_y_high = WINDOW_BOTTOM(*w);
8322 int div_y_low = WINDOW_TOP(*w);
8324 if (div_x_low < x_coord && x_coord <= div_x_high &&
8325 div_y_low < y_coord && y_coord <= div_y_high) {
8326 low_x_coord = div_x_low;
8327 high_x_coord = div_x_high;
8328 low_y_coord = div_y_low;
8329 high_y_coord = div_y_high;
8330 position = OVER_V_DIVIDER;
8331 UPDATE_CACHE_RETURN;
8335 dla = window_display_lines(*w, CURRENT_DISP);
8337 for (*row = 0; *row < Dynarr_length(dla); (*row)++) {
8338 int really_over_nothing = 0;
8339 struct display_line *dl = Dynarr_atp(dla, *row);
8341 if ((int)(dl->ypos - dl->ascent) <= y_coord
8342 && y_coord <= (int)(dl->ypos + dl->descent)) {
8343 int check_margin_glyphs = 0;
8344 struct display_block *db =
8345 get_display_block_from_line(dl, TEXT);
8346 struct rune *rb = 0;
8348 if (x_coord < dl->bounds.left_white
8349 || x_coord >= dl->bounds.right_white)
8350 check_margin_glyphs = 1;
8352 low_y_coord = dl->ypos - dl->ascent;
8353 high_y_coord = dl->ypos + dl->descent + 1;
8355 if (position == OVER_BORDER
8356 || position == OVER_OUTSIDE
8357 || check_margin_glyphs) {
8358 int x_check, left_bound;
8360 if (check_margin_glyphs) {
8362 left_bound = dl->bounds.left_white;
8364 x_check = high_x_coord;
8365 left_bound = frm_left;
8368 if (Dynarr_length(db->runes)) {
8369 if (x_check <= left_bound) {
8404 *modeline_closest += dl->offset;
8406 *closest += dl->offset;
8408 /* #### What should be here. */
8410 *modeline_closest = 0;
8415 if (check_margin_glyphs) {
8416 if (x_coord < dl->bounds.left_in
8417 || x_coord >= dl->bounds.right_in) {
8418 /* If we are over the outside margins then we
8419 know the loop over the text block isn't going
8420 to accomplish anything. So we go ahead and
8421 set what information we can right here and
8425 y_coord - (dl->ypos -
8427 get_position_object(dl, obj1,
8433 UPDATE_CACHE_RETURN;
8436 UPDATE_CACHE_RETURN;
8439 for (*col = 0; *col <= Dynarr_length(db->runes);
8442 (*col == Dynarr_length(db->runes));
8445 rb = Dynarr_atp(db->runes, *col);
8448 (rb->xpos <= x_coord
8449 && x_coord < rb->xpos + rb->width)) {
8452 rb = Dynarr_atp(db->runes,
8456 *bufpos = rb->bufpos + dl->offset;
8457 low_x_coord = rb->xpos;
8458 high_x_coord = rb->xpos + rb->width;
8460 if (rb->type == RUNE_DGLYPH) {
8463 /* Find the first character after the glyph. */
8500 /* In this case we failed to find a non-glyph
8501 character so we return the last position
8502 displayed on the line. */
8504 Dynarr_length(db->runes)) {
8516 really_over_nothing = 1;
8531 window_displayed_height(*w);
8533 if (position == OVER_NOTHING)
8537 if (rb->type == RUNE_DGLYPH) {
8544 } else if (rb->type ==
8553 UPDATE_CACHE_RETURN;
8555 || (rb->type == RUNE_CHAR
8556 && rb->object.chr.ch ==
8559 /* At this point we may have glyphs in the right
8561 if (check_margin_glyphs)
8562 get_position_object(dl,
8568 UPDATE_CACHE_RETURN;
8571 if (rb->type == RUNE_DGLYPH) {
8578 } else if (rb->type ==
8587 *obj_x = x_coord - rb->xpos;
8589 y_coord - (dl->ypos -
8592 /* At this point we may have glyphs in the left
8594 if (check_margin_glyphs)
8595 get_position_object(dl,
8602 if (position == OVER_NOTHING
8603 && !really_over_nothing)
8604 position = OVER_TEXT;
8606 UPDATE_CACHE_RETURN;
8613 *row = Dynarr_length(dla) - 1;
8614 if (FRAME_WIN_P(f)) {
8615 int bot_elt = Dynarr_length(dla) - 1;
8618 struct display_line *dl = Dynarr_atp(dla, bot_elt);
8619 int adj_area = y_coord - (dl->ypos + dl->descent);
8623 XSETWINDOW(lwin, *w);
8624 default_face_height_and_width(lwin, 0, &defheight);
8626 *row += (adj_area / defheight);
8630 /* #### This should be checked out some more to determine what
8631 should really be going on. */
8632 if (!MARKERP((*w)->start[CURRENT_DISP]))
8635 *closest = end_of_last_line_may_error(*w,
8636 marker_position((*w)->
8640 UPDATE_CACHE_RETURN;
8643 #undef UPDATE_CACHE_RETURN
8645 /***************************************************************************/
8647 /* Lisp functions */
8649 /***************************************************************************/
8651 DEFUN("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8652 Ensure that all minibuffers are correctly showing the echo area.
8656 Lisp_Object devcons, concons;
8658 DEVICE_LOOP_NO_BREAK(devcons, concons) {
8659 struct device *d = XDEVICE(XCAR(devcons));
8660 Lisp_Object frmcons;
8662 DEVICE_FRAME_LOOP(frmcons, d) {
8663 struct frame *f = XFRAME(XCAR(frmcons));
8665 if (FRAME_REPAINT_P(f) && FRAME_HAS_MINIBUF_P(f)) {
8666 Lisp_Object window = FRAME_MINIBUF_WINDOW(f);
8668 MAYBE_DEVMETH(d, frame_output_begin, (f));
8671 * If the frame size has changed, there may be random
8672 * chud on the screen left from previous messages
8673 * because redisplay_frame hasn't been called yet.
8674 * Clear the screen to get rid of the potential mess.
8676 if (f->echo_area_garbaged) {
8677 MAYBE_DEVMETH(d, clear_frame, (f));
8678 f->echo_area_garbaged = 0;
8680 redisplay_window(window, 0);
8681 MAYBE_DEVMETH(d, frame_output_end, (f));
8683 call_redisplay_end_triggers(XWINDOW(window), 0);
8691 static Lisp_Object restore_disable_preemption_value(Lisp_Object value)
8693 disable_preemption = XINT(value);
8697 DEFUN("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8698 Clear frame FRAME and output again what is supposed to appear on it.
8699 FRAME defaults to the selected frame if omitted.
8700 Normally, redisplay is preempted as normal if input arrives. However,
8701 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8702 input and is guaranteed to proceed to completion.
8704 (frame, no_preempt))
8706 struct frame *f = decode_frame(frame);
8707 int count = specpdl_depth();
8709 if (!NILP(no_preempt)) {
8710 record_unwind_protect(restore_disable_preemption_value,
8711 make_int(disable_preemption));
8712 disable_preemption++;
8716 redisplay_frame(f, 1);
8718 /* See the comment in Fredisplay_frame. */
8719 RESET_CHANGED_SET_FLAGS;
8721 return unbind_to(count, Qnil);
8724 DEFUN("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8725 Ensure that FRAME's contents are correctly displayed.
8726 This differs from `redraw-frame' in that it only redraws what needs to
8727 be updated, as opposed to unconditionally clearing and redrawing
8729 FRAME defaults to the selected frame if omitted.
8730 Normally, redisplay is preempted as normal if input arrives. However,
8731 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8732 input and is guaranteed to proceed to completion.
8734 (frame, no_preempt))
8736 struct frame *f = decode_frame(frame);
8737 int count = specpdl_depth();
8739 if (!NILP(no_preempt)) {
8740 record_unwind_protect(restore_disable_preemption_value,
8741 make_int(disable_preemption));
8742 disable_preemption++;
8745 redisplay_frame(f, 1);
8747 /* If we don't reset the global redisplay flags here, subsequent
8748 changes to the display will not get registered by redisplay
8749 because it thinks it already has registered changes. If you
8750 really knew what you were doing you could confuse redisplay by
8751 calling Fredisplay_frame while updating another frame. We assume
8752 that if you know what you are doing you will not be that
8754 RESET_CHANGED_SET_FLAGS;
8756 return unbind_to(count, Qnil);
8759 DEFUN("redraw-device", Fredraw_device, 0, 2, 0, /*
8760 Clear device DEVICE and output again what is supposed to appear on it.
8761 DEVICE defaults to the selected device if omitted.
8762 Normally, redisplay is preempted as normal if input arrives. However,
8763 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8764 input and is guaranteed to proceed to completion.
8766 (device, no_preempt))
8768 struct device *d = decode_device(device);
8769 Lisp_Object frmcons;
8770 int count = specpdl_depth();
8772 if (!NILP(no_preempt)) {
8773 record_unwind_protect(restore_disable_preemption_value,
8774 make_int(disable_preemption));
8775 disable_preemption++;
8778 DEVICE_FRAME_LOOP(frmcons, d) {
8779 XFRAME(XCAR(frmcons))->clear = 1;
8781 redisplay_device(d, 0);
8783 /* See the comment in Fredisplay_frame. */
8784 RESET_CHANGED_SET_FLAGS;
8786 return unbind_to(count, Qnil);
8789 DEFUN("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8790 Ensure that DEVICE's contents are correctly displayed.
8791 This differs from `redraw-device' in that it only redraws what needs to
8792 be updated, as opposed to unconditionally clearing and redrawing
8794 DEVICE defaults to the selected device if omitted.
8795 Normally, redisplay is preempted as normal if input arrives. However,
8796 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8797 input and is guaranteed to proceed to completion.
8799 (device, no_preempt))
8801 struct device *d = decode_device(device);
8802 int count = specpdl_depth();
8804 if (!NILP(no_preempt)) {
8805 record_unwind_protect(restore_disable_preemption_value,
8806 make_int(disable_preemption));
8807 disable_preemption++;
8810 redisplay_device(d, 0);
8812 /* See the comment in Fredisplay_frame. */
8813 RESET_CHANGED_SET_FLAGS;
8815 return unbind_to(count, Qnil);
8818 /* Big lie. Big lie. This will force all modelines to be updated
8819 regardless if the all flag is set or not. It remains in existence
8820 solely for backwards compatibility. */
8821 DEFUN("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8822 Force the modeline of the current buffer to be redisplayed.
8823 With optional non-nil ALL, force redisplay of all modelines.
8827 MARK_MODELINE_CHANGED;
8831 DEFUN("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8832 Force an immediate update of the cursor on FRAME.
8833 FRAME defaults to the selected frame if omitted.
8837 redisplay_redraw_cursor(decode_frame(frame), 1);
8841 /***************************************************************************/
8843 /* Lisp-variable change triggers */
8845 /***************************************************************************/
8848 margin_width_changed_in_frame(Lisp_Object specifier, struct frame *f,
8851 /* Nothing to be done? */
8855 redisplay_variable_changed(Lisp_Object sym, Lisp_Object * val,
8856 Lisp_Object in_object, int flags)
8858 /* #### clip_changed should really be renamed something like
8859 global_redisplay_change. */
8864 /* This is called if the built-in glyphs have their properties
8867 redisplay_glyph_changed(Lisp_Object glyph, Lisp_Object property,
8870 if (WINDOWP(locale)) {
8871 MARK_FRAME_GLYPHS_CHANGED(XFRAME
8872 (WINDOW_FRAME(XWINDOW(locale))));
8873 } else if (FRAMEP(locale)) {
8874 MARK_FRAME_GLYPHS_CHANGED(XFRAME(locale));
8875 } else if (DEVICEP(locale)) {
8876 Lisp_Object frmcons;
8877 DEVICE_FRAME_LOOP(frmcons, XDEVICE(locale))
8878 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8879 } else if (CONSOLEP(locale)) {
8880 Lisp_Object frmcons, devcons;
8881 CONSOLE_FRAME_LOOP_NO_BREAK(frmcons, devcons, XCONSOLE(locale))
8882 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8883 } else { /* global or buffer */
8885 Lisp_Object frmcons, devcons, concons;
8886 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons)
8887 MARK_FRAME_GLYPHS_CHANGED(XFRAME(XCAR(frmcons)));
8892 text_cursor_visible_p_changed(Lisp_Object specifier, struct window *w,
8895 if (XFRAME(w->frame)->init_finished)
8896 Fforce_cursor_redisplay(w->frame);
8899 #if defined MEMORY_USAGE_STATS && !(defined HAVE_BDWGC && defined EF_USE_BDWGC)
8901 /***************************************************************************/
8903 /* memory usage computation */
8905 /***************************************************************************/
8908 compute_rune_dynarr_usage(rune_dynarr * dyn, struct overhead_stats *ovstats)
8910 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8914 compute_display_block_dynarr_usage(display_block_dynarr * dyn,
8915 struct overhead_stats *ovstats)
8922 total = Dynarr_memory_usage(dyn, ovstats);
8923 for (i = 0; i < Dynarr_largest(dyn); i++)
8925 compute_rune_dynarr_usage(Dynarr_at(dyn, i).runes, ovstats);
8931 compute_glyph_block_dynarr_usage(glyph_block_dynarr * dyn,
8932 struct overhead_stats *ovstats)
8934 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8938 compute_display_line_dynarr_usage(display_line_dynarr * dyn,
8939 struct overhead_stats *ovstats)
8946 total = Dynarr_memory_usage(dyn, ovstats);
8947 for (i = 0; i < Dynarr_largest(dyn); i++) {
8948 struct display_line *dl = &Dynarr_at(dyn, i);
8950 compute_display_block_dynarr_usage(dl->display_blocks,
8953 compute_glyph_block_dynarr_usage(dl->left_glyphs, ovstats);
8955 compute_glyph_block_dynarr_usage(dl->right_glyphs, ovstats);
8962 compute_line_start_cache_dynarr_usage(line_start_cache_dynarr * dyn,
8963 struct overhead_stats *ovstats)
8965 return dyn ? Dynarr_memory_usage(dyn, ovstats) : 0;
8968 #endif /* MEMORY_USAGE_STATS */
8970 /***************************************************************************/
8972 /* initialization */
8974 /***************************************************************************/
8976 void init_redisplay(void)
8978 disable_preemption = 0;
8979 preemption_count = 0;
8980 max_preempts = INIT_MAX_PREEMPTS;
8986 if (!cmotion_display_lines)
8987 cmotion_display_lines = Dynarr_new(display_line);
8988 if (!mode_spec_bufbyte_string)
8989 mode_spec_bufbyte_string = Dynarr_new(Bufbyte);
8990 if (!formatted_string_extent_dynarr)
8991 formatted_string_extent_dynarr = Dynarr_new(EXTENT);
8992 if (!formatted_string_extent_start_dynarr)
8993 formatted_string_extent_start_dynarr =
8994 Dynarr_new(Bytecount);
8995 if (!formatted_string_extent_end_dynarr)
8996 formatted_string_extent_end_dynarr =
8997 Dynarr_new(Bytecount);
8998 if (!internal_cache)
8999 internal_cache = Dynarr_new(line_start_cache);
9002 /* window system is nil when in -batch mode */
9003 if (!initialized || noninteractive)
9006 /* If the user wants to use a window system, we shouldn't bother
9007 initializing the terminal. This is especially important when the
9008 terminal is so dumb that emacs gives up before and doesn't bother
9009 using the window system.
9011 If the DISPLAY environment variable is set, try to use X, and die
9012 with an error message if that doesn't work. */
9014 #ifdef HAVE_X_WINDOWS
9015 if (!strcmp(display_use, "x")) {
9016 /* Some stuff checks this way early. */
9017 Vwindow_system = Qx;
9018 Vinitial_window_system = Qx;
9021 #endif /* HAVE_X_WINDOWS */
9024 /* If no window system has been specified, try to use the terminal. */
9026 stderr_out("SXEmacs: standard input is not a tty\n");
9030 /* Look at the TERM variable */
9031 if (!getenv("TERM")) {
9033 ("Please set the environment variable TERM; see tset(1).\n");
9037 Vinitial_window_system = Qtty;
9039 #else /* not HAVE_TTY */
9040 /* No DISPLAY specified, and no TTY support. */
9041 stderr_out("SXEmacs: Cannot open display.\n\
9042 Please set the environmental variable DISPLAY to an appropriate value.\n");
9048 void syms_of_redisplay(void)
9050 defsymbol(&Qcursor_in_echo_area, "cursor-in-echo-area");
9051 #ifndef INHIBIT_REDISPLAY_HOOKS
9052 defsymbol(&Qpre_redisplay_hook, "pre-redisplay-hook");
9053 defsymbol(&Qpost_redisplay_hook, "post-redisplay-hook");
9054 #endif /* INHIBIT_REDISPLAY_HOOKS */
9055 defsymbol(&Qdisplay_warning_buffer, "display-warning-buffer");
9056 defsymbol(&Qbar_cursor, "bar-cursor");
9057 defsymbol(&Qredisplay_end_trigger_functions,
9058 "redisplay-end-trigger-functions");
9059 defsymbol(&Qtop_bottom, "top-bottom");
9060 defsymbol(&Qbuffer_list_changed_hook, "buffer-list-changed-hook");
9062 DEFSUBR(Fredisplay_echo_area);
9063 DEFSUBR(Fredraw_frame);
9064 DEFSUBR(Fredisplay_frame);
9065 DEFSUBR(Fredraw_device);
9066 DEFSUBR(Fredisplay_device);
9067 DEFSUBR(Fredraw_modeline);
9068 DEFSUBR(Fforce_cursor_redisplay);
9071 void vars_of_redisplay(void)
9075 staticpro(&last_arrow_position);
9076 staticpro(&last_arrow_string);
9077 last_arrow_position = Qnil;
9078 last_arrow_string = Qnil;
9081 /* #### Probably temporary */
9082 DEFVAR_INT("redisplay-cache-adjustment", &cache_adjustment /*
9083 \(Temporary) Setting this will impact the performance of the internal
9086 cache_adjustment = 2;
9088 DEFVAR_INT_MAGIC("pixel-vertical-clip-threshold", &vertical_clip /*
9089 Minimum pixel height for clipped bottom display line.
9090 A clipped line shorter than this won't be displayed.
9092 redisplay_variable_changed);
9095 DEFVAR_INT_MAGIC("pixel-horizontal-clip-threshold", &horizontal_clip /*
9096 Minimum visible area for clipped glyphs at right boundary.
9097 Clipped glyphs shorter than this won't be displayed.
9098 Only pixmap glyph instances are currently allowed to be clipped.
9100 redisplay_variable_changed);
9101 horizontal_clip = 5;
9103 DEFVAR_LISP("global-mode-string", &Vglobal_mode_string /*
9104 String displayed by modeline-format's "%m" specification.
9106 Vglobal_mode_string = Qnil;
9108 DEFVAR_LISP_MAGIC("overlay-arrow-position", &Voverlay_arrow_position /*
9109 Marker for where to display an arrow on top of the buffer text.
9110 This must be the beginning of a line in order to work.
9111 See also `overlay-arrow-string'.
9113 redisplay_variable_changed);
9114 Voverlay_arrow_position = Qnil;
9116 DEFVAR_LISP_MAGIC("overlay-arrow-string", &Voverlay_arrow_string /*
9117 String or glyph to display as an arrow. See also `overlay-arrow-position'.
9118 \(Note that despite the name of this variable, it can be set to a glyph as
9121 redisplay_variable_changed);
9122 Voverlay_arrow_string = Qnil;
9124 DEFVAR_INT("scroll-step", &scroll_step /*
9125 *The number of lines to try scrolling a window by when point moves out.
9126 If that fails to bring point back on frame, point is centered instead.
9127 If this is zero, point is always centered after it moves off screen.
9131 DEFVAR_INT("scroll-conservatively", &scroll_conservatively /*
9132 *Scroll up to this many lines, to bring point back on screen.
9134 scroll_conservatively = 0;
9136 DEFVAR_BOOL_MAGIC("truncate-partial-width-windows", &truncate_partial_width_windows /*
9137 *Non-nil means truncate lines in all windows less than full frame wide.
9139 redisplay_variable_changed);
9140 truncate_partial_width_windows = 1;
9142 DEFVAR_LISP("visible-bell", &Vvisible_bell /*
9143 *Non-nil substitutes a visual signal for the audible bell.
9145 Default behavior is to flash the whole screen. On some platforms,
9146 special effects are available using the following values:
9148 'display Flash the whole screen (ie, the default behavior).
9149 'top-bottom Flash only the top and bottom lines of the selected frame.
9151 When effects are unavailable on a platform, the visual bell is the
9152 default, whole screen. (Currently only X supports any special effects.)
9154 Vvisible_bell = Qnil;
9156 DEFVAR_BOOL("no-redraw-on-reenter", &no_redraw_on_reenter /*
9157 *Non-nil means no need to redraw entire frame after suspending.
9158 A non-nil value is useful if the terminal can automatically preserve
9159 Emacs's frame display when you reenter Emacs.
9160 It is up to you to set this variable if your terminal can do that.
9162 no_redraw_on_reenter = 0;
9164 DEFVAR_LISP("window-system", &Vwindow_system /*
9165 A symbol naming the window-system under which Emacs is running,
9166 such as `x', or nil if emacs is running on an ordinary terminal.
9168 Do not use this variable, except for GNU Emacs compatibility, as it
9169 gives wrong values in a multi-device environment. Use `console-type'
9172 Vwindow_system = Qnil;
9174 /* #### Temporary shit until window-system is eliminated. */
9175 DEFVAR_CONST_LISP("initial-window-system", &Vinitial_window_system /*
9178 Vinitial_window_system = Qnil;
9180 DEFVAR_BOOL("cursor-in-echo-area", &cursor_in_echo_area /*
9181 Non-nil means put cursor in minibuffer, at end of any message there.
9183 cursor_in_echo_area = 0;
9185 /* #### Shouldn't this be generalized as follows:
9187 if nil, use block cursor.
9188 if a number, use a bar cursor of that width.
9189 Otherwise, use a 1-pixel bar cursor.
9191 #### Or better yet, this variable should be trashed entirely
9192 (use a Lisp-magic variable to maintain compatibility)
9193 and a specifier `cursor-shape' added, which allows a block
9194 cursor, a bar cursor, a flashing block or bar cursor,
9195 maybe a caret cursor, etc. */
9197 DEFVAR_LISP("bar-cursor", &Vbar_cursor /*
9198 *Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9202 #ifndef INHIBIT_REDISPLAY_HOOKS
9203 xxDEFVAR_LISP("pre-redisplay-hook", &Vpre_redisplay_hook /*
9204 Function or functions to run before every redisplay.
9206 Vpre_redisplay_hook = Qnil;
9208 xxDEFVAR_LISP("post-redisplay-hook", &Vpost_redisplay_hook /*
9209 Function or functions to run after every redisplay.
9211 Vpost_redisplay_hook = Qnil;
9212 #endif /* INHIBIT_REDISPLAY_HOOKS */
9214 DEFVAR_LISP("buffer-list-changed-hook", &Vbuffer_list_changed_hook /*
9215 Function or functions to call when a frame's buffer list has changed.
9216 This is called during redisplay, before redisplaying each frame.
9217 Functions on this hook are called with one argument, the frame.
9219 Vbuffer_list_changed_hook = Qnil;
9221 DEFVAR_INT("display-warning-tick", &display_warning_tick /*
9222 Bump this to tell the C code to call `display-warning-buffer'
9223 at next redisplay. You should not normally change this; the function
9224 `display-warning' automatically does this at appropriate times.
9226 display_warning_tick = 0;
9228 DEFVAR_BOOL("inhibit-warning-display", &inhibit_warning_display /*
9229 Non-nil means inhibit display of warning messages.
9230 You should *bind* this, not set it. Any pending warning messages
9231 will be displayed when the binding no longer applies.
9233 /* reset to 0 by startup.el after the splash screen has displayed.
9234 This way, the warnings don't obliterate the splash screen. */
9235 inhibit_warning_display = 1;
9237 DEFVAR_LISP("window-size-change-functions", &Vwindow_size_change_functions /*
9238 Not currently implemented.
9239 Functions called before redisplay, if window sizes have changed.
9240 The value should be a list of functions that take one argument.
9241 Just before redisplay, for each frame, if any of its windows have changed
9242 size since the last redisplay, or have been split or deleted,
9243 all the functions in the list are called, with the frame as argument.
9245 Vwindow_size_change_functions = Qnil;
9247 DEFVAR_LISP("window-scroll-functions", &Vwindow_scroll_functions /*
9248 Not currently implemented.
9249 Functions to call before redisplaying a window with scrolling.
9250 Each function is called with two arguments, the window
9251 and its new display-start position. Note that the value of `window-end'
9252 is not valid when these functions are called.
9254 Vwindow_scroll_functions = Qnil;
9256 DEFVAR_LISP("redisplay-end-trigger-functions", &Vredisplay_end_trigger_functions /*
9257 See `set-window-redisplay-end-trigger'.
9259 Vredisplay_end_trigger_functions = Qnil;
9261 DEFVAR_BOOL("column-number-start-at-one", &column_number_start_at_one /*
9262 *Non-nil means column display number starts at 1.
9264 column_number_start_at_one = 0;
9267 void specifier_vars_of_redisplay(void)
9269 DEFVAR_SPECIFIER("left-margin-width", &Vleft_margin_width /*
9270 *Width of left margin.
9271 This is a specifier; use `set-specifier' to change it.
9273 Vleft_margin_width = Fmake_specifier(Qnatnum);
9274 set_specifier_fallback(Vleft_margin_width, list1(Fcons(Qnil, Qzero)));
9275 set_specifier_caching(Vleft_margin_width,
9276 offsetof(struct window, left_margin_width),
9277 some_window_value_changed,
9278 offsetof(struct frame, left_margin_width),
9279 margin_width_changed_in_frame, 0);
9281 DEFVAR_SPECIFIER("right-margin-width", &Vright_margin_width /*
9282 *Width of right margin.
9283 This is a specifier; use `set-specifier' to change it.
9285 Vright_margin_width = Fmake_specifier(Qnatnum);
9286 set_specifier_fallback(Vright_margin_width, list1(Fcons(Qnil, Qzero)));
9287 set_specifier_caching(Vright_margin_width,
9288 offsetof(struct window, right_margin_width),
9289 some_window_value_changed,
9290 offsetof(struct frame, right_margin_width),
9291 margin_width_changed_in_frame, 0);
9293 DEFVAR_SPECIFIER("minimum-line-ascent", &Vminimum_line_ascent /*
9294 *Minimum ascent height of lines.
9295 This is a specifier; use `set-specifier' to change it.
9297 Vminimum_line_ascent = Fmake_specifier(Qnatnum);
9298 set_specifier_fallback(Vminimum_line_ascent, list1(Fcons(Qnil, Qzero)));
9299 set_specifier_caching(Vminimum_line_ascent,
9300 offsetof(struct window, minimum_line_ascent),
9301 some_window_value_changed, 0, 0, 0);
9303 DEFVAR_SPECIFIER("minimum-line-descent", &Vminimum_line_descent /*
9304 *Minimum descent height of lines.
9305 This is a specifier; use `set-specifier' to change it.
9307 Vminimum_line_descent = Fmake_specifier(Qnatnum);
9308 set_specifier_fallback(Vminimum_line_descent,
9309 list1(Fcons(Qnil, Qzero)));
9310 set_specifier_caching(Vminimum_line_descent,
9311 offsetof(struct window, minimum_line_descent),
9312 some_window_value_changed, 0, 0, 0);
9314 DEFVAR_SPECIFIER("use-left-overflow", &Vuse_left_overflow /*
9315 *Non-nil means use the left outside margin as extra whitespace when
9316 displaying 'whitespace or 'inside-margin glyphs.
9317 This is a specifier; use `set-specifier' to change it.
9319 Vuse_left_overflow = Fmake_specifier(Qboolean);
9320 set_specifier_fallback(Vuse_left_overflow, list1(Fcons(Qnil, Qnil)));
9321 set_specifier_caching(Vuse_left_overflow,
9322 offsetof(struct window, use_left_overflow),
9323 some_window_value_changed, 0, 0, 0);
9325 DEFVAR_SPECIFIER("use-right-overflow", &Vuse_right_overflow /*
9326 *Non-nil means use the right outside margin as extra whitespace when
9327 displaying 'whitespace or 'inside-margin glyphs.
9328 This is a specifier; use `set-specifier' to change it.
9330 Vuse_right_overflow = Fmake_specifier(Qboolean);
9331 set_specifier_fallback(Vuse_right_overflow, list1(Fcons(Qnil, Qnil)));
9332 set_specifier_caching(Vuse_right_overflow,
9333 offsetof(struct window, use_right_overflow),
9334 some_window_value_changed, 0, 0, 0);
9336 DEFVAR_SPECIFIER("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9337 *Non-nil means the text cursor is visible (this is usually the case).
9338 This is a specifier; use `set-specifier' to change it.
9340 Vtext_cursor_visible_p = Fmake_specifier(Qboolean);
9341 set_specifier_fallback(Vtext_cursor_visible_p, list1(Fcons(Qnil, Qt)));
9342 set_specifier_caching(Vtext_cursor_visible_p,
9343 offsetof(struct window, text_cursor_visible_p),
9344 text_cursor_visible_p_changed, 0, 0, 0);