comparison src/redisplay.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children a5df635868b2
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
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.
7
8 This file is part of XEmacs.
9
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
14
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
24
25 /* Synched up with: Not in FSF. */
26
27 /* Author: Chuck Thompson */
28
29 /* Fixed up by Ben Wing for Mule */
30
31 /* This file has been Mule-ized. */
32
33 /*****************************************************************************
34 The Golden Rules of Redisplay
35
36 First: It Is Better To Be Correct Than Fast
37 Second: Thou Shalt Not Run Elisp From Within Redisplay
38 Third: It Is Better To Be Fast Than Not To Be
39 ****************************************************************************/
40
41 #include <config.h>
42 #include "lisp.h"
43 #include <limits.h>
44
45 #include "buffer.h"
46 #include "commands.h"
47 #include "debug.h"
48 #include "device.h"
49 #include "elhash.h"
50 #include "extents.h"
51 #include "faces.h"
52 #include "frame.h"
53 #include "glyphs.h"
54 #include "gutter.h"
55 #include "insdel.h"
56 #include "menubar.h"
57 #include "objects.h"
58 #include "process.h"
59 #include "redisplay.h"
60 #include "toolbar.h"
61 #include "window.h"
62 #include "line-number.h"
63 #ifdef FILE_CODING
64 #include "file-coding.h"
65 #endif
66
67 #ifdef HAVE_TTY
68 #include "console-tty.h"
69 #ifdef HAVE_UNISTD_H
70 #include <unistd.h> /* for isatty() */
71 #endif
72 #endif /* HAVE_TTY */
73
74 /* Note: We have to be careful throughout this code to properly handle
75 and differentiate between Bufbytes and Emchars.
76
77 Since strings are generally composed of Bufbytes, I've taken the tack
78 that any contiguous set of Bufbytes is called a "string", while
79 any contiguous set of Emchars is called an "array". */
80
81 /* Return value to indicate a failure by an add_*_rune routine to add
82 a rune, but no propagation information needs to be returned. */
83 #define ADD_FAILED (prop_block_dynarr *) 1
84
85 #define BEGIN_GLYPHS 0
86 #define END_GLYPHS 1
87 #define LEFT_GLYPHS 2
88 #define RIGHT_GLYPHS 3
89
90 /* Set the vertical clip to 0 if we are currently updating the line
91 start cache. Otherwise for buffers of line height 1 it may fail to
92 be able to work properly because regenerate_window will not layout
93 a single line. */
94 #define VERTICAL_CLIP(w, display) \
95 (updating_line_start_cache \
96 ? 0 \
97 : ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines)) \
98 ? INT_MAX \
99 : vertical_clip))
100
101 /* The following structures are completely private to redisplay.c so
102 we put them here instead of in a header file, for modularity. */
103
104 /* NOTE: Bytinds not Bufpos's in this structure. */
105
106 typedef struct position_redisplay_data_type
107 {
108 /* This information is normally filled in by the create_*_block
109 routines and is used by the add_*_rune routines. */
110 Lisp_Object window;
111 /* if we are working with strings rather than buffers we need a
112 handle to the string */
113 Lisp_Object string;
114 struct device *d;
115 struct display_block *db;
116 struct display_line *dl;
117 Emchar ch; /* Character that is to be added. This is
118 used to communicate this information to
119 add_emchar_rune(). */
120 Lisp_Object last_charset; /* The charset of the previous character.
121 Used to optimize some lookups -- we
122 only have to do some things when
123 the charset changes. */
124 face_index last_findex; /* The face index of the previous character.
125 Needed to ensure the validity of the
126 last_charset optimization. */
127
128 int last_char_width; /* The width of the previous character. */
129 int font_is_bogus; /* If true, it means we couldn't instantiate
130 the font for this charset, so we substitute
131 ~'s from the ASCII charset. */
132 Bytind bi_bufpos;
133 Bytind bi_endpos;
134 int pixpos;
135 int max_pixpos;
136 int blank_width; /* Width of the blank that is to be added.
137 This is used to communicate this information
138 to add_blank_rune().
139
140 This is also used rather cheesily to
141 communicate the width of the eol-cursor-size
142 blank that exists at the end of the line.
143 add_emchar_rune() is called cheesily with
144 the non-printing char '\n', which is stuck
145 in the output routines with its width being
146 BLANK_WIDTH. */
147 Bytind bi_cursor_bufpos;/* This stores the buffer position of the cursor. */
148 unsigned int cursor_type :3;
149 int cursor_x; /* rune block cursor is at */
150 int start_col; /* Number of character columns (each column has
151 a width of the default char width) that still
152 need to be skipped. This is used for horizontal
153 scrolling, where a certain number of columns
154 (those off the left side of the screen) need
155 to be skipped before anything is displayed. */
156 Bytind bi_start_col_enabled;
157 int start_col_xoffset; /* Number of pixels that still need to
158 be skipped. This is used for
159 horizontal scrolling of glyphs, where we want
160 to be able to scroll over part of the glyph. */
161
162 int hscroll_glyph_width_adjust; /* how much the width of the hscroll
163 glyph differs from space_width (w).
164 0 if no hscroll glyph was used,
165 i.e. the window is not scrolled
166 horizontally. Used in tab
167 calculations. */
168
169 /* Information about the face the text should be displayed in and
170 any begin-glyphs and end-glyphs. */
171 struct extent_fragment *ef;
172 face_index findex;
173
174 /* The height of a pixmap may either be predetermined if the user
175 has set a baseline value, or it may be dependent on whatever the
176 line ascent and descent values end up being, based just on font
177 information. In the first case we can immediately update the
178 values, thus their inclusion here. In the last case we cannot
179 determine the actual contribution to the line height until we
180 have finished laying out all text on the line. Thus we propagate
181 the max height of such pixmaps and do a final calculation after
182 all text has been added to the line. */
183 int new_ascent;
184 int new_descent;
185 int max_pixmap_height;
186
187 Lisp_Object result_str; /* String where we put the result of
188 generating a formatted string in the modeline. */
189 int is_modeline; /* Non-zero if we're generating the modeline. */
190 Charcount modeline_charpos; /* Number of chars used in result_str so far;
191 corresponds to bytepos. */
192 Bytecount bytepos; /* Number of bytes used in result_str so far.
193 We don't actually copy the bytes into result_str
194 until the end because we don't know how big the
195 string is going to be until then. */
196 } pos_data;
197
198 enum prop_type
199 {
200 PROP_STRING,
201 PROP_CHAR,
202 PROP_MINIBUF_PROMPT,
203 PROP_BLANK
204 };
205
206 /* Data that should be propagated to the next line. Either a single
207 Emchar or a string of Bufbyte's.
208
209 The actual data that is propagated ends up as a Dynarr of these
210 blocks.
211
212 #### It's unclean that both Emchars and Bufbytes are here.
213 */
214
215 typedef struct prop_block prop_block;
216 struct prop_block
217 {
218 enum prop_type type;
219
220 union data
221 {
222 struct
223 {
224 Bufbyte *str;
225 Bytecount len; /* length of the string. */
226 } p_string;
227
228 struct
229 {
230 Emchar ch;
231 Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
232 unsigned int cursor_type :3;
233 } p_char;
234
235 struct
236 {
237 int width;
238 face_index findex;
239 } p_blank;
240 } data;
241 };
242
243 typedef struct
244 {
245 Dynarr_declare (prop_block);
246 } prop_block_dynarr;
247
248
249 static void generate_formatted_string_db (Lisp_Object format_str,
250 Lisp_Object result_str,
251 struct window *w,
252 struct display_line *dl,
253 struct display_block *db,
254 face_index findex, int min_pixpos,
255 int max_pixpos, int type);
256 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
257 Charcount pos, Charcount min_pos,
258 Charcount max_pos, Lisp_Object elt,
259 int depth, int max_pixsize,
260 face_index findex, int type);
261 static prop_block_dynarr *add_glyph_rune (pos_data *data,
262 struct glyph_block *gb,
263 int pos_type, int allow_cursor,
264 struct glyph_cachel *cachel);
265 static Bytind create_text_block (struct window *w, struct display_line *dl,
266 Bytind bi_start_pos, prop_block_dynarr **prop,
267 int type);
268 static int create_overlay_glyph_block (struct window *w,
269 struct display_line *dl);
270 static void create_left_glyph_block (struct window *w,
271 struct display_line *dl,
272 int overlay_width);
273 static void create_right_glyph_block (struct window *w,
274 struct display_line *dl);
275 static void redisplay_windows (Lisp_Object window, int skip_selected);
276 static void decode_mode_spec (struct window *w, Emchar spec, int type);
277 static void free_display_line (struct display_line *dl);
278 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
279 Bufpos point, int no_regen);
280 static int point_visible (struct window *w, Bufpos point, int type);
281
282 /* This used to be 10 but 30 seems to give much better performance. */
283 #define INIT_MAX_PREEMPTS 30
284 static int max_preempts;
285
286 #define REDISPLAY_PREEMPTION_CHECK \
287 ((void) \
288 (preempted = \
289 (!disable_preemption && \
290 ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) && \
291 (!INTERACTIVE || detect_input_pending ()))))
292
293 /*
294 * Redisplay global variables.
295 */
296
297 /* We need a third set of display structures for the cursor motion
298 routines. We used to just give each window a third set. However,
299 we always fully regenerate the structures when needed so there
300 isn't any reason we need more than a single set. */
301 display_line_dynarr *cmotion_display_lines;
302
303 /* Used by generate_formatted_string. Global because they get used so
304 much that the dynamic allocation time adds up. */
305 static Emchar_dynarr *formatted_string_emchar_dynarr;
306 static struct display_line formatted_string_display_line;
307 /* We store the extents that we need to generate in a Dynarr and then
308 frob them all on at the end of generating the string. We do it
309 this way rather than adding them as we generate the string because
310 we don't store the text into the resulting string until we're done
311 (to avoid having to resize the string multiple times), and we don't
312 want to go around adding extents to a string when the extents might
313 stretch off the end of the string. */
314 static EXTENT_dynarr *formatted_string_extent_dynarr;
315 static Bytecount_dynarr *formatted_string_extent_start_dynarr;
316 static Bytecount_dynarr *formatted_string_extent_end_dynarr;
317
318
319 /* #### probably temporary */
320 int cache_adjustment;
321
322 /* This holds a string representing the text corresponding to a single
323 modeline % spec. */
324 static Bufbyte_dynarr *mode_spec_bufbyte_string;
325
326 int in_display; /* 1 if in redisplay. */
327
328 int disable_preemption; /* Used for debugging redisplay and for
329 force-redisplay. */
330
331 /* We only allow max_preempts preemptions before we force a redisplay. */
332 static int preemption_count;
333
334 /* Minimum pixel height of clipped bottom display line. */
335 int vertical_clip;
336
337 /* Minimum visible pixel width of clipped glyphs at right margin. */
338 int horizontal_clip;
339
340 /* Set if currently inside update_line_start_cache. */
341 static int updating_line_start_cache;
342
343 /* Nonzero means reading single-character input with prompt
344 so put cursor on minibuffer after the prompt. */
345 int cursor_in_echo_area;
346 Lisp_Object Qcursor_in_echo_area;
347
348 /* Nonzero means truncate lines in all windows less wide than the frame */
349 int truncate_partial_width_windows;
350
351 /* non-nil if a buffer has changed since the last time redisplay completed */
352 int buffers_changed;
353 int buffers_changed_set;
354
355 /* non-nil if hscroll has changed somewhere or a buffer has been
356 narrowed or widened */
357 int clip_changed;
358 int clip_changed_set;
359
360 /* non-nil if any extent has changed since the last time redisplay completed */
361 int extents_changed;
362 int extents_changed_set;
363
364 /* non-nil if any face has changed since the last time redisplay completed */
365 int faces_changed;
366
367 /* Nonzero means some frames have been marked as garbaged */
368 int frame_changed;
369
370 /* non-zero if any of the builtin display glyphs (continuation,
371 hscroll, control-arrow, etc) is in need of updating
372 somewhere. */
373 int glyphs_changed;
374 int glyphs_changed_set;
375
376 /* non-zero if any displayed subwindow is in need of updating
377 somewhere. */
378 int subwindows_changed;
379 int subwindows_changed_set;
380
381 /* non-zero if any displayed subwindow is in need of updating
382 somewhere. */
383 int subwindows_state_changed;
384 int subwindows_state_changed_set;
385
386 /* This variable is 1 if the icon has to be updated.
387 It is set to 1 when `frame-icon-glyph' changes. */
388 int icon_changed;
389 int icon_changed_set;
390
391 /* This variable is 1 if the menubar widget has to be updated.
392 It is set to 1 by set-menubar-dirty-flag and cleared when the widget
393 has been updated. */
394 int menubar_changed;
395 int menubar_changed_set;
396
397 /* true iff we should redraw the modelines on the next redisplay */
398 int modeline_changed;
399 int modeline_changed_set;
400
401 /* non-nil if point has changed in some buffer since the last time
402 redisplay completed */
403 int point_changed;
404 int point_changed_set;
405
406 /* non-nil if some frame has changed its size */
407 int size_changed;
408
409 /* non-nil if some device has signaled that it wants to change size */
410 int asynch_device_change_pending;
411
412 /* non-nil if any toolbar has changed */
413 int toolbar_changed;
414 int toolbar_changed_set;
415
416 /* non-nil if any gutter has changed */
417 int gutter_changed;
418 int gutter_changed_set;
419
420 /* non-nil if any window has changed since the last time redisplay completed */
421 int windows_changed;
422
423 /* non-nil if any frame's window structure has changed since the last
424 time redisplay completed */
425 int windows_structure_changed;
426
427 /* If non-nil, use vertical bar cursor. */
428 Lisp_Object Vbar_cursor;
429 Lisp_Object Qbar_cursor;
430
431
432 int visible_bell; /* If true and the terminal will support it
433 then the frame will flash instead of
434 beeping when an error occurs */
435
436 /* Nonzero means no need to redraw the entire frame on resuming
437 a suspended Emacs. This is useful on terminals with multiple pages,
438 where one page is used for Emacs and another for all else. */
439 int no_redraw_on_reenter;
440
441 Lisp_Object Vwindow_system; /* nil or a symbol naming the window system
442 under which emacs is running
443 ('x is the only current possibility) */
444 Lisp_Object Vinitial_window_system;
445
446 Lisp_Object Vglobal_mode_string;
447
448 /* The number of lines scroll a window by when point leaves the window; if
449 it is <=0 then point is centered in the window */
450 int scroll_step;
451
452 /* Scroll up to this many lines, to bring point back on screen. */
453 int scroll_conservatively;
454
455 /* Marker for where to display an arrow on top of the buffer text. */
456 Lisp_Object Voverlay_arrow_position;
457 /* String to display for the arrow. */
458 Lisp_Object Voverlay_arrow_string;
459
460 Lisp_Object Vwindow_size_change_functions;
461 Lisp_Object Vwindow_scroll_functions;
462 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
463
464 #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about
465 this more. */
466 #ifndef INHIBIT_REDISPLAY_HOOKS
467 /* #### Chuck says: I think this needs more thought.
468 Think about this for 19.14. */
469 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
470 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
471 #endif /* INHIBIT_REDISPLAY_HOOKS */
472
473 static int last_display_warning_tick, display_warning_tick;
474 Lisp_Object Qdisplay_warning_buffer;
475 int inhibit_warning_display;
476
477 Lisp_Object Vleft_margin_width, Vright_margin_width;
478 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
479 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
480 Lisp_Object Vtext_cursor_visible_p;
481
482 int column_number_start_at_one;
483
484 #define WINDOW_SCROLLED(w) \
485 (w->hscroll > 0 || w->left_xoffset)
486
487
488 /***************************************************************************/
489 /* */
490 /* low-level interfaces onto device routines */
491 /* */
492 /***************************************************************************/
493
494 static int
495 redisplay_text_width_emchar_string (struct window *w, int findex,
496 Emchar *str, Charcount len)
497 {
498 unsigned char charsets[NUM_LEADING_BYTES];
499 Lisp_Object window;
500
501 find_charsets_in_emchar_string (charsets, str, len);
502 XSETWINDOW (window, w);
503 ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
504 charsets);
505 return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))),
506 text_width, (XFRAME (WINDOW_FRAME (w)),
507 WINDOW_FACE_CACHEL (w, findex), str, len));
508 }
509
510 static Emchar_dynarr *rtw_emchar_dynarr;
511
512 int
513 redisplay_text_width_string (struct window *w, int findex,
514 Bufbyte *nonreloc, Lisp_Object reloc,
515 Bytecount offset, Bytecount len)
516 {
517 if (!rtw_emchar_dynarr)
518 rtw_emchar_dynarr = Dynarr_new (Emchar);
519 Dynarr_reset (rtw_emchar_dynarr);
520
521 fixup_internal_substring (nonreloc, reloc, offset, &len);
522 if (STRINGP (reloc))
523 nonreloc = XSTRING_DATA (reloc);
524 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
525 return redisplay_text_width_emchar_string
526 (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
527 Dynarr_length (rtw_emchar_dynarr));
528 }
529
530 int
531 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face,
532 Bufbyte *nonreloc, Lisp_Object reloc,
533 Bytecount offset, Bytecount len)
534 {
535 unsigned char charsets[NUM_LEADING_BYTES];
536 Lisp_Object frame;
537 struct face_cachel cachel;
538
539 if (!rtw_emchar_dynarr)
540 rtw_emchar_dynarr = Dynarr_new (Emchar);
541 Dynarr_reset (rtw_emchar_dynarr);
542
543 fixup_internal_substring (nonreloc, reloc, offset, &len);
544 if (STRINGP (reloc))
545 nonreloc = XSTRING_DATA (reloc);
546 convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
547 find_charsets_in_bufbyte_string (charsets, nonreloc, len);
548 reset_face_cachel (&cachel);
549 cachel.face = face;
550 XSETFRAME (frame, f);
551 ensure_face_cachel_complete (&cachel, frame, charsets);
552 return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
553 text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
554 Dynarr_length (rtw_emchar_dynarr)));
555 }
556
557 /* Return the display block from DL of the given TYPE. A display line
558 can have only one display block of each possible type. If DL does
559 not have a block of type TYPE, one will be created and added to DL. */
560
561 struct display_block *
562 get_display_block_from_line (struct display_line *dl, enum display_type type)
563 {
564 int elt;
565 struct display_block db;
566
567 /* Check if this display line already has a block of the desired type and
568 if so, return it. */
569 if (dl->display_blocks)
570 {
571 for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++)
572 {
573 if (Dynarr_at (dl->display_blocks, elt).type == type)
574 return Dynarr_atp (dl->display_blocks, elt);
575 }
576
577 /* There isn't an active block of the desired type, but there
578 might still be allocated blocks we need to reuse. */
579 if (elt < Dynarr_largest (dl->display_blocks))
580 {
581 struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
582
583 /* 'add' the block to the list */
584 Dynarr_increment (dl->display_blocks);
585
586 /* initialize and return */
587 dbp->type = type;
588 return dbp;
589 }
590 }
591 else
592 {
593 /* This line doesn't have any display blocks, so initialize the display
594 bock array. */
595 dl->display_blocks = Dynarr_new (display_block);
596 }
597
598 /* The line doesn't have a block of the desired type so go ahead and create
599 one and add it to the line. */
600 xzero (db);
601 db.type = type;
602 db.runes = Dynarr_new (rune);
603 Dynarr_add (dl->display_blocks, db);
604
605 /* Return the newly added display block. */
606 elt = Dynarr_length (dl->display_blocks) - 1;
607
608 return Dynarr_atp (dl->display_blocks, elt);
609 }
610
611 static int
612 tab_char_width (struct window *w)
613 {
614 struct buffer *b = XBUFFER (w->buffer);
615 int char_tab_width = XINT (b->tab_width);
616
617 if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8;
618
619 return char_tab_width;
620 }
621
622 static int
623 space_width (struct window *w)
624 {
625 /* While tabs are traditional composed of spaces, for variable-width
626 fonts the space character tends to give too narrow a value. So
627 we use 'n' instead. Except that we don't. We use the default
628 character width for the default face. If this is actually
629 defined by the font then it is probably the best thing to
630 actually use. If it isn't, we have assumed it is 'n' and have
631 already calculated its width. Thus we can avoid a call to
632 XTextWidth on X frames by just querying the default width. */
633 return XFONT_INSTANCE
634 (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width;
635 }
636
637 static int
638 tab_pix_width (struct window *w)
639 {
640 return space_width (w) * tab_char_width (w);
641 }
642
643 /* Given a pixel position in a window, return the pixel location of
644 the next tabstop. Tabs are calculated from the left window edge in
645 terms of spaces displayed in the default face. Formerly the space
646 width was determined using the currently active face. That method
647 leads to tabstops which do not line up. */
648
649 static int
650 next_tab_position (struct window *w, int start_pixpos, int left_pixpos)
651 {
652 int n_pos = left_pixpos;
653 int pix_tab_width = tab_pix_width (w);
654
655 /* Adjust n_pos for any hscrolling which has happened. */
656 if (WINDOW_SCROLLED (w))
657 n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset;
658
659 while (n_pos <= start_pixpos)
660 n_pos += pix_tab_width;
661
662 return n_pos;
663 }
664
665 /* For the given window, calculate the outside and margin boundaries for a
666 display line. The whitespace boundaries must be calculated by the text
667 layout routines. */
668
669 layout_bounds
670 calculate_display_line_boundaries (struct window *w, int modeline)
671 {
672 layout_bounds bounds;
673
674 /* Set the outermost boundaries which are the boundaries of the
675 window itself minus the gutters (and minus the scrollbars if this
676 is for the modeline). */
677 if (!modeline)
678 {
679 bounds.left_out = WINDOW_TEXT_LEFT (w);
680 bounds.right_out = WINDOW_TEXT_RIGHT (w);
681 }
682 else
683 {
684 bounds.left_out = WINDOW_MODELINE_LEFT (w);
685 bounds.right_out = WINDOW_MODELINE_RIGHT (w);
686 }
687
688 /* The inner boundaries mark where the glyph margins are located. */
689 bounds.left_in = bounds.left_out + window_left_margin_width (w);
690 bounds.right_in = bounds.right_out - window_right_margin_width (w);
691
692 /* We cannot fully calculate the whitespace boundaries as they
693 depend on the contents of the line being displayed. */
694 bounds.left_white = bounds.left_in;
695 bounds.right_white = bounds.right_in;
696
697 return bounds;
698 }
699
700 /* Given a display line and a starting position, ensure that the
701 contents of the display line accurately represent the visual
702 representation of the buffer contents starting from the given
703 position when displayed in the given window. The display line ends
704 when the contents of the line reach the right boundary of the given
705 window. */
706
707 static Bufpos
708 generate_display_line (struct window *w, struct display_line *dl, int bounds,
709 Bufpos start_pos, prop_block_dynarr **prop,
710 int type)
711 {
712 Bufpos ret_bufpos;
713 int overlay_width;
714 struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
715
716 /* If our caller hasn't already set the boundaries, then do so now. */
717 if (!bounds)
718 dl->bounds = calculate_display_line_boundaries (w, 0);
719
720 /* Reset what this line is using. */
721 if (dl->display_blocks)
722 Dynarr_reset (dl->display_blocks);
723 if (dl->left_glyphs)
724 {
725 Dynarr_free (dl->left_glyphs);
726 dl->left_glyphs = 0;
727 }
728 if (dl->right_glyphs)
729 {
730 Dynarr_free (dl->right_glyphs);
731 dl->right_glyphs = 0;
732 }
733
734 /* We aren't generating a modeline at the moment. */
735 dl->modeline = 0;
736
737 /* Create a display block for the text region of the line. */
738 {
739 /* #### urk urk urk!!! Chuck fix this shit! */
740 Bytind hacked_up_bytind =
741 create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
742 prop, type);
743 if (hacked_up_bytind > BI_BUF_ZV (b))
744 ret_bufpos = BUF_ZV (b) + 1;
745 else
746 ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
747 }
748 dl->bufpos = start_pos;
749 if (dl->end_bufpos < dl->bufpos)
750 dl->end_bufpos = dl->bufpos;
751
752 if (MARKERP (Voverlay_arrow_position)
753 && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
754 && start_pos == marker_position (Voverlay_arrow_position)
755 && (STRINGP (Voverlay_arrow_string)
756 || GLYPHP (Voverlay_arrow_string)))
757 {
758 overlay_width = create_overlay_glyph_block (w, dl);
759 }
760 else
761 overlay_width = 0;
762
763 /* If there are left glyphs associated with any character in the
764 text block, then create a display block to handle them. */
765 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
766 create_left_glyph_block (w, dl, overlay_width);
767
768 /* If there are right glyphs associated with any character in the
769 text block, then create a display block to handle them. */
770 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
771 create_right_glyph_block (w, dl);
772
773 /* In the future additional types of display blocks may be generated
774 here. */
775
776 w->last_redisplay_pos = ret_bufpos;
777
778 return ret_bufpos;
779 }
780
781 /* Adds an hscroll glyph to a display block. If this is called, then
782 the block had better be empty.
783
784 Yes, there are multiple places where this function is called but
785 that is the way it has to be. Each calling function has to deal
786 with bi_start_col_enabled a little differently depending on the
787 object being worked with. */
788
789 static prop_block_dynarr *
790 add_hscroll_rune (pos_data *data)
791 {
792 struct glyph_block gb;
793 prop_block_dynarr *retval;
794 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
795 unsigned int old_cursor_type = data->cursor_type;
796 Bytind bi_old_bufpos = data->bi_bufpos;
797
798 if (data->cursor_type == CURSOR_ON
799 && data->bi_cursor_bufpos >= data->bi_start_col_enabled
800 && data->bi_cursor_bufpos <= data->bi_bufpos)
801 {
802 data->bi_cursor_bufpos = data->bi_start_col_enabled;
803 }
804 else
805 {
806 data->cursor_type = NO_CURSOR;
807 }
808
809 data->bi_endpos = data->bi_bufpos;
810 data->bi_bufpos = data->bi_start_col_enabled;
811
812 gb.extent = Qnil;
813 gb.glyph = Vhscroll_glyph;
814 {
815 int oldpixpos = data->pixpos;
816 retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
817 GLYPH_CACHEL (XWINDOW (data->window),
818 HSCROLL_GLYPH_INDEX));
819 data->hscroll_glyph_width_adjust =
820 data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
821 }
822 data->bi_endpos = 0;
823 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
824 data->cursor_type = old_cursor_type;
825 data->bi_bufpos = bi_old_bufpos;
826
827 data->bi_start_col_enabled = 0;
828 return retval;
829 }
830
831 /* Adds a character rune to a display block. If there is not enough
832 room to fit the rune on the display block (as determined by the
833 MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
834
835 static prop_block_dynarr *
836 add_emchar_rune (pos_data *data)
837 {
838 struct rune rb, *crb;
839 int width, local;
840
841 if (data->start_col)
842 {
843 data->start_col--;
844
845 if (data->start_col)
846 return NULL;
847 }
848
849 if (data->bi_start_col_enabled)
850 {
851 return add_hscroll_rune (data);
852 }
853
854 if (data->ch == '\n')
855 {
856 data->font_is_bogus = 0;
857 /* Cheesy end-of-line pseudo-character. */
858 width = data->blank_width;
859 }
860 else
861 {
862 Lisp_Object charset = CHAR_CHARSET (data->ch);
863 if (!EQ (charset, data->last_charset) ||
864 data->findex != data->last_findex)
865 {
866 /* OK, we need to do things the hard way. */
867 struct window *w = XWINDOW (data->window);
868 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
869 Lisp_Object font_instance =
870 ensure_face_cachel_contains_charset (cachel, data->window,
871 charset);
872 struct Lisp_Font_Instance *fi;
873
874 if (EQ (font_instance, Vthe_null_font_instance))
875 {
876 font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
877 data->font_is_bogus = 1;
878 }
879 else
880 data->font_is_bogus = 0;
881
882 fi = XFONT_INSTANCE (font_instance);
883 if (!fi->proportional_p)
884 /* sweetness and light. */
885 data->last_char_width = fi->width;
886 else
887 data->last_char_width = -1;
888 data->new_ascent = max (data->new_ascent, (int) fi->ascent);
889 data->new_descent = max (data->new_descent, (int) fi->descent);
890 data->last_charset = charset;
891 data->last_findex = data->findex;
892 }
893
894 width = data->last_char_width;
895 if (width < 0)
896 {
897 /* bummer. Proportional fonts. */
898 width = redisplay_text_width_emchar_string (XWINDOW (data->window),
899 data->findex,
900 &data->ch, 1);
901 }
902 }
903
904 if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
905 {
906 return ADD_FAILED;
907 }
908
909 if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
910 {
911 crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
912 local = 0;
913 }
914 else
915 {
916 crb = &rb;
917 local = 1;
918 }
919
920 crb->findex = data->findex;
921 crb->xpos = data->pixpos;
922 crb->width = width;
923 if (data->bi_bufpos)
924 {
925 if (NILP (data->string))
926 crb->bufpos =
927 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
928 data->bi_bufpos);
929 else
930 crb->bufpos =
931 bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
932 }
933 else if (data->is_modeline)
934 crb->bufpos = data->modeline_charpos;
935 else
936 /* fuckme if this shouldn't be an abort. */
937 /* abort (); fuckme harder, this abort gets tripped quite often,
938 in propagation and whatnot. #### fixme */
939 crb->bufpos = 0;
940 crb->type = RUNE_CHAR;
941 crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
942 crb->endpos = 0;
943
944 if (data->cursor_type == CURSOR_ON)
945 {
946 if (data->bi_bufpos == data->bi_cursor_bufpos)
947 {
948 crb->cursor_type = CURSOR_ON;
949 data->cursor_x = Dynarr_length (data->db->runes);
950 }
951 else
952 crb->cursor_type = CURSOR_OFF;
953 }
954 else if (data->cursor_type == NEXT_CURSOR)
955 {
956 crb->cursor_type = CURSOR_ON;
957 data->cursor_x = Dynarr_length (data->db->runes);
958 data->cursor_type = NO_CURSOR;
959 }
960 else if (data->cursor_type == IGNORE_CURSOR)
961 crb->cursor_type = IGNORE_CURSOR;
962 else
963 crb->cursor_type = CURSOR_OFF;
964
965 if (local)
966 Dynarr_add (data->db->runes, *crb);
967 else
968 Dynarr_increment (data->db->runes);
969
970 data->pixpos += width;
971
972 return NULL;
973 }
974
975 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
976 for each character in the string. Propagate any left-over data
977 unless NO_PROP is non-zero. */
978
979 static prop_block_dynarr *
980 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
981 Bytecount c_length, int no_prop)
982 {
983 Bufbyte *pos, *end = c_string + c_length;
984 prop_block_dynarr *prop;
985
986 /* #### This function is too simplistic. It needs to do the same
987 sort of character interpretation (display-table lookup,
988 ctl-arrow checking), etc. that create_text_block() does.
989 The functionality to do this in that routine needs to be
990 modularized. */
991
992 for (pos = c_string; pos < end;)
993 {
994 data->ch = charptr_emchar (pos);
995
996 prop = add_emchar_rune (data);
997
998 if (prop)
999 {
1000 if (no_prop)
1001 return ADD_FAILED;
1002 else
1003 {
1004 struct prop_block pb;
1005 Bytecount len = end - pos;
1006 prop = Dynarr_new (prop_block);
1007
1008 pb.type = PROP_STRING;
1009 pb.data.p_string.str = xnew_array (Bufbyte, len);
1010 strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
1011 pb.data.p_string.len = len;
1012
1013 Dynarr_add (prop, pb);
1014 return prop;
1015 }
1016 }
1017 INC_CHARPTR (pos);
1018 assert (pos <= end);
1019 }
1020
1021 return NULL;
1022 }
1023
1024 /* Add a single rune of the specified width. The area covered by this
1025 rune will be displayed in the foreground color of the associated
1026 face. */
1027
1028 static prop_block_dynarr *
1029 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1030 {
1031 struct rune rb;
1032
1033 /* If data->start_col is not 0 then this call to add_blank_rune must have
1034 been to add it as a tab. */
1035 if (data->start_col)
1036 {
1037 /* assert (w != NULL) */
1038 prop_block_dynarr *retval;
1039
1040 /* If we have still not fully scrolled horizontally, subtract
1041 the width of this tab and return. */
1042 if (char_tab_width < data->start_col)
1043 {
1044 data->start_col -= char_tab_width;
1045 return NULL;
1046 }
1047 else if (char_tab_width == data->start_col)
1048 data->blank_width = 0;
1049 else
1050 {
1051 int spcwid = space_width (w);
1052
1053 if (spcwid >= data->blank_width)
1054 data->blank_width = 0;
1055 else
1056 data->blank_width -= spcwid;
1057 }
1058
1059 data->start_col = 0;
1060 retval = add_hscroll_rune (data);
1061
1062 /* Could be caused by the handling of the hscroll rune. */
1063 if (retval != NULL || !data->blank_width)
1064 return retval;
1065 }
1066
1067 /* Blank runes are always calculated to fit. */
1068 assert (data->pixpos + data->blank_width <= data->max_pixpos);
1069
1070 rb.findex = data->findex;
1071 rb.xpos = data->pixpos;
1072 rb.width = data->blank_width;
1073 if (data->bi_bufpos)
1074 rb.bufpos =
1075 bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1076 data->bi_bufpos);
1077 else
1078 /* #### and this is really correct too? */
1079 rb.bufpos = 0;
1080 rb.endpos = 0;
1081 rb.type = RUNE_BLANK;
1082
1083 if (data->cursor_type == CURSOR_ON)
1084 {
1085 if (data->bi_bufpos == data->bi_cursor_bufpos)
1086 {
1087 rb.cursor_type = CURSOR_ON;
1088 data->cursor_x = Dynarr_length (data->db->runes);
1089 }
1090 else
1091 rb.cursor_type = CURSOR_OFF;
1092 }
1093 else if (data->cursor_type == NEXT_CURSOR)
1094 {
1095 rb.cursor_type = CURSOR_ON;
1096 data->cursor_x = Dynarr_length (data->db->runes);
1097 data->cursor_type = NO_CURSOR;
1098 }
1099 else
1100 rb.cursor_type = CURSOR_OFF;
1101
1102 Dynarr_add (data->db->runes, rb);
1103 data->pixpos += data->blank_width;
1104
1105 return NULL;
1106 }
1107
1108 /* Add runes representing a character in octal. */
1109
1110 #define ADD_NEXT_OCTAL_RUNE_CHAR do \
1111 { \
1112 if (add_failed || (add_failed = add_emchar_rune (data))) \
1113 { \
1114 struct prop_block pb; \
1115 if (!prop) \
1116 prop = Dynarr_new (prop_block); \
1117 \
1118 pb.type = PROP_CHAR; \
1119 pb.data.p_char.ch = data->ch; \
1120 pb.data.p_char.cursor_type = data->cursor_type; \
1121 Dynarr_add (prop, pb); \
1122 } \
1123 } while (0)
1124
1125 static prop_block_dynarr *
1126 add_octal_runes (pos_data *data)
1127 {
1128 prop_block_dynarr *prop, *add_failed;
1129 Emchar orig_char = data->ch;
1130 unsigned int orig_cursor_type = data->cursor_type;
1131
1132 /* Initialize */
1133 prop = NULL;
1134 add_failed = NULL;
1135
1136 if (data->start_col)
1137 data->start_col--;
1138
1139 if (!data->start_col)
1140 {
1141 if (data->bi_start_col_enabled)
1142 {
1143 add_failed = add_hscroll_rune (data);
1144 }
1145 else
1146 {
1147 struct glyph_block gb;
1148 struct window *w = XWINDOW (data->window);
1149
1150 gb.extent = Qnil;
1151 gb.glyph = Voctal_escape_glyph;
1152 add_failed =
1153 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1154 GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1155 }
1156 }
1157
1158 /* We only propagate information if the glyph was partially
1159 added. */
1160 if (add_failed)
1161 return add_failed;
1162
1163 data->cursor_type = IGNORE_CURSOR;
1164
1165 if (data->ch >= 0x100)
1166 {
1167 /* If the character is an extended Mule character, it could have
1168 up to 19 bits. For the moment, we treat it as a seven-digit
1169 octal number. This is not that pretty, but whatever. */
1170 data->ch = (7 & (orig_char >> 18)) + '0';
1171 ADD_NEXT_OCTAL_RUNE_CHAR;
1172
1173 data->ch = (7 & (orig_char >> 15)) + '0';
1174 ADD_NEXT_OCTAL_RUNE_CHAR;
1175
1176 data->ch = (7 & (orig_char >> 12)) + '0';
1177 ADD_NEXT_OCTAL_RUNE_CHAR;
1178
1179 data->ch = (7 & (orig_char >> 9)) + '0';
1180 ADD_NEXT_OCTAL_RUNE_CHAR;
1181 }
1182
1183 data->ch = (7 & (orig_char >> 6)) + '0';
1184 ADD_NEXT_OCTAL_RUNE_CHAR;
1185
1186 data->ch = (7 & (orig_char >> 3)) + '0';
1187 ADD_NEXT_OCTAL_RUNE_CHAR;
1188
1189 data->ch = (7 & orig_char) + '0';
1190 ADD_NEXT_OCTAL_RUNE_CHAR;
1191
1192 data->cursor_type = orig_cursor_type;
1193 return prop;
1194 }
1195
1196 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1197
1198 /* Add runes representing a control character to a display block. */
1199
1200 static prop_block_dynarr *
1201 add_control_char_runes (pos_data *data, struct buffer *b)
1202 {
1203 if (!NILP (b->ctl_arrow))
1204 {
1205 prop_block_dynarr *prop;
1206 Emchar orig_char = data->ch;
1207 unsigned int old_cursor_type = data->cursor_type;
1208
1209 /* Initialize */
1210 prop = NULL;
1211
1212 if (data->start_col)
1213 data->start_col--;
1214
1215 if (!data->start_col)
1216 {
1217 if (data->bi_start_col_enabled)
1218 {
1219 prop_block_dynarr *retval;
1220
1221 retval = add_hscroll_rune (data);
1222 if (retval)
1223 return retval;
1224 }
1225 else
1226 {
1227 struct glyph_block gb;
1228 struct window *w = XWINDOW (data->window);
1229
1230 gb.extent = Qnil;
1231 gb.glyph = Vcontrol_arrow_glyph;
1232
1233 /* We only propagate information if the glyph was partially
1234 added. */
1235 if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1236 GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1237 return ADD_FAILED;
1238 }
1239 }
1240
1241 if (orig_char == 0177)
1242 data->ch = '?';
1243 else
1244 data->ch = orig_char ^ 0100;
1245 data->cursor_type = IGNORE_CURSOR;
1246
1247 if (add_emchar_rune (data))
1248 {
1249 struct prop_block pb;
1250 if (!prop)
1251 prop = Dynarr_new (prop_block);
1252
1253 pb.type = PROP_CHAR;
1254 pb.data.p_char.ch = data->ch;
1255 pb.data.p_char.cursor_type = data->cursor_type;
1256 Dynarr_add (prop, pb);
1257 }
1258
1259 data->cursor_type = old_cursor_type;
1260 return prop;
1261 }
1262 else
1263 {
1264 return add_octal_runes (data);
1265 }
1266 }
1267
1268 static prop_block_dynarr *
1269 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
1270 {
1271 prop_block_dynarr *prop = NULL;
1272
1273 if (STRINGP (entry))
1274 {
1275 prop = add_bufbyte_string_runes (data,
1276 XSTRING_DATA (entry),
1277 XSTRING_LENGTH (entry),
1278 0);
1279 }
1280 else if (GLYPHP (entry))
1281 {
1282 if (data->start_col)
1283 data->start_col--;
1284
1285 if (!data->start_col && data->bi_start_col_enabled)
1286 {
1287 prop = add_hscroll_rune (data);
1288 }
1289 else
1290 {
1291 struct glyph_block gb;
1292
1293 gb.glyph = entry;
1294 gb.extent = Qnil;
1295 prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1296 }
1297 }
1298 else if (CHAR_OR_CHAR_INTP (entry))
1299 {
1300 data->ch = XCHAR_OR_CHAR_INT (entry);
1301 prop = add_emchar_rune (data);
1302 }
1303 else if (CONSP (entry))
1304 {
1305 if (EQ (XCAR (entry), Qformat)
1306 && CONSP (XCDR (entry))
1307 && STRINGP (XCAR (XCDR (entry))))
1308 {
1309 Lisp_Object format = XCAR (XCDR (entry));
1310 Bytind len = XSTRING_LENGTH (format);
1311 Bufbyte *src = XSTRING_DATA (format), *end = src + len;
1312 Bufbyte *result = alloca_array (Bufbyte, len);
1313 Bufbyte *dst = result;
1314
1315 while (src < end)
1316 {
1317 Emchar c = charptr_emchar (src);
1318 INC_CHARPTR (src);
1319 if (c != '%' || src == end)
1320 dst += set_charptr_emchar (dst, c);
1321 else
1322 {
1323 c = charptr_emchar (src);
1324 INC_CHARPTR (src);
1325 switch (c)
1326 {
1327 /*case 'x':
1328 dst += long_to_string_base ((char *)dst, data->ch, 16);
1329 break;*/
1330 case '%':
1331 dst += set_charptr_emchar (dst, '%');
1332 break;
1333 }
1334 }
1335 }
1336 prop = add_bufbyte_string_runes (data, result, dst - result, 0);
1337 }
1338 }
1339
1340 /* Else blow it off because someone added a bad entry and we don't
1341 have any safe way of signaling an error. */
1342 return prop;
1343 }
1344
1345 /* Given a display table entry, call the appropriate functions to
1346 display each element of the entry. */
1347
1348 static prop_block_dynarr *
1349 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1350 {
1351 prop_block_dynarr *prop = NULL;
1352 if (VECTORP (entry))
1353 {
1354 struct Lisp_Vector *de = XVECTOR (entry);
1355 EMACS_INT len = vector_length (de);
1356 int elt;
1357
1358 for (elt = 0; elt < len; elt++)
1359 {
1360 if (NILP (vector_data (de)[elt]))
1361 continue;
1362 else
1363 prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
1364 /* Else blow it off because someone added a bad entry and we
1365 don't have any safe way of signaling an error. Hey, this
1366 comment sounds familiar. */
1367
1368 /* #### Still need to add any remaining elements to the
1369 propagation information. */
1370 if (prop)
1371 return prop;
1372 }
1373 }
1374 else
1375 prop = add_disp_table_entry_runes_1 (data, entry);
1376 return prop;
1377 }
1378
1379 /* Add runes which were propagated from the previous line. */
1380
1381 static prop_block_dynarr *
1382 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1383 {
1384 /* #### Remember to handle start_col parameter of data when the rest of
1385 this is finished. */
1386 /* #### Chuck -- I've redone this function a bit. It looked like the
1387 case of not all the propagation blocks being added was not handled
1388 well. */
1389 /* #### Chuck -- I also think the double indirection of PROP is kind
1390 of bogus. A cleaner solution is just to check for
1391 Dynarr_length (prop) > 0. */
1392 /* #### This function also doesn't even pay attention to ADD_FAILED!
1393 This is seriously fucked! Seven ####'s in 130 lines -- is that a
1394 record? */
1395 int elt;
1396 prop_block_dynarr *add_failed;
1397 Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1398 unsigned int old_cursor_type = data->cursor_type;
1399
1400 for (elt = 0; elt < Dynarr_length (*prop); elt++)
1401 {
1402 struct prop_block *pb = Dynarr_atp (*prop, elt);
1403
1404 switch (pb->type)
1405 {
1406 case PROP_CHAR:
1407 data->ch = pb->data.p_char.ch;
1408 data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1409 data->cursor_type = pb->data.p_char.cursor_type;
1410 add_failed = add_emchar_rune (data);
1411
1412 if (add_failed)
1413 goto oops_no_more_space;
1414 break;
1415 case PROP_STRING:
1416 if (pb->data.p_string.str)
1417 xfree (pb->data.p_string.str);
1418 /* #### bogus bogus -- this doesn't do anything!
1419 Should probably call add_bufbyte_string_runes(),
1420 once that function is fixed. */
1421 break;
1422 case PROP_MINIBUF_PROMPT:
1423 {
1424 face_index old_findex = data->findex;
1425 Bytind bi_old_bufpos = data->bi_bufpos;
1426
1427 data->findex = DEFAULT_INDEX;
1428 data->bi_bufpos = 0;
1429 data->cursor_type = NO_CURSOR;
1430
1431 while (pb->data.p_string.len > 0)
1432 {
1433 data->ch = charptr_emchar (pb->data.p_string.str);
1434 add_failed = add_emchar_rune (data);
1435
1436 if (add_failed)
1437 {
1438 data->findex = old_findex;
1439 data->bi_bufpos = bi_old_bufpos;
1440 goto oops_no_more_space;
1441 }
1442 else
1443 {
1444 /* Complicated equivalent of ptr++, len-- */
1445 Bufbyte *oldpos = pb->data.p_string.str;
1446 INC_CHARPTR (pb->data.p_string.str);
1447 pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1448 }
1449 }
1450
1451 data->findex = old_findex;
1452 /* ##### FIXME FIXME FIXME -- Upon successful return from
1453 this function, data->bi_bufpos is automatically incremented.
1454 However, we don't want that to happen if we were adding
1455 the minibuffer prompt. */
1456 {
1457 struct buffer *buf =
1458 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1459 /* #### Chuck fix this shit or I'm gonna scream! */
1460 if (bi_old_bufpos > BI_BUF_BEGV (buf))
1461 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1462 else
1463 /* #### is this correct? Does anyone know?
1464 Does anyone care? Is this a cheesy hack or what? */
1465 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1466 }
1467 }
1468 break;
1469 case PROP_BLANK:
1470 {
1471 /* #### I think it's unnecessary and misleading to preserve
1472 the blank_width, as it implies that the value carries
1473 over from one rune to the next, which is wrong. */
1474 int old_width = data->blank_width;
1475 face_index old_findex = data->findex;
1476
1477 data->findex = pb->data.p_blank.findex;
1478 data->blank_width = pb->data.p_blank.width;
1479 data->bi_cursor_bufpos = 0;
1480 data->cursor_type = IGNORE_CURSOR;
1481
1482 if (data->pixpos + data->blank_width > data->max_pixpos)
1483 data->blank_width = data->max_pixpos - data->pixpos;
1484
1485 /* We pass a bogus value of char_tab_width. It shouldn't
1486 matter because unless something is really screwed up
1487 this call won't cause that arg to be used. */
1488 add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1489
1490 /* This can happen in the case where we have a tab which
1491 is wider than the window. */
1492 if (data->blank_width != pb->data.p_blank.width)
1493 {
1494 pb->data.p_blank.width -= data->blank_width;
1495 add_failed = ADD_FAILED;
1496 }
1497
1498 data->findex = old_findex;
1499 data->blank_width = old_width;
1500
1501 if (add_failed)
1502 goto oops_no_more_space;
1503 }
1504 break;
1505 default:
1506 abort ();
1507 }
1508 }
1509
1510 oops_no_more_space:
1511
1512 data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1513 data->cursor_type = old_cursor_type;
1514 if (elt < Dynarr_length (*prop))
1515 {
1516 Dynarr_delete_many (*prop, 0, elt);
1517 return *prop;
1518 }
1519 else
1520 {
1521 Dynarr_free (*prop);
1522 return NULL;
1523 }
1524 }
1525
1526 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1527 the display block, but add all other types to the appropriate list
1528 of the display line. They will be added later by different
1529 routines. */
1530
1531 static prop_block_dynarr *
1532 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1533 int allow_cursor, struct glyph_cachel *cachel)
1534 {
1535 struct window *w = XWINDOW (data->window);
1536
1537 /* A nil extent indicates a special glyph (ex. truncator). */
1538 if (NILP (gb->extent)
1539 || (pos_type == BEGIN_GLYPHS &&
1540 extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1541 || (pos_type == END_GLYPHS &&
1542 extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT))
1543 {
1544 struct rune rb;
1545 int width;
1546 int xoffset = 0;
1547 int ascent, descent;
1548 Lisp_Object baseline;
1549 Lisp_Object face;
1550
1551 if (cachel)
1552 width = cachel->width;
1553 else
1554 width = glyph_width (gb->glyph, Qnil, data->findex, data->window);
1555
1556 if (!width)
1557 return NULL;
1558
1559 if (data->start_col || data->start_col_xoffset)
1560 {
1561 prop_block_dynarr *retval;
1562 int glyph_char_width = width / space_width (w);
1563
1564 /* If we still have not fully scrolled horizontally after
1565 taking into account the width of the glyph, subtract its
1566 width and return. */
1567 if (glyph_char_width < data->start_col)
1568 {
1569 data->start_col -= glyph_char_width;
1570 return NULL;
1571 }
1572 else if (glyph_char_width == data->start_col)
1573 width = 0;
1574 else
1575 {
1576 xoffset = space_width (w) * data->start_col;
1577 width -= xoffset;
1578
1579 /* #### Can this happen? */
1580 if (width < 0)
1581 width = 0;
1582 }
1583
1584 data->start_col = 0;
1585 retval = add_hscroll_rune (data);
1586
1587 /* Could be caused by the handling of the hscroll rune. */
1588 if (retval != NULL || !width)
1589 return retval;
1590 }
1591 else
1592 xoffset = 0;
1593
1594 if (data->pixpos + width > data->max_pixpos)
1595 {
1596 /* If this is the first object we are attempting to add to
1597 the line then we ignore the horizontal_clip threshold.
1598 Otherwise we will loop until the bottom of the window
1599 continually failing to add this glyph because it is wider
1600 than the window. We could alternatively just completely
1601 ignore the glyph and proceed from there but I think that
1602 this is a better solution. */
1603 if (Dynarr_length (data->db->runes)
1604 && data->max_pixpos - data->pixpos < horizontal_clip)
1605 return ADD_FAILED;
1606 else
1607 width = data->max_pixpos - data->pixpos;
1608 }
1609
1610 if (cachel)
1611 {
1612 ascent = cachel->ascent;
1613 descent = cachel->descent;
1614 }
1615 else
1616 {
1617 ascent = glyph_ascent (gb->glyph, Qnil, data->findex, data->window);
1618 descent = glyph_descent (gb->glyph, Qnil, data->findex,
1619 data->window);
1620 }
1621
1622 baseline = glyph_baseline (gb->glyph, data->window);
1623
1624 if (glyph_contrib_p (gb->glyph, data->window))
1625 {
1626 /* A pixmap that has not had a baseline explicitly set. Its
1627 contribution will be determined later. */
1628 if (NILP (baseline))
1629 {
1630 int height = ascent + descent;
1631 data->max_pixmap_height = max (data->max_pixmap_height, height);
1632 }
1633
1634 /* A string so determine contribution normally. */
1635 else if (EQ (baseline, Qt))
1636 {
1637 data->new_ascent = max (data->new_ascent, ascent);
1638 data->new_descent = max (data->new_descent, descent);
1639 }
1640
1641 /* A pixmap with an explicitly set baseline. We determine the
1642 contribution here. */
1643 else if (INTP (baseline))
1644 {
1645 int height = ascent + descent;
1646 int pix_ascent, pix_descent;
1647
1648 pix_ascent = height * XINT (baseline) / 100;
1649 pix_descent = height - pix_ascent;
1650
1651 data->new_ascent = max (data->new_ascent, pix_ascent);
1652 data->new_descent = max (data->new_descent, pix_descent);
1653 }
1654
1655 /* Otherwise something is screwed up. */
1656 else
1657 abort ();
1658 }
1659
1660 face = glyph_face (gb->glyph, data->window);
1661 if (NILP (face))
1662 rb.findex = data->findex;
1663 else
1664 rb.findex = get_builtin_face_cache_index (w, face);
1665
1666 rb.xpos = data->pixpos;
1667 rb.width = width;
1668 rb.bufpos = 0; /* glyphs are never "at" anywhere */
1669 if (data->bi_endpos)
1670 /* #### is this necessary at all? */
1671 rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1672 data->bi_endpos);
1673 else
1674 rb.endpos = 0;
1675 rb.type = RUNE_DGLYPH;
1676 /* #### Ben sez: this is way bogus if the glyph is a string.
1677 You should not make the output routines have to cope with
1678 this. The string could contain Mule characters, or non-
1679 printable characters, or characters to be passed through
1680 the display table, or non-character objects (when this gets
1681 implemented), etc. Instead, this routine here should parse
1682 the string into a series of runes. */
1683 rb.object.dglyph.glyph = gb->glyph;
1684 rb.object.dglyph.extent = gb->extent;
1685 rb.object.dglyph.xoffset = xoffset;
1686
1687 if (allow_cursor)
1688 {
1689 rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1690 data->bi_bufpos);
1691
1692 if (data->cursor_type == CURSOR_ON)
1693 {
1694 if (data->bi_bufpos == data->bi_cursor_bufpos)
1695 {
1696 rb.cursor_type = CURSOR_ON;
1697 data->cursor_x = Dynarr_length (data->db->runes);
1698 }
1699 else
1700 rb.cursor_type = CURSOR_OFF;
1701 }
1702 else if (data->cursor_type == NEXT_CURSOR)
1703 {
1704 rb.cursor_type = CURSOR_ON;
1705 data->cursor_x = Dynarr_length (data->db->runes);
1706 data->cursor_type = NO_CURSOR;
1707 }
1708 else if (data->cursor_type == IGNORE_CURSOR)
1709 rb.cursor_type = IGNORE_CURSOR;
1710 else if (data->cursor_type == NO_CURSOR)
1711 rb.cursor_type = NO_CURSOR;
1712 else
1713 rb.cursor_type = CURSOR_OFF;
1714 }
1715 else
1716 rb.cursor_type = CURSOR_OFF;
1717
1718 Dynarr_add (data->db->runes, rb);
1719 data->pixpos += width;
1720
1721 return NULL;
1722 }
1723 else
1724 {
1725 if (!NILP (glyph_face (gb->glyph, data->window)))
1726 gb->findex =
1727 get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1728 data->window));
1729 else
1730 gb->findex = data->findex;
1731
1732 if (pos_type == BEGIN_GLYPHS)
1733 {
1734 if (!data->dl->left_glyphs)
1735 data->dl->left_glyphs = Dynarr_new (glyph_block);
1736 Dynarr_add (data->dl->left_glyphs, *gb);
1737 return NULL;
1738 }
1739 else if (pos_type == END_GLYPHS)
1740 {
1741 if (!data->dl->right_glyphs)
1742 data->dl->right_glyphs = Dynarr_new (glyph_block);
1743 Dynarr_add (data->dl->right_glyphs, *gb);
1744 return NULL;
1745 }
1746 else
1747 abort (); /* there are no unknown types */
1748 }
1749
1750 return NULL; /* shut up compiler */
1751 }
1752
1753 /* Add all glyphs at position POS_TYPE that are contained in the given
1754 data. */
1755
1756 static prop_block_dynarr *
1757 add_glyph_runes (pos_data *data, int pos_type)
1758 {
1759 /* #### This still needs to handle the start_col parameter. Duh, Chuck,
1760 why didn't you just modify add_glyph_rune in the first place? */
1761 int elt;
1762 glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1763 ? data->ef->begin_glyphs
1764 : data->ef->end_glyphs);
1765 prop_block_dynarr *prop;
1766
1767 for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1768 {
1769 prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1770 0);
1771
1772 if (prop)
1773 {
1774 /* #### Add some propagation information. */
1775 return prop;
1776 }
1777 }
1778
1779 Dynarr_reset (glyph_arr);
1780
1781 return NULL;
1782 }
1783
1784 /* Given a position for a buffer in a window, ensure that the given
1785 display line DL accurately represents the text on a line starting
1786 at the given position.
1787
1788 NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1789 You must do appropriate conversion. */
1790
1791 static Bytind
1792 create_text_block (struct window *w, struct display_line *dl,
1793 Bytind bi_start_pos, prop_block_dynarr **prop,
1794 int type)
1795 {
1796 struct frame *f = XFRAME (w->frame);
1797 struct buffer *b = XBUFFER (w->buffer);
1798 struct device *d = XDEVICE (f->device);
1799
1800 pos_data data;
1801
1802 /* Don't display anything in the minibuffer if this window is not on
1803 a selected frame. We consider all other windows to be active
1804 minibuffers as it simplifies the coding. */
1805 int active_minibuffer = (!MINI_WINDOW_P (w) ||
1806 (f == device_selected_frame (d)) ||
1807 is_surrogate_for_selected_frame (f));
1808
1809 int truncate_win = window_truncation_on (w);
1810 int end_glyph_width;
1811
1812 /* If the buffer's value of selective_display is an integer then
1813 only lines that start with less than selective_display columns of
1814 space will be displayed. If selective_display is t then all text
1815 after a ^M is invisible. */
1816 int selective = (INTP (b->selective_display)
1817 ? XINT (b->selective_display)
1818 : ((!NILP (b->selective_display) ? -1 : 0)));
1819
1820 /* The variable ctl-arrow allows the user to specify what characters
1821 can actually be displayed and which octal should be used for.
1822 #### This variable should probably have some rethought done to
1823 it.
1824
1825 #### It would also be really nice if you could specify that
1826 the characters come out in hex instead of in octal. Mule
1827 does that by adding a ctl-hexa variable similar to ctl-arrow,
1828 but that's bogus -- we need a more general solution. I
1829 think you need to extend the concept of display tables
1830 into a more general conversion mechanism. Ideally you
1831 could specify a Lisp function that converts characters,
1832 but this violates the Second Golden Rule and besides would
1833 make things way way way way slow.
1834
1835 So instead, we extend the display-table concept, which was
1836 historically limited to 256-byte vectors, to one of the
1837 following:
1838
1839 a) A 256-entry vector, for backward compatibility;
1840 b) char-table, mapping characters to values;
1841 c) range-table, mapping ranges of characters to values;
1842 d) a list of the above.
1843
1844 The (d) option allows you to specify multiple display tables
1845 instead of just one. Each display table can specify conversions
1846 for some characters and leave others unchanged. The way the
1847 character gets displayed is determined by the first display table
1848 with a binding for that character. This way, you could call a
1849 function `enable-hex-display' that adds a hex display-table to
1850 the list of display tables for the current buffer.
1851
1852 #### ...not yet implemented... Also, we extend the concept of
1853 "mapping" to include a printf-like spec. Thus you can make all
1854 extended characters show up as hex with a display table like
1855 this:
1856
1857 #s(range-table data ((256 524288) (format "%x")))
1858
1859 Since more than one display table is possible, you have
1860 great flexibility in mapping ranges of characters. */
1861 Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1862 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1863 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1864 ? 255 : 160));
1865
1866 Lisp_Object face_dt, window_dt;
1867
1868 /* The text display block for this display line. */
1869 struct display_block *db = get_display_block_from_line (dl, TEXT);
1870
1871 /* The first time through the main loop we need to force the glyph
1872 data to be updated. */
1873 int initial = 1;
1874
1875 /* Apparently the new extent_fragment_update returns an end position
1876 equal to the position passed in if there are no more runs to be
1877 displayed. */
1878 int no_more_frags = 0;
1879
1880 Lisp_Object synch_minibuffers_value =
1881 symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1882
1883 dl->used_prop_data = 0;
1884 dl->num_chars = 0;
1885
1886 xzero (data);
1887 data.ef = extent_fragment_new (w->buffer, f);
1888
1889 /* These values are used by all of the rune addition routines. We add
1890 them to this structure for ease of passing. */
1891 data.d = d;
1892 XSETWINDOW (data.window, w);
1893 data.string = Qnil;
1894 data.db = db;
1895 data.dl = dl;
1896
1897 data.bi_bufpos = bi_start_pos;
1898 data.pixpos = dl->bounds.left_in;
1899 data.last_charset = Qunbound;
1900 data.last_findex = DEFAULT_INDEX;
1901 data.result_str = Qnil;
1902
1903 /* Set the right boundary adjusting it to take into account any end
1904 glyph. Save the width of the end glyph for later use. */
1905 data.max_pixpos = dl->bounds.right_in;
1906 if (truncate_win)
1907 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1908 else
1909 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1910 data.max_pixpos -= end_glyph_width;
1911
1912 if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1913 {
1914 data.bi_cursor_bufpos = BI_BUF_ZV (b);
1915 data.cursor_type = CURSOR_ON;
1916 }
1917 else if (MINI_WINDOW_P (w) && !active_minibuffer)
1918 data.cursor_type = NO_CURSOR;
1919 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1920 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1921 d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1922 f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1923 {
1924 data.bi_cursor_bufpos = BI_BUF_PT (b);
1925 data.cursor_type = CURSOR_ON;
1926 }
1927 else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1928 {
1929 data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1930 data.cursor_type = CURSOR_ON;
1931 }
1932 else
1933 data.cursor_type = NO_CURSOR;
1934 data.cursor_x = -1;
1935
1936 data.start_col = w->hscroll;
1937 data.start_col_xoffset = w->left_xoffset;
1938 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1939 data.hscroll_glyph_width_adjust = 0;
1940
1941 /* We regenerate the line from the very beginning. */
1942 Dynarr_reset (db->runes);
1943
1944 /* Why is this less than or equal and not just less than? If the
1945 starting position is already equal to the maximum we can't add
1946 anything else, right? Wrong. We might still have a newline to
1947 add. A newline can use the room allocated for an end glyph since
1948 if we add it we know we aren't going to be adding any end
1949 glyph. */
1950
1951 /* #### Chuck -- I think this condition should be while (1).
1952 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1953 and the begin-glyph ends exactly at the end of the window, the
1954 end-glyph and text might not be displayed. while (1) ensures
1955 that the loop terminates only when either (a) there is
1956 propagation data or (b) the end-of-line or end-of-buffer is hit.
1957
1958 #### Also I think you need to ensure that the operation
1959 "add begin glyphs; add end glyphs; add text" is atomic and
1960 can't get interrupted in the middle. If you run off the end
1961 of the line during that operation, then you keep accumulating
1962 propagation data until you're done. Otherwise, if the (e.g.)
1963 there's a begin glyph at a particular position and attempting
1964 to display that glyph results in window-end being hit and
1965 propagation data being generated, then the character at that
1966 position won't be displayed.
1967
1968 #### See also the comment after the end of this loop, below.
1969 */
1970 while (data.pixpos <= data.max_pixpos
1971 && (active_minibuffer || !NILP (synch_minibuffers_value)))
1972 {
1973 /* #### This check probably should not be necessary. */
1974 if (data.bi_bufpos > BI_BUF_ZV (b))
1975 {
1976 /* #### urk! More of this lossage! */
1977 data.bi_bufpos--;
1978 goto done;
1979 }
1980
1981 /* If selective display was an integer and we aren't working on
1982 a continuation line then find the next line we are actually
1983 supposed to display. */
1984 if (selective > 0
1985 && (data.bi_bufpos == BI_BUF_BEGV (b)
1986 || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
1987 {
1988 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
1989 {
1990 data.bi_bufpos =
1991 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
1992 if (data.bi_bufpos >= BI_BUF_ZV (b))
1993 {
1994 data.bi_bufpos = BI_BUF_ZV (b);
1995 goto done;
1996 }
1997 }
1998 }
1999
2000 /* Check for face changes. */
2001 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
2002 {
2003 /* Now compute the face and begin/end-glyph information. */
2004 data.findex =
2005 /* Remember that the extent-fragment routines deal in Bytind's. */
2006 extent_fragment_update (w, data.ef, data.bi_bufpos);
2007
2008 get_display_tables (w, data.findex, &face_dt, &window_dt);
2009
2010 if (data.bi_bufpos == data.ef->end)
2011 no_more_frags = 1;
2012 }
2013 initial = 0;
2014
2015 /* Determine what is next to be displayed. We first handle any
2016 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
2017 display then we determine what to do based on the character at the
2018 current buffer position. */
2019
2020 /* If the current position is covered by an invisible extent, do
2021 nothing (except maybe add some ellipses).
2022
2023 #### The behavior of begin and end-glyphs at the edge of an
2024 invisible extent should be investigated further. This is
2025 fairly low priority though. */
2026 if (data.ef->invisible)
2027 {
2028 /* #### Chuck, perhaps you could look at this code? I don't
2029 really know what I'm doing. */
2030 if (*prop)
2031 {
2032 Dynarr_free (*prop);
2033 *prop = 0;
2034 }
2035
2036 /* The extent fragment code only sets this when we should
2037 really display the ellipses. It makes sure the ellipses
2038 don't get displayed more than once in a row. */
2039 if (data.ef->invisible_ellipses)
2040 {
2041 struct glyph_block gb;
2042
2043 data.ef->invisible_ellipses_already_displayed = 1;
2044 data.ef->invisible_ellipses = 0;
2045 gb.extent = Qnil;
2046 gb.glyph = Vinvisible_text_glyph;
2047 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2048 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2049 /* Perhaps they shouldn't propagate if the very next thing
2050 is to display a newline (for compatibility with
2051 selective-display-ellipses)? Maybe that's too
2052 abstruse. */
2053 if (*prop)
2054 goto done;
2055 }
2056
2057 /* If point is in an invisible region we place it on the
2058 next visible character. */
2059 if (data.cursor_type == CURSOR_ON
2060 && data.bi_bufpos == data.bi_cursor_bufpos)
2061 {
2062 data.cursor_type = NEXT_CURSOR;
2063 }
2064
2065 /* #### What if we we're dealing with a display table? */
2066 if (data.start_col)
2067 data.start_col--;
2068
2069 if (data.bi_bufpos == BI_BUF_ZV (b))
2070 goto done;
2071 else
2072 INC_BYTIND (b, data.bi_bufpos);
2073 }
2074
2075 /* If there is propagation data, then it represents the current
2076 buffer position being displayed. Add them and advance the
2077 position counter. This might also add the minibuffer
2078 prompt. */
2079 else if (*prop)
2080 {
2081 dl->used_prop_data = 1;
2082 *prop = add_propagation_runes (prop, &data);
2083
2084 if (*prop)
2085 goto done; /* gee, a really narrow window */
2086 else if (data.bi_bufpos == BI_BUF_ZV (b))
2087 goto done;
2088 else if (data.bi_bufpos < BI_BUF_BEGV (b))
2089 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2090 data.bi_bufpos = BI_BUF_BEGV (b);
2091 else
2092 INC_BYTIND (b, data.bi_bufpos);
2093 }
2094
2095 /* If there are end glyphs, add them to the line. These are
2096 the end glyphs for the previous run of text. We add them
2097 here rather than doing them at the end of handling the
2098 previous run so that glyphs at the beginning and end of
2099 a line are handled correctly. */
2100 else if (Dynarr_length (data.ef->end_glyphs) > 0)
2101 {
2102 *prop = add_glyph_runes (&data, END_GLYPHS);
2103 if (*prop)
2104 goto done;
2105 }
2106
2107 /* If there are begin glyphs, add them to the line. */
2108 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2109 {
2110 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2111 if (*prop)
2112 goto done;
2113 }
2114
2115 /* If at end-of-buffer, we've already processed begin and
2116 end-glyphs at this point and there's no text to process,
2117 so we're done. */
2118 else if (data.bi_bufpos == BI_BUF_ZV (b))
2119 goto done;
2120
2121 else
2122 {
2123 Lisp_Object entry = Qnil;
2124 /* Get the character at the current buffer position. */
2125 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2126 if (!NILP (face_dt) || !NILP (window_dt))
2127 entry = display_table_entry (data.ch, face_dt, window_dt);
2128
2129 /* If there is a display table entry for it, hand it off to
2130 add_disp_table_entry_runes and let it worry about it. */
2131 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
2132 {
2133 *prop = add_disp_table_entry_runes (&data, entry);
2134
2135 if (*prop)
2136 goto done;
2137 }
2138
2139 /* Check if we have hit a newline character. If so, add a marker
2140 to the line and end this loop. */
2141 else if (data.ch == '\n')
2142 {
2143 /* We aren't going to be adding an end glyph so give its
2144 space back in order to make sure that the cursor can
2145 fit. */
2146 data.max_pixpos += end_glyph_width;
2147
2148 if (selective > 0
2149 && (bi_spaces_at_point
2150 (b, next_bytind (b, data.bi_bufpos))
2151 >= selective))
2152 {
2153 if (!NILP (b->selective_display_ellipses))
2154 {
2155 struct glyph_block gb;
2156
2157 gb.extent = Qnil;
2158 gb.glyph = Vinvisible_text_glyph;
2159 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2160 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2161 }
2162 else
2163 {
2164 /* Cheesy, cheesy, cheesy. We mark the end of the
2165 line with a special "character rune" whose width
2166 is the EOL cursor width and whose character is
2167 the non-printing character '\n'. */
2168 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2169 *prop = add_emchar_rune (&data);
2170 }
2171
2172 /* We need to set data.bi_bufpos to the start of the
2173 next visible region in order to make this line
2174 appear to contain all of the invisible area.
2175 Otherwise, the line cache won't work
2176 correctly. */
2177 INC_BYTIND (b, data.bi_bufpos);
2178 while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2179 {
2180 data.bi_bufpos =
2181 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2182 if (data.bi_bufpos >= BI_BUF_ZV (b))
2183 {
2184 data.bi_bufpos = BI_BUF_ZV (b);
2185 break;
2186 }
2187 }
2188 if (BI_BUF_FETCH_CHAR
2189 (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2190 DEC_BYTIND (b, data.bi_bufpos);
2191 }
2192 else
2193 {
2194 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2195 *prop = add_emchar_rune (&data);
2196 }
2197
2198 goto done;
2199 }
2200
2201 /* If the current character is ^M, and selective display is
2202 enabled, then add the invisible-text-glyph if
2203 selective-display-ellipses is set. In any case, this
2204 line is done. */
2205 else if (data.ch == (('M' & 037)) && selective == -1)
2206 {
2207 Bytind bi_next_bufpos;
2208
2209 /* Find the buffer position at the end of the line. */
2210 bi_next_bufpos =
2211 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2212 if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2213 == '\n')
2214 DEC_BYTIND (b, bi_next_bufpos);
2215
2216 /* If the cursor is somewhere in the elided text make
2217 sure that the cursor gets drawn appropriately. */
2218 if (data.cursor_type == CURSOR_ON
2219 && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2220 data.bi_cursor_bufpos < bi_next_bufpos))
2221 {
2222 data.cursor_type = NEXT_CURSOR;
2223 }
2224
2225 /* We won't be adding a truncation or continuation glyph
2226 so give up the room allocated for them. */
2227 data.max_pixpos += end_glyph_width;
2228
2229 if (!NILP (b->selective_display_ellipses))
2230 {
2231 /* We don't propagate anything from the invisible
2232 text glyph if it fails to fit. This is
2233 intentional. */
2234 struct glyph_block gb;
2235
2236 gb.extent = Qnil;
2237 gb.glyph = Vinvisible_text_glyph;
2238 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2239 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2240 }
2241
2242 /* Set the buffer position to the end of the line. We
2243 need to do this before potentially adding a newline
2244 so that the cursor flag will get set correctly (if
2245 needed). */
2246 data.bi_bufpos = bi_next_bufpos;
2247
2248 if (NILP (b->selective_display_ellipses)
2249 || data.bi_cursor_bufpos == bi_next_bufpos)
2250 {
2251 /* We have to at least add a newline character so
2252 that the cursor shows up properly. */
2253 data.ch = '\n';
2254 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2255 data.findex = DEFAULT_INDEX;
2256 data.start_col = 0;
2257 data.start_col_xoffset = 0;
2258 data.bi_start_col_enabled = 0;
2259
2260 add_emchar_rune (&data);
2261 }
2262
2263 /* This had better be a newline but doing it this way
2264 we'll see obvious incorrect results if it isn't. No
2265 need to abort here. */
2266 data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2267
2268 goto done;
2269 }
2270
2271 /* If the current character is considered to be printable, then
2272 just add it. */
2273 else if (data.ch >= printable_min)
2274 {
2275 *prop = add_emchar_rune (&data);
2276 if (*prop)
2277 goto done;
2278 }
2279
2280 /* If the current character is a tab, determine the next tab
2281 starting position and add a blank rune which extends from the
2282 current pixel position to that starting position. */
2283 else if (data.ch == '\t')
2284 {
2285 int tab_start_pixpos = data.pixpos;
2286 int next_tab_start;
2287 int char_tab_width;
2288 int prop_width = 0;
2289
2290 if (data.start_col > 1)
2291 tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
2292 + data.start_col_xoffset;
2293
2294 next_tab_start =
2295 next_tab_position (w, tab_start_pixpos,
2296 dl->bounds.left_in +
2297 data.hscroll_glyph_width_adjust);
2298 if (next_tab_start > data.max_pixpos)
2299 {
2300 prop_width = next_tab_start - data.max_pixpos;
2301 next_tab_start = data.max_pixpos;
2302 }
2303 data.blank_width = next_tab_start - data.pixpos;
2304 char_tab_width =
2305 (next_tab_start - tab_start_pixpos) / space_width (w);
2306
2307 *prop = add_blank_rune (&data, w, char_tab_width);
2308
2309 /* add_blank_rune is only supposed to be called with
2310 sizes guaranteed to fit in the available space. */
2311 assert (!(*prop));
2312
2313 if (prop_width)
2314 {
2315 struct prop_block pb;
2316 *prop = Dynarr_new (prop_block);
2317
2318 pb.type = PROP_BLANK;
2319 pb.data.p_blank.width = prop_width;
2320 pb.data.p_blank.findex = data.findex;
2321 Dynarr_add (*prop, pb);
2322
2323 goto done;
2324 }
2325 }
2326
2327 /* If character is a control character, pass it off to
2328 add_control_char_runes.
2329
2330 The is_*() routines have undefined results on
2331 arguments outside of the range [-1, 255]. (This
2332 often bites people who carelessly use `char' instead
2333 of `unsigned char'.)
2334 */
2335 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2336 {
2337 *prop = add_control_char_runes (&data, b);
2338
2339 if (*prop)
2340 goto done;
2341 }
2342
2343 /* If the character is above the ASCII range and we have not
2344 already handled it, then print it as an octal number. */
2345 else if (data.ch >= 0200)
2346 {
2347 *prop = add_octal_runes (&data);
2348
2349 if (*prop)
2350 goto done;
2351 }
2352
2353 /* Assume the current character is considered to be printable,
2354 then just add it. */
2355 else
2356 {
2357 *prop = add_emchar_rune (&data);
2358 if (*prop)
2359 goto done;
2360 }
2361
2362 INC_BYTIND (b, data.bi_bufpos);
2363 }
2364 }
2365
2366 done:
2367
2368 /* Determine the starting point of the next line if we did not hit the
2369 end of the buffer. */
2370 if (data.bi_bufpos < BI_BUF_ZV (b)
2371 && (active_minibuffer || !NILP (synch_minibuffers_value)))
2372 {
2373 /* #### This check is not correct. If the line terminated
2374 due to a begin-glyph or end-glyph hitting window-end, then
2375 data.ch will not point to the character at data.bi_bufpos. If
2376 you make the two changes mentioned at the top of this loop,
2377 you should be able to say '(if (*prop))'. That should also
2378 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2379 check. */
2380
2381 /* The common case is that the line ended because we hit a newline.
2382 In that case, the next character is just the next buffer
2383 position. */
2384 if (data.ch == '\n')
2385 {
2386 /* If data.start_col_enabled is still true, then the window is
2387 scrolled far enough so that nothing on this line is visible.
2388 We need to stick a truncation glyph at the beginning of the
2389 line in that case unless the line is completely blank. */
2390 if (data.bi_start_col_enabled)
2391 {
2392 if (data.cursor_type == CURSOR_ON)
2393 {
2394 if (data.bi_cursor_bufpos >= bi_start_pos
2395 && data.bi_cursor_bufpos <= data.bi_bufpos)
2396 data.bi_cursor_bufpos = data.bi_bufpos;
2397 }
2398 data.findex = DEFAULT_INDEX;
2399 data.start_col = 0;
2400 data.bi_start_col_enabled = 0;
2401
2402 if (data.bi_bufpos != bi_start_pos)
2403 {
2404 struct glyph_block gb;
2405
2406 gb.extent = Qnil;
2407 gb.glyph = Vhscroll_glyph;
2408 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2409 GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2410 }
2411 else
2412 {
2413 /* This duplicates code down below to add a newline to
2414 the end of an otherwise empty line.*/
2415 data.ch = '\n';
2416 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2417
2418 add_emchar_rune (&data);
2419 }
2420 }
2421
2422 INC_BYTIND (b, data.bi_bufpos);
2423 }
2424
2425 /* Otherwise we have a buffer line which cannot fit on one display
2426 line. */
2427 else
2428 {
2429 struct glyph_block gb;
2430 struct glyph_cachel *cachel;
2431
2432 /* If the line is to be truncated then we actually have to look
2433 for the next newline. We also add the end-of-line glyph which
2434 we know will fit because we adjusted the right border before
2435 we starting laying out the line. */
2436 data.max_pixpos += end_glyph_width;
2437 data.findex = DEFAULT_INDEX;
2438 gb.extent = Qnil;
2439
2440 if (truncate_win)
2441 {
2442 Bytind bi_pos;
2443
2444 /* Now find the start of the next line. */
2445 bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2446
2447 /* If the cursor is past the truncation line then we
2448 make it appear on the truncation glyph. If we've hit
2449 the end of the buffer then we also make the cursor
2450 appear unless eob is immediately preceded by a
2451 newline. In that case the cursor should actually
2452 appear on the next line. */
2453 if (data.cursor_type == CURSOR_ON
2454 && data.bi_cursor_bufpos >= data.bi_bufpos
2455 && (data.bi_cursor_bufpos < bi_pos ||
2456 (bi_pos == BI_BUF_ZV (b)
2457 && (bi_pos == BI_BUF_BEGV (b)
2458 || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2459 != '\n')))))
2460 data.bi_cursor_bufpos = bi_pos;
2461 else
2462 data.cursor_type = NO_CURSOR;
2463
2464 data.bi_bufpos = bi_pos;
2465 gb.glyph = Vtruncation_glyph;
2466 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2467 }
2468 else
2469 {
2470 /* The cursor can never be on the continuation glyph. */
2471 data.cursor_type = NO_CURSOR;
2472
2473 /* data.bi_bufpos is already at the start of the next line. */
2474
2475 gb.glyph = Vcontinuation_glyph;
2476 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2477 }
2478
2479 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1, cachel);
2480
2481 if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2482 && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2483 /* #### Damn this losing shit. */
2484 data.bi_bufpos++;
2485 }
2486 }
2487 else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2488 && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2489 {
2490 /* We need to add a marker to the end of the line since there is no
2491 newline character in order for the cursor to get drawn. We label
2492 it as a newline so that it gets handled correctly by the
2493 whitespace routines below. */
2494
2495 data.ch = '\n';
2496 data.blank_width = DEVMETH (d, eol_cursor_width, ());
2497 data.findex = DEFAULT_INDEX;
2498 data.start_col = 0;
2499 data.start_col_xoffset = 0;
2500 data.bi_start_col_enabled = 0;
2501
2502 data.max_pixpos += data.blank_width;
2503 add_emchar_rune (&data);
2504 data.max_pixpos -= data.blank_width;
2505
2506 /* #### urk! Chuck, this shit is bad news. Going around
2507 manipulating invalid positions is guaranteed to result in
2508 trouble sooner or later. */
2509 data.bi_bufpos = BI_BUF_ZV (b) + 1;
2510 }
2511
2512 /* Calculate left whitespace boundary. */
2513 {
2514 int elt = 0;
2515
2516 /* Whitespace past a newline is considered right whitespace. */
2517 while (elt < Dynarr_length (db->runes))
2518 {
2519 struct rune *rb = Dynarr_atp (db->runes, elt);
2520
2521 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2522 || rb->type == RUNE_BLANK)
2523 {
2524 dl->bounds.left_white += rb->width;
2525 elt++;
2526 }
2527 else
2528 elt = Dynarr_length (db->runes);
2529 }
2530 }
2531
2532 /* Calculate right whitespace boundary. */
2533 {
2534 int elt = Dynarr_length (db->runes) - 1;
2535 int done = 0;
2536
2537 while (!done && elt >= 0)
2538 {
2539 struct rune *rb = Dynarr_atp (db->runes, elt);
2540
2541 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2542 && isspace (rb->object.chr.ch))
2543 && !rb->type == RUNE_BLANK)
2544 {
2545 dl->bounds.right_white = rb->xpos + rb->width;
2546 done = 1;
2547 }
2548
2549 elt--;
2550
2551 }
2552
2553 /* The line is blank so everything is considered to be right
2554 whitespace. */
2555 if (!done)
2556 dl->bounds.right_white = dl->bounds.left_in;
2557 }
2558
2559 /* Set the display blocks bounds. */
2560 db->start_pos = dl->bounds.left_in;
2561 if (Dynarr_length (db->runes))
2562 {
2563 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2564
2565 db->end_pos = rb->xpos + rb->width;
2566 }
2567 else
2568 db->end_pos = dl->bounds.right_white;
2569
2570 /* update line height parameters */
2571 if (!data.new_ascent && !data.new_descent)
2572 {
2573 /* We've got a blank line so initialize these values from the default
2574 face. */
2575 default_face_font_info (data.window, &data.new_ascent,
2576 &data.new_descent, 0, 0, 0);
2577 }
2578
2579 if (data.max_pixmap_height)
2580 {
2581 int height = data.new_ascent + data.new_descent;
2582 int pix_ascent, pix_descent;
2583
2584 pix_descent = data.max_pixmap_height * data.new_descent / height;
2585 pix_ascent = data.max_pixmap_height - pix_descent;
2586
2587 data.new_ascent = max (data.new_ascent, pix_ascent);
2588 data.new_descent = max (data.new_descent, pix_descent);
2589 }
2590
2591 dl->ascent = data.new_ascent;
2592 dl->descent = data.new_descent;
2593
2594 {
2595 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2596
2597 if (dl->ascent < ascent)
2598 dl->ascent = ascent;
2599 }
2600 {
2601 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2602
2603 if (dl->descent < descent)
2604 dl->descent = descent;
2605 }
2606
2607 dl->cursor_elt = data.cursor_x;
2608 /* #### lossage lossage lossage! Fix this shit! */
2609 if (data.bi_bufpos > BI_BUF_ZV (b))
2610 dl->end_bufpos = BUF_ZV (b);
2611 else
2612 dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2613 if (truncate_win)
2614 data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2615 else
2616 /* This doesn't correctly take into account tabs and control
2617 characters but if the window isn't being truncated then this
2618 value isn't going to end up being used anyhow. */
2619 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2620
2621 /* #### handle horizontally scrolled line with text none of which
2622 was actually laid out. */
2623
2624 /* #### handle any remainder of overlay arrow */
2625
2626 if (*prop == ADD_FAILED)
2627 *prop = NULL;
2628
2629 if (truncate_win && *prop)
2630 {
2631 Dynarr_free (*prop);
2632 *prop = NULL;
2633 }
2634
2635 extent_fragment_delete (data.ef);
2636
2637 /* #### If we started at EOB, then make sure we return a value past
2638 it so that regenerate_window will exit properly. This is bogus.
2639 The main loop should get fixed so that it isn't necessary to call
2640 this function if we are already at EOB. */
2641
2642 if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2643 return data.bi_bufpos + 1; /* Yuck! */
2644 else
2645 return data.bi_bufpos;
2646 }
2647
2648 /* Display the overlay arrow at the beginning of the given line. */
2649
2650 static int
2651 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2652 {
2653 struct frame *f = XFRAME (w->frame);
2654 struct device *d = XDEVICE (f->device);
2655 pos_data data;
2656
2657 /* If Voverlay_arrow_string isn't valid then just fail silently. */
2658 if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2659 return 0;
2660
2661 xzero (data);
2662 data.ef = NULL;
2663 data.d = d;
2664 XSETWINDOW (data.window, w);
2665 data.db = get_display_block_from_line (dl, OVERWRITE);
2666 data.dl = dl;
2667 data.pixpos = dl->bounds.left_in;
2668 data.max_pixpos = dl->bounds.right_in;
2669 data.cursor_type = NO_CURSOR;
2670 data.cursor_x = -1;
2671 data.findex = DEFAULT_INDEX;
2672 data.last_charset = Qunbound;
2673 data.last_findex = DEFAULT_INDEX;
2674 data.result_str = Qnil;
2675 data.string = Qnil;
2676
2677 Dynarr_reset (data.db->runes);
2678
2679 if (STRINGP (Voverlay_arrow_string))
2680 {
2681 add_bufbyte_string_runes
2682 (&data,
2683 XSTRING_DATA (Voverlay_arrow_string),
2684 XSTRING_LENGTH (Voverlay_arrow_string),
2685 1);
2686 }
2687 else if (GLYPHP (Voverlay_arrow_string))
2688 {
2689 struct glyph_block gb;
2690
2691 gb.glyph = Voverlay_arrow_string;
2692 gb.extent = Qnil;
2693 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2694 }
2695
2696 if (data.max_pixmap_height)
2697 {
2698 int height = data.new_ascent + data.new_descent;
2699 int pix_ascent, pix_descent;
2700
2701 pix_descent = data.max_pixmap_height * data.new_descent / height;
2702 pix_ascent = data.max_pixmap_height - pix_descent;
2703
2704 data.new_ascent = max (data.new_ascent, pix_ascent);
2705 data.new_descent = max (data.new_descent, pix_descent);
2706 }
2707
2708 dl->ascent = data.new_ascent;
2709 dl->descent = data.new_descent;
2710
2711 data.db->start_pos = dl->bounds.left_in;
2712 data.db->end_pos = data.pixpos;
2713
2714 return data.pixpos - dl->bounds.left_in;
2715 }
2716
2717 /* Add a type of glyph to a margin display block. */
2718
2719 static int
2720 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2721 int count, enum glyph_layout layout, int side, Lisp_Object window)
2722 {
2723 glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2724 ? dl->left_glyphs
2725 : dl->right_glyphs);
2726 int elt, end;
2727 int xpos = start;
2728 int reverse;
2729
2730 if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2731 || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2732 {
2733 reverse = 1;
2734 elt = Dynarr_length (gbd) - 1;
2735 end = 0;
2736 }
2737 else
2738 {
2739 reverse = 0;
2740 elt = 0;
2741 end = Dynarr_length (gbd);
2742 }
2743
2744 while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2745 {
2746 struct glyph_block *gb = Dynarr_atp (gbd, elt);
2747
2748 if (NILP (gb->extent))
2749 abort (); /* these should have been handled in add_glyph_rune */
2750
2751 if (gb->active &&
2752 ((side == LEFT_GLYPHS &&
2753 extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2754 || (side == RIGHT_GLYPHS &&
2755 extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2756 {
2757 struct rune rb;
2758
2759 rb.width = gb->width;
2760 rb.findex = gb->findex;
2761 rb.xpos = xpos;
2762 rb.bufpos = -1;
2763 rb.endpos = 0;
2764 rb.type = RUNE_DGLYPH;
2765 rb.object.dglyph.glyph = gb->glyph;
2766 rb.object.dglyph.extent = gb->extent;
2767 rb.object.dglyph.xoffset = 0;
2768 rb.cursor_type = CURSOR_OFF;
2769
2770 Dynarr_add (db->runes, rb);
2771 xpos += rb.width;
2772 count--;
2773 gb->active = 0;
2774
2775 if (glyph_contrib_p (gb->glyph, window))
2776 {
2777 unsigned short ascent, descent;
2778 Lisp_Object baseline = glyph_baseline (gb->glyph, window);
2779
2780 ascent = glyph_ascent (gb->glyph, Qnil, gb->findex, window);
2781 descent = glyph_descent (gb->glyph, Qnil, gb->findex, window);
2782
2783 /* A pixmap that has not had a baseline explicitly set.
2784 We use the existing ascent / descent ratio of the
2785 line. */
2786 if (NILP (baseline))
2787 {
2788 int gheight = ascent + descent;
2789 int line_height = dl->ascent + dl->descent;
2790 int pix_ascent, pix_descent;
2791
2792 pix_descent = (int) (gheight * dl->descent) / line_height;
2793 pix_ascent = gheight - pix_descent;
2794
2795 dl->ascent = max ((int) dl->ascent, pix_ascent);
2796 dl->descent = max ((int) dl->descent, pix_descent);
2797 }
2798
2799 /* A string so determine contribution normally. */
2800 else if (EQ (baseline, Qt))
2801 {
2802 dl->ascent = max (dl->ascent, ascent);
2803 dl->descent = max (dl->descent, descent);
2804 }
2805
2806 /* A pixmap with an explicitly set baseline. We determine the
2807 contribution here. */
2808 else if (INTP (baseline))
2809 {
2810 int height = ascent + descent;
2811 int pix_ascent, pix_descent;
2812
2813 pix_ascent = height * XINT (baseline) / 100;
2814 pix_descent = height - pix_ascent;
2815
2816 dl->ascent = max ((int) dl->ascent, pix_ascent);
2817 dl->descent = max ((int) dl->descent, pix_descent);
2818 }
2819
2820 /* Otherwise something is screwed up. */
2821 else
2822 abort ();
2823 }
2824 }
2825
2826 (reverse ? elt-- : elt++);
2827 }
2828
2829 return xpos;
2830 }
2831
2832 /* Add a blank to a margin display block. */
2833
2834 static void
2835 add_margin_blank (struct display_line *dl, struct display_block *db,
2836 struct window *w, int xpos, int width, int side)
2837 {
2838 struct rune rb;
2839
2840 rb.findex = (side == LEFT_GLYPHS
2841 ? get_builtin_face_cache_index (w, Vleft_margin_face)
2842 : get_builtin_face_cache_index (w, Vright_margin_face));
2843 rb.xpos = xpos;
2844 rb.width = width;
2845 rb.bufpos = -1;
2846 rb.endpos = 0;
2847 rb.type = RUNE_BLANK;
2848 rb.cursor_type = CURSOR_OFF;
2849
2850 Dynarr_add (db->runes, rb);
2851 }
2852
2853 /* Display glyphs in the left outside margin, left inside margin and
2854 left whitespace area. */
2855
2856 static void
2857 create_left_glyph_block (struct window *w, struct display_line *dl,
2858 int overlay_width)
2859 {
2860 Lisp_Object window;
2861
2862 int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2863 int elt, end_xpos;
2864 int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2865 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2866 int left_in_start = dl->bounds.left_in;
2867 int left_in_end = dl->bounds.left_in + overlay_width;
2868
2869 struct display_block *odb, *idb;
2870
2871 XSETWINDOW (window, w);
2872
2873 /* We have to add the glyphs to the line in the order outside,
2874 inside, whitespace. However the precedence dictates that we
2875 determine how many will fit in the reverse order. */
2876
2877 /* Determine how many whitespace glyphs we can display and where
2878 they should start. */
2879 white_in_start = dl->bounds.left_white;
2880 white_out_start = left_in_start;
2881 white_out_cnt = white_in_cnt = 0;
2882 elt = 0;
2883
2884 while (elt < Dynarr_length (dl->left_glyphs))
2885 {
2886 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2887
2888 if (NILP (gb->extent))
2889 abort (); /* these should have been handled in add_glyph_rune */
2890
2891 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2892 {
2893 int width;
2894
2895 width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2896
2897 if (white_in_start - width >= left_in_end)
2898 {
2899 white_in_cnt++;
2900 white_in_start -= width;
2901 gb->width = width;
2902 gb->active = 1;
2903 }
2904 else if (use_overflow
2905 && (white_out_start - width > dl->bounds.left_out))
2906 {
2907 white_out_cnt++;
2908 white_out_start -= width;
2909 gb->width = width;
2910 gb->active = 1;
2911 }
2912 else
2913 gb->active = 0;
2914 }
2915
2916 elt++;
2917 }
2918
2919 /* Determine how many inside margin glyphs we can display and where
2920 they should start. The inside margin glyphs get whatever space
2921 is left after the whitespace glyphs have been displayed. These
2922 are tricky to calculate since if we decide to use the overflow
2923 area we basically have to start over. So for these we build up a
2924 list of just the inside margin glyphs and manipulate it to
2925 determine the needed info. */
2926 {
2927 glyph_block_dynarr *ib;
2928 int avail_in, avail_out;
2929 int done = 0;
2930 int marker = 0;
2931 int used_in, used_out;
2932
2933 elt = 0;
2934 used_in = used_out = 0;
2935 ib = Dynarr_new (glyph_block);
2936 while (elt < Dynarr_length (dl->left_glyphs))
2937 {
2938 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2939
2940 if (NILP (gb->extent))
2941 abort (); /* these should have been handled in add_glyph_rune */
2942
2943 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2944 GL_INSIDE_MARGIN)
2945 {
2946 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
2947 used_in += gb->width;
2948 Dynarr_add (ib, *gb);
2949 }
2950
2951 elt++;
2952 }
2953
2954 if (white_out_cnt)
2955 avail_in = 0;
2956 else
2957 {
2958 avail_in = white_in_start - left_in_end;
2959 if (avail_in < 0)
2960 avail_in = 0;
2961 }
2962
2963 if (!use_overflow)
2964 avail_out = 0;
2965 else
2966 avail_out = white_out_start - dl->bounds.left_out;
2967
2968 marker = 0;
2969 while (!done && marker < Dynarr_length (ib))
2970 {
2971 int width = Dynarr_atp (ib, marker)->width;
2972
2973 /* If everything now fits in the available inside margin
2974 space, we're done. */
2975 if (used_in <= avail_in)
2976 done = 1;
2977 else
2978 {
2979 /* Otherwise see if we have room to move a glyph to the
2980 outside. */
2981 if (used_out + width <= avail_out)
2982 {
2983 used_out += width;
2984 used_in -= width;
2985 }
2986 else
2987 done = 1;
2988 }
2989
2990 if (!done)
2991 marker++;
2992 }
2993
2994 /* At this point we now know that everything from marker on goes in
2995 the inside margin and everything before it goes in the outside
2996 margin. The stuff going into the outside margin is guaranteed
2997 to fit, but we may have to trim some stuff from the inside. */
2998
2999 in_in_end = left_in_end;
3000 in_out_start = white_out_start;
3001 in_out_cnt = in_in_cnt = 0;
3002
3003 Dynarr_free (ib);
3004 elt = 0;
3005 while (elt < Dynarr_length (dl->left_glyphs))
3006 {
3007 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3008
3009 if (NILP (gb->extent))
3010 abort (); /* these should have been handled in add_glyph_rune */
3011
3012 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3013 GL_INSIDE_MARGIN)
3014 {
3015 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3016
3017 if (used_out)
3018 {
3019 in_out_cnt++;
3020 in_out_start -= width;
3021 gb->width = width;
3022 gb->active = 1;
3023 used_out -= width;
3024 }
3025 else if (in_in_end + width < white_in_start)
3026 {
3027 in_in_cnt++;
3028 in_in_end += width;
3029 gb->width = width;
3030 gb->active = 1;
3031 }
3032 else
3033 gb->active = 0;
3034 }
3035
3036 elt++;
3037 }
3038 }
3039
3040 /* Determine how many outside margin glyphs we can display. They
3041 always start at the left outside margin and can only use the
3042 outside margin space. */
3043 out_end = dl->bounds.left_out;
3044 out_cnt = 0;
3045 elt = 0;
3046
3047 while (elt < Dynarr_length (dl->left_glyphs))
3048 {
3049 struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3050
3051 if (NILP (gb->extent))
3052 abort (); /* these should have been handled in add_glyph_rune */
3053
3054 if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3055 GL_OUTSIDE_MARGIN)
3056 {
3057 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3058
3059 if (out_end + width <= in_out_start)
3060 {
3061 out_cnt++;
3062 out_end += width;
3063 gb->width = width;
3064 gb->active = 1;
3065 }
3066 else
3067 gb->active = 0;
3068 }
3069
3070 elt++;
3071 }
3072
3073 /* Now that we know where everything goes, we add the glyphs as
3074 runes to the appropriate display blocks. */
3075 if (out_cnt || in_out_cnt || white_out_cnt)
3076 {
3077 odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3078 odb->start_pos = dl->bounds.left_out;
3079 /* #### We should stop adding a blank to account for the space
3080 between the end of the glyphs and the margin and instead set
3081 this accordingly. */
3082 odb->end_pos = dl->bounds.left_in;
3083 Dynarr_reset (odb->runes);
3084 }
3085 else
3086 odb = 0;
3087
3088 if (in_in_cnt || white_in_cnt)
3089 {
3090 idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3091 idb->start_pos = dl->bounds.left_in;
3092 /* #### See above comment for odb->end_pos */
3093 idb->end_pos = dl->bounds.left_white;
3094 Dynarr_reset (idb->runes);
3095 }
3096 else
3097 idb = 0;
3098
3099 /* First add the outside margin glyphs. */
3100 if (out_cnt)
3101 end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3102 GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3103 else
3104 end_xpos = dl->bounds.left_out;
3105
3106 /* There may be blank space between the outside margin glyphs and
3107 the inside margin glyphs. If so, add a blank. */
3108 if (in_out_cnt && (in_out_start - end_xpos))
3109 {
3110 add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3111 LEFT_GLYPHS);
3112 }
3113
3114 /* Next add the inside margin glyphs which are actually in the
3115 outside margin. */
3116 if (in_out_cnt)
3117 {
3118 end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3119 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3120 }
3121
3122 /* If we didn't add any inside margin glyphs to the outside margin,
3123 but are adding whitespace glyphs, then we need to add a blank
3124 here. */
3125 if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3126 {
3127 add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3128 LEFT_GLYPHS);
3129 }
3130
3131 /* Next add the whitespace margin glyphs which are actually in the
3132 outside margin. */
3133 if (white_out_cnt)
3134 {
3135 end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3136 GL_WHITESPACE, LEFT_GLYPHS, window);
3137 }
3138
3139 /* We take care of clearing between the end of the glyphs and the
3140 start of the inside margin for lines which have glyphs. */
3141 if (odb && (left_in_start - end_xpos))
3142 {
3143 add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3144 LEFT_GLYPHS);
3145 }
3146
3147 /* Next add the inside margin glyphs which are actually in the
3148 inside margin. */
3149 if (in_in_cnt)
3150 {
3151 end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3152 GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3153 }
3154 else
3155 end_xpos = left_in_end;
3156
3157 /* Make sure that the area between the end of the inside margin
3158 glyphs and the whitespace glyphs is cleared. */
3159 if (idb && (white_in_start - end_xpos > 0))
3160 {
3161 add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3162 LEFT_GLYPHS);
3163 }
3164
3165 /* Next add the whitespace margin glyphs which are actually in the
3166 inside margin. */
3167 if (white_in_cnt)
3168 {
3169 add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3170 LEFT_GLYPHS, window);
3171 }
3172
3173 /* Whitespace glyphs always end right next to the text block so
3174 there is nothing we have to make sure is cleared after them. */
3175 }
3176
3177 /* Display glyphs in the right outside margin, right inside margin and
3178 right whitespace area. */
3179
3180 static void
3181 create_right_glyph_block (struct window *w, struct display_line *dl)
3182 {
3183 Lisp_Object window;
3184
3185 int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3186 int elt, end_xpos;
3187 int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3188 int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3189
3190 struct display_block *odb, *idb;
3191
3192 XSETWINDOW (window, w);
3193
3194 /* We have to add the glyphs to the line in the order outside,
3195 inside, whitespace. However the precedence dictates that we
3196 determine how many will fit in the reverse order. */
3197
3198 /* Determine how many whitespace glyphs we can display and where
3199 they should start. */
3200 white_in_end = dl->bounds.right_white;
3201 white_out_end = dl->bounds.right_in;
3202 white_out_cnt = white_in_cnt = 0;
3203 elt = 0;
3204
3205 while (elt < Dynarr_length (dl->right_glyphs))
3206 {
3207 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3208
3209 if (NILP (gb->extent))
3210 abort (); /* these should have been handled in add_glyph_rune */
3211
3212 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3213 {
3214 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3215
3216 if (white_in_end + width <= dl->bounds.right_in)
3217 {
3218 white_in_cnt++;
3219 white_in_end += width;
3220 gb->width = width;
3221 gb->active = 1;
3222 }
3223 else if (use_overflow
3224 && (white_out_end + width <= dl->bounds.right_out))
3225 {
3226 white_out_cnt++;
3227 white_out_end += width;
3228 gb->width = width;
3229 gb->active = 1;
3230 }
3231 else
3232 gb->active = 0;
3233 }
3234
3235 elt++;
3236 }
3237
3238 /* Determine how many inside margin glyphs we can display and where
3239 they should start. The inside margin glyphs get whatever space
3240 is left after the whitespace glyphs have been displayed. These
3241 are tricky to calculate since if we decide to use the overflow
3242 area we basically have to start over. So for these we build up a
3243 list of just the inside margin glyphs and manipulate it to
3244 determine the needed info. */
3245 {
3246 glyph_block_dynarr *ib;
3247 int avail_in, avail_out;
3248 int done = 0;
3249 int marker = 0;
3250 int used_in, used_out;
3251
3252 elt = 0;
3253 used_in = used_out = 0;
3254 ib = Dynarr_new (glyph_block);
3255 while (elt < Dynarr_length (dl->right_glyphs))
3256 {
3257 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3258
3259 if (NILP (gb->extent))
3260 abort (); /* these should have been handled in add_glyph_rune */
3261
3262 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3263 {
3264 gb->width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3265 used_in += gb->width;
3266 Dynarr_add (ib, *gb);
3267 }
3268
3269 elt++;
3270 }
3271
3272 if (white_out_cnt)
3273 avail_in = 0;
3274 else
3275 avail_in = dl->bounds.right_in - white_in_end;
3276
3277 if (!use_overflow)
3278 avail_out = 0;
3279 else
3280 avail_out = dl->bounds.right_out - white_out_end;
3281
3282 marker = 0;
3283 while (!done && marker < Dynarr_length (ib))
3284 {
3285 int width = Dynarr_atp (ib, marker)->width;
3286
3287 /* If everything now fits in the available inside margin
3288 space, we're done. */
3289 if (used_in <= avail_in)
3290 done = 1;
3291 else
3292 {
3293 /* Otherwise see if we have room to move a glyph to the
3294 outside. */
3295 if (used_out + width <= avail_out)
3296 {
3297 used_out += width;
3298 used_in -= width;
3299 }
3300 else
3301 done = 1;
3302 }
3303
3304 if (!done)
3305 marker++;
3306 }
3307
3308 /* At this point we now know that everything from marker on goes in
3309 the inside margin and everything before it goes in the outside
3310 margin. The stuff going into the outside margin is guaranteed
3311 to fit, but we may have to trim some stuff from the inside. */
3312
3313 in_in_start = dl->bounds.right_in;
3314 in_out_end = dl->bounds.right_in;
3315 in_out_cnt = in_in_cnt = 0;
3316
3317 Dynarr_free (ib);
3318 elt = 0;
3319 while (elt < Dynarr_length (dl->right_glyphs))
3320 {
3321 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3322
3323 if (NILP (gb->extent))
3324 abort (); /* these should have been handled in add_glyph_rune */
3325
3326 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3327 {
3328 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3329
3330 if (used_out)
3331 {
3332 in_out_cnt++;
3333 in_out_end += width;
3334 gb->width = width;
3335 gb->active = 1;
3336 used_out -= width;
3337 }
3338 else if (in_in_start - width >= white_in_end)
3339 {
3340 in_in_cnt++;
3341 in_in_start -= width;
3342 gb->width = width;
3343 gb->active = 1;
3344 }
3345 else
3346 gb->active = 0;
3347 }
3348
3349 elt++;
3350 }
3351 }
3352
3353 /* Determine how many outside margin glyphs we can display. They
3354 always start at the right outside margin and can only use the
3355 outside margin space. */
3356 out_start = dl->bounds.right_out;
3357 out_cnt = 0;
3358 elt = 0;
3359
3360 while (elt < Dynarr_length (dl->right_glyphs))
3361 {
3362 struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3363
3364 if (NILP (gb->extent))
3365 abort (); /* these should have been handled in add_glyph_rune */
3366
3367 if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3368 {
3369 int width = glyph_width (gb->glyph, Qnil, gb->findex, window);
3370
3371 if (out_start - width >= in_out_end)
3372 {
3373 out_cnt++;
3374 out_start -= width;
3375 gb->width = width;
3376 gb->active = 1;
3377 }
3378 else
3379 gb->active = 0;
3380 }
3381
3382 elt++;
3383 }
3384
3385 /* Now that we now where everything goes, we add the glyphs as runes
3386 to the appropriate display blocks. */
3387 if (out_cnt || in_out_cnt || white_out_cnt)
3388 {
3389 odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3390 /* #### See comments before odb->start_pos init in
3391 create_left_glyph_block */
3392 odb->start_pos = dl->bounds.right_in;
3393 odb->end_pos = dl->bounds.right_out;
3394 Dynarr_reset (odb->runes);
3395 }
3396 else
3397 odb = 0;
3398
3399 if (in_in_cnt || white_in_cnt)
3400 {
3401 idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3402 idb->start_pos = dl->bounds.right_white;
3403 /* #### See comments before odb->start_pos init in
3404 create_left_glyph_block */
3405 idb->end_pos = dl->bounds.right_in;
3406 Dynarr_reset (idb->runes);
3407 }
3408 else
3409 idb = 0;
3410
3411 /* First add the whitespace margin glyphs which are actually in the
3412 inside margin. */
3413 if (white_in_cnt)
3414 {
3415 end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3416 white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3417 window);
3418 }
3419 else
3420 end_xpos = dl->bounds.right_white;
3421
3422 /* Make sure that the area between the end of the whitespace glyphs
3423 and the inside margin glyphs is cleared. */
3424 if (in_in_cnt && (in_in_start - end_xpos))
3425 {
3426 add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3427 RIGHT_GLYPHS);
3428 }
3429
3430 /* Next add the inside margin glyphs which are actually in the
3431 inside margin. */
3432 if (in_in_cnt)
3433 {
3434 end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3435 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3436 }
3437
3438 /* If we didn't add any inside margin glyphs then make sure the rest
3439 of the inside margin area gets cleared. */
3440 if (idb && (dl->bounds.right_in - end_xpos))
3441 {
3442 add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3443 RIGHT_GLYPHS);
3444 }
3445
3446 /* Next add any whitespace glyphs in the outside margin. */
3447 if (white_out_cnt)
3448 {
3449 end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3450 GL_WHITESPACE, RIGHT_GLYPHS, window);
3451 }
3452 else
3453 end_xpos = dl->bounds.right_in;
3454
3455 /* Next add any inside margin glyphs in the outside margin. */
3456 if (in_out_cnt)
3457 {
3458 end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3459 GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3460 }
3461
3462 /* There may be space between any whitespace or inside margin glyphs
3463 in the outside margin and the actual outside margin glyphs. */
3464 if (odb && (out_start - end_xpos))
3465 {
3466 add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3467 RIGHT_GLYPHS);
3468 }
3469
3470 /* Finally, add the outside margin glyphs. */
3471 if (out_cnt)
3472 {
3473 add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3474 RIGHT_GLYPHS, window);
3475 }
3476 }
3477
3478
3479 /***************************************************************************/
3480 /* */
3481 /* modeline routines */
3482 /* */
3483 /***************************************************************************/
3484
3485 /* Ensure that the given display line DL accurately represents the
3486 modeline for the given window. */
3487
3488 static void
3489 generate_modeline (struct window *w, struct display_line *dl, int type)
3490 {
3491 struct buffer *b = XBUFFER (w->buffer);
3492 struct frame *f = XFRAME (w->frame);
3493 struct device *d = XDEVICE (f->device);
3494
3495 /* Unlike display line and rune pointers, this one can't change underneath
3496 our feet. */
3497 struct display_block *db = get_display_block_from_line (dl, TEXT);
3498 int max_pixpos, min_pixpos, ypos_adj;
3499 Lisp_Object font_inst;
3500
3501 /* This will actually determine incorrect inside boundaries for the
3502 modeline since it ignores the margins. However being aware of this fact
3503 we never use those values anywhere so it doesn't matter. */
3504 dl->bounds = calculate_display_line_boundaries (w, 1);
3505
3506 /* We are generating a modeline. */
3507 dl->modeline = 1;
3508 dl->cursor_elt = -1;
3509
3510 /* Reset the runes on the modeline. */
3511 Dynarr_reset (db->runes);
3512
3513 if (!WINDOW_HAS_MODELINE_P (w))
3514 {
3515 struct rune rb;
3516
3517 /* If there is a horizontal scrollbar, don't add anything. */
3518 if (window_scrollbar_height (w))
3519 return;
3520
3521 dl->ascent = DEVMETH (d, divider_height, ());
3522 dl->descent = 0;
3523 /* The modeline is at the bottom of the gutters. */
3524 dl->ypos = WINDOW_BOTTOM (w);
3525
3526 /* adjust for the bottom gutter */
3527 if (window_is_lowest (w))
3528 dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
3529
3530 rb.findex = MODELINE_INDEX;
3531 rb.xpos = dl->bounds.left_out;
3532 rb.width = dl->bounds.right_out - dl->bounds.left_out;
3533 rb.bufpos = 0;
3534 rb.endpos = 0;
3535 rb.type = RUNE_HLINE;
3536 rb.object.hline.thickness = 1;
3537 rb.object.hline.yoffset = 0;
3538 rb.cursor_type = NO_CURSOR;
3539
3540 if (!EQ (Qzero, w->modeline_shadow_thickness)
3541 && FRAME_WIN_P (f))
3542 {
3543 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3544
3545 dl->ypos -= shadow_thickness;
3546 rb.xpos += shadow_thickness;
3547 rb.width -= 2 * shadow_thickness;
3548 }
3549
3550 Dynarr_add (db->runes, rb);
3551 return;
3552 }
3553
3554 /* !!#### not right; needs to compute the max height of
3555 all the charsets */
3556 font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3557
3558 dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3559 dl->descent = XFONT_INSTANCE (font_inst)->descent;
3560
3561 min_pixpos = dl->bounds.left_out;
3562 max_pixpos = dl->bounds.right_out;
3563
3564 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3565 {
3566 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3567
3568 ypos_adj = shadow_thickness;
3569 min_pixpos += shadow_thickness;
3570 max_pixpos -= shadow_thickness;
3571 }
3572 else
3573 ypos_adj = 0;
3574
3575 generate_formatted_string_db (b->modeline_format,
3576 b->generated_modeline_string, w, dl, db,
3577 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3578
3579 /* The modeline is at the bottom of the gutters. We have to wait to
3580 set this until we've generated the modeline in order to account
3581 for any embedded faces. */
3582 dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3583 /* adjust for the bottom gutter */
3584 if (window_is_lowest (w))
3585 dl->ypos -= FRAME_BOTTOM_GUTTER_BOUNDS (f);
3586 }
3587
3588 static void
3589 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3590 struct window *w, struct display_line *dl,
3591 struct display_block *db, face_index findex,
3592 int min_pixpos, int max_pixpos, int type)
3593 {
3594 struct frame *f = XFRAME (w->frame);
3595 struct device *d = XDEVICE (f->device);
3596
3597 pos_data data;
3598 int c_pixpos;
3599
3600 xzero (data);
3601 data.d = d;
3602 data.db = db;
3603 data.dl = dl;
3604 data.findex = findex;
3605 data.pixpos = min_pixpos;
3606 data.max_pixpos = max_pixpos;
3607 data.cursor_type = NO_CURSOR;
3608 data.last_charset = Qunbound;
3609 data.last_findex = DEFAULT_INDEX;
3610 data.result_str = result_str;
3611 data.is_modeline = 1;
3612 data.string = Qnil;
3613 XSETWINDOW (data.window, w);
3614
3615 Dynarr_reset (formatted_string_extent_dynarr);
3616 Dynarr_reset (formatted_string_extent_start_dynarr);
3617 Dynarr_reset (formatted_string_extent_end_dynarr);
3618
3619 /* This recursively builds up the modeline. */
3620 generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3621 max_pixpos - min_pixpos, findex, type);
3622
3623 if (Dynarr_length (db->runes))
3624 {
3625 struct rune *rb =
3626 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3627 c_pixpos = rb->xpos + rb->width;
3628 }
3629 else
3630 c_pixpos = min_pixpos;
3631
3632 /* If we don't reach the right side of the window, add a blank rune
3633 to make up the difference. This usually only occurs if the
3634 modeline face is using a proportional width font or a fixed width
3635 font of a different size from the default face font. */
3636
3637 if (c_pixpos < max_pixpos)
3638 {
3639 data.pixpos = c_pixpos;
3640 data.blank_width = max_pixpos - data.pixpos;
3641
3642 add_blank_rune (&data, NULL, 0);
3643 }
3644
3645 /* Now create the result string and frob the extents into it. */
3646 if (!NILP (result_str))
3647 {
3648 int elt;
3649 Bytecount len;
3650 Bufbyte *strdata;
3651 struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3652
3653 detach_all_extents (result_str);
3654 resize_string (XSTRING (result_str), -1,
3655 data.bytepos - XSTRING_LENGTH (result_str));
3656
3657 strdata = XSTRING_DATA (result_str);
3658
3659 for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3660 {
3661 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3662 {
3663 len += (set_charptr_emchar
3664 (strdata + len, Dynarr_atp (db->runes,
3665 elt)->object.chr.ch));
3666 }
3667 }
3668
3669 for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3670 elt++)
3671 {
3672 Lisp_Object extent = Qnil;
3673 Lisp_Object child;
3674
3675 XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3676 child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3677 if (NILP (child))
3678 {
3679 child = Fmake_extent (Qnil, Qnil, result_str);
3680 Fputhash (extent, child, buf->modeline_extent_table);
3681 }
3682 Fset_extent_parent (child, extent);
3683 set_extent_endpoints
3684 (XEXTENT (child),
3685 Dynarr_at (formatted_string_extent_start_dynarr, elt),
3686 Dynarr_at (formatted_string_extent_end_dynarr, elt),
3687 result_str);
3688 }
3689 }
3690 }
3691
3692 static Charcount
3693 add_string_to_fstring_db_runes (pos_data *data, CONST Bufbyte *str,
3694 Charcount pos, Charcount min_pos, Charcount max_pos)
3695 {
3696 /* This function has been Mule-ized. */
3697 Charcount end;
3698 CONST Bufbyte *cur_pos = str;
3699 struct display_block *db = data->db;
3700
3701 data->blank_width = space_width (XWINDOW (data->window));
3702 while (Dynarr_length (db->runes) < pos)
3703 add_blank_rune (data, NULL, 0);
3704
3705 end = (Dynarr_length (db->runes) +
3706 bytecount_to_charcount (str, strlen ((CONST char *) str)));
3707 if (max_pos != -1)
3708 end = min (max_pos, end);
3709
3710 while (pos < end && *cur_pos)
3711 {
3712 CONST Bufbyte *old_cur_pos = cur_pos;
3713 int succeeded;
3714
3715 data->ch = charptr_emchar (cur_pos);
3716 succeeded = (add_emchar_rune (data) != ADD_FAILED);
3717 INC_CHARPTR (cur_pos);
3718 if (succeeded)
3719 {
3720 pos++;
3721 data->modeline_charpos++;
3722 data->bytepos += cur_pos - old_cur_pos;
3723 }
3724 }
3725
3726 while (Dynarr_length (db->runes) < min_pos &&
3727 (data->pixpos + data->blank_width <= data->max_pixpos))
3728 add_blank_rune (data, NULL, 0);
3729
3730 return Dynarr_length (db->runes);
3731 }
3732
3733 /* #### Urk! Should also handle begin-glyphs and end-glyphs in
3734 modeline extents. */
3735 static Charcount
3736 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3737 Charcount pos, Charcount min_pos, Charcount max_pos)
3738 {
3739 /* This function has been Mule-ized. */
3740 Charcount end;
3741 struct display_block *db = data->db;
3742 struct glyph_block gb;
3743
3744 data->blank_width = space_width (XWINDOW (data->window));
3745 while (Dynarr_length (db->runes) < pos)
3746 add_blank_rune (data, NULL, 0);
3747
3748 end = Dynarr_length (db->runes) + 1;
3749 if (max_pos != -1)
3750 end = min (max_pos, end);
3751
3752 gb.glyph = glyph;
3753 gb.extent = Qnil;
3754 add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3755 pos++;
3756
3757 while (Dynarr_length (db->runes) < pos &&
3758 (data->pixpos + data->blank_width <= data->max_pixpos))
3759 add_blank_rune (data, NULL, 0);
3760
3761 return Dynarr_length (db->runes);
3762 }
3763
3764 /* If max_pos is == -1, it is considered to be infinite. The same is
3765 true of max_pixsize. */
3766 #define SET_CURRENT_MODE_CHARS_PIXSIZE \
3767 if (Dynarr_length (data->db->runes)) \
3768 cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3769 else \
3770 cur_pixsize = 0;
3771
3772 /* Note that this function does "positions" in terms of characters and
3773 not in terms of columns. This is necessary to make the formatting
3774 work correctly when proportional width fonts are used in the
3775 modeline. */
3776 static Charcount
3777 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3778 Charcount min_pos, Charcount max_pos,
3779 Lisp_Object elt, int depth, int max_pixsize,
3780 face_index findex, int type)
3781 {
3782 /* This function has been Mule-ized. */
3783 /* #### The other losing things in this function are:
3784
3785 -- C zero-terminated-string lossage.
3786 -- Non-printable characters should be converted into something
3787 appropriate (e.g. ^F) instead of blindly being printed anyway.
3788 */
3789
3790 tail_recurse:
3791 if (depth > 10)
3792 goto invalid;
3793
3794 depth++;
3795
3796 if (STRINGP (elt))
3797 {
3798 /* A string. Add to the display line and check for %-constructs
3799 within it. */
3800
3801 Bufbyte *this = XSTRING_DATA (elt);
3802
3803 while ((pos < max_pos || max_pos == -1) && *this)
3804 {
3805 Bufbyte *last = this;
3806
3807 while (*this && *this != '%')
3808 this++;
3809
3810 if (this != last)
3811 {
3812 /* The string is just a string. */
3813 Charcount size =
3814 bytecount_to_charcount (last, this - last) + pos;
3815 Charcount tmp_max = (max_pos == -1 ? size : min (size, max_pos));
3816
3817 pos = add_string_to_fstring_db_runes (data, last, pos, pos,
3818 tmp_max);
3819 }
3820 else /* *this == '%' */
3821 {
3822 Charcount spec_width = 0;
3823
3824 this++; /* skip over '%' */
3825
3826 /* We can't allow -ve args due to the "%-" construct.
3827 * Argument specifies minwidth but not maxwidth
3828 * (maxwidth can be specified by
3829 * (<negative-number> . <stuff>) modeline elements)
3830 */
3831 while (isdigit (*this))
3832 {
3833 spec_width = spec_width * 10 + (*this - '0');
3834 this++;
3835 }
3836 spec_width += pos;
3837
3838 if (*this == 'M')
3839 {
3840 pos = generate_fstring_runes (w, data, pos, spec_width,
3841 max_pos, Vglobal_mode_string,
3842 depth, max_pixsize, findex,
3843 type);
3844 }
3845 else if (*this == '-')
3846 {
3847 Charcount num_to_add;
3848
3849 if (max_pixsize < 0)
3850 num_to_add = 0;
3851 else if (max_pos != -1)
3852 num_to_add = max_pos - pos;
3853 else
3854 {
3855 int cur_pixsize;
3856 int dash_pixsize;
3857 Bufbyte ch = '-';
3858 SET_CURRENT_MODE_CHARS_PIXSIZE;
3859
3860 dash_pixsize =
3861 redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3862 1);
3863
3864 num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3865 num_to_add++;
3866 }
3867
3868 while (num_to_add--)
3869 pos = add_string_to_fstring_db_runes
3870 (data, (CONST Bufbyte *) "-", pos, pos, max_pos);
3871 }
3872 else if (*this != 0)
3873 {
3874 Bufbyte *str;
3875 Emchar ch = charptr_emchar (this);
3876 decode_mode_spec (w, ch, type);
3877
3878 str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3879 pos = add_string_to_fstring_db_runes (data,str, pos, pos,
3880 max_pos);
3881 }
3882
3883 /* NOT this++. There could be any sort of character at
3884 the current position. */
3885 INC_CHARPTR (this);
3886 }
3887
3888 if (max_pixsize > 0)
3889 {
3890 int cur_pixsize;
3891 SET_CURRENT_MODE_CHARS_PIXSIZE;
3892
3893 if (cur_pixsize >= max_pixsize)
3894 break;
3895 }
3896 }
3897 }
3898 else if (SYMBOLP (elt))
3899 {
3900 /* A symbol: process the value of the symbol recursively
3901 as if it appeared here directly. */
3902 Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3903
3904 if (!UNBOUNDP (tem))
3905 {
3906 /* If value is a string, output that string literally:
3907 don't check for % within it. */
3908 if (STRINGP (tem))
3909 {
3910 pos =
3911 add_string_to_fstring_db_runes
3912 (data, XSTRING_DATA (tem), pos, min_pos, max_pos);
3913 }
3914 /* Give up right away for nil or t. */
3915 else if (!EQ (tem, elt))
3916 {
3917 elt = tem;
3918 goto tail_recurse;
3919 }
3920 }
3921 }
3922 else if (GENERIC_SPECIFIERP (elt))
3923 {
3924 Lisp_Object window, tem;
3925 XSETWINDOW (window, w);
3926 tem = specifier_instance_no_quit (elt, Qunbound, window,
3927 ERROR_ME_NOT, 0, Qzero);
3928 if (!UNBOUNDP (tem))
3929 {
3930 elt = tem;
3931 goto tail_recurse;
3932 }
3933 }
3934 else if (CONSP (elt))
3935 {
3936 /* A cons cell: four distinct cases.
3937 * If first element is a string or a cons, process all the elements
3938 * and effectively concatenate them.
3939 * If first element is a negative number, truncate displaying cdr to
3940 * at most that many characters. If positive, pad (with spaces)
3941 * to at least that many characters.
3942 * If first element is a symbol, process the cadr or caddr recursively
3943 * according to whether the symbol's value is non-nil or nil.
3944 * If first element is a face, process the cdr recursively
3945 * without altering the depth.
3946 */
3947 Lisp_Object car, tem;
3948
3949 car = XCAR (elt);
3950 if (SYMBOLP (car))
3951 {
3952 elt = XCDR (elt);
3953 if (!CONSP (elt))
3954 goto invalid;
3955 tem = symbol_value_in_buffer (car, w->buffer);
3956 /* elt is now the cdr, and we know it is a cons cell.
3957 Use its car if CAR has a non-nil value. */
3958 if (!UNBOUNDP (tem))
3959 {
3960 if (!NILP (tem))
3961 {
3962 elt = XCAR (elt);
3963 goto tail_recurse;
3964 }
3965 }
3966 /* Symbol's value is nil (or symbol is unbound)
3967 * Get the cddr of the original list
3968 * and if possible find the caddr and use that.
3969 */
3970 elt = XCDR (elt);
3971 if (NILP (elt))
3972 ;
3973 else if (!CONSP (elt))
3974 goto invalid;
3975 else
3976 {
3977 elt = XCAR (elt);
3978 goto tail_recurse;
3979 }
3980 }
3981 else if (INTP (car))
3982 {
3983 Charcount lim = XINT (car);
3984
3985 elt = XCDR (elt);
3986
3987 if (lim < 0)
3988 {
3989 /* Negative int means reduce maximum width.
3990 * DO NOT change MIN_PIXPOS here!
3991 * (20 -10 . foo) should truncate foo to 10 col
3992 * and then pad to 20.
3993 */
3994 if (max_pos == -1)
3995 max_pos = pos - lim;
3996 else
3997 max_pos = min (max_pos, pos - lim);
3998 }
3999 else if (lim > 0)
4000 {
4001 /* Padding specified. Don't let it be more than
4002 * current maximum.
4003 */
4004 lim += pos;
4005 if (max_pos != -1 && lim > max_pos)
4006 lim = max_pos;
4007 /* If that's more padding than already wanted, queue it.
4008 * But don't reduce padding already specified even if
4009 * that is beyond the current truncation point.
4010 */
4011 if (lim > min_pos)
4012 min_pos = lim;
4013 }
4014 goto tail_recurse;
4015 }
4016 else if (STRINGP (car) || CONSP (car))
4017 {
4018 int limit = 50;
4019 /* LIMIT is to protect against circular lists. */
4020 while (CONSP (elt) && --limit > 0
4021 && (pos < max_pos || max_pos == -1))
4022 {
4023 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4024 XCAR (elt), depth,
4025 max_pixsize, findex, type);
4026 elt = XCDR (elt);
4027 }
4028 }
4029 else if (EXTENTP (car))
4030 {
4031 struct extent *ext = XEXTENT (car);
4032
4033 if (EXTENT_LIVE_P (ext))
4034 {
4035 face_index old_findex = data->findex;
4036 Lisp_Object face;
4037 Lisp_Object font_inst;
4038 face_index new_findex;
4039 Bytecount start = data->bytepos;
4040
4041 face = extent_face (ext);
4042 if (FACEP (face))
4043 {
4044 /* #### needs to merge faces, sigh */
4045 /* #### needs to handle list of faces */
4046 new_findex = get_builtin_face_cache_index (w, face);
4047 /* !!#### not right; needs to compute the max height of
4048 all the charsets */
4049 font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
4050 Vcharset_ascii);
4051
4052 data->dl->ascent = max (data->dl->ascent,
4053 XFONT_INSTANCE (font_inst)->ascent);
4054 data->dl->descent = max (data->dl->descent,
4055 XFONT_INSTANCE (font_inst)->
4056 descent);
4057 }
4058 else
4059 new_findex = old_findex;
4060
4061 data->findex = new_findex;
4062 pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4063 XCDR (elt), depth - 1,
4064 max_pixsize, new_findex, type);
4065 data->findex = old_findex;
4066 Dynarr_add (formatted_string_extent_dynarr, ext);
4067 Dynarr_add (formatted_string_extent_start_dynarr, start);
4068 Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4069 }
4070 }
4071 }
4072 else if (GLYPHP (elt))
4073 {
4074 pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos);
4075 }
4076 else
4077 {
4078 invalid:
4079 pos =
4080 add_string_to_fstring_db_runes
4081 (data, (CONST Bufbyte *) GETTEXT ("*invalid*"), pos, min_pos,
4082 max_pos);
4083 }
4084
4085 if (min_pos > pos)
4086 {
4087 add_string_to_fstring_db_runes (data, (CONST Bufbyte *) "", pos, min_pos,
4088 -1);
4089 }
4090
4091 return pos;
4092 }
4093
4094 /* The caller is responsible for freeing the returned string. */
4095 Bufbyte *
4096 generate_formatted_string (struct window *w, Lisp_Object format_str,
4097 Lisp_Object result_str, face_index findex, int type)
4098 {
4099 struct display_line *dl;
4100 struct display_block *db;
4101 int elt = 0;
4102
4103 dl = &formatted_string_display_line;
4104 db = get_display_block_from_line (dl, TEXT);
4105 Dynarr_reset (db->runes);
4106
4107 generate_formatted_string_db (format_str, result_str, w, dl, db, findex, 0,
4108 -1, type);
4109
4110 Dynarr_reset (formatted_string_emchar_dynarr);
4111 while (elt < Dynarr_length (db->runes))
4112 {
4113 if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
4114 Dynarr_add (formatted_string_emchar_dynarr,
4115 Dynarr_atp (db->runes, elt)->object.chr.ch);
4116 elt++;
4117 }
4118
4119 return
4120 convert_emchar_string_into_malloced_string
4121 ( Dynarr_atp (formatted_string_emchar_dynarr, 0),
4122 Dynarr_length (formatted_string_emchar_dynarr), 0);
4123 }
4124
4125 /* Update just the modeline. Assumes the desired display structs. If
4126 they do not have a modeline block, it does nothing. */
4127 static void
4128 regenerate_modeline (struct window *w)
4129 {
4130 display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4131
4132 if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4133 return;
4134 else
4135 {
4136 generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4137 redisplay_update_line (w, 0, 0, 0);
4138 }
4139 }
4140
4141 /* Make sure that modeline display line is present in the given
4142 display structs if the window has a modeline and update that
4143 line. Returns true if a modeline was needed. */
4144 static int
4145 ensure_modeline_generated (struct window *w, int type)
4146 {
4147 int need_modeline;
4148
4149 /* minibuffer windows don't have modelines */
4150 if (MINI_WINDOW_P (w))
4151 need_modeline = 0;
4152 /* windows which haven't had it turned off do */
4153 else if (WINDOW_HAS_MODELINE_P (w))
4154 need_modeline = 1;
4155 /* windows which have it turned off don't have a divider if there is
4156 a horizontal scrollbar */
4157 else if (window_scrollbar_height (w))
4158 need_modeline = 0;
4159 /* and in this case there is none */
4160 else
4161 need_modeline = 1;
4162
4163 if (need_modeline)
4164 {
4165 display_line_dynarr *dla;
4166
4167 dla = window_display_lines (w, type);
4168
4169 /* We don't care if there is a display line which is not
4170 currently a modeline because it is definitely going to become
4171 one if we have gotten to this point. */
4172 if (Dynarr_length (dla) == 0)
4173 {
4174 if (Dynarr_largest (dla) > 0)
4175 {
4176 struct display_line *mlp = Dynarr_atp (dla, 0);
4177 Dynarr_add (dla, *mlp);
4178 }
4179 else
4180 {
4181 struct display_line modeline;
4182 xzero (modeline);
4183 Dynarr_add (dla, modeline);
4184 }
4185 }
4186
4187 /* If we're adding a new place marker go ahead and generate the
4188 modeline so that it is available for use by
4189 window_modeline_height. */
4190 generate_modeline (w, Dynarr_atp (dla, 0), type);
4191 }
4192
4193 return need_modeline;
4194 }
4195
4196 /* #### Kludge or not a kludge. I tend towards the former. */
4197 int
4198 real_current_modeline_height (struct window *w)
4199 {
4200 Fset_marker (w->start[CMOTION_DISP], w->start[CURRENT_DISP], w->buffer);
4201 Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4202
4203 if (ensure_modeline_generated (w, CMOTION_DISP))
4204 {
4205 display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4206
4207 if (Dynarr_length (dla))
4208 {
4209 if (Dynarr_atp (dla, 0)->modeline)
4210 return (Dynarr_atp (dla, 0)->ascent +
4211 Dynarr_atp (dla, 0)->descent);
4212 }
4213 }
4214 return 0;
4215 }
4216
4217
4218 /***************************************************************************/
4219 /* */
4220 /* displayable string routines */
4221 /* */
4222 /***************************************************************************/
4223
4224 /* Given a position for a string in a window, ensure that the given
4225 display line DL accurately represents the text on a line starting
4226 at the given position.
4227
4228 Yes, this is duplicating the code of create_text_block, but it
4229 looked just too hard to change create_text_block to handle strings
4230 *and* buffers. We already make a distinction between the two
4231 elsewhere in the code so I think unifying them would require a
4232 complete MULE rewrite. Besides, the other distinction is that these
4233 functions cover text that the user *cannot edit* so we can remove
4234 everything to do with cursors, minibuffers etc. Eventually the
4235 modeline routines should be modified to use this code as it copes
4236 with many more types of display situation. */
4237
4238 static Bufpos
4239 create_string_text_block (struct window *w, Lisp_Object disp_string,
4240 struct display_line *dl,
4241 Bufpos start_pos,
4242 prop_block_dynarr **prop,
4243 face_index default_face)
4244 {
4245 struct frame *f = XFRAME (w->frame);
4246 /* Note that a lot of the buffer controlled stuff has been left in
4247 because you might well want to make use of it (selective display
4248 etc), its just the buffer text that we do not use. However, it
4249 seems to be possible for buffer to be nil sometimes so protect
4250 against this case. */
4251 struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
4252 struct device *d = XDEVICE (f->device);
4253 struct Lisp_String* s = XSTRING (disp_string);
4254
4255 /* we're working with these a lot so precalculate them */
4256 Bytecount slen = XSTRING_LENGTH (disp_string);
4257 Bytecount bi_string_zv = slen;
4258 Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4259
4260 pos_data data;
4261
4262 int truncate_win = b ? window_truncation_on (w) : 0;
4263 int end_glyph_width = 0;
4264
4265 /* we're going to ditch selective display for static text, its an
4266 FSF thing and invisble extents are the way to go
4267 here. Implementing it also relies on a number of buffer-specific
4268 functions that we don't have the luxury of being able to use
4269 here. */
4270
4271 /* The variable ctl-arrow allows the user to specify what characters
4272 can actually be displayed and which octal should be used for.
4273 #### This variable should probably have some rethought done to
4274 it.
4275
4276 #### It would also be really nice if you could specify that
4277 the characters come out in hex instead of in octal. Mule
4278 does that by adding a ctl-hexa variable similar to ctl-arrow,
4279 but that's bogus -- we need a more general solution. I
4280 think you need to extend the concept of display tables
4281 into a more general conversion mechanism. Ideally you
4282 could specify a Lisp function that converts characters,
4283 but this violates the Second Golden Rule and besides would
4284 make things way way way way slow.
4285
4286 So instead, we extend the display-table concept, which was
4287 historically limited to 256-byte vectors, to one of the
4288 following:
4289
4290 a) A 256-entry vector, for backward compatibility;
4291 b) char-table, mapping characters to values;
4292 c) range-table, mapping ranges of characters to values;
4293 d) a list of the above.
4294
4295 The (d) option allows you to specify multiple display tables
4296 instead of just one. Each display table can specify conversions
4297 for some characters and leave others unchanged. The way the
4298 character gets displayed is determined by the first display table
4299 with a binding for that character. This way, you could call a
4300 function `enable-hex-display' that adds a hex display-table to
4301 the list of display tables for the current buffer.
4302
4303 #### ...not yet implemented... Also, we extend the concept of
4304 "mapping" to include a printf-like spec. Thus you can make all
4305 extended characters show up as hex with a display table like
4306 this:
4307
4308 #s(range-table data ((256 524288) (format "%x")))
4309
4310 Since more than one display table is possible, you have
4311 great flexibility in mapping ranges of characters. */
4312 Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4313 ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4314 : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4315 ? 255 : 160)) : 255;
4316
4317 Lisp_Object face_dt, window_dt;
4318
4319 /* The text display block for this display line. */
4320 struct display_block *db = get_display_block_from_line (dl, TEXT);
4321
4322 /* The first time through the main loop we need to force the glyph
4323 data to be updated. */
4324 int initial = 1;
4325
4326 /* Apparently the new extent_fragment_update returns an end position
4327 equal to the position passed in if there are no more runs to be
4328 displayed. */
4329 int no_more_frags = 0;
4330
4331 dl->used_prop_data = 0;
4332 dl->num_chars = 0;
4333
4334 /* set up faces to use for clearing areas, used by
4335 output_display_line */
4336 dl->default_findex = default_face;
4337 if (default_face)
4338 {
4339 dl->left_margin_findex = default_face;
4340 dl->right_margin_findex = default_face;
4341 }
4342 else
4343 {
4344 dl->left_margin_findex =
4345 get_builtin_face_cache_index (w, Vleft_margin_face);
4346 dl->right_margin_findex =
4347 get_builtin_face_cache_index (w, Vright_margin_face);
4348 }
4349
4350 xzero (data);
4351 data.ef = extent_fragment_new (disp_string, f);
4352
4353 /* These values are used by all of the rune addition routines. We add
4354 them to this structure for ease of passing. */
4355 data.d = d;
4356 XSETWINDOW (data.window, w);
4357 data.db = db;
4358 data.dl = dl;
4359
4360 data.bi_bufpos = bi_start_pos;
4361 data.pixpos = dl->bounds.left_in;
4362 data.last_charset = Qunbound;
4363 data.last_findex = default_face;
4364 data.result_str = Qnil;
4365 data.string = disp_string;
4366
4367 /* Set the right boundary adjusting it to take into account any end
4368 glyph. Save the width of the end glyph for later use. */
4369 data.max_pixpos = dl->bounds.right_in;
4370 #if 0
4371 if (truncate_win)
4372 end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
4373 else
4374 end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
4375 #endif
4376 data.max_pixpos -= end_glyph_width;
4377
4378 data.cursor_type = NO_CURSOR;
4379 data.cursor_x = -1;
4380
4381 data.start_col = 0;
4382 /* I don't think we want this, string areas should not scroll with
4383 the window
4384 data.start_col = w->hscroll;
4385 data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4386 */
4387 data.bi_start_col_enabled = 0;
4388 data.hscroll_glyph_width_adjust = 0;
4389
4390 /* We regenerate the line from the very beginning. */
4391 Dynarr_reset (db->runes);
4392
4393 /* Why is this less than or equal and not just less than? If the
4394 starting position is already equal to the maximum we can't add
4395 anything else, right? Wrong. We might still have a newline to
4396 add. A newline can use the room allocated for an end glyph since
4397 if we add it we know we aren't going to be adding any end
4398 glyph. */
4399
4400 /* #### Chuck -- I think this condition should be while (1).
4401 Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4402 and the begin-glyph ends exactly at the end of the window, the
4403 end-glyph and text might not be displayed. while (1) ensures
4404 that the loop terminates only when either (a) there is
4405 propagation data or (b) the end-of-line or end-of-buffer is hit.
4406
4407 #### Also I think you need to ensure that the operation
4408 "add begin glyphs; add end glyphs; add text" is atomic and
4409 can't get interrupted in the middle. If you run off the end
4410 of the line during that operation, then you keep accumulating
4411 propagation data until you're done. Otherwise, if the (e.g.)
4412 there's a begin glyph at a particular position and attempting
4413 to display that glyph results in window-end being hit and
4414 propagation data being generated, then the character at that
4415 position won't be displayed.
4416
4417 #### See also the comment after the end of this loop, below.
4418 */
4419 while (data.pixpos <= data.max_pixpos)
4420 {
4421 /* #### This check probably should not be necessary. */
4422 if (data.bi_bufpos > bi_string_zv)
4423 {
4424 /* #### urk! More of this lossage! */
4425 data.bi_bufpos--;
4426 goto done;
4427 }
4428
4429 /* Check for face changes. */
4430 if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
4431 {
4432 /* Now compute the face and begin/end-glyph information. */
4433 data.findex =
4434 /* Remember that the extent-fragment routines deal in Bytind's. */
4435 extent_fragment_update (w, data.ef, data.bi_bufpos);
4436 /* This is somewhat cheesy but the alternative is to
4437 propagate default_face into extent_fragment_update. */
4438 if (data.findex == DEFAULT_INDEX)
4439 data.findex = default_face;
4440
4441 get_display_tables (w, data.findex, &face_dt, &window_dt);
4442
4443 if (data.bi_bufpos == data.ef->end)
4444 no_more_frags = 1;
4445 }
4446 initial = 0;
4447
4448 /* Determine what is next to be displayed. We first handle any
4449 glyphs returned by glyphs_at_bufpos. If there are no glyphs to
4450 display then we determine what to do based on the character at the
4451 current buffer position. */
4452
4453 /* If the current position is covered by an invisible extent, do
4454 nothing (except maybe add some ellipses).
4455
4456 #### The behavior of begin and end-glyphs at the edge of an
4457 invisible extent should be investigated further. This is
4458 fairly low priority though. */
4459 if (data.ef->invisible)
4460 {
4461 /* #### Chuck, perhaps you could look at this code? I don't
4462 really know what I'm doing. */
4463 if (*prop)
4464 {
4465 Dynarr_free (*prop);
4466 *prop = 0;
4467 }
4468
4469 /* The extent fragment code only sets this when we should
4470 really display the ellipses. It makes sure the ellipses
4471 don't get displayed more than once in a row. */
4472 if (data.ef->invisible_ellipses)
4473 {
4474 struct glyph_block gb;
4475
4476 data.ef->invisible_ellipses_already_displayed = 1;
4477 data.ef->invisible_ellipses = 0;
4478 gb.extent = Qnil;
4479 gb.glyph = Vinvisible_text_glyph;
4480 *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
4481 GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
4482 /* Perhaps they shouldn't propagate if the very next thing
4483 is to display a newline (for compatibility with
4484 selective-display-ellipses)? Maybe that's too
4485 abstruse. */
4486 if (*prop)
4487 goto done;
4488 }
4489
4490 /* #### What if we we're dealing with a display table? */
4491 if (data.start_col)
4492 data.start_col--;
4493
4494 if (data.bi_bufpos == bi_string_zv)
4495 goto done;
4496 else
4497 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4498 }
4499
4500 /* If there is propagation data, then it represents the current
4501 buffer position being displayed. Add them and advance the
4502 position counter. This might also add the minibuffer
4503 prompt. */
4504 else if (*prop)
4505 {
4506 dl->used_prop_data = 1;
4507 *prop = add_propagation_runes (prop, &data);
4508
4509 if (*prop)
4510 goto done; /* gee, a really narrow window */
4511 else if (data.bi_bufpos == bi_string_zv)
4512 goto done;
4513 else if (data.bi_bufpos < 0)
4514 /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4515 data.bi_bufpos = 0;
4516 else
4517 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4518 }
4519
4520 /* If there are end glyphs, add them to the line. These are
4521 the end glyphs for the previous run of text. We add them
4522 here rather than doing them at the end of handling the
4523 previous run so that glyphs at the beginning and end of
4524 a line are handled correctly. */
4525 else if (Dynarr_length (data.ef->end_glyphs) > 0)
4526 {
4527 *prop = add_glyph_runes (&data, END_GLYPHS);
4528 if (*prop)
4529 goto done;
4530 }
4531
4532 /* If there are begin glyphs, add them to the line. */
4533 else if (Dynarr_length (data.ef->begin_glyphs) > 0)
4534 {
4535 *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
4536 if (*prop)
4537 goto done;
4538 }
4539
4540 /* If at end-of-buffer, we've already processed begin and
4541 end-glyphs at this point and there's no text to process,
4542 so we're done. */
4543 else if (data.bi_bufpos == bi_string_zv)
4544 goto done;
4545
4546 else
4547 {
4548 Lisp_Object entry = Qnil;
4549 /* Get the character at the current buffer position. */
4550 data.ch = string_char (s, data.bi_bufpos);
4551 if (!NILP (face_dt) || !NILP (window_dt))
4552 entry = display_table_entry (data.ch, face_dt, window_dt);
4553
4554 /* If there is a display table entry for it, hand it off to
4555 add_disp_table_entry_runes and let it worry about it. */
4556 if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
4557 {
4558 *prop = add_disp_table_entry_runes (&data, entry);
4559
4560 if (*prop)
4561 goto done;
4562 }
4563
4564 /* Check if we have hit a newline character. If so, add a marker
4565 to the line and end this loop. */
4566 else if (data.ch == '\n')
4567 {
4568 /* We aren't going to be adding an end glyph so give its
4569 space back in order to make sure that the cursor can
4570 fit. */
4571 data.max_pixpos += end_glyph_width;
4572 goto done;
4573 }
4574
4575 /* If the current character is considered to be printable, then
4576 just add it. */
4577 else if (data.ch >= printable_min)
4578 {
4579 *prop = add_emchar_rune (&data);
4580 if (*prop)
4581 goto done;
4582 }
4583
4584 /* If the current character is a tab, determine the next tab
4585 starting position and add a blank rune which extends from the
4586 current pixel position to that starting position. */
4587 else if (data.ch == '\t')
4588 {
4589 int tab_start_pixpos = data.pixpos;
4590 int next_tab_start;
4591 int char_tab_width;
4592 int prop_width = 0;
4593
4594 if (data.start_col > 1)
4595 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
4596
4597 next_tab_start =
4598 next_tab_position (w, tab_start_pixpos,
4599 dl->bounds.left_in +
4600 data.hscroll_glyph_width_adjust);
4601 if (next_tab_start > data.max_pixpos)
4602 {
4603 prop_width = next_tab_start - data.max_pixpos;
4604 next_tab_start = data.max_pixpos;
4605 }
4606 data.blank_width = next_tab_start - data.pixpos;
4607 char_tab_width =
4608 (next_tab_start - tab_start_pixpos) / space_width (w);
4609
4610 *prop = add_blank_rune (&data, w, char_tab_width);
4611
4612 /* add_blank_rune is only supposed to be called with
4613 sizes guaranteed to fit in the available space. */
4614 assert (!(*prop));
4615
4616 if (prop_width)
4617 {
4618 struct prop_block pb;
4619 *prop = Dynarr_new (prop_block);
4620
4621 pb.type = PROP_BLANK;
4622 pb.data.p_blank.width = prop_width;
4623 pb.data.p_blank.findex = data.findex;
4624 Dynarr_add (*prop, pb);
4625
4626 goto done;
4627 }
4628 }
4629
4630 /* If character is a control character, pass it off to
4631 add_control_char_runes.
4632
4633 The is_*() routines have undefined results on
4634 arguments outside of the range [-1, 255]. (This
4635 often bites people who carelessly use `char' instead
4636 of `unsigned char'.)
4637 */
4638 else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
4639 {
4640 *prop = add_control_char_runes (&data, b);
4641
4642 if (*prop)
4643 goto done;
4644 }
4645
4646 /* If the character is above the ASCII range and we have not
4647 already handled it, then print it as an octal number. */
4648 else if (data.ch >= 0200)
4649 {
4650 *prop = add_octal_runes (&data);
4651
4652 if (*prop)
4653 goto done;
4654 }
4655
4656 /* Assume the current character is considered to be printable,
4657 then just add it. */
4658 else
4659 {
4660 *prop = add_emchar_rune (&data);
4661 if (*prop)
4662 goto done;
4663 }
4664
4665 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4666 }
4667 }
4668
4669 done:
4670
4671 /* Determine the starting point of the next line if we did not hit the
4672 end of the buffer. */
4673 if (data.bi_bufpos < bi_string_zv)
4674 {
4675 /* #### This check is not correct. If the line terminated
4676 due to a begin-glyph or end-glyph hitting window-end, then
4677 data.ch will not point to the character at data.bi_bufpos. If
4678 you make the two changes mentioned at the top of this loop,
4679 you should be able to say '(if (*prop))'. That should also
4680 make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4681 check. */
4682
4683 /* The common case is that the line ended because we hit a newline.
4684 In that case, the next character is just the next buffer
4685 position. */
4686 if (data.ch == '\n')
4687 {
4688 INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4689 }
4690
4691 /* Otherwise we have a buffer line which cannot fit on one display
4692 line. */
4693 else
4694 {
4695 struct glyph_block gb;
4696 struct glyph_cachel *cachel;
4697
4698 /* If the line is to be truncated then we actually have to look
4699 for the next newline. We also add the end-of-line glyph which
4700 we know will fit because we adjusted the right border before
4701 we starting laying out the line. */
4702 data.max_pixpos += end_glyph_width;
4703 data.findex = default_face;
4704 gb.extent = Qnil;
4705
4706 if (truncate_win)
4707 {
4708 Bytind bi_pos;
4709
4710 /* Now find the start of the next line. */
4711 bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
4712
4713 data.cursor_type = NO_CURSOR;
4714 data.bi_bufpos = bi_pos;
4715 gb.glyph = Vtruncation_glyph;
4716 cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
4717 }
4718 else
4719 {
4720 /* The cursor can never be on the continuation glyph. */
4721 data.cursor_type = NO_CURSOR;
4722
4723 /* data.bi_bufpos is already at the start of the next line. */
4724
4725 gb.glyph = Vcontinuation_glyph;
4726 cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
4727 }
4728
4729 if (end_glyph_width)
4730 add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
4731
4732 if (truncate_win && data.bi_bufpos == bi_string_zv)
4733 {
4734 CONST Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
4735 DEC_CHARPTR (endb);
4736 if (charptr_emchar (endb) != '\n')
4737 {
4738 /* #### Damn this losing shit. */
4739 data.bi_bufpos++;
4740 }
4741 }
4742 }
4743 }
4744 else if (data.bi_bufpos == bi_string_zv)
4745 {
4746 /* create_text_block () adds a bogus \n marker here which screws
4747 up subwindow display. Since we never have a cursor in the
4748 gutter we can safely ignore it. */
4749 }
4750 /* Calculate left whitespace boundary. */
4751 {
4752 int elt = 0;
4753
4754 /* Whitespace past a newline is considered right whitespace. */
4755 while (elt < Dynarr_length (db->runes))
4756 {
4757 struct rune *rb = Dynarr_atp (db->runes, elt);
4758
4759 if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4760 || rb->type == RUNE_BLANK)
4761 {
4762 dl->bounds.left_white += rb->width;
4763 elt++;
4764 }
4765 else
4766 elt = Dynarr_length (db->runes);
4767 }
4768 }
4769
4770 /* Calculate right whitespace boundary. */
4771 {
4772 int elt = Dynarr_length (db->runes) - 1;
4773 int done = 0;
4774
4775 while (!done && elt >= 0)
4776 {
4777 struct rune *rb = Dynarr_atp (db->runes, elt);
4778
4779 if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4780 && isspace (rb->object.chr.ch))
4781 && !rb->type == RUNE_BLANK)
4782 {
4783 dl->bounds.right_white = rb->xpos + rb->width;
4784 done = 1;
4785 }
4786
4787 elt--;
4788
4789 }
4790
4791 /* The line is blank so everything is considered to be right
4792 whitespace. */
4793 if (!done)
4794 dl->bounds.right_white = dl->bounds.left_in;
4795 }
4796
4797 /* Set the display blocks bounds. */
4798 db->start_pos = dl->bounds.left_in;
4799 if (Dynarr_length (db->runes))
4800 {
4801 struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4802
4803 db->end_pos = rb->xpos + rb->width;
4804 }
4805 else
4806 db->end_pos = dl->bounds.right_white;
4807
4808 /* update line height parameters */
4809 if (!data.new_ascent && !data.new_descent)
4810 {
4811 /* We've got a blank line so initialize these values from the default
4812 face. */
4813 default_face_font_info (data.window, &data.new_ascent,
4814 &data.new_descent, 0, 0, 0);
4815 }
4816
4817 if (data.max_pixmap_height)
4818 {
4819 int height = data.new_ascent + data.new_descent;
4820 int pix_ascent, pix_descent;
4821
4822 pix_descent = data.max_pixmap_height * data.new_descent / height;
4823 pix_ascent = data.max_pixmap_height - pix_descent;
4824
4825 data.new_ascent = max (data.new_ascent, pix_ascent);
4826 data.new_descent = max (data.new_descent, pix_descent);
4827 }
4828
4829 dl->ascent = data.new_ascent;
4830 dl->descent = data.new_descent;
4831
4832 {
4833 unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
4834
4835 if (dl->ascent < ascent)
4836 dl->ascent = ascent;
4837 }
4838 {
4839 unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
4840
4841 if (dl->descent < descent)
4842 dl->descent = descent;
4843 }
4844
4845 dl->cursor_elt = data.cursor_x;
4846 /* #### lossage lossage lossage! Fix this shit! */
4847 if (data.bi_bufpos > bi_string_zv)
4848 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4849 else
4850 dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4851 if (truncate_win)
4852 data.dl->num_chars =
4853 string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
4854 else
4855 /* This doesn't correctly take into account tabs and control
4856 characters but if the window isn't being truncated then this
4857 value isn't going to end up being used anyhow. */
4858 data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4859
4860 /* #### handle horizontally scrolled line with text none of which
4861 was actually laid out. */
4862
4863 /* #### handle any remainder of overlay arrow */
4864
4865 if (*prop == ADD_FAILED)
4866 *prop = NULL;
4867
4868 if (truncate_win && *prop)
4869 {
4870 Dynarr_free (*prop);
4871 *prop = NULL;
4872 }
4873
4874 extent_fragment_delete (data.ef);
4875
4876 /* #### If we started at EOB, then make sure we return a value past
4877 it so that regenerate_window will exit properly. This is bogus.
4878 The main loop should get fixed so that it isn't necessary to call
4879 this function if we are already at EOB. */
4880
4881 if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4882 return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
4883 else
4884 return bytecount_to_charcount (string_data (s), data.bi_bufpos);
4885 }
4886
4887 /* Given a display line and a starting position, ensure that the
4888 contents of the display line accurately represent the visual
4889 representation of the buffer contents starting from the given
4890 position when displayed in the given window. The display line ends
4891 when the contents of the line reach the right boundary of the given
4892 window.
4893
4894 This is very similar to generate_display_line but with the same
4895 limitations as create_string_text_block. I have taken the liberty
4896 of fixing the bytind stuff though.*/
4897
4898 static Bufpos
4899 generate_string_display_line (struct window *w, Lisp_Object disp_string,
4900 struct display_line *dl,
4901 Bufpos start_pos,
4902 prop_block_dynarr **prop,
4903 face_index default_face)
4904 {
4905 Bufpos ret_bufpos;
4906
4907 /* you must set bounds before calling this. */
4908
4909 /* Reset what this line is using. */
4910 if (dl->display_blocks)
4911 Dynarr_reset (dl->display_blocks);
4912 if (dl->left_glyphs)
4913 {
4914 Dynarr_free (dl->left_glyphs);
4915 dl->left_glyphs = 0;
4916 }
4917 if (dl->right_glyphs)
4918 {
4919 Dynarr_free (dl->right_glyphs);
4920 dl->right_glyphs = 0;
4921 }
4922
4923 /* We aren't generating a modeline at the moment. */
4924 dl->modeline = 0;
4925
4926 /* Create a display block for the text region of the line. */
4927 ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
4928 prop, default_face);
4929 dl->bufpos = start_pos;
4930 if (dl->end_bufpos < dl->bufpos)
4931 dl->end_bufpos = dl->bufpos;
4932
4933 /* If there are left glyphs associated with any character in the
4934 text block, then create a display block to handle them. */
4935 if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
4936 create_left_glyph_block (w, dl, 0);
4937
4938 /* If there are right glyphs associated with any character in the
4939 text block, then create a display block to handle them. */
4940 if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
4941 create_right_glyph_block (w, dl);
4942
4943 return ret_bufpos;
4944 }
4945
4946 /* This is ripped off from regenerate_window. All we want to do is
4947 loop through elements in the string creating display lines until we
4948 have covered the provided area. Simple really. */
4949 void
4950 generate_displayable_area (struct window *w, Lisp_Object disp_string,
4951 int xpos, int ypos, int width, int height,
4952 display_line_dynarr* dla,
4953 Bufpos start_pos,
4954 face_index default_face)
4955 {
4956 int yend = ypos + height;
4957 Charcount s_zv;
4958
4959 prop_block_dynarr *prop = 0;
4960 layout_bounds bounds;
4961 assert (dla);
4962
4963 Dynarr_reset (dla);
4964 /* if there's nothing to do then do nothing. code after this assumes
4965 there is something to do. */
4966 if (NILP (disp_string))
4967 return;
4968
4969 s_zv = XSTRING_CHAR_LENGTH (disp_string);
4970
4971 bounds.left_out = xpos;
4972 bounds.right_out = xpos + width;
4973 /* The inner boundaries mark where the glyph margins are located. */
4974 bounds.left_in = bounds.left_out + window_left_margin_width (w);
4975 bounds.right_in = bounds.right_out - window_right_margin_width (w);
4976 /* We cannot fully calculate the whitespace boundaries as they
4977 depend on the contents of the line being displayed. */
4978 bounds.left_white = bounds.left_in;
4979 bounds.right_white = bounds.right_in;
4980
4981 while (ypos < yend)
4982 {
4983 struct display_line dl;
4984 struct display_line *dlp;
4985 Bufpos next_pos;
4986 int local;
4987
4988 if (Dynarr_length (dla) < Dynarr_largest (dla))
4989 {
4990 dlp = Dynarr_atp (dla, Dynarr_length (dla));
4991 local = 0;
4992 }
4993 else
4994 {
4995
4996 xzero (dl);
4997 dlp = &dl;
4998 local = 1;
4999 }
5000
5001 dlp->bounds = bounds;
5002 dlp->offset = 0;
5003 next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5004 &prop, default_face);
5005 /* we need to make sure that we continue along the line if there
5006 is more left to display otherwise we just end up redisplaying
5007 the same chunk over and over again. */
5008 if (next_pos == start_pos && next_pos < s_zv)
5009 start_pos++;
5010 else
5011 start_pos = next_pos;
5012
5013 dlp->ypos = ypos + dlp->ascent;
5014 ypos = dlp->ypos + dlp->descent;
5015
5016 if (ypos > yend)
5017 {
5018 int visible_height = dlp->ascent + dlp->descent;
5019
5020 dlp->clip = (ypos - yend);
5021 visible_height -= dlp->clip;
5022
5023 if (visible_height < VERTICAL_CLIP (w, 1))
5024 {
5025 if (local)
5026 free_display_line (dlp);
5027 break;
5028 }
5029 }
5030 else
5031 dlp->clip = 0;
5032
5033 Dynarr_add (dla, *dlp);
5034
5035 /* #### This type of check needs to be done down in the
5036 generate_display_line call. */
5037 if (start_pos >= s_zv)
5038 break;
5039 }
5040
5041 if (prop)
5042 Dynarr_free (prop);
5043 }
5044
5045
5046 /***************************************************************************/
5047 /* */
5048 /* window-regeneration routines */
5049 /* */
5050 /***************************************************************************/
5051
5052 /* For a given window and starting position in the buffer it contains,
5053 ensure that the TYPE display lines accurately represent the
5054 presentation of the window. We pass the buffer instead of getting
5055 it from the window since redisplay_window may have temporarily
5056 changed it to the echo area buffer. */
5057
5058 static void
5059 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
5060 {
5061 struct frame *f = XFRAME (w->frame);
5062 struct buffer *b = XBUFFER (w->buffer);
5063 int ypos = WINDOW_TEXT_TOP (w);
5064 int yend; /* set farther down */
5065 int yclip = WINDOW_TEXT_TOP_CLIP (w);
5066
5067 prop_block_dynarr *prop;
5068 layout_bounds bounds;
5069 display_line_dynarr *dla;
5070 int need_modeline;
5071
5072 /* The lines had better exist by this point. */
5073 if (!(dla = window_display_lines (w, type)))
5074 abort ();
5075 Dynarr_reset (dla);
5076 w->max_line_len = 0;
5077
5078 /* Normally these get updated in redisplay_window but it is possible
5079 for this function to get called from some other points where that
5080 update may not have occurred. This acts as a safety check. */
5081 if (!Dynarr_length (w->face_cachels))
5082 reset_face_cachels (w);
5083 if (!Dynarr_length (w->glyph_cachels))
5084 reset_glyph_cachels (w);
5085
5086 Fset_marker (w->start[type], make_int (start_pos), w->buffer);
5087 Fset_marker (w->pointm[type], make_int (point), w->buffer);
5088 w->last_point_x[type] = -1;
5089 w->last_point_y[type] = -1;
5090
5091 /* Make sure a modeline is in the structs if needed. */
5092 need_modeline = ensure_modeline_generated (w, type);
5093
5094 /* Wait until here to set this so that the structs have a modeline
5095 generated in the case where one didn't exist. */
5096 yend = WINDOW_TEXT_BOTTOM (w);
5097
5098 bounds = calculate_display_line_boundaries (w, 0);
5099
5100 /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5101 if (MINI_WINDOW_P (w)
5102 && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
5103 && !echo_area_active (f)
5104 && start_pos == BUF_BEGV (b))
5105 {
5106 struct prop_block pb;
5107 Lisp_Object string;
5108 prop = Dynarr_new (prop_block);
5109
5110 string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5111 pb.type = PROP_MINIBUF_PROMPT;
5112 pb.data.p_string.str = XSTRING_DATA(string);
5113 pb.data.p_string.len = XSTRING_LENGTH(string);
5114 Dynarr_add (prop, pb);
5115 }
5116 else
5117 prop = 0;
5118
5119 while (ypos < yend)
5120 {
5121 struct display_line dl;
5122 struct display_line *dlp;
5123 int local;
5124
5125 if (Dynarr_length (dla) < Dynarr_largest (dla))
5126 {
5127 dlp = Dynarr_atp (dla, Dynarr_length (dla));
5128 local = 0;
5129 }
5130 else
5131 {
5132
5133 xzero (dl);
5134 dlp = &dl;
5135 local = 1;
5136 }
5137
5138 dlp->bounds = bounds;
5139 dlp->offset = 0;
5140 start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
5141
5142 if (yclip > dlp->ascent)
5143 {
5144 /* this should never happen, but if it does just display the
5145 whole line */
5146 yclip = 0;
5147 }
5148
5149 dlp->ypos = (ypos + dlp->ascent) - yclip;
5150 ypos = dlp->ypos + dlp->descent;
5151
5152 /* See if we've been asked to start midway through a line, for
5153 partial display line scrolling. */
5154 if (yclip)
5155 {
5156 dlp->top_clip = yclip;
5157 yclip = 0;
5158 }
5159 else
5160 dlp->top_clip = 0;
5161
5162 if (ypos > yend)
5163 {
5164 int visible_height = dlp->ascent + dlp->descent;
5165
5166 dlp->clip = (ypos - yend);
5167 /* Although this seems strange we could have a single very
5168 tall line visible for which we need to account for both
5169 the top clip and the bottom clip. */
5170 visible_height -= (dlp->clip + dlp->top_clip);
5171
5172 if (visible_height < VERTICAL_CLIP (w, 1))
5173 {
5174 if (local)
5175 free_display_line (dlp);
5176 break;
5177 }
5178 }
5179 else
5180 dlp->clip = 0;
5181
5182 if (dlp->cursor_elt != -1)
5183 {
5184 /* #### This check is steaming crap. Have to get things
5185 fixed so when create_text_block hits EOB, we're done,
5186 period. */
5187 if (w->last_point_x[type] == -1)
5188 {
5189 w->last_point_x[type] = dlp->cursor_elt;
5190 w->last_point_y[type] = Dynarr_length (dla);
5191 }
5192 else
5193 {
5194 /* #### This means that we've added a cursor at EOB
5195 twice. Yuck oh yuck. */
5196 struct display_block *db =
5197 get_display_block_from_line (dlp, TEXT);
5198
5199 Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
5200 dlp->cursor_elt = -1;
5201 }
5202 }
5203
5204 if (dlp->num_chars > w->max_line_len)
5205 w->max_line_len = dlp->num_chars;
5206
5207 Dynarr_add (dla, *dlp);
5208
5209 /* #### This isn't right, but it is close enough for now. */
5210 w->window_end_pos[type] = start_pos;
5211
5212 /* #### This type of check needs to be done down in the
5213 generate_display_line call. */
5214 if (start_pos > BUF_ZV (b))
5215 break;
5216 }
5217
5218 if (prop)
5219 Dynarr_free (prop);
5220
5221 /* #### More not quite right, but close enough. */
5222 /* #### Ben sez: apparently window_end_pos[] is measured
5223 as the number of characters between the window end and the
5224 end of the buffer? This seems rather weirdo. What's
5225 the justification for this? */
5226 w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
5227
5228 if (need_modeline)
5229 {
5230 /* We know that this is the right thing to use because we put it
5231 there when we first started working in this function. */
5232 generate_modeline (w, Dynarr_atp (dla, 0), type);
5233 }
5234 }
5235
5236 #define REGEN_INC_FIND_START_END \
5237 do { \
5238 /* Determine start and end of lines. */ \
5239 if (!Dynarr_length (cdla)) \
5240 return 0; \
5241 else \
5242 { \
5243 if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5244 { \
5245 dla_start = 1; \
5246 } \
5247 else if (!Dynarr_atp (cdla, 0)->modeline \
5248 && !Dynarr_atp (ddla, 0)->modeline) \
5249 { \
5250 dla_start = 0; \
5251 } \
5252 else \
5253 abort (); /* structs differ */ \
5254 \
5255 dla_end = Dynarr_length (cdla) - 1; \
5256 } \
5257 \
5258 start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5259 + Dynarr_atp (cdla, dla_start)->offset); \
5260 /* If this isn't true, then startp has changed and we need to do a \
5261 full regen. */ \
5262 if (startp != start_pos) \
5263 return 0; \
5264 \
5265 /* Point is outside the visible region so give up. */ \
5266 if (pointm < start_pos) \
5267 return 0; \
5268 \
5269 } while (0)
5270
5271 /* This attempts to incrementally update the display structures. It
5272 returns a boolean indicating success or failure. This function is
5273 very similar to regenerate_window_incrementally and is in fact only
5274 called from that function. However, because of the nature of the
5275 changes it deals with it sometimes makes different assumptions
5276 which can lead to success which are much more difficult to make
5277 when dealing with buffer changes. */
5278
5279 static int
5280 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
5281 Bufpos pointm,
5282 Charcount beg_unchanged,
5283 Charcount end_unchanged)
5284 {
5285 struct buffer *b = XBUFFER (w->buffer);
5286 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5287 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5288
5289 int dla_start = 0;
5290 int dla_end, line;
5291 int first_line, last_line;
5292 Bufpos start_pos;
5293 /* Don't define this in the loop where it is used because we
5294 definitely want its value to survive between passes. */
5295 prop_block_dynarr *prop = NULL;
5296
5297 /* If we don't have any buffer change recorded but the modiff flag has
5298 been incremented, then fail. I'm not sure of the exact circumstances
5299 under which this can happen, but I believe that it is probably a
5300 reasonable happening. */
5301 if (!point_visible (w, pointm, CURRENT_DISP)
5302 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
5303 return 0;
5304
5305 /* If the cursor is moved we attempt to update it. If we succeed we
5306 go ahead and proceed with the optimization attempt. */
5307 if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5308 || pointm != marker_position (w->last_point[CURRENT_DISP]))
5309 {
5310 struct frame *f = XFRAME (w->frame);
5311 struct device *d = XDEVICE (f->device);
5312 struct frame *sel_f = device_selected_frame (d);
5313 int success = 0;
5314
5315 if (w->last_point_x[CURRENT_DISP] != -1
5316 && w->last_point_y[CURRENT_DISP] != -1)
5317 {
5318
5319 if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
5320 {
5321 /* Always regenerate the modeline in case it is
5322 displaying the current line or column. */
5323 regenerate_modeline (w);
5324 success = 1;
5325 }
5326 }
5327 else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
5328 {
5329 if (f->modeline_changed)
5330 regenerate_modeline (w);
5331 success = 1;
5332 }
5333
5334 if (!success)
5335 return 0;
5336 }
5337
5338 if (beg_unchanged == -1 && end_unchanged == -1)
5339 return 1;
5340
5341 /* assert: There are no buffer modifications or they are all below the
5342 visible region. We assume that regenerate_window_incrementally has
5343 not called us unless this is true. */
5344
5345 REGEN_INC_FIND_START_END;
5346
5347 /* If the changed are starts before the visible area, give up. */
5348 if (beg_unchanged < startp)
5349 return 0;
5350
5351 /* Find what display line the extent changes first affect. */
5352 line = dla_start;
5353 while (line <= dla_end)
5354 {
5355 struct display_line *dl = Dynarr_atp (cdla, line);
5356 Bufpos lstart = dl->bufpos + dl->offset;
5357 Bufpos lend = dl->end_bufpos + dl->offset;
5358
5359 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5360 break;
5361
5362 line++;
5363 }
5364
5365 /* If the changes are below the visible area then if point hasn't
5366 moved return success otherwise fail in order to be safe. */
5367 if (line > dla_end)
5368 {
5369 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5370 && pointm == marker_position (w->last_point[CURRENT_DISP]))
5371 return 1;
5372 else
5373 return 0;
5374 }
5375
5376 /* At this point we know what line the changes first affect. We now
5377 begin redrawing lines as long as we are still in the affected
5378 region and the line's size and positioning don't change.
5379 Otherwise we fail. If we fail we will have altered the desired
5380 structs which could lead to an assertion failure. However, if we
5381 fail the next thing that is going to happen is a full regen so we
5382 will actually end up being safe. */
5383 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5384 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5385 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5386 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5387
5388 first_line = last_line = line;
5389 while (line <= dla_end)
5390 {
5391 Bufpos old_start, old_end, new_start;
5392 struct display_line *cdl = Dynarr_atp (cdla, line);
5393 struct display_line *ddl = Dynarr_atp (ddla, line);
5394 struct display_block *db;
5395 int initial_size;
5396
5397 assert (cdl->bufpos == ddl->bufpos);
5398 assert (cdl->end_bufpos == ddl->end_bufpos);
5399 assert (cdl->offset == ddl->offset);
5400
5401 db = get_display_block_from_line (ddl, TEXT);
5402 initial_size = Dynarr_length (db->runes);
5403 old_start = ddl->bufpos + ddl->offset;
5404 old_end = ddl->end_bufpos + ddl->offset;
5405
5406 /* If this is the first line being updated and it used
5407 propagation data, fail. Otherwise we'll be okay because
5408 we'll have the necessary propagation data. */
5409 if (line == first_line && ddl->used_prop_data)
5410 return 0;
5411
5412 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5413 &prop, DESIRED_DISP);
5414 ddl->offset = 0;
5415
5416 /* #### If there is propagated stuff the fail. We could
5417 probably actually deal with this if the line had propagated
5418 information when originally created by a full
5419 regeneration. */
5420 if (prop)
5421 {
5422 Dynarr_free (prop);
5423 return 0;
5424 }
5425
5426 /* If any line position parameters have changed or a
5427 cursor has disappeared or disappeared, fail. */
5428 db = get_display_block_from_line (ddl, TEXT);
5429 if (cdl->ypos != ddl->ypos
5430 || cdl->ascent != ddl->ascent
5431 || cdl->descent != ddl->descent
5432 || cdl->top_clip != ddl->top_clip
5433 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5434 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5435 || old_start != ddl->bufpos
5436 || old_end != ddl->end_bufpos
5437 || initial_size != Dynarr_length (db->runes))
5438 {
5439 return 0;
5440 }
5441
5442 if (ddl->cursor_elt != -1)
5443 {
5444 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5445 w->last_point_y[DESIRED_DISP] = line;
5446 }
5447
5448 last_line = line;
5449
5450 /* If the extent changes end on the line we just updated then
5451 we're done. Otherwise go on to the next line. */
5452 if (end_unchanged <= ddl->end_bufpos)
5453 break;
5454 else
5455 line++;
5456 }
5457
5458 redisplay_update_line (w, first_line, last_line, 1);
5459 return 1;
5460 }
5461
5462 /* Attempt to update the display data structures based on knowledge of
5463 the changed region in the buffer. Returns a boolean indicating
5464 success or failure. If this function returns a failure then a
5465 regenerate_window _must_ be performed next in order to maintain
5466 invariants located here. */
5467
5468 static int
5469 regenerate_window_incrementally (struct window *w, Bufpos startp,
5470 Bufpos pointm)
5471 {
5472 struct buffer *b = XBUFFER (w->buffer);
5473 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5474 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5475 Charcount beg_unchanged, end_unchanged;
5476 Charcount extent_beg_unchanged, extent_end_unchanged;
5477
5478 int dla_start = 0;
5479 int dla_end, line;
5480 Bufpos start_pos;
5481
5482 /* If this function is called, the current and desired structures
5483 had better be identical. If they are not, then that is a bug. */
5484 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
5485
5486 /* We don't handle minibuffer windows yet. The minibuffer prompt
5487 screws us up. */
5488 if (MINI_WINDOW_P (w))
5489 return 0;
5490
5491 extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
5492 extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
5493 ? -1
5494 : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
5495
5496 /* If nothing has changed in the buffer, then make sure point is ok
5497 and succeed. */
5498 if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
5499 return regenerate_window_extents_only_changed (w, startp, pointm,
5500 extent_beg_unchanged,
5501 extent_end_unchanged);
5502
5503 /* We can't deal with deleted newlines. */
5504 if (BUF_NEWLINE_WAS_DELETED (b))
5505 return 0;
5506
5507 beg_unchanged = BUF_BEGIN_UNCHANGED (b);
5508 end_unchanged = (BUF_END_UNCHANGED (b) == -1
5509 ? -1
5510 : BUF_Z (b) - BUF_END_UNCHANGED (b));
5511
5512 REGEN_INC_FIND_START_END;
5513
5514 /* If the changed area starts before the visible area, give up. */
5515 if (beg_unchanged < startp)
5516 return 0;
5517
5518 /* Find what display line the buffer changes first affect. */
5519 line = dla_start;
5520 while (line <= dla_end)
5521 {
5522 struct display_line *dl = Dynarr_atp (cdla, line);
5523 Bufpos lstart = dl->bufpos + dl->offset;
5524 Bufpos lend = dl->end_bufpos + dl->offset;
5525
5526 if (beg_unchanged >= lstart && beg_unchanged <= lend)
5527 break;
5528
5529 line++;
5530 }
5531
5532 /* If the changes are below the visible area then if point hasn't
5533 moved return success otherwise fail in order to be safe. */
5534 if (line > dla_end)
5535 return regenerate_window_extents_only_changed (w, startp, pointm,
5536 extent_beg_unchanged,
5537 extent_end_unchanged);
5538 else
5539 /* At this point we know what line the changes first affect. We
5540 now redraw that line. If the changes are contained within it
5541 we are going to succeed and can update just that one line.
5542 Otherwise we fail. If we fail we will have altered the desired
5543 structs which could lead to an assertion failure. However, if
5544 we fail the next thing that is going to happen is a full regen
5545 so we will actually end up being safe. */
5546 {
5547 Bufpos new_start;
5548 prop_block_dynarr *prop = NULL;
5549 struct display_line *cdl = Dynarr_atp (cdla, line);
5550 struct display_line *ddl = Dynarr_atp (ddla, line);
5551
5552 assert (cdl->bufpos == ddl->bufpos);
5553 assert (cdl->end_bufpos == ddl->end_bufpos);
5554 assert (cdl->offset == ddl->offset);
5555
5556 /* If the last rune is already a continuation glyph, fail.
5557 #### We should be able to handle this better. */
5558 {
5559 struct display_block *db = get_display_block_from_line (ddl, TEXT);
5560 if (Dynarr_length (db->runes))
5561 {
5562 struct rune *rb =
5563 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
5564
5565 if (rb->type == RUNE_DGLYPH
5566 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
5567 return 0;
5568 }
5569 }
5570
5571 /* If the line was generated using propagation data, fail. */
5572 if (ddl->used_prop_data)
5573 return 0;
5574
5575 new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5576 &prop, DESIRED_DISP);
5577 ddl->offset = 0;
5578
5579 /* If there is propagated stuff then it is pretty much a
5580 guarantee that more than just the one line is affected. */
5581 if (prop)
5582 {
5583 Dynarr_free (prop);
5584 return 0;
5585 }
5586
5587 /* If the last rune is now a continuation glyph, fail. */
5588 {
5589 struct display_block *db = get_display_block_from_line (ddl, TEXT);
5590 if (Dynarr_length (db->runes))
5591 {
5592 struct rune *rb =
5593 Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
5594
5595 if (rb->type == RUNE_DGLYPH
5596 && EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))
5597 return 0;
5598 }
5599 }
5600
5601 /* If any line position parameters have changed or a
5602 cursor has disappeared or disappeared, fail. */
5603 if (cdl->ypos != ddl->ypos
5604 || cdl->ascent != ddl->ascent
5605 || cdl->descent != ddl->descent
5606 || cdl->top_clip != ddl->top_clip
5607 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5608 || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
5609 {
5610 return 0;
5611 }
5612
5613 /* If the changed area also ends on this line, then we may be in
5614 business. Update everything and return success. */
5615 if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
5616 {
5617 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5618 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5619 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
5620 w->buffer);
5621 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
5622 w->buffer);
5623
5624 if (ddl->cursor_elt != -1)
5625 {
5626 w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5627 w->last_point_y[DESIRED_DISP] = line;
5628 }
5629
5630 redisplay_update_line (w, line, line, 1);
5631 regenerate_modeline (w);
5632
5633 /* #### For now we just flush the cache until this has been
5634 tested. After that is done, this should correct the
5635 cache directly. */
5636 Dynarr_reset (w->line_start_cache);
5637
5638 /* Adjust the extent changed boundaries to remove any
5639 overlap with the buffer changes since we've just
5640 successfully updated that area. */
5641 if (extent_beg_unchanged != -1
5642 && extent_beg_unchanged >= beg_unchanged
5643 && extent_beg_unchanged < end_unchanged)
5644 extent_beg_unchanged = end_unchanged;
5645
5646 if (extent_end_unchanged != -1
5647 && extent_end_unchanged >= beg_unchanged
5648 && extent_end_unchanged < end_unchanged)
5649 extent_end_unchanged = beg_unchanged - 1;
5650
5651 if (extent_end_unchanged <= extent_beg_unchanged)
5652 extent_beg_unchanged = extent_end_unchanged = -1;
5653
5654 /* This could lead to odd results if it fails, but since the
5655 buffer changes update succeeded this probably will to.
5656 We already know that the extent changes start at or after
5657 the line because we checked before entering the loop. */
5658 if (extent_beg_unchanged != -1
5659 && extent_end_unchanged != -1
5660 && ((extent_beg_unchanged < ddl->bufpos)
5661 || (extent_end_unchanged > ddl->end_bufpos)))
5662 return regenerate_window_extents_only_changed (w, startp, pointm,
5663 extent_beg_unchanged,
5664 extent_end_unchanged);
5665 else
5666 return 1;
5667 }
5668 }
5669
5670 /* Oh, well. */
5671 return 0;
5672 }
5673
5674 /* Given a window and a point, update the given display lines such
5675 that point is displayed in the middle of the window.
5676 Return the window's new start position. */
5677
5678 static Bufpos
5679 regenerate_window_point_center (struct window *w, Bufpos point, int type)
5680 {
5681 Bufpos startp;
5682
5683 /* We need to make sure that the modeline is generated so that the
5684 window height can be calculated correctly. */
5685 ensure_modeline_generated (w, type);
5686
5687 startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
5688 regenerate_window (w, startp, point, type);
5689 Fset_marker (w->start[type], make_int (startp), w->buffer);
5690
5691 return startp;
5692 }
5693
5694 /* Given a window and a set of display lines, return a boolean
5695 indicating whether the given point is contained within. */
5696
5697 static int
5698 point_visible (struct window *w, Bufpos point, int type)
5699 {
5700 struct buffer *b = XBUFFER (w->buffer);
5701 display_line_dynarr *dla = window_display_lines (w, type);
5702 int first_line;
5703
5704 if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5705 first_line = 1;
5706 else
5707 first_line = 0;
5708
5709 if (Dynarr_length (dla) > first_line)
5710 {
5711 Bufpos start, end;
5712 struct display_line *dl = Dynarr_atp (dla, first_line);
5713
5714 start = dl->bufpos;
5715 end = BUF_Z (b) - w->window_end_pos[type] - 1;
5716
5717 if (point >= start && point <= end)
5718 {
5719 if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
5720 {
5721 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
5722
5723 if (point >= (dl->bufpos + dl->offset)
5724 && point <= (dl->end_bufpos + dl->offset))
5725 return !dl->clip;
5726 else
5727 return 1;
5728 }
5729 else
5730 return 1;
5731 }
5732 else
5733 return 0;
5734 }
5735 else
5736 return 0;
5737 }
5738
5739 /* Return pixel position the middle of the window, not including the
5740 modeline and any potential horizontal scrollbar. */
5741
5742 int
5743 window_half_pixpos (struct window *w)
5744 {
5745 return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
5746 }
5747
5748 /* Return the display line which is currently in the middle of the
5749 window W for display lines TYPE. */
5750
5751 int
5752 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5753 {
5754 display_line_dynarr *dla;
5755 int half;
5756 int elt;
5757 int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
5758
5759 if (type == CMOTION_DISP)
5760 regenerate_window (w, start, point, type);
5761
5762 dla = window_display_lines (w, type);
5763 half = window_half_pixpos (w);
5764
5765 for (elt = first_elt; elt < Dynarr_length (dla); elt++)
5766 {
5767 struct display_line *dl = Dynarr_atp (dla, elt);
5768 int line_bot = dl->ypos + dl->descent;
5769
5770 if (line_bot > half)
5771 return elt;
5772 }
5773
5774 /* We may not have a line at the middle if the end of the buffer is
5775 being displayed. */
5776 return -1;
5777 }
5778
5779 /* Return a value for point that would place it at the beginning of
5780 the line which is in the middle of the window. */
5781
5782 Bufpos
5783 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5784 {
5785 /* line_at_center will regenerate the display structures, if necessary. */
5786 int line = line_at_center (w, type, start, point);
5787
5788 if (line == -1)
5789 return BUF_ZV (XBUFFER (w->buffer));
5790 else
5791 {
5792 display_line_dynarr *dla = window_display_lines (w, type);
5793 struct display_line *dl = Dynarr_atp (dla, line);
5794
5795 return dl->bufpos;
5796 }
5797 }
5798
5799 /* For a given window, ensure that the current visual representation
5800 is accurate. */
5801
5802 static void
5803 redisplay_window (Lisp_Object window, int skip_selected)
5804 {
5805 struct window *w = XWINDOW (window);
5806 struct frame *f = XFRAME (w->frame);
5807 struct device *d = XDEVICE (f->device);
5808 Lisp_Object old_buffer = w->buffer;
5809 Lisp_Object the_buffer = w->buffer;
5810 struct buffer *b;
5811 int echo_active = 0;
5812 int startp = 1;
5813 int pointm;
5814 int old_startp = 1;
5815 int old_pointm = 1;
5816 int selected_in_its_frame;
5817 int selected_globally;
5818 int skip_output = 0;
5819 int truncation_changed;
5820 int inactive_minibuffer =
5821 (MINI_WINDOW_P (w) &&
5822 (f != device_selected_frame (d)) &&
5823 !is_surrogate_for_selected_frame (f));
5824
5825 /* #### In the new world this function actually does a bunch of
5826 optimizations such as buffer-based scrolling, but none of that is
5827 implemented yet. */
5828
5829 /* If this is a combination window, do its children; that's all.
5830 The selected window is always a leaf so we don't check for
5831 skip_selected here. */
5832 if (!NILP (w->vchild))
5833 {
5834 redisplay_windows (w->vchild, skip_selected);
5835 return;
5836 }
5837 if (!NILP (w->hchild))
5838 {
5839 redisplay_windows (w->hchild, skip_selected);
5840 return;
5841 }
5842
5843 /* Is this window the selected window on its frame? */
5844 selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
5845 selected_globally =
5846 selected_in_its_frame &&
5847 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5848 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
5849 XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5850 if (skip_selected && selected_in_its_frame)
5851 return;
5852
5853 /* It is possible that the window is not fully initialized yet. */
5854 if (NILP (w->buffer))
5855 return;
5856
5857 if (MINI_WINDOW_P (w) && echo_area_active (f))
5858 {
5859 w->buffer = the_buffer = Vecho_area_buffer;
5860 echo_active = 1;
5861 }
5862
5863 b = XBUFFER (w->buffer);
5864
5865 if (echo_active)
5866 {
5867 old_pointm = selected_globally
5868 ? BUF_PT (b)
5869 : marker_position (w->pointm[CURRENT_DISP]);
5870 pointm = 1;
5871 }
5872 else
5873 {
5874 if (selected_globally)
5875 {
5876 pointm = BUF_PT (b);
5877 }
5878 else
5879 {
5880 pointm = marker_position (w->pointm[CURRENT_DISP]);
5881
5882 if (pointm < BUF_BEGV (b))
5883 pointm = BUF_BEGV (b);
5884 else if (pointm > BUF_ZV (b))
5885 pointm = BUF_ZV (b);
5886 }
5887 }
5888 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
5889
5890 /* If the buffer has changed we have to invalidate all of our face
5891 cache elements. */
5892 if ((!echo_active && b != window_display_buffer (w))
5893 || !Dynarr_length (w->face_cachels)
5894 || f->faces_changed)
5895 reset_face_cachels (w);
5896 else
5897 mark_face_cachels_as_not_updated (w);
5898
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))
5904 reset_glyph_cachels (w);
5905 else
5906 mark_glyph_cachels_as_not_updated (w);
5907
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))
5912 {
5913 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5914
5915 goto regeneration_done;
5916 }
5917
5918 if (echo_active)
5919 {
5920 old_startp = marker_position (w->start[CURRENT_DISP]);
5921 startp = 1;
5922 }
5923 else
5924 {
5925 startp = marker_position (w->start[CURRENT_DISP]);
5926 if (startp < BUF_BEGV (b))
5927 startp = BUF_BEGV (b);
5928 else if (startp > BUF_ZV (b))
5929 startp = BUF_ZV (b);
5930 }
5931 Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5932
5933 truncation_changed = (find_window_mirror (w)->truncate_win !=
5934 window_truncation_on (w));
5935
5936 /* If w->force_start is set, then some function set w->start and we
5937 should display from there and change point, if necessary, to
5938 ensure that it is visible. */
5939 if (w->force_start || inactive_minibuffer)
5940 {
5941 w->force_start = 0;
5942 w->last_modified[DESIRED_DISP] = Qzero;
5943 w->last_facechange[DESIRED_DISP] = Qzero;
5944
5945 regenerate_window (w, startp, pointm, DESIRED_DISP);
5946
5947 if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5948 {
5949 pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5950
5951 if (selected_globally)
5952 BUF_SET_PT (b, pointm);
5953
5954 Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5955 the_buffer);
5956
5957 /* #### BUFU amounts of overkill just to get the cursor
5958 location marked properly. FIX ME FIX ME FIX ME */
5959 regenerate_window (w, startp, pointm, DESIRED_DISP);
5960 }
5961
5962 goto regeneration_done;
5963 }
5964
5965 /* If nothing has changed since the last redisplay, then we just
5966 need to make sure that point is still visible. */
5967 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5968 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
5969 && pointm >= startp
5970 /* This check is to make sure we restore the minibuffer after a
5971 temporary change to the echo area. */
5972 && !(MINI_WINDOW_P (w) && f->buffers_changed)
5973 && !f->frame_changed
5974 && !truncation_changed
5975 /* check whether start is really at the begining of a line GE */
5976 && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
5977 )
5978 {
5979 /* Check if the cursor has actually moved. */
5980 if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5981 && pointm == marker_position (w->last_point[CURRENT_DISP])
5982 && selected_globally
5983 && !w->windows_changed
5984 && !f->clip_changed
5985 && !f->extents_changed
5986 && !f->faces_changed
5987 && !f->glyphs_changed
5988 && !f->subwindows_changed
5989 && !f->subwindows_state_changed
5990 && !f->point_changed
5991 && !f->windows_structure_changed)
5992 {
5993 /* If not, we're done. */
5994 if (f->modeline_changed)
5995 regenerate_modeline (w);
5996
5997 skip_output = 1;
5998 goto regeneration_done;
5999 }
6000 else
6001 {
6002 /* If the new point is visible in the redisplay structures,
6003 then let the output update routines handle it, otherwise
6004 do things the hard way. */
6005 if (!w->windows_changed
6006 && !f->clip_changed
6007 && !f->extents_changed
6008 && !f->faces_changed
6009 && !f->glyphs_changed
6010 && !f->subwindows_changed
6011 && !f->subwindows_state_changed
6012 && !f->windows_structure_changed)
6013 {
6014 if (point_visible (w, pointm, CURRENT_DISP)
6015 && w->last_point_x[CURRENT_DISP] != -1
6016 && w->last_point_y[CURRENT_DISP] != -1)
6017 {
6018 if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
6019 {
6020 /* Always regenerate in case it is displaying
6021 the current line or column. */
6022 regenerate_modeline (w);
6023
6024 skip_output = 1;
6025 goto regeneration_done;
6026 }
6027 }
6028 else if (!selected_in_its_frame && !f->point_changed)
6029 {
6030 if (f->modeline_changed)
6031 regenerate_modeline (w);
6032
6033 skip_output = 1;
6034 goto regeneration_done;
6035 }
6036 }
6037
6038 /* If we weren't able to take the shortcut method, then use
6039 the brute force method. */
6040 regenerate_window (w, startp, pointm, DESIRED_DISP);
6041
6042 if (point_visible (w, pointm, DESIRED_DISP))
6043 goto regeneration_done;
6044 }
6045 }
6046
6047 /* Check if the starting point is no longer at the beginning of a
6048 line, in which case find a new starting point. We also recenter
6049 if our start position is equal to point-max. Otherwise we'll end
6050 up with a blank window. */
6051 else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
6052 && !(startp == BUF_BEGV (b)
6053 || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
6054 || (pointm == startp &&
6055 EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
6056 startp < marker_position (w->last_start[CURRENT_DISP]))
6057 || (startp == BUF_ZV (b)))
6058 {
6059 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6060
6061 goto regeneration_done;
6062 }
6063 /* See if we can update the data structures locally based on
6064 knowledge of what changed in the buffer. */
6065 else if (!w->windows_changed
6066 && !f->clip_changed
6067 && !f->faces_changed
6068 && !f->glyphs_changed
6069 && !f->subwindows_changed
6070 && !f->subwindows_state_changed
6071 && !f->windows_structure_changed
6072 && !f->frame_changed
6073 && !truncation_changed
6074 && pointm >= startp
6075 && regenerate_window_incrementally (w, startp, pointm))
6076 {
6077 if (f->modeline_changed
6078 || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
6079 || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
6080 regenerate_modeline (w);
6081
6082 skip_output = 1;
6083 goto regeneration_done;
6084 }
6085 /* #### This is where a check for structure based scrolling would go. */
6086 /* If all else fails, try just regenerating and see what happens. */
6087 else
6088 {
6089 regenerate_window (w, startp, pointm, DESIRED_DISP);
6090
6091 if (point_visible (w, pointm, DESIRED_DISP))
6092 goto regeneration_done;
6093 }
6094
6095 /* We still haven't gotten the window regenerated with point
6096 visible. Next we try scrolling a little and see if point comes
6097 back onto the screen. */
6098 if (scroll_step > 0)
6099 {
6100 int scrolled = scroll_conservatively;
6101 for (; scrolled >= 0; scrolled -= scroll_step)
6102 {
6103 startp = vmotion (w, startp,
6104 (pointm < startp) ? -scroll_step : scroll_step, 0);
6105 regenerate_window (w, startp, pointm, DESIRED_DISP);
6106
6107 if (point_visible (w, pointm, DESIRED_DISP))
6108 goto regeneration_done;
6109 }
6110 }
6111
6112 /* We still haven't managed to get the screen drawn with point on
6113 the screen, so just center it and be done with it. */
6114 startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6115
6116
6117 regeneration_done:
6118
6119 /* If the window's frame is changed then reset the current display
6120 lines in order to force a full repaint. */
6121 if (f->frame_changed)
6122 {
6123 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
6124
6125 Dynarr_reset (cla);
6126 }
6127
6128 /* Must do this before calling redisplay_output_window because it
6129 sets some markers on the window. */
6130 if (echo_active)
6131 {
6132 w->buffer = old_buffer;
6133 Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
6134 Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
6135 }
6136
6137 /* These also have to be set before calling redisplay_output_window
6138 since it sets the CURRENT_DISP values based on them. */
6139 w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
6140 w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
6141 Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
6142 Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
6143
6144 if (!skip_output)
6145 {
6146 Bufpos start = marker_position (w->start[DESIRED_DISP]);
6147 Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
6148 ? BUF_ZV (b)
6149 : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
6150 /* Don't pollute the cache if not sure if we are correct */
6151 if (w->start_at_line_beg)
6152 update_line_start_cache (w, start, end, pointm, 1);
6153 redisplay_output_window (w);
6154 /*
6155 * If we just displayed the echo area, the line start cache is
6156 * no longer valid, because the minibuffer window is associated
6157 * with the window now.
6158 */
6159 if (echo_active)
6160 w->line_cache_last_updated = make_int (-1);
6161 }
6162
6163 /* #### This should be dependent on face changes and will need to be
6164 somewhere else once tty updates occur on a per-frame basis. */
6165 mark_face_cachels_as_clean (w);
6166
6167 /* The glyph cachels only get dirty if someone changed something. */
6168 if (glyphs_changed)
6169 mark_glyph_cachels_as_clean (w);
6170
6171 w->windows_changed = 0;
6172 }
6173
6174 /* Call buffer_reset_changes for all buffers present in any window
6175 currently visible in all frames on all devices. #### There has to
6176 be a better way to do this. */
6177
6178 static int
6179 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
6180 {
6181 buffer_reset_changes (XBUFFER (w->buffer));
6182 return 0;
6183 }
6184
6185 static void
6186 reset_buffer_changes (void)
6187 {
6188 Lisp_Object frmcons, devcons, concons;
6189
6190 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6191 {
6192 struct frame *f = XFRAME (XCAR (frmcons));
6193
6194 if (FRAME_REPAINT_P (f))
6195 map_windows (f, reset_buffer_changes_mapfun, 0);
6196 }
6197 }
6198
6199 /* Ensure that all windows underneath the given window in the window
6200 hierarchy are correctly displayed. */
6201
6202 static void
6203 redisplay_windows (Lisp_Object window, int skip_selected)
6204 {
6205 for (; !NILP (window) ; window = XWINDOW (window)->next)
6206 {
6207 redisplay_window (window, skip_selected);
6208 }
6209 }
6210
6211 static int
6212 call_redisplay_end_triggers (struct window *w, void *closure)
6213 {
6214 Bufpos lrpos = w->last_redisplay_pos;
6215 w->last_redisplay_pos = 0;
6216 if (!NILP (w->buffer)
6217 && !NILP (w->redisplay_end_trigger)
6218 && lrpos > 0)
6219 {
6220 Bufpos pos;
6221
6222 if (MARKERP (w->redisplay_end_trigger)
6223 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
6224 pos = marker_position (w->redisplay_end_trigger);
6225 else if (INTP (w->redisplay_end_trigger))
6226 pos = XINT (w->redisplay_end_trigger);
6227 else
6228 {
6229 w->redisplay_end_trigger = Qnil;
6230 return 0;
6231 }
6232
6233 if (lrpos >= pos)
6234 {
6235 Lisp_Object window;
6236 XSETWINDOW (window, w);
6237 va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
6238 Qredisplay_end_trigger_functions,
6239 2, window,
6240 w->redisplay_end_trigger);
6241 w->redisplay_end_trigger = Qnil;
6242 }
6243 }
6244
6245 return 0;
6246 }
6247
6248 /* Ensure that all windows on the given frame are correctly displayed. */
6249
6250 static int
6251 redisplay_frame (struct frame *f, int preemption_check)
6252 {
6253 struct device *d = XDEVICE (f->device);
6254
6255 if (preemption_check)
6256 {
6257 /* The preemption check itself takes a lot of time,
6258 so normally don't do it here. We do it if called
6259 from Lisp, though (`redisplay-frame'). */
6260 int preempted;
6261
6262 REDISPLAY_PREEMPTION_CHECK;
6263 if (preempted)
6264 return 1;
6265 }
6266
6267 /* Before we put a hold on frame size changes, attempt to process
6268 any which are already pending. */
6269 if (f->size_change_pending)
6270 change_frame_size (f, f->new_height, f->new_width, 0);
6271
6272 /* If frame size might need to be changed, due to changed size
6273 of toolbars, scrollbars etc, change it now */
6274 if (f->size_slipped)
6275 {
6276 adjust_frame_size (f);
6277 assert (!f->size_slipped);
6278 }
6279
6280 /* The menubar, toolbar, and icon updates must be done before
6281 hold_frame_size_changes is called and we are officially
6282 'in_display'. They may eval lisp code which may call Fsignal.
6283 If in_display is set Fsignal will abort. */
6284
6285 #ifdef HAVE_MENUBARS
6286 /* Update the menubar. It is done first since it could change
6287 the menubar's visibility. This way we avoid having flashing
6288 caused by an Expose event generated by the visibility change
6289 being handled. */
6290 update_frame_menubars (f);
6291 #endif /* HAVE_MENUBARS */
6292 /* widgets are similar to menus in that they can call lisp to
6293 determine activation etc. Therefore update them before we get
6294 into redisplay. This is primarily for connected widgets such as
6295 radio buttons. */
6296 update_frame_subwindows (f);
6297 #ifdef HAVE_TOOLBARS
6298 /* Update the toolbars. */
6299 update_frame_toolbars (f);
6300 #endif /* HAVE_TOOLBARS */
6301
6302 /* If we clear the frame we have to force its contents to be redrawn. */
6303 if (f->clear)
6304 f->frame_changed = 1;
6305
6306 /* invalidate the subwindow cache. We use subwindows_changed here to
6307 cause subwindows to get instantiated. This is because
6308 subwindows_state_changed is less strict - dealing with things
6309 like the clicked state of button. We have to do this before
6310 redisplaying the gutters as subwindows get unmapped in the
6311 process.*/
6312 if (!Dynarr_length (f->subwindow_cachels)
6313 || f->subwindows_changed
6314 || f->frame_changed)
6315 {
6316 reset_subwindow_cachels (f);
6317 /* we have to do this so the gutter gets regenerated. */
6318 reset_gutter_display_lines (f);
6319 }
6320 else
6321 mark_subwindow_cachels_as_not_updated (f);
6322 /* We can now update the gutters, safe in the knowledge that our
6323 efforts won't get undone. */
6324 update_frame_gutters (f);
6325
6326 hold_frame_size_changes ();
6327
6328 /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
6329 /* Within this section, we are defenseless and assume that the
6330 following cannot happen:
6331
6332 1) garbage collection
6333 2) Lisp code evaluation
6334 3) frame size changes
6335
6336 We ensure (3) by calling hold_frame_size_changes(), which
6337 will cause any pending frame size changes to get put on hold
6338 till after the end of the critical section. (1) follows
6339 automatically if (2) is met. #### Unfortunately, there are
6340 some places where Lisp code can be called within this section.
6341 We need to remove them.
6342
6343 If Fsignal() is called during this critical section, we
6344 will abort().
6345
6346 If garbage collection is called during this critical section,
6347 we simply return. #### We should abort instead.
6348
6349 #### If a frame-size change does occur we should probably
6350 actually be preempting redisplay. */
6351
6352 /* Erase the frame before outputting its contents. */
6353 if (f->clear)
6354 {
6355 DEVMETH (d, clear_frame, (f));
6356 }
6357
6358 /* Do the selected window first. */
6359 redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
6360
6361 /* Then do the rest. */
6362 redisplay_windows (f->root_window, 1);
6363
6364 /* We now call the output_end routine for tty frames. We delay
6365 doing so in order to avoid cursor flicker. So much for 100%
6366 encapsulation. */
6367 if (FRAME_TTY_P (f))
6368 DEVMETH (d, output_end, (d));
6369
6370 update_frame_title (f);
6371
6372 CLASS_RESET_CHANGED_FLAGS (f);
6373 f->window_face_cache_reset = 0;
6374 f->echo_area_garbaged = 0;
6375 f->clear = 0;
6376
6377 if (!f->size_change_pending)
6378 f->size_changed = 0;
6379
6380 /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
6381
6382 /* Allow frame size changes to occur again.
6383
6384 #### what happens if changes to other frames happen? */
6385 unhold_one_frame_size_changes (f);
6386
6387 map_windows (f, call_redisplay_end_triggers, 0);
6388 return 0;
6389 }
6390
6391 /* Ensure that all frames on the given device are correctly displayed. */
6392
6393 static int
6394 redisplay_device (struct device *d)
6395 {
6396 Lisp_Object frame, frmcons;
6397 int preempted = 0;
6398 int size_change_failed = 0;
6399 struct frame *f;
6400
6401 if (DEVICE_STREAM_P (d)) /* nothing to do */
6402 return 0;
6403
6404 /* It is possible that redisplay has been called before the
6405 device is fully initialized. If so then continue with the
6406 next device. */
6407 if (NILP (DEVICE_SELECTED_FRAME (d)))
6408 return 0;
6409
6410 REDISPLAY_PREEMPTION_CHECK;
6411 if (preempted)
6412 return 1;
6413
6414 /* Always do the selected frame first. */
6415 frame = DEVICE_SELECTED_FRAME (d);
6416
6417 f = XFRAME (frame);
6418
6419 if (f->icon_changed || f->windows_changed)
6420 update_frame_icon (f);
6421
6422 if (FRAME_REPAINT_P (f))
6423 {
6424 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f))
6425 {
6426 preempted = redisplay_frame (f, 0);
6427 }
6428
6429 if (preempted)
6430 return 1;
6431
6432 /* If the frame redisplay did not get preempted, then this flag
6433 should have gotten set to 0. It might be possible for that
6434 not to happen if a size change event were to occur at an odd
6435 time. To make sure we don't miss anything we simply don't
6436 reset the top level flags until the condition ends up being
6437 in the right state. */
6438 if (f->size_changed)
6439 size_change_failed = 1;
6440 }
6441
6442 DEVICE_FRAME_LOOP (frmcons, d)
6443 {
6444 f = XFRAME (XCAR (frmcons));
6445
6446 if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
6447 continue;
6448
6449 if (f->icon_changed || f->windows_changed)
6450 update_frame_icon (f);
6451
6452 if (FRAME_REPAINT_P (f))
6453 {
6454 if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)
6455 || f->size_changed)
6456 {
6457 preempted = redisplay_frame (f, 0);
6458 }
6459
6460 if (preempted)
6461 return 1;
6462
6463 if (f->size_change_pending)
6464 size_change_failed = 1;
6465 }
6466 }
6467
6468 /* If we get here then we redisplayed all of our frames without
6469 getting preempted so mark ourselves as clean. */
6470 CLASS_RESET_CHANGED_FLAGS (d);
6471
6472 if (!size_change_failed)
6473 d->size_changed = 0;
6474
6475 return 0;
6476 }
6477
6478 static Lisp_Object
6479 restore_profiling_redisplay_flag (Lisp_Object val)
6480 {
6481 profiling_redisplay_flag = XINT (val);
6482 return Qnil;
6483 }
6484
6485 /* Ensure that all windows on all frames on all devices are displaying
6486 the current contents of their respective buffers. */
6487
6488 static void
6489 redisplay_without_hooks (void)
6490 {
6491 Lisp_Object devcons, concons;
6492 int size_change_failed = 0;
6493 int count = specpdl_depth ();
6494
6495 if (profiling_active)
6496 {
6497 record_unwind_protect (restore_profiling_redisplay_flag,
6498 make_int (profiling_redisplay_flag));
6499 profiling_redisplay_flag = 1;
6500 }
6501
6502 if (asynch_device_change_pending)
6503 handle_asynch_device_change ();
6504
6505 if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP &&
6506 !size_changed && !disable_preemption && preemption_count < max_preempts)
6507 goto done;
6508
6509 DEVICE_LOOP_NO_BREAK (devcons, concons)
6510 {
6511 struct device *d = XDEVICE (XCAR (devcons));
6512 int preempted;
6513
6514 if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d)
6515 || d->size_changed)
6516 {
6517 preempted = redisplay_device (d);
6518
6519 if (preempted)
6520 {
6521 preemption_count++;
6522 RESET_CHANGED_SET_FLAGS;
6523 goto done;
6524 }
6525
6526 /* See comment in redisplay_device. */
6527 if (d->size_changed)
6528 size_change_failed = 1;
6529 }
6530 }
6531 preemption_count = 0;
6532
6533 /* Mark redisplay as accurate */
6534 GLOBAL_RESET_CHANGED_FLAGS;
6535 RESET_CHANGED_SET_FLAGS;
6536
6537 if (faces_changed)
6538 {
6539 mark_all_faces_as_clean ();
6540 faces_changed = 0;
6541 }
6542
6543 if (!size_change_failed)
6544 size_changed = 0;
6545
6546 reset_buffer_changes ();
6547
6548 done:
6549 unbind_to (count, Qnil);
6550 }
6551
6552 void
6553 redisplay (void)
6554 {
6555 if (last_display_warning_tick != display_warning_tick &&
6556 !inhibit_warning_display)
6557 {
6558 /* If an error occurs during this function, oh well.
6559 If we report another warning, we could get stuck in an
6560 infinite loop reporting warnings. */
6561 call0_trapping_errors (0, Qdisplay_warning_buffer);
6562 last_display_warning_tick = display_warning_tick;
6563 }
6564 /* The run_hook_trapping_errors functions are smart enough not
6565 to do any evalling if the hook function is empty, so there
6566 should not be any significant time loss. All places in the
6567 C code that call redisplay() are prepared to handle GCing,
6568 so we should be OK. */
6569 #ifndef INHIBIT_REDISPLAY_HOOKS
6570 run_hook_trapping_errors ("Error in pre-redisplay-hook",
6571 Qpre_redisplay_hook);
6572 #endif /* INHIBIT_REDISPLAY_HOOKS */
6573
6574 redisplay_without_hooks ();
6575
6576 #ifndef INHIBIT_REDISPLAY_HOOKS
6577 run_hook_trapping_errors ("Error in post-redisplay-hook",
6578 Qpost_redisplay_hook);
6579 #endif /* INHIBIT_REDISPLAY_HOOKS */
6580 }
6581
6582
6583 static char window_line_number_buf[32];
6584
6585 /* Efficiently determine the window line number, and return a pointer
6586 to its printed representation. Do this regardless of whether
6587 line-number-mode is on. The first line in the buffer is counted as
6588 1. If narrowing is in effect, the lines are counted from the
6589 beginning of the visible portion of the buffer. */
6590 static char *
6591 window_line_number (struct window *w, int type)
6592 {
6593 struct device *d = XDEVICE (XFRAME (w->frame)->device);
6594 struct buffer *b = XBUFFER (w->buffer);
6595 /* Be careful in the order of these tests. The first clause will
6596 fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
6597 This can occur when the frame title is computed really early */
6598 Bufpos pos =
6599 ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
6600 (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
6601 EQ(DEVICE_CONSOLE(d), Vselected_console) &&
6602 XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
6603 ? BUF_PT (b)
6604 : marker_position (w->pointm[type]));
6605 EMACS_INT line;
6606
6607 line = buffer_line_number (b, pos, 1);
6608
6609 long_to_string (window_line_number_buf, line + 1);
6610
6611 return window_line_number_buf;
6612 }
6613
6614
6615 /* Given a character representing an object in a modeline
6616 specification, return a string (stored into the global array
6617 `mode_spec_bufbyte_string') with the information that object
6618 represents.
6619
6620 This function is largely unchanged from previous versions of the
6621 redisplay engine.
6622
6623 Warning! This code is also used for frame titles and can be called
6624 very early in the device/frame update process! JV
6625 */
6626
6627 static void
6628 decode_mode_spec (struct window *w, Emchar spec, int type)
6629 {
6630 Lisp_Object obj = Qnil;
6631 CONST char *str = NULL;
6632 struct buffer *b = XBUFFER (w->buffer);
6633
6634 Dynarr_reset (mode_spec_bufbyte_string);
6635
6636 switch (spec)
6637 {
6638 /* print buffer name */
6639 case 'b':
6640 obj = b->name;
6641 break;
6642
6643 /* print visited file name */
6644 case 'f':
6645 obj = b->filename;
6646 break;
6647
6648 /* print the current column */
6649 case 'c':
6650 {
6651 Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
6652 ? BUF_PT (b)
6653 : marker_position (w->pointm[type]);
6654 int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
6655 char buf[32];
6656
6657 long_to_string (buf, col);
6658
6659 Dynarr_add_many (mode_spec_bufbyte_string,
6660 (CONST Bufbyte *) buf, strlen (buf));
6661
6662 goto decode_mode_spec_done;
6663 }
6664 /* print the file coding system */
6665 case 'C':
6666 #ifdef FILE_CODING
6667 {
6668 Lisp_Object codesys = b->buffer_file_coding_system;
6669 /* Be very careful here not to get an error. */
6670 if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
6671 {
6672 codesys = Ffind_coding_system (codesys);
6673 if (CODING_SYSTEMP (codesys))
6674 obj = XCODING_SYSTEM_MNEMONIC (codesys);
6675 }
6676 }
6677 #endif /* FILE_CODING */
6678 break;
6679
6680 /* print the current line number */
6681 case 'l':
6682 str = window_line_number (w, type);
6683 break;
6684
6685 /* print value of mode-name (obsolete) */
6686 case 'm':
6687 obj = b->mode_name;
6688 break;
6689
6690 /* print hyphen and frame number, if != 1 */
6691 case 'N':
6692 #ifdef HAVE_TTY
6693 {
6694 struct frame *f = XFRAME (w->frame);
6695 if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
6696 {
6697 /* Naughty, naughty */
6698 char * writable_str = alloca_array (char, 10);
6699 sprintf (writable_str, "-%d", f->order_count);
6700 str = writable_str;
6701 }
6702 }
6703 #endif /* HAVE_TTY */
6704 break;
6705
6706 /* print Narrow if appropriate */
6707 case 'n':
6708 if (BUF_BEGV (b) > BUF_BEG (b)
6709 || BUF_ZV (b) < BUF_Z (b))
6710 str = " Narrow";
6711 break;
6712
6713 /* print %, * or hyphen, if buffer is read-only, modified or neither */
6714 case '*':
6715 str = (!NILP (b->read_only)
6716 ? "%"
6717 : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6718 ? "*"
6719 : "-"));
6720 break;
6721
6722 /* print * or hyphen -- XEmacs change to allow a buffer to be
6723 read-only but still indicate whether it is modified. */
6724 case '+':
6725 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6726 ? "*"
6727 : (!NILP (b->read_only)
6728 ? "%"
6729 : "-"));
6730 break;
6731
6732 /* #### defined in 19.29 decode_mode_spec, but not in
6733 modeline-format doc string. */
6734 /* This differs from %* in that it ignores read-only-ness. */
6735 case '&':
6736 str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
6737 ? "*"
6738 : "-");
6739 break;
6740
6741 /* print process status */
6742 case 's':
6743 obj = Fget_buffer_process (w->buffer);
6744 if (NILP (obj))
6745 str = GETTEXT ("no process");
6746 else
6747 obj = Fsymbol_name (Fprocess_status (obj));
6748 break;
6749
6750 /* Print name of selected frame. */
6751 case 'S':
6752 obj = XFRAME (w->frame)->name;
6753 break;
6754
6755 /* indicate TEXT or BINARY */
6756 case 't':
6757 /* #### NT does not use this any more. Now what? */
6758 str = "T";
6759 break;
6760
6761 /* print percent of buffer above top of window, or Top, Bot or All */
6762 case 'p':
6763 {
6764 Bufpos pos = marker_position (w->start[type]);
6765
6766 /* This had better be while the desired lines are being done. */
6767 if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
6768 {
6769 if (pos <= BUF_BEGV (b))
6770 str = "All";
6771 else
6772 str = "Bottom";
6773 }
6774 else if (pos <= BUF_BEGV (b))
6775 str = "Top";
6776 else
6777 {
6778 /* This hard limit is ok since the string it will hold has a
6779 fixed maximum length of 3. But just to be safe... */
6780 char buf[10];
6781 Charcount chars = pos - BUF_BEGV (b);
6782 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6783
6784 /* Avoid overflow on big buffers */
6785 int percent = total > LONG_MAX/200 ?
6786 (chars + total/200) / (total / 100) :
6787 (chars * 100 + total/2) / total;
6788
6789 /* We can't normally display a 3-digit number, so get us a
6790 2-digit number that is close. */
6791 if (percent == 100)
6792 percent = 99;
6793
6794 sprintf (buf, "%d%%", percent);
6795 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6796 strlen (buf));
6797
6798 goto decode_mode_spec_done;
6799 }
6800 break;
6801 }
6802
6803 /* print percent of buffer above bottom of window, perhaps plus
6804 Top, or print Bottom or All */
6805 case 'P':
6806 {
6807 Bufpos toppos = marker_position (w->start[type]);
6808 Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
6809
6810 /* botpos is only accurate as of the last redisplay, so we can
6811 only treat it as a hint. In particular, after erase-buffer,
6812 botpos may be negative. */
6813 if (botpos < toppos)
6814 botpos = toppos;
6815
6816 if (botpos >= BUF_ZV (b))
6817 {
6818 if (toppos <= BUF_BEGV (b))
6819 str = "All";
6820 else
6821 str = "Bottom";
6822 }
6823 else
6824 {
6825 /* This hard limit is ok since the string it will hold has a
6826 fixed maximum length of around 6. But just to be safe... */
6827 char buf[10];
6828 Charcount chars = botpos - BUF_BEGV (b);
6829 Charcount total = BUF_ZV (b) - BUF_BEGV (b);
6830
6831 /* Avoid overflow on big buffers */
6832 int percent = total > LONG_MAX/200 ?
6833 (chars + total/200) / (total / 100) :
6834 (chars * 100 + total/2) / max (total, 1);
6835
6836 /* We can't normally display a 3-digit number, so get us a
6837 2-digit number that is close. */
6838 if (percent == 100)
6839 percent = 99;
6840
6841 if (toppos <= BUF_BEGV (b))
6842 sprintf (buf, "Top%d%%", percent);
6843 else
6844 sprintf (buf, "%d%%", percent);
6845
6846 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
6847 strlen (buf));
6848
6849 goto decode_mode_spec_done;
6850 }
6851 break;
6852 }
6853
6854 /* print % */
6855 case '%':
6856 str = "%";
6857 break;
6858
6859 /* print one [ for each recursive editing level. */
6860 case '[':
6861 {
6862 int i;
6863
6864 if (command_loop_level > 5)
6865 {
6866 str = "[[[... ";
6867 break;
6868 }
6869
6870 for (i = 0; i < command_loop_level; i++)
6871 Dynarr_add (mode_spec_bufbyte_string, '[');
6872
6873 goto decode_mode_spec_done;
6874 }
6875
6876 /* print one ] for each recursive editing level. */
6877 case ']':
6878 {
6879 int i;
6880
6881 if (command_loop_level > 5)
6882 {
6883 str = "...]]]";
6884 break;
6885 }
6886
6887 for (i = 0; i < command_loop_level; i++)
6888 Dynarr_add (mode_spec_bufbyte_string, ']');
6889
6890 goto decode_mode_spec_done;
6891 }
6892
6893 /* print infinitely many dashes -- handle at top level now */
6894 case '-':
6895 break;
6896
6897 }
6898
6899 if (STRINGP (obj))
6900 Dynarr_add_many (mode_spec_bufbyte_string,
6901 XSTRING_DATA (obj),
6902 XSTRING_LENGTH (obj));
6903 else if (str)
6904 Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6905
6906 decode_mode_spec_done:
6907 Dynarr_add (mode_spec_bufbyte_string, '\0');
6908 }
6909
6910 /* Given a display line, free all of its data structures. */
6911
6912 static void
6913 free_display_line (struct display_line *dl)
6914 {
6915 int block;
6916
6917 if (dl->display_blocks)
6918 {
6919 for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6920 {
6921 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6922
6923 Dynarr_free (db->runes);
6924 }
6925
6926 Dynarr_free (dl->display_blocks);
6927 dl->display_blocks = NULL;
6928 }
6929
6930 if (dl->left_glyphs)
6931 {
6932 Dynarr_free (dl->left_glyphs);
6933 dl->left_glyphs = NULL;
6934 }
6935
6936 if (dl->right_glyphs)
6937 {
6938 Dynarr_free (dl->right_glyphs);
6939 dl->right_glyphs = NULL;
6940 }
6941 }
6942
6943
6944 /* Given an array of display lines, free them and all data structures
6945 contained within them. */
6946
6947 void
6948 free_display_lines (display_line_dynarr *dla)
6949 {
6950 int line;
6951
6952 for (line = 0; line < Dynarr_largest (dla); line++)
6953 {
6954 free_display_line (Dynarr_atp (dla, line));
6955 }
6956
6957 Dynarr_free (dla);
6958 }
6959
6960 /* Call internal free routine for each set of display lines. */
6961
6962 void
6963 free_display_structs (struct window_mirror *mir)
6964 {
6965 if (mir->current_display_lines)
6966 {
6967 free_display_lines (mir->current_display_lines);
6968 mir->current_display_lines = 0;
6969 }
6970
6971 if (mir->desired_display_lines)
6972 {
6973 free_display_lines (mir->desired_display_lines);
6974 mir->desired_display_lines = 0;
6975 }
6976 }
6977
6978
6979 static void
6980 mark_glyph_block_dynarr (glyph_block_dynarr *gba)
6981 {
6982 if (gba)
6983 {
6984 glyph_block *gb = Dynarr_atp (gba, 0);
6985 glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
6986
6987 for (; gb < gb_last; gb++)
6988 {
6989 if (!NILP (gb->glyph))
6990 mark_object (gb->glyph);
6991 if (!NILP (gb->extent))
6992 mark_object (gb->extent);
6993 }
6994 }
6995 }
6996
6997 static void
6998 mark_redisplay_structs (display_line_dynarr *dla)
6999 {
7000 display_line *dl = Dynarr_atp (dla, 0);
7001 display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
7002
7003 for (; dl < dl_last; dl++)
7004 {
7005 display_block_dynarr *dba = dl->display_blocks;
7006 display_block *db = Dynarr_atp (dba, 0);
7007 display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
7008
7009 for (; db < db_last; db++)
7010 {
7011 rune_dynarr *ra = db->runes;
7012 rune *r = Dynarr_atp (ra, 0);
7013 rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
7014
7015 for (; r < r_last; r++)
7016 {
7017 if (r->type == RUNE_DGLYPH)
7018 {
7019 if (!NILP (r->object.dglyph.glyph))
7020 mark_object (r->object.dglyph.glyph);
7021 if (!NILP (r->object.dglyph.extent))
7022 mark_object (r->object.dglyph.extent);
7023 }
7024 }
7025 }
7026
7027 mark_glyph_block_dynarr (dl->left_glyphs);
7028 mark_glyph_block_dynarr (dl->right_glyphs);
7029 }
7030 }
7031
7032 static void
7033 mark_window_mirror (struct window_mirror *mir)
7034 {
7035 mark_redisplay_structs (mir->current_display_lines);
7036 mark_redisplay_structs (mir->desired_display_lines);
7037
7038 if (mir->next)
7039 mark_window_mirror (mir->next);
7040
7041 if (mir->hchild)
7042 mark_window_mirror (mir->hchild);
7043 else if (mir->vchild)
7044 mark_window_mirror (mir->vchild);
7045 }
7046
7047 void
7048 mark_redisplay (void)
7049 {
7050 Lisp_Object frmcons, devcons, concons;
7051
7052 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
7053 {
7054 struct frame *f = XFRAME (XCAR (frmcons));
7055 update_frame_window_mirror (f);
7056 mark_window_mirror (f->root_mirror);
7057 }
7058 }
7059
7060 /*****************************************************************************
7061 Line Start Cache Description and Rationale
7062
7063 The traditional scrolling code in Emacs breaks in a variable height world.
7064 It depends on the key assumption that the number of lines that can be
7065 displayed at any given time is fixed. This led to a complete separation
7066 of the scrolling code from the redisplay code. In order to fully support
7067 variable height lines, the scrolling code must actually be tightly
7068 integrated with redisplay. Only redisplay can determine how many lines
7069 will be displayed on a screen for any given starting point.
7070
7071 What is ideally wanted is a complete list of the starting buffer position
7072 for every possible display line of a buffer along with the height of that
7073 display line. Maintaining such a full list would be very expensive. We
7074 settle for having it include information for all areas which we happen to
7075 generate anyhow (i.e. the region currently being displayed) and for those
7076 areas we need to work with.
7077
7078 In order to ensure that the cache accurately represents what redisplay
7079 would actually show, it is necessary to invalidate it in many situations.
7080 If the buffer changes, the starting positions may no longer be correct.
7081 If a face or an extent has changed then the line heights may have altered.
7082 These events happen frequently enough that the cache can end up being
7083 constantly disabled. With this potentially constant invalidation when is
7084 the cache ever useful?
7085
7086 Even if the cache is invalidated before every single usage, it is
7087 necessary. Scrolling often requires knowledge about display lines which
7088 are actually above or below the visible region. The cache provides a
7089 convenient light-weight method of storing this information for multiple
7090 display regions. This knowledge is necessary for the scrolling code to
7091 always obey the First Golden Rule of Redisplay.
7092
7093 If the cache already contains all of the information that the scrolling
7094 routines happen to need so that it doesn't have to go generate it, then we
7095 are able to obey the Third Golden Rule of Redisplay. The first thing we
7096 do to help out the cache is to always add the displayed region. This
7097 region had to be generated anyway, so the cache ends up getting the
7098 information basically for free. In those cases where a user is simply
7099 scrolling around viewing a buffer there is a high probability that this is
7100 sufficient to always provide the needed information. The second thing we
7101 can do is be smart about invalidating the cache.
7102
7103 TODO -- Be smart about invalidating the cache. Potential places:
7104
7105 + Insertions at end-of-line which don't cause line-wraps do not alter the
7106 starting positions of any display lines. These types of buffer
7107 modifications should not invalidate the cache. This is actually a large
7108 optimization for redisplay speed as well.
7109
7110 + Buffer modifications frequently only affect the display of lines at and
7111 below where they occur. In these situations we should only invalidate
7112 the part of the cache starting at where the modification occurs.
7113
7114 In case you're wondering, the Second Golden Rule of Redisplay is not
7115 applicable.
7116 ****************************************************************************/
7117
7118 /* This will get used quite a bit so we don't want to be constantly
7119 allocating and freeing it. */
7120 static line_start_cache_dynarr *internal_cache;
7121
7122 /* Makes internal_cache represent the TYPE display structs and only
7123 the TYPE display structs. */
7124
7125 static void
7126 update_internal_cache_list (struct window *w, int type)
7127 {
7128 int line;
7129 display_line_dynarr *dla = window_display_lines (w, type);
7130
7131 Dynarr_reset (internal_cache);
7132 for (line = 0; line < Dynarr_length (dla); line++)
7133 {
7134 struct display_line *dl = Dynarr_atp (dla, line);
7135
7136 if (dl->modeline)
7137 continue;
7138 else
7139 {
7140 struct line_start_cache lsc;
7141
7142 lsc.start = dl->bufpos;
7143 lsc.end = dl->end_bufpos;
7144 lsc.height = dl->ascent + dl->descent;
7145
7146 Dynarr_add (internal_cache, lsc);
7147 }
7148 }
7149 }
7150
7151 /* Reset the line cache if necessary. This should be run at the
7152 beginning of any function which access the cache. */
7153
7154 static void
7155 validate_line_start_cache (struct window *w)
7156 {
7157 struct buffer *b = XBUFFER (w->buffer);
7158 struct frame *f = XFRAME (w->frame);
7159
7160 if (!w->line_cache_validation_override)
7161 {
7162 /* f->extents_changed used to be in here because extent face and
7163 size changes can cause text shifting. However, the extent
7164 covering the region is constantly having its face set and
7165 priority altered by the mouse code. This means that the line
7166 start cache is constantly being invalidated. This is bad
7167 since the mouse code also triggers heavy usage of the cache.
7168 Since it is an unlikely that f->extents being changed
7169 indicates that the cache really needs to be updated and if it
7170 does redisplay will catch it pretty quickly we no longer
7171 invalidate the cache if it is set. This greatly speeds up
7172 dragging out regions with the mouse. */
7173 if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
7174 || f->faces_changed
7175 || f->clip_changed)
7176 {
7177 Dynarr_reset (w->line_start_cache);
7178 }
7179 }
7180 }
7181
7182 /* Return the very first buffer position contained in the given
7183 window's cache, or -1 if the cache is empty. Assumes that the
7184 cache is valid. */
7185
7186 static Bufpos
7187 line_start_cache_start (struct window *w)
7188 {
7189 line_start_cache_dynarr *cache = w->line_start_cache;
7190
7191 if (!Dynarr_length (cache))
7192 return -1;
7193 else
7194 return Dynarr_atp (cache, 0)->start;
7195 }
7196
7197 /* Return the very last buffer position contained in the given
7198 window's cache, or -1 if the cache is empty. Assumes that the
7199 cache is valid. */
7200
7201 static Bufpos
7202 line_start_cache_end (struct window *w)
7203 {
7204 line_start_cache_dynarr *cache = w->line_start_cache;
7205
7206 if (!Dynarr_length (cache))
7207 return -1;
7208 else
7209 return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7210 }
7211
7212 /* Return the index of the line POINT is contained within in window
7213 W's line start cache. It will enlarge the cache or move the cache
7214 window in order to have POINT be present in the cache. MIN_PAST is
7215 a guarantee of the number of entries in the cache present on either
7216 side of POINT (unless a buffer boundary is hit). If MIN_PAST is -1
7217 then it will be treated as 0, but the cache window will not be
7218 allowed to shift. Returns -1 if POINT cannot be found in the cache
7219 for any reason. */
7220
7221 int
7222 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
7223 {
7224 struct buffer *b = XBUFFER (w->buffer);
7225 line_start_cache_dynarr *cache = w->line_start_cache;
7226 unsigned int top, bottom, pos;
7227
7228 validate_line_start_cache (w);
7229 w->line_cache_validation_override++;
7230
7231 /* Let functions pass in negative values, but we still treat -1
7232 specially. */
7233 /* #### bogosity alert */
7234 if (min_past < 0 && min_past != -1)
7235 min_past = -min_past;
7236
7237 if (!Dynarr_length (cache) || line_start_cache_start (w) > point
7238 || line_start_cache_end (w) < point)
7239 {
7240 int loop;
7241 int win_char_height = window_char_height (w, 1);
7242
7243 /* Occasionally we get here with a 0 height
7244 window. find_next_newline_no_quit will abort if we pass it a
7245 count of 0 so handle that case. */
7246 if (!win_char_height)
7247 win_char_height = 1;
7248
7249 if (!Dynarr_length (cache))
7250 {
7251 Bufpos from = find_next_newline_no_quit (b, point, -1);
7252 Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
7253
7254 update_line_start_cache (w, from, to, point, 0);
7255
7256 if (!Dynarr_length (cache))
7257 {
7258 w->line_cache_validation_override--;
7259 return -1;
7260 }
7261 }
7262
7263 assert (Dynarr_length (cache));
7264
7265 loop = 0;
7266 while (line_start_cache_start (w) > point
7267 && (loop < cache_adjustment || min_past == -1))
7268 {
7269 Bufpos from, to;
7270
7271 from = line_start_cache_start (w);
7272 if (from <= BUF_BEGV (b))
7273 break;
7274
7275 from = find_next_newline_no_quit (b, from, -win_char_height);
7276 to = line_start_cache_end (w);
7277
7278 update_line_start_cache (w, from, to, point, 0);
7279 loop++;
7280 }
7281
7282 if (line_start_cache_start (w) > point)
7283 {
7284 Bufpos from, to;
7285
7286 from = find_next_newline_no_quit (b, point, -1);
7287 if (from >= BUF_ZV (b))
7288 {
7289 to = find_next_newline_no_quit (b, from, -win_char_height);
7290 from = to;
7291 to = BUF_ZV (b);
7292 }
7293 else
7294 to = find_next_newline_no_quit (b, from, win_char_height);
7295
7296 update_line_start_cache (w, from, to, point, 0);
7297 }
7298
7299 loop = 0;
7300 while (line_start_cache_end (w) < point
7301 && (loop < cache_adjustment || min_past == -1))
7302 {
7303 Bufpos from, to;
7304
7305 to = line_start_cache_end (w);
7306 if (to >= BUF_ZV (b))
7307 break;
7308
7309 from = line_start_cache_end (w);
7310 to = find_next_newline_no_quit (b, from, win_char_height);
7311
7312 update_line_start_cache (w, from, to, point, 0);
7313 loop++;
7314 }
7315
7316 if (line_start_cache_end (w) < point)
7317 {
7318 Bufpos from, to;
7319
7320 from = find_next_newline_no_quit (b, point, -1);
7321 if (from >= BUF_ZV (b))
7322 {
7323 to = find_next_newline_no_quit (b, from, -win_char_height);
7324 from = to;
7325 to = BUF_ZV (b);
7326 }
7327 else
7328 to = find_next_newline_no_quit (b, from, win_char_height);
7329
7330 update_line_start_cache (w, from, to, point, 0);
7331 }
7332 }
7333
7334 assert (Dynarr_length (cache));
7335
7336 if (min_past == -1)
7337 min_past = 0;
7338
7339 /* This could happen if the buffer is narrowed. */
7340 if (line_start_cache_start (w) > point
7341 || line_start_cache_end (w) < point)
7342 {
7343 w->line_cache_validation_override--;
7344 return -1;
7345 }
7346
7347 find_point_loop:
7348
7349 top = Dynarr_length (cache) - 1;
7350 bottom = 0;
7351
7352 while (1)
7353 {
7354 unsigned int new_pos;
7355 Bufpos start, end;
7356
7357 pos = (bottom + top + 1) >> 1;
7358 start = Dynarr_atp (cache, pos)->start;
7359 end = Dynarr_atp (cache, pos)->end;
7360
7361 if (point >= start && point <= end)
7362 {
7363 if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
7364 {
7365 Bufpos from =
7366 find_next_newline_no_quit (b, line_start_cache_start (w),
7367 -min_past - 1);
7368 Bufpos to = line_start_cache_end (w);
7369
7370 update_line_start_cache (w, from, to, point, 0);
7371 goto find_point_loop;
7372 }
7373 else if ((Dynarr_length (cache) - pos - 1) < min_past
7374 && line_start_cache_end (w) < BUF_ZV (b))
7375 {
7376 Bufpos from = line_start_cache_end (w);
7377 Bufpos to = find_next_newline_no_quit (b, from,
7378 (min_past
7379 ? min_past
7380 : 1));
7381
7382 update_line_start_cache (w, from, to, point, 0);
7383 goto find_point_loop;
7384 }
7385 else
7386 {
7387 w->line_cache_validation_override--;
7388 return pos;
7389 }
7390 }
7391 else if (point > end)
7392 bottom = pos + 1;
7393 else if (point < start)
7394 top = pos - 1;
7395 else
7396 abort ();
7397
7398 new_pos = (bottom + top + 1) >> 1;
7399 if (pos == new_pos)
7400 {
7401 w->line_cache_validation_override--;
7402 return -1;
7403 }
7404 }
7405 }
7406
7407 /* Return a boolean indicating if POINT would be visible in window W
7408 if display of the window was to begin at STARTP. */
7409
7410 int
7411 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
7412 {
7413 struct buffer *b = XBUFFER (w->buffer);
7414 int pixpos = 0;
7415 int bottom = WINDOW_TEXT_HEIGHT (w);
7416 int start_elt;
7417
7418 /* If point is before the intended start it obviously can't be visible. */
7419 if (point < startp)
7420 return 0;
7421
7422 /* If point or start are not in the accessible buffer range, then
7423 fail. */
7424 if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
7425 || point < BUF_BEGV (b) || point > BUF_ZV (b))
7426 return 0;
7427
7428 validate_line_start_cache (w);
7429 w->line_cache_validation_override++;
7430
7431 start_elt = point_in_line_start_cache (w, startp, 0);
7432 if (start_elt == -1)
7433 {
7434 w->line_cache_validation_override--;
7435 return 0;
7436 }
7437
7438 assert (line_start_cache_start (w) <= startp
7439 && line_start_cache_end (w) >= startp);
7440
7441 while (1)
7442 {
7443 int height;
7444
7445 /* Expand the cache if necessary. */
7446 if (start_elt == Dynarr_length (w->line_start_cache))
7447 {
7448 Bufpos old_startp =
7449 Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
7450
7451 start_elt = point_in_line_start_cache (w, old_startp,
7452 window_char_height (w, 0));
7453
7454 /* We've already actually processed old_startp, so increment
7455 immediately. */
7456 start_elt++;
7457
7458 /* If this happens we didn't add any extra elements. Bummer. */
7459 if (start_elt == Dynarr_length (w->line_start_cache))
7460 {
7461 w->line_cache_validation_override--;
7462 return 0;
7463 }
7464 }
7465
7466 height = Dynarr_atp (w->line_start_cache, start_elt)->height;
7467
7468 if (pixpos + height > bottom)
7469 {
7470 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7471 {
7472 w->line_cache_validation_override--;
7473 return 0;
7474 }
7475 }
7476
7477 pixpos += height;
7478 if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
7479 {
7480 w->line_cache_validation_override--;
7481 return 1;
7482 }
7483
7484 start_elt++;
7485 }
7486 }
7487
7488 /* For the given window W, if display starts at STARTP, what will be
7489 the buffer position at the beginning or end of the last line
7490 displayed. The end of the last line is also know as the window end
7491 position.
7492
7493 #### With a little work this could probably be reworked as just a
7494 call to start_with_line_at_pixpos. */
7495
7496 static Bufpos
7497 start_end_of_last_line (struct window *w, Bufpos startp, int end)
7498 {
7499 struct buffer *b = XBUFFER (w->buffer);
7500 line_start_cache_dynarr *cache = w->line_start_cache;
7501 int pixpos = 0;
7502 int bottom = WINDOW_TEXT_HEIGHT (w);
7503 Bufpos cur_start;
7504 int start_elt;
7505
7506 validate_line_start_cache (w);
7507 w->line_cache_validation_override++;
7508
7509 if (startp < BUF_BEGV (b))
7510 startp = BUF_BEGV (b);
7511 else if (startp > BUF_ZV (b))
7512 startp = BUF_ZV (b);
7513 cur_start = startp;
7514
7515 start_elt = point_in_line_start_cache (w, cur_start, 0);
7516 if (start_elt == -1)
7517 abort (); /* this had better never happen */
7518
7519 while (1)
7520 {
7521 int height = Dynarr_atp (cache, start_elt)->height;
7522
7523 cur_start = Dynarr_atp (cache, start_elt)->start;
7524
7525 if (pixpos + height > bottom)
7526 {
7527 /* Adjust for any possible clip. */
7528 if (bottom - pixpos < VERTICAL_CLIP (w, 0))
7529 start_elt--;
7530
7531 if (start_elt < 0)
7532 {
7533 w->line_cache_validation_override--;
7534 if (end)
7535 return BUF_ZV (b);
7536 else
7537 return BUF_BEGV (b);
7538 }
7539 else
7540 {
7541 w->line_cache_validation_override--;
7542 if (end)
7543 return Dynarr_atp (cache, start_elt)->end;
7544 else
7545 return Dynarr_atp (cache, start_elt)->start;
7546 }
7547 }
7548
7549 pixpos += height;
7550 start_elt++;
7551 if (start_elt == Dynarr_length (cache))
7552 {
7553 Bufpos from = line_start_cache_end (w);
7554 int win_char_height = window_char_height (w, 0);
7555 Bufpos to = find_next_newline_no_quit (b, from,
7556 (win_char_height
7557 ? win_char_height
7558 : 1));
7559
7560 /* We've hit the end of the bottom so that's what it is. */
7561 if (from >= BUF_ZV (b))
7562 {
7563 w->line_cache_validation_override--;
7564 return BUF_ZV (b);
7565 }
7566
7567 update_line_start_cache (w, from, to, BUF_PT (b), 0);
7568
7569 /* Updating the cache invalidates any current indexes. */
7570 start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
7571 }
7572 }
7573 }
7574
7575 /* For the given window W, if display starts at STARTP, what will be
7576 the buffer position at the beginning of the last line displayed. */
7577
7578 Bufpos
7579 start_of_last_line (struct window *w, Bufpos startp)
7580 {
7581 return start_end_of_last_line (w, startp, 0);
7582 }
7583
7584 /* For the given window W, if display starts at STARTP, what will be
7585 the buffer position at the end of the last line displayed. This is
7586 also know as the window end position. */
7587
7588 Bufpos
7589 end_of_last_line (struct window *w, Bufpos startp)
7590 {
7591 return start_end_of_last_line (w, startp, 1);
7592 }
7593
7594 /* For window W, what does the starting position have to be so that
7595 the line containing POINT will cover pixel position PIXPOS. */
7596
7597 Bufpos
7598 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
7599 {
7600 struct buffer *b = XBUFFER (w->buffer);
7601 int cur_elt;
7602 Bufpos cur_pos, prev_pos = point;
7603 int point_line_height;
7604 int pixheight = pixpos - WINDOW_TEXT_TOP (w);
7605
7606 validate_line_start_cache (w);
7607 w->line_cache_validation_override++;
7608
7609 cur_elt = point_in_line_start_cache (w, point, 0);
7610 /* #### See comment in update_line_start_cache about big minibuffers. */
7611 if (cur_elt < 0)
7612 {
7613 w->line_cache_validation_override--;
7614 return point;
7615 }
7616
7617 point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
7618
7619 while (1)
7620 {
7621 cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7622
7623 pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7624
7625 /* Do not take into account the value of vertical_clip here.
7626 That is the responsibility of the calling functions. */
7627 if (pixheight < 0)
7628 {
7629 w->line_cache_validation_override--;
7630 if (-pixheight > point_line_height)
7631 /* We can't make the target line cover pixpos, so put it
7632 above pixpos. That way it will at least be visible. */
7633 return prev_pos;
7634 else
7635 return cur_pos;
7636 }
7637
7638 cur_elt--;
7639 while (cur_elt < 0)
7640 {
7641 Bufpos from, to;
7642 int win_char_height;
7643
7644 if (cur_pos <= BUF_BEGV (b))
7645 {
7646 w->line_cache_validation_override--;
7647 return BUF_BEGV (b);
7648 }
7649
7650 win_char_height = window_char_height (w, 0);
7651 if (!win_char_height)
7652 win_char_height = 1;
7653
7654 from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
7655 to = line_start_cache_end (w);
7656 update_line_start_cache (w, from, to, point, 0);
7657
7658 cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
7659 assert (cur_elt >= -1);
7660 /* This used to be cur_elt>=0 under the assumption that if
7661 point is in the top line and not at BUF_BEGV, then
7662 setting the window_start to a newline before the start of
7663 the first line will always cause scrolling.
7664
7665 However in my (jv) opinion this is wrong. That new line
7666 can be hidden in various ways: invisible extents, an
7667 explicit window-start not at a newline character etc.
7668 The existence of those are indeed known to create crashes
7669 on that assert. So we have no option but to continue the
7670 search if we found point at the top of the line_start_cache
7671 again. */
7672 cur_pos = Dynarr_atp (w->line_start_cache,0)->start;
7673 }
7674 prev_pos = cur_pos;
7675 }
7676 }
7677
7678 /* For window W, what does the starting position have to be so that
7679 the line containing point is on display line LINE. If LINE is
7680 positive it is considered to be the number of lines from the top of
7681 the window (0 is the top line). If it is negative the number is
7682 considered to be the number of lines from the bottom (-1 is the
7683 bottom line). */
7684
7685 Bufpos
7686 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
7687 {
7688 validate_line_start_cache (w);
7689 w->line_cache_validation_override++;
7690
7691 if (line >= 0)
7692 {
7693 int cur_elt = point_in_line_start_cache (w, point, line);
7694
7695 if (cur_elt - line < 0)
7696 cur_elt = 0; /* Hit the top */
7697 else
7698 cur_elt -= line;
7699
7700 w->line_cache_validation_override--;
7701 return Dynarr_atp (w->line_start_cache, cur_elt)->start;
7702 }
7703 else
7704 {
7705 /* The calculated value of pixpos is correct for the bottom line
7706 or what we want when line is -1. Therefore we subtract one
7707 because we have already handled one line. */
7708 int new_line = -line - 1;
7709 int cur_elt = point_in_line_start_cache (w, point, new_line);
7710 int pixpos = WINDOW_TEXT_BOTTOM (w);
7711 Bufpos retval, search_point;
7712
7713 /* If scroll_on_clipped_lines is false, the last "visible" line of
7714 the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
7715 If s_o_c_l is true, then we don't want to count a clipped
7716 line, so back up from the bottom by the height of the line
7717 containing point. */
7718 if (scroll_on_clipped_lines)
7719 pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
7720 else
7721 pixpos -= 1;
7722
7723 if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
7724 {
7725 /* Hit the bottom of the buffer. */
7726 int adjustment =
7727 (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
7728 Lisp_Object window;
7729 int defheight;
7730
7731 XSETWINDOW (window, w);
7732 default_face_height_and_width (window, &defheight, 0);
7733
7734 cur_elt = Dynarr_length (w->line_start_cache) - 1;
7735
7736 pixpos -= (adjustment * defheight);
7737 if (pixpos < WINDOW_TEXT_TOP (w))
7738 pixpos = WINDOW_TEXT_TOP (w);
7739 }
7740 else
7741 cur_elt = cur_elt + new_line;
7742
7743 search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
7744
7745 retval = start_with_line_at_pixpos (w, search_point, pixpos);
7746 w->line_cache_validation_override--;
7747 return retval;
7748 }
7749 }
7750
7751 /* This is used to speed up vertical scrolling by caching the known
7752 buffer starting positions for display lines. This allows the
7753 scrolling routines to avoid costly calls to regenerate_window. If
7754 NO_REGEN is true then it will only add the values in the DESIRED
7755 display structs which are in the given range.
7756
7757 Note also that the FROM/TO values are minimums. It is possible
7758 that this function will actually add information outside of the
7759 lines containing those positions. This can't hurt but it could
7760 possibly help.
7761
7762 #### We currently force the cache to have only 1 contiguous region.
7763 It might help to make the cache a dynarr of caches so that we can
7764 cover more areas. This might, however, turn out to be a lot of
7765 overhead for too little gain. */
7766
7767 static void
7768 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
7769 Bufpos point, int no_regen)
7770 {
7771 struct buffer *b = XBUFFER (w->buffer);
7772 line_start_cache_dynarr *cache = w->line_start_cache;
7773 Bufpos low_bound, high_bound;
7774
7775 validate_line_start_cache (w);
7776 w->line_cache_validation_override++;
7777 updating_line_start_cache = 1;
7778
7779 if (from < BUF_BEGV (b))
7780 from = BUF_BEGV (b);
7781 if (to > BUF_ZV (b))
7782 to = BUF_ZV (b);
7783
7784 if (from > to)
7785 {
7786 updating_line_start_cache = 0;
7787 w->line_cache_validation_override--;
7788 return;
7789 }
7790
7791 if (Dynarr_length (cache))
7792 {
7793 low_bound = line_start_cache_start (w);
7794 high_bound = line_start_cache_end (w);
7795
7796 /* Check to see if the desired range is already in the cache. */
7797 if (from >= low_bound && to <= high_bound)
7798 {
7799 updating_line_start_cache = 0;
7800 w->line_cache_validation_override--;
7801 return;
7802 }
7803
7804 /* Check to make sure that the desired range is adjacent to the
7805 current cache. If not, invalidate the cache. */
7806 if (to < low_bound || from > high_bound)
7807 {
7808 Dynarr_reset (cache);
7809 low_bound = high_bound = -1;
7810 }
7811 }
7812 else
7813 {
7814 low_bound = high_bound = -1;
7815 }
7816
7817 w->line_cache_last_updated = make_int (BUF_MODIFF (b));
7818
7819 /* This could be integrated into the next two sections, but it is easier
7820 to follow what's going on by having it separate. */
7821 if (no_regen)
7822 {
7823 Bufpos start, end;
7824
7825 update_internal_cache_list (w, DESIRED_DISP);
7826 if (!Dynarr_length (internal_cache))
7827 {
7828 updating_line_start_cache = 0;
7829 w->line_cache_validation_override--;
7830 return;
7831 }
7832
7833 start = Dynarr_atp (internal_cache, 0)->start;
7834 end =
7835 Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
7836
7837 /* We aren't allowed to generate additional information to fill in
7838 gaps, so if the DESIRED structs don't overlap the cache, reset the
7839 cache. */
7840 if (Dynarr_length (cache))
7841 {
7842 if (end < low_bound || start > high_bound)
7843 Dynarr_reset (cache);
7844
7845 /* #### What should really happen if what we are doing is
7846 extending a line (the last line)? */
7847 if (Dynarr_length (cache) == 1
7848 && Dynarr_length (internal_cache) == 1)
7849 Dynarr_reset (cache);
7850 }
7851
7852 if (!Dynarr_length (cache))
7853 {
7854 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7855 Dynarr_length (internal_cache));
7856 updating_line_start_cache = 0;
7857 w->line_cache_validation_override--;
7858 return;
7859 }
7860
7861 /* An extra check just in case the calling function didn't pass in
7862 the bounds of the DESIRED structs in the first place. */
7863 if (start >= low_bound && end <= high_bound)
7864 {
7865 updating_line_start_cache = 0;
7866 w->line_cache_validation_override--;
7867 return;
7868 }
7869
7870 /* At this point we know that the internal cache partially overlaps
7871 the main cache. */
7872 if (start < low_bound)
7873 {
7874 int ic_elt = Dynarr_length (internal_cache) - 1;
7875 while (ic_elt >= 0)
7876 {
7877 if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7878 break;
7879 else
7880 ic_elt--;
7881 }
7882
7883 if (!(ic_elt >= 0))
7884 {
7885 Dynarr_reset (cache);
7886 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7887 Dynarr_length (internal_cache));
7888 updating_line_start_cache = 0;
7889 w->line_cache_validation_override--;
7890 return;
7891 }
7892
7893 Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7894 ic_elt + 1);
7895 }
7896
7897 if (end > high_bound)
7898 {
7899 int ic_elt = 0;
7900
7901 while (ic_elt < Dynarr_length (internal_cache))
7902 {
7903 if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7904 break;
7905 else
7906 ic_elt++;
7907 }
7908
7909 if (!(ic_elt < Dynarr_length (internal_cache)))
7910 {
7911 Dynarr_reset (cache);
7912 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7913 Dynarr_length (internal_cache));
7914 updating_line_start_cache = 0;
7915 w->line_cache_validation_override--;
7916 return;
7917 }
7918
7919 Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7920 Dynarr_length (internal_cache) - ic_elt);
7921 }
7922
7923 updating_line_start_cache = 0;
7924 w->line_cache_validation_override--;
7925 return;
7926 }
7927
7928 if (!Dynarr_length (cache) || from < low_bound)
7929 {
7930 Bufpos startp = find_next_newline_no_quit (b, from, -1);
7931 int marker = 0;
7932 int old_lb = low_bound;
7933
7934 while (startp < old_lb || low_bound == -1)
7935 {
7936 int ic_elt;
7937 Bufpos new_startp;
7938
7939 regenerate_window (w, startp, point, CMOTION_DISP);
7940 update_internal_cache_list (w, CMOTION_DISP);
7941
7942 /* If this assert is triggered then regenerate_window failed
7943 to layout a single line. That is not supposed to be
7944 possible because we impose a minimum height on the buffer
7945 and override vertical clip when we are in here. */
7946 /* #### Ah, but it is because the window may temporarily
7947 exist but not have any lines at all if the minibuffer is
7948 real big. Look into that situation better. */
7949 if (!Dynarr_length (internal_cache))
7950 {
7951 if (old_lb == -1 && low_bound == -1)
7952 {
7953 updating_line_start_cache = 0;
7954 w->line_cache_validation_override--;
7955 return;
7956 }
7957
7958 assert (Dynarr_length (internal_cache));
7959 }
7960 assert (startp == Dynarr_atp (internal_cache, 0)->start);
7961
7962 ic_elt = Dynarr_length (internal_cache) - 1;
7963 if (low_bound != -1)
7964 {
7965 while (ic_elt >= 0)
7966 {
7967 if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
7968 break;
7969 else
7970 ic_elt--;
7971 }
7972 }
7973 assert (ic_elt >= 0);
7974
7975 new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
7976
7977 /*
7978 * Handle invisible text properly:
7979 * If the last line we're inserting has the same end as the
7980 * line before which it will be added, merge the two lines.
7981 */
7982 if (Dynarr_length (cache) &&
7983 Dynarr_atp (internal_cache, ic_elt)->end ==
7984 Dynarr_atp (cache, marker)->end)
7985 {
7986 Dynarr_atp (cache, marker)->start
7987 = Dynarr_atp (internal_cache, ic_elt)->start;
7988 Dynarr_atp (cache, marker)->height
7989 = Dynarr_atp (internal_cache, ic_elt)->height;
7990 ic_elt--;
7991 }
7992
7993 if (ic_elt >= 0) /* we still have lines to add.. */
7994 {
7995 Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
7996 ic_elt + 1, marker);
7997 marker += (ic_elt + 1);
7998 }
7999
8000 if (startp < low_bound || low_bound == -1)
8001 low_bound = startp;
8002 startp = new_startp;
8003 if (startp > BUF_ZV (b))
8004 {
8005 updating_line_start_cache = 0;
8006 w->line_cache_validation_override--;
8007 return;
8008 }
8009 }
8010 }
8011
8012 assert (Dynarr_length (cache));
8013 assert (from >= low_bound);
8014
8015 /* Readjust the high_bound to account for any changes made while
8016 correcting the low_bound. */
8017 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8018
8019 if (to > high_bound)
8020 {
8021 Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
8022
8023 do
8024 {
8025 regenerate_window (w, startp, point, CMOTION_DISP);
8026 update_internal_cache_list (w, CMOTION_DISP);
8027
8028 /* See comment above about regenerate_window failing. */
8029 assert (Dynarr_length (internal_cache));
8030
8031 Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
8032 Dynarr_length (internal_cache));
8033 high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
8034 startp = high_bound + 1;
8035 }
8036 while (to > high_bound);
8037 }
8038
8039 updating_line_start_cache = 0;
8040 w->line_cache_validation_override--;
8041 assert (to <= high_bound);
8042 }
8043
8044
8045 /* Given x and y coordinates in characters, relative to a window,
8046 return the pixel location corresponding to those coordinates. The
8047 pixel location returned is the center of the given character
8048 position. The pixel values are generated relative to the window,
8049 not the frame.
8050
8051 The modeline is considered to be part of the window. */
8052
8053 void
8054 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
8055 int *pix_x, int *pix_y)
8056 {
8057 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
8058 int num_disp_lines, modeline;
8059 Lisp_Object window;
8060 int defheight, defwidth;
8061
8062 XSETWINDOW (window, w);
8063 default_face_height_and_width (window, &defheight, &defwidth);
8064
8065 /* If we get a bogus value indicating somewhere above or to the left of
8066 the window, use the first window line or character position
8067 instead. */
8068 if (char_y < 0)
8069 char_y = 0;
8070 if (char_x < 0)
8071 char_x = 0;
8072
8073 num_disp_lines = Dynarr_length (dla);
8074 modeline = 0;
8075 if (num_disp_lines)
8076 {
8077 if (Dynarr_atp (dla, 0)->modeline)
8078 {
8079 num_disp_lines--;
8080 modeline = 1;
8081 }
8082 }
8083
8084 /* First check if the y position intersects the display lines. */
8085 if (char_y < num_disp_lines)
8086 {
8087 struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
8088 struct display_block *db = get_display_block_from_line (dl, TEXT);
8089
8090 *pix_y = (dl->ypos - dl->ascent +
8091 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
8092
8093 if (char_x < Dynarr_length (db->runes))
8094 {
8095 struct rune *rb = Dynarr_atp (db->runes, char_x);
8096
8097 *pix_x = rb->xpos + (rb->width >> 1);
8098 }
8099 else
8100 {
8101 int last_rune = Dynarr_length (db->runes) - 1;
8102 struct rune *rb = Dynarr_atp (db->runes, last_rune);
8103
8104 char_x -= last_rune;
8105
8106 *pix_x = rb->xpos + rb->width;
8107 *pix_x += ((char_x - 1) * defwidth);
8108 *pix_x += (defwidth >> 1);
8109 }
8110 }
8111 else
8112 {
8113 /* It didn't intersect, so extrapolate. #### For now, we include the
8114 modeline in this since we don't have true character positions in
8115 it. */
8116
8117 if (!Dynarr_length (w->face_cachels))
8118 reset_face_cachels (w);
8119
8120 char_y -= num_disp_lines;
8121
8122 if (Dynarr_length (dla))
8123 {
8124 struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
8125 *pix_y = dl->ypos + dl->descent - dl->clip;
8126 }
8127 else
8128 *pix_y = WINDOW_TEXT_TOP (w);
8129
8130 *pix_y += (char_y * defheight);
8131 *pix_y += (defheight >> 1);
8132
8133 *pix_x = WINDOW_TEXT_LEFT (w);
8134 /* Don't adjust by one because this is still the unadjusted value. */
8135 *pix_x += (char_x * defwidth);
8136 *pix_x += (defwidth >> 1);
8137 }
8138
8139 if (*pix_x > w->pixel_left + w->pixel_width)
8140 *pix_x = w->pixel_left + w->pixel_width;
8141 if (*pix_y > w->pixel_top + w->pixel_height)
8142 *pix_y = w->pixel_top + w->pixel_height;
8143
8144 *pix_x -= w->pixel_left;
8145 *pix_y -= w->pixel_top;
8146 }
8147
8148 /* Given a display line and a position, determine if there is a glyph
8149 there and return information about it if there is. */
8150
8151 static void
8152 get_position_object (struct display_line *dl, Lisp_Object *obj1,
8153 Lisp_Object *obj2, int x_coord, int *low_x_coord,
8154 int *high_x_coord)
8155 {
8156 struct display_block *db;
8157 int elt;
8158 int block =
8159 get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
8160
8161 /* We use get_next_display_block to get the actual display block
8162 that would be displayed at x_coord. */
8163
8164 if (block == NO_BLOCK)
8165 return;
8166 else
8167 db = Dynarr_atp (dl->display_blocks, block);
8168
8169 for (elt = 0; elt < Dynarr_length (db->runes); elt++)
8170 {
8171 struct rune *rb = Dynarr_atp (db->runes, elt);
8172
8173 if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
8174 {
8175 if (rb->type == RUNE_DGLYPH)
8176 {
8177 *obj1 = rb->object.dglyph.glyph;
8178 *obj2 = rb->object.dglyph.extent;
8179 }
8180 else
8181 {
8182 *obj1 = Qnil;
8183 *obj2 = Qnil;
8184 }
8185
8186 if (low_x_coord)
8187 *low_x_coord = rb->xpos;
8188 if (high_x_coord)
8189 *high_x_coord = rb->xpos + rb->width;
8190
8191 return;
8192 }
8193 }
8194 }
8195
8196 #define UPDATE_CACHE_RETURN \
8197 do { \
8198 d->pixel_to_glyph_cache.valid = 1; \
8199 d->pixel_to_glyph_cache.low_x_coord = low_x_coord; \
8200 d->pixel_to_glyph_cache.high_x_coord = high_x_coord; \
8201 d->pixel_to_glyph_cache.low_y_coord = low_y_coord; \
8202 d->pixel_to_glyph_cache.high_y_coord = high_y_coord; \
8203 d->pixel_to_glyph_cache.frame = f; \
8204 d->pixel_to_glyph_cache.col = *col; \
8205 d->pixel_to_glyph_cache.row = *row; \
8206 d->pixel_to_glyph_cache.obj_x = *obj_x; \
8207 d->pixel_to_glyph_cache.obj_y = *obj_y; \
8208 d->pixel_to_glyph_cache.w = *w; \
8209 d->pixel_to_glyph_cache.bufpos = *bufpos; \
8210 d->pixel_to_glyph_cache.closest = *closest; \
8211 d->pixel_to_glyph_cache.modeline_closest = *modeline_closest; \
8212 d->pixel_to_glyph_cache.obj1 = *obj1; \
8213 d->pixel_to_glyph_cache.obj2 = *obj2; \
8214 d->pixel_to_glyph_cache.retval = position; \
8215 RETURN_SANS_WARNINGS position; \
8216 } while (0)
8217
8218 /* Given x and y coordinates in pixels relative to a frame, return
8219 information about what is located under those coordinates.
8220
8221 The return value will be one of:
8222
8223 OVER_TOOLBAR: over one of the 4 frame toolbars
8224 OVER_MODELINE: over a modeline
8225 OVER_BORDER: over an internal border
8226 OVER_NOTHING: over the text area, but not over text
8227 OVER_OUTSIDE: outside of the frame border
8228 OVER_TEXT: over text in the text area
8229
8230 OBJ1 is one of
8231
8232 -- a toolbar button
8233 -- a glyph
8234 -- nil if the coordinates are not over a glyph or a toolbar button.
8235
8236 OBJ2 is one of
8237
8238 -- an extent, if the coordinates are over a glyph in the text area
8239 -- nil otherwise.
8240
8241 If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
8242 equivalent coordinates relative to the upper-left corner of the glyph.
8243
8244 If the coordinates are over a character, OBJ_X and OBJ_Y give the
8245 equivalent coordinates relative to the upper-left corner of the character.
8246
8247 Otherwise, OBJ_X and OBJ_Y are undefined.
8248 */
8249
8250 int
8251 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
8252 int *col, int *row, int *obj_x, int *obj_y,
8253 struct window **w, Bufpos *bufpos,
8254 Bufpos *closest, Charcount *modeline_closest,
8255 Lisp_Object *obj1, Lisp_Object *obj2)
8256 {
8257 struct device *d;
8258 struct pixel_to_glyph_translation_cache *cache;
8259 Lisp_Object window;
8260 int frm_left, frm_right, frm_top, frm_bottom;
8261 int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
8262 int position = OVER_NOTHING;
8263 int device_check_failed = 0;
8264 display_line_dynarr *dla;
8265
8266 /* This is a safety valve in case this got called with a frame in
8267 the middle of being deleted. */
8268 if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
8269 {
8270 device_check_failed = 1;
8271 d = NULL, cache = NULL; /* Warning suppression */
8272 }
8273 else
8274 {
8275 d = XDEVICE (f->device);
8276 cache = &d->pixel_to_glyph_cache;
8277 }
8278
8279 if (!device_check_failed
8280 && cache->valid
8281 && cache->frame == f
8282 && cache->low_x_coord <= x_coord
8283 && cache->high_x_coord > x_coord
8284 && cache->low_y_coord <= y_coord
8285 && cache->high_y_coord > y_coord)
8286 {
8287 *col = cache->col;
8288 *row = cache->row;
8289 *obj_x = cache->obj_x;
8290 *obj_y = cache->obj_y;
8291 *w = cache->w;
8292 *bufpos = cache->bufpos;
8293 *closest = cache->closest;
8294 *modeline_closest = cache->modeline_closest;
8295 *obj1 = cache->obj1;
8296 *obj2 = cache->obj2;
8297
8298 return cache->retval;
8299 }
8300 else
8301 {
8302 *col = 0;
8303 *row = 0;
8304 *obj_x = 0;
8305 *obj_y = 0;
8306 *w = 0;
8307 *bufpos = 0;
8308 *closest = 0;
8309 *modeline_closest = -1;
8310 *obj1 = Qnil;
8311 *obj2 = Qnil;
8312
8313 low_x_coord = x_coord;
8314 high_x_coord = x_coord + 1;
8315 low_y_coord = y_coord;
8316 high_y_coord = y_coord + 1;
8317 }
8318
8319 if (device_check_failed)
8320 return OVER_NOTHING;
8321
8322 frm_left = FRAME_LEFT_BORDER_END (f);
8323 frm_right = FRAME_RIGHT_BORDER_START (f);
8324 frm_top = FRAME_TOP_BORDER_END (f);
8325 frm_bottom = FRAME_BOTTOM_BORDER_START (f);
8326
8327 /* Check if the mouse is outside of the text area actually used by
8328 redisplay. */
8329 if (y_coord < frm_top)
8330 {
8331 if (y_coord >= FRAME_TOP_BORDER_START (f))
8332 {
8333 low_y_coord = FRAME_TOP_BORDER_START (f);
8334 high_y_coord = frm_top;
8335 position = OVER_BORDER;
8336 }
8337 else if (y_coord >= 0)
8338 {
8339 low_y_coord = 0;
8340 high_y_coord = FRAME_TOP_BORDER_START (f);
8341 position = OVER_TOOLBAR;
8342 }
8343 else
8344 {
8345 low_y_coord = y_coord;
8346 high_y_coord = 0;
8347 position = OVER_OUTSIDE;
8348 }
8349 }
8350 else if (y_coord >= frm_bottom)
8351 {
8352 if (y_coord < FRAME_BOTTOM_BORDER_END (f))
8353 {
8354 low_y_coord = frm_bottom;
8355 high_y_coord = FRAME_BOTTOM_BORDER_END (f);
8356 position = OVER_BORDER;
8357 }
8358 else if (y_coord < FRAME_PIXHEIGHT (f))
8359 {
8360 low_y_coord = FRAME_BOTTOM_BORDER_END (f);
8361 high_y_coord = FRAME_PIXHEIGHT (f);
8362 position = OVER_TOOLBAR;
8363 }
8364 else
8365 {
8366 low_y_coord = FRAME_PIXHEIGHT (f);
8367 high_y_coord = y_coord;
8368 position = OVER_OUTSIDE;
8369 }
8370 }
8371
8372 if (position != OVER_TOOLBAR && position != OVER_BORDER)
8373 {
8374 if (x_coord < frm_left)
8375 {
8376 if (x_coord >= FRAME_LEFT_BORDER_START (f))
8377 {
8378 low_x_coord = FRAME_LEFT_BORDER_START (f);
8379 high_x_coord = frm_left;
8380 position = OVER_BORDER;
8381 }
8382 else if (x_coord >= 0)
8383 {
8384 low_x_coord = 0;
8385 high_x_coord = FRAME_LEFT_BORDER_START (f);
8386 position = OVER_TOOLBAR;
8387 }
8388 else
8389 {
8390 low_x_coord = x_coord;
8391 high_x_coord = 0;
8392 position = OVER_OUTSIDE;
8393 }
8394 }
8395 else if (x_coord >= frm_right)
8396 {
8397 if (x_coord < FRAME_RIGHT_BORDER_END (f))
8398 {
8399 low_x_coord = frm_right;
8400 high_x_coord = FRAME_RIGHT_BORDER_END (f);
8401 position = OVER_BORDER;
8402 }
8403 else if (x_coord < FRAME_PIXWIDTH (f))
8404 {
8405 low_x_coord = FRAME_RIGHT_BORDER_END (f);
8406 high_x_coord = FRAME_PIXWIDTH (f);
8407 position = OVER_TOOLBAR;
8408 }
8409 else
8410 {
8411 low_x_coord = FRAME_PIXWIDTH (f);
8412 high_x_coord = x_coord;
8413 position = OVER_OUTSIDE;
8414 }
8415 }
8416 }
8417
8418 #ifdef HAVE_TOOLBARS
8419 if (position == OVER_TOOLBAR)
8420 {
8421 *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
8422 *obj2 = Qnil;
8423 *w = 0;
8424 UPDATE_CACHE_RETURN;
8425 }
8426 #endif /* HAVE_TOOLBARS */
8427
8428 /* We still have to return the window the pointer is next to and its
8429 relative y position even if it is outside the x boundary. */
8430 if (x_coord < frm_left)
8431 x_coord = frm_left;
8432 else if (x_coord > frm_right)
8433 x_coord = frm_right;
8434
8435 /* Same in reverse. */
8436 if (y_coord < frm_top)
8437 y_coord = frm_top;
8438 else if (y_coord > frm_bottom)
8439 y_coord = frm_bottom;
8440
8441 /* Find what window the given coordinates are actually in. */
8442 window = f->root_window;
8443 *w = find_window_by_pixel_pos (x_coord, y_coord, window);
8444
8445 /* If we didn't find a window, we're done. */
8446 if (!*w)
8447 {
8448 UPDATE_CACHE_RETURN;
8449 }
8450 else if (position != OVER_NOTHING)
8451 {
8452 *closest = 0;
8453 *modeline_closest = -1;
8454
8455 if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
8456 {
8457 *w = 0;
8458 UPDATE_CACHE_RETURN;
8459 }
8460 }
8461
8462 /* Check if the window is a minibuffer but isn't active. */
8463 if (MINI_WINDOW_P (*w) && !minibuf_level)
8464 {
8465 /* Must reset the window value since some callers will ignore
8466 the return value if it is set. */
8467 *w = 0;
8468 UPDATE_CACHE_RETURN;
8469 }
8470
8471 /* See if the point is over window vertical divider */
8472 if (window_needs_vertical_divider (*w))
8473 {
8474 int div_x_high = WINDOW_RIGHT (*w);
8475 int div_x_low = div_x_high - window_divider_width (*w);
8476 int div_y_high = WINDOW_BOTTOM (*w);
8477 int div_y_low = WINDOW_TOP (*w);
8478
8479 if (div_x_low < x_coord && x_coord <= div_x_high &&
8480 div_y_low < y_coord && y_coord <= div_y_high)
8481 {
8482 low_x_coord = div_x_low;
8483 high_x_coord = div_x_high;
8484 low_y_coord = div_y_low;
8485 high_y_coord = div_y_high;
8486 position = OVER_V_DIVIDER;
8487 UPDATE_CACHE_RETURN;
8488 }
8489 }
8490
8491 dla = window_display_lines (*w, CURRENT_DISP);
8492
8493 for (*row = 0; *row < Dynarr_length (dla); (*row)++)
8494 {
8495 int really_over_nothing = 0;
8496 struct display_line *dl = Dynarr_atp (dla, *row);
8497
8498 if ((int) (dl->ypos - dl->ascent) <= y_coord
8499 && y_coord <= (int) (dl->ypos + dl->descent))
8500 {
8501 int check_margin_glyphs = 0;
8502 struct display_block *db = get_display_block_from_line (dl, TEXT);
8503 struct rune *rb = 0;
8504
8505 if (x_coord < dl->bounds.left_white
8506 || x_coord >= dl->bounds.right_white)
8507 check_margin_glyphs = 1;
8508
8509 low_y_coord = dl->ypos - dl->ascent;
8510 high_y_coord = dl->ypos + dl->descent + 1;
8511
8512 if (position == OVER_BORDER
8513 || position == OVER_OUTSIDE
8514 || check_margin_glyphs)
8515 {
8516 int x_check, left_bound;
8517
8518 if (check_margin_glyphs)
8519 {
8520 x_check = x_coord;
8521 left_bound = dl->bounds.left_white;
8522 }
8523 else
8524 {
8525 x_check = high_x_coord;
8526 left_bound = frm_left;
8527 }
8528
8529 if (Dynarr_length (db->runes))
8530 {
8531 if (x_check <= left_bound)
8532 {
8533 if (dl->modeline)
8534 *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
8535 else
8536 *closest = Dynarr_atp (db->runes, 0)->bufpos;
8537 }
8538 else
8539 {
8540 if (dl->modeline)
8541 *modeline_closest =
8542 Dynarr_atp (db->runes,
8543 Dynarr_length (db->runes) - 1)->bufpos;
8544 else
8545 *closest =
8546 Dynarr_atp (db->runes,
8547 Dynarr_length (db->runes) - 1)->bufpos;
8548 }
8549
8550 if (dl->modeline)
8551 *modeline_closest += dl->offset;
8552 else
8553 *closest += dl->offset;
8554 }
8555 else
8556 {
8557 /* #### What should be here. */
8558 if (dl->modeline)
8559 *modeline_closest = 0;
8560 else
8561 *closest = 0;
8562 }
8563
8564 if (check_margin_glyphs)
8565 {
8566 if (x_coord < dl->bounds.left_in
8567 || x_coord >= dl->bounds.right_in)
8568 {
8569 /* If we are over the outside margins then we
8570 know the loop over the text block isn't going
8571 to accomplish anything. So we go ahead and
8572 set what information we can right here and
8573 return. */
8574 (*row)--;
8575 *obj_y = y_coord - (dl->ypos - dl->ascent);
8576 get_position_object (dl, obj1, obj2, x_coord,
8577 &low_x_coord, &high_x_coord);
8578
8579 UPDATE_CACHE_RETURN;
8580 }
8581 }
8582 else
8583 UPDATE_CACHE_RETURN;
8584 }
8585
8586 for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
8587 {
8588 int past_end = (*col == Dynarr_length (db->runes));
8589
8590 if (!past_end)
8591 rb = Dynarr_atp (db->runes, *col);
8592
8593 if (past_end ||
8594 (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
8595 {
8596 if (past_end)
8597 {
8598 (*col)--;
8599 rb = Dynarr_atp (db->runes, *col);
8600 }
8601
8602 *bufpos = rb->bufpos + dl->offset;
8603 low_x_coord = rb->xpos;
8604 high_x_coord = rb->xpos + rb->width;
8605
8606 if (rb->type == RUNE_DGLYPH)
8607 {
8608 int elt = *col + 1;
8609
8610 /* Find the first character after the glyph. */
8611 while (elt < Dynarr_length (db->runes))
8612 {
8613 if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
8614 {
8615 if (dl->modeline)
8616 *modeline_closest =
8617 (Dynarr_atp (db->runes, elt)->bufpos +
8618 dl->offset);
8619 else
8620 *closest =
8621 (Dynarr_atp (db->runes, elt)->bufpos +
8622 dl->offset);
8623 break;
8624 }
8625
8626 elt++;
8627 }
8628
8629 /* In this case we failed to find a non-glyph
8630 character so we return the last position
8631 displayed on the line. */
8632 if (elt == Dynarr_length (db->runes))
8633 {
8634 if (dl->modeline)
8635 *modeline_closest = dl->end_bufpos + dl->offset;
8636 else
8637 *closest = dl->end_bufpos + dl->offset;
8638 really_over_nothing = 1;
8639 }
8640 }
8641 else
8642 {
8643 if (dl->modeline)
8644 *modeline_closest = rb->bufpos + dl->offset;
8645 else
8646 *closest = rb->bufpos + dl->offset;
8647 }
8648
8649 if (dl->modeline)
8650 {
8651 *row = window_displayed_height (*w);
8652
8653 if (position == OVER_NOTHING)
8654 position = OVER_MODELINE;
8655
8656 if (rb->type == RUNE_DGLYPH)
8657 {
8658 *obj1 = rb->object.dglyph.glyph;
8659 *obj2 = rb->object.dglyph.extent;
8660 }
8661 else if (rb->type == RUNE_CHAR)
8662 {
8663 *obj1 = Qnil;
8664 *obj2 = Qnil;
8665 }
8666 else
8667 {
8668 *obj1 = Qnil;
8669 *obj2 = Qnil;
8670 }
8671
8672 UPDATE_CACHE_RETURN;
8673 }
8674 else if (past_end
8675 || (rb->type == RUNE_CHAR
8676 && rb->object.chr.ch == '\n'))
8677 {
8678 (*row)--;
8679 /* At this point we may have glyphs in the right
8680 inside margin. */
8681 if (check_margin_glyphs)
8682 get_position_object (dl, obj1, obj2, x_coord,
8683 &low_x_coord, &high_x_coord);
8684 UPDATE_CACHE_RETURN;
8685 }
8686 else
8687 {
8688 (*row)--;
8689 if (rb->type == RUNE_DGLYPH)
8690 {
8691 *obj1 = rb->object.dglyph.glyph;
8692 *obj2 = rb->object.dglyph.extent;
8693 }
8694 else if (rb->type == RUNE_CHAR)
8695 {
8696 *obj1 = Qnil;
8697 *obj2 = Qnil;
8698 }
8699 else
8700 {
8701 *obj1 = Qnil;
8702 *obj2 = Qnil;
8703 }
8704
8705 *obj_x = x_coord - rb->xpos;
8706 *obj_y = y_coord - (dl->ypos - dl->ascent);
8707
8708 /* At this point we may have glyphs in the left
8709 inside margin. */
8710 if (check_margin_glyphs)
8711 get_position_object (dl, obj1, obj2, x_coord, 0, 0);
8712
8713 if (position == OVER_NOTHING && !really_over_nothing)
8714 position = OVER_TEXT;
8715
8716 UPDATE_CACHE_RETURN;
8717 }
8718 }
8719 }
8720 }
8721 }
8722
8723 *row = Dynarr_length (dla) - 1;
8724 if (FRAME_WIN_P (f))
8725 {
8726 int bot_elt = Dynarr_length (dla) - 1;
8727
8728 if (bot_elt >= 0)
8729 {
8730 struct display_line *dl = Dynarr_atp (dla, bot_elt);
8731 int adj_area = y_coord - (dl->ypos + dl->descent);
8732 Lisp_Object lwin;
8733 int defheight;
8734
8735 XSETWINDOW (lwin, *w);
8736 default_face_height_and_width (lwin, 0, &defheight);
8737
8738 *row += (adj_area / defheight);
8739 }
8740 }
8741
8742 /* #### This should be checked out some more to determine what
8743 should really be going on. */
8744 if (!MARKERP ((*w)->start[CURRENT_DISP]))
8745 *closest = 0;
8746 else
8747 *closest = end_of_last_line (*w,
8748 marker_position ((*w)->start[CURRENT_DISP]));
8749 *col = 0;
8750 UPDATE_CACHE_RETURN;
8751 }
8752 #undef UPDATE_CACHE_RETURN
8753
8754
8755 /***************************************************************************/
8756 /* */
8757 /* Lisp functions */
8758 /* */
8759 /***************************************************************************/
8760
8761 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
8762 Ensure that all minibuffers are correctly showing the echo area.
8763 */
8764 ())
8765 {
8766 Lisp_Object devcons, concons;
8767
8768 DEVICE_LOOP_NO_BREAK (devcons, concons)
8769 {
8770 struct device *d = XDEVICE (XCAR (devcons));
8771 Lisp_Object frmcons;
8772
8773 DEVICE_FRAME_LOOP (frmcons, d)
8774 {
8775 struct frame *f = XFRAME (XCAR (frmcons));
8776
8777 if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
8778 {
8779 Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
8780 /*
8781 * If the frame size has changed, there may be random
8782 * chud on the screen left from previous messages
8783 * because redisplay_frame hasn't been called yet.
8784 * Clear the screen to get rid of the potential mess.
8785 */
8786 if (f->echo_area_garbaged)
8787 {
8788 DEVMETH (d, clear_frame, (f));
8789 f->echo_area_garbaged = 0;
8790 }
8791 redisplay_window (window, 0);
8792 call_redisplay_end_triggers (XWINDOW (window), 0);
8793 }
8794 }
8795
8796 /* We now call the output_end routine for tty frames. We delay
8797 doing so in order to avoid cursor flicker. So much for 100%
8798 encapsulation. */
8799 if (DEVICE_TTY_P (d))
8800 DEVMETH (d, output_end, (d));
8801 }
8802
8803 return Qnil;
8804 }
8805
8806 static Lisp_Object
8807 restore_disable_preemption_value (Lisp_Object value)
8808 {
8809 disable_preemption = XINT (value);
8810 return Qnil;
8811 }
8812
8813 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
8814 Clear frame FRAME and output again what is supposed to appear on it.
8815 FRAME defaults to the selected frame if omitted.
8816 Normally, redisplay is preempted as normal if input arrives. However,
8817 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8818 input and is guaranteed to proceed to completion.
8819 */
8820 (frame, no_preempt))
8821 {
8822 struct frame *f = decode_frame (frame);
8823 int count = specpdl_depth ();
8824
8825 if (!NILP (no_preempt))
8826 {
8827 record_unwind_protect (restore_disable_preemption_value,
8828 make_int (disable_preemption));
8829 disable_preemption++;
8830 }
8831
8832 f->clear = 1;
8833 redisplay_frame (f, 1);
8834
8835 return unbind_to (count, Qnil);
8836 }
8837
8838 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
8839 Ensure that FRAME's contents are correctly displayed.
8840 This differs from `redraw-frame' in that it only redraws what needs to
8841 be updated, as opposed to unconditionally clearing and redrawing
8842 the frame.
8843 FRAME defaults to the selected frame if omitted.
8844 Normally, redisplay is preempted as normal if input arrives. However,
8845 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8846 input and is guaranteed to proceed to completion.
8847 */
8848 (frame, no_preempt))
8849 {
8850 struct frame *f = decode_frame (frame);
8851 int count = specpdl_depth ();
8852
8853 if (!NILP (no_preempt))
8854 {
8855 record_unwind_protect (restore_disable_preemption_value,
8856 make_int (disable_preemption));
8857 disable_preemption++;
8858 }
8859
8860 redisplay_frame (f, 1);
8861
8862 return unbind_to (count, Qnil);
8863 }
8864
8865 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
8866 Clear device DEVICE and output again what is supposed to appear on it.
8867 DEVICE defaults to the selected device if omitted.
8868 Normally, redisplay is preempted as normal if input arrives. However,
8869 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8870 input and is guaranteed to proceed to completion.
8871 */
8872 (device, no_preempt))
8873 {
8874 struct device *d = decode_device (device);
8875 Lisp_Object frmcons;
8876 int count = specpdl_depth ();
8877
8878 if (!NILP (no_preempt))
8879 {
8880 record_unwind_protect (restore_disable_preemption_value,
8881 make_int (disable_preemption));
8882 disable_preemption++;
8883 }
8884
8885 DEVICE_FRAME_LOOP (frmcons, d)
8886 {
8887 XFRAME (XCAR (frmcons))->clear = 1;
8888 }
8889 redisplay_device (d);
8890
8891 return unbind_to (count, Qnil);
8892 }
8893
8894 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8895 Ensure that DEVICE's contents are correctly displayed.
8896 This differs from `redraw-device' in that it only redraws what needs to
8897 be updated, as opposed to unconditionally clearing and redrawing
8898 the device.
8899 DEVICE defaults to the selected device if omitted.
8900 Normally, redisplay is preempted as normal if input arrives. However,
8901 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8902 input and is guaranteed to proceed to completion.
8903 */
8904 (device, no_preempt))
8905 {
8906 struct device *d = decode_device (device);
8907 int count = specpdl_depth ();
8908
8909 if (!NILP (no_preempt))
8910 {
8911 record_unwind_protect (restore_disable_preemption_value,
8912 make_int (disable_preemption));
8913 disable_preemption++;
8914 }
8915
8916 redisplay_device (d);
8917
8918 return unbind_to (count, Qnil);
8919 }
8920
8921 /* Big lie. Big lie. This will force all modelines to be updated
8922 regardless if the all flag is set or not. It remains in existence
8923 solely for backwards compatibility. */
8924 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8925 Force the modeline of the current buffer to be redisplayed.
8926 With optional non-nil ALL, force redisplay of all modelines.
8927 */
8928 (all))
8929 {
8930 MARK_MODELINE_CHANGED;
8931 return Qnil;
8932 }
8933
8934 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8935 Force an immediate update of the cursor on FRAME.
8936 FRAME defaults to the selected frame if omitted.
8937 */
8938 (frame))
8939 {
8940 redisplay_redraw_cursor (decode_frame (frame), 1);
8941 return Qnil;
8942 }
8943
8944
8945 /***************************************************************************/
8946 /* */
8947 /* Lisp-variable change triggers */
8948 /* */
8949 /***************************************************************************/
8950
8951 static void
8952 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
8953 Lisp_Object oldval)
8954 {
8955 /* Nothing to be done? */
8956 }
8957
8958 int
8959 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
8960 Lisp_Object in_object, int flags)
8961 {
8962 /* #### clip_changed should really be renamed something like
8963 global_redisplay_change. */
8964 MARK_CLIP_CHANGED;
8965 return 0;
8966 }
8967
8968 /* This is called if the built-in glyphs have their properties
8969 changed. */
8970 void
8971 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8972 Lisp_Object locale)
8973 {
8974 if (WINDOWP (locale))
8975 {
8976 MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
8977 }
8978 else if (FRAMEP (locale))
8979 {
8980 MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
8981 }
8982 else if (DEVICEP (locale))
8983 {
8984 Lisp_Object frmcons;
8985 DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
8986 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8987 }
8988 else if (CONSOLEP (locale))
8989 {
8990 Lisp_Object frmcons, devcons;
8991 CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
8992 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8993 }
8994 else /* global or buffer */
8995 {
8996 Lisp_Object frmcons, devcons, concons;
8997 FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
8998 MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8999 }
9000 }
9001
9002 static void
9003 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
9004 Lisp_Object oldval)
9005 {
9006 if (XFRAME (w->frame)->init_finished)
9007 Fforce_cursor_redisplay (w->frame);
9008 }
9009
9010 #ifdef MEMORY_USAGE_STATS
9011
9012
9013 /***************************************************************************/
9014 /* */
9015 /* memory usage computation */
9016 /* */
9017 /***************************************************************************/
9018
9019 static int
9020 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
9021 {
9022 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9023 }
9024
9025 static int
9026 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
9027 struct overhead_stats *ovstats)
9028 {
9029 int total, i;
9030
9031 if (!dyn)
9032 return 0;
9033
9034 total = Dynarr_memory_usage (dyn, ovstats);
9035 for (i = 0; i < Dynarr_largest (dyn); i++)
9036 total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
9037
9038 return total;
9039 }
9040
9041 static int
9042 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
9043 struct overhead_stats *ovstats)
9044 {
9045 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9046 }
9047
9048 int
9049 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
9050 struct overhead_stats *ovstats)
9051 {
9052 int total, i;
9053
9054 if (!dyn)
9055 return 0;
9056
9057 total = Dynarr_memory_usage (dyn, ovstats);
9058 for (i = 0; i < Dynarr_largest (dyn); i++)
9059 {
9060 struct display_line *dl = &Dynarr_at (dyn, i);
9061 total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
9062 total += compute_glyph_block_dynarr_usage (dl->left_glyphs, ovstats);
9063 total += compute_glyph_block_dynarr_usage (dl->right_glyphs, ovstats);
9064 }
9065
9066 return total;
9067 }
9068
9069 int
9070 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
9071 struct overhead_stats *ovstats)
9072 {
9073 return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
9074 }
9075
9076 #endif /* MEMORY_USAGE_STATS */
9077
9078
9079 /***************************************************************************/
9080 /* */
9081 /* initialization */
9082 /* */
9083 /***************************************************************************/
9084
9085 void
9086 init_redisplay (void)
9087 {
9088 disable_preemption = 0;
9089 preemption_count = 0;
9090 max_preempts = INIT_MAX_PREEMPTS;
9091
9092 #ifndef PDUMP
9093 if (!initialized)
9094 #endif
9095 {
9096 cmotion_display_lines = Dynarr_new (display_line);
9097 mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
9098 formatted_string_emchar_dynarr = Dynarr_new (Emchar);
9099 formatted_string_extent_dynarr = Dynarr_new (EXTENT);
9100 formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
9101 formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
9102 internal_cache = Dynarr_new (line_start_cache);
9103 xzero (formatted_string_display_line);
9104 }
9105
9106 /* window system is nil when in -batch mode */
9107 if (!initialized || noninteractive)
9108 return;
9109
9110 /* If the user wants to use a window system, we shouldn't bother
9111 initializing the terminal. This is especially important when the
9112 terminal is so dumb that emacs gives up before and doesn't bother
9113 using the window system.
9114
9115 If the DISPLAY environment variable is set, try to use X, and die
9116 with an error message if that doesn't work. */
9117
9118 #ifdef HAVE_X_WINDOWS
9119 if (!strcmp (display_use, "x"))
9120 {
9121 /* Some stuff checks this way early. */
9122 Vwindow_system = Qx;
9123 Vinitial_window_system = Qx;
9124 return;
9125 }
9126 #endif /* HAVE_X_WINDOWS */
9127
9128 #ifdef HAVE_MS_WINDOWS
9129 if (!strcmp (display_use, "mswindows"))
9130 {
9131 /* Some stuff checks this way early. */
9132 Vwindow_system = Qmswindows;
9133 Vinitial_window_system = Qmswindows;
9134 return;
9135 }
9136 #endif /* HAVE_MS_WINDOWS */
9137
9138 #ifdef HAVE_TTY
9139 /* If no window system has been specified, try to use the terminal. */
9140 if (!isatty (0))
9141 {
9142 stderr_out ("XEmacs: standard input is not a tty\n");
9143 exit (1);
9144 }
9145
9146 /* Look at the TERM variable */
9147 if (!getenv ("TERM"))
9148 {
9149 stderr_out ("Please set the environment variable TERM; see tset(1).\n");
9150 exit (1);
9151 }
9152
9153 Vinitial_window_system = Qtty;
9154 return;
9155 #else /* not HAVE_TTY */
9156 /* No DISPLAY specified, and no TTY support. */
9157 stderr_out ("XEmacs: Cannot open display.\n\
9158 Please set the environmental variable DISPLAY to an appropriate value.\n");
9159 exit (1);
9160 #endif
9161 /* Unreached. */
9162 }
9163
9164 void
9165 syms_of_redisplay (void)
9166 {
9167 defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
9168 #ifndef INHIBIT_REDISPLAY_HOOKS
9169 defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
9170 defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
9171 #endif /* INHIBIT_REDISPLAY_HOOKS */
9172 defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
9173 defsymbol (&Qbar_cursor, "bar-cursor");
9174 defsymbol (&Qredisplay_end_trigger_functions,
9175 "redisplay-end-trigger-functions");
9176
9177 DEFSUBR (Fredisplay_echo_area);
9178 DEFSUBR (Fredraw_frame);
9179 DEFSUBR (Fredisplay_frame);
9180 DEFSUBR (Fredraw_device);
9181 DEFSUBR (Fredisplay_device);
9182 DEFSUBR (Fredraw_modeline);
9183 DEFSUBR (Fforce_cursor_redisplay);
9184 }
9185
9186 void
9187 reinit_vars_of_redisplay (void)
9188 {
9189 updating_line_start_cache = 0;
9190 }
9191
9192 void
9193 vars_of_redisplay (void)
9194 {
9195 reinit_vars_of_redisplay ();
9196
9197 #if 0
9198 staticpro (&last_arrow_position);
9199 staticpro (&last_arrow_string);
9200 last_arrow_position = Qnil;
9201 last_arrow_string = Qnil;
9202 #endif /* 0 */
9203
9204 /* #### Probably temporary */
9205 DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
9206 \(Temporary) Setting this will impact the performance of the internal
9207 line start cache.
9208 */ );
9209 cache_adjustment = 2;
9210
9211 DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
9212 Minimum pixel height for clipped bottom display line.
9213 A clipped line shorter than this won't be displayed.
9214 */ ,
9215 redisplay_variable_changed);
9216 vertical_clip = 5;
9217
9218 DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
9219 Minimum visible area for clipped glyphs at right boundary.
9220 Clipped glyphs shorter than this won't be displayed.
9221 Only pixmap glyph instances are currently allowed to be clipped.
9222 */ ,
9223 redisplay_variable_changed);
9224 horizontal_clip = 5;
9225
9226 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
9227 String displayed by modeline-format's "%m" specification.
9228 */ );
9229 Vglobal_mode_string = Qnil;
9230
9231 DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
9232 Marker for where to display an arrow on top of the buffer text.
9233 This must be the beginning of a line in order to work.
9234 See also `overlay-arrow-string'.
9235 */ ,
9236 redisplay_variable_changed);
9237 Voverlay_arrow_position = Qnil;
9238
9239 DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
9240 String to display as an arrow. See also `overlay-arrow-position'.
9241 */ ,
9242 redisplay_variable_changed);
9243 Voverlay_arrow_string = Qnil;
9244
9245 DEFVAR_INT ("scroll-step", &scroll_step /*
9246 *The number of lines to try scrolling a window by when point moves out.
9247 If that fails to bring point back on frame, point is centered instead.
9248 If this is zero, point is always centered after it moves off screen.
9249 */ );
9250 scroll_step = 0;
9251
9252 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
9253 *Scroll up to this many lines, to bring point back on screen.
9254 */ );
9255 scroll_conservatively = 0;
9256
9257 DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
9258 &truncate_partial_width_windows /*
9259 *Non-nil means truncate lines in all windows less than full frame wide.
9260 */ ,
9261 redisplay_variable_changed);
9262 truncate_partial_width_windows = 1;
9263
9264 DEFVAR_BOOL ("visible-bell", &visible_bell /*
9265 *Non-nil means try to flash the frame to represent a bell.
9266 */ );
9267 visible_bell = 0;
9268
9269 DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
9270 *Non-nil means no need to redraw entire frame after suspending.
9271 A non-nil value is useful if the terminal can automatically preserve
9272 Emacs's frame display when you reenter Emacs.
9273 It is up to you to set this variable if your terminal can do that.
9274 */ );
9275 no_redraw_on_reenter = 0;
9276
9277 DEFVAR_LISP ("window-system", &Vwindow_system /*
9278 A symbol naming the window-system under which Emacs is running,
9279 such as `x', or nil if emacs is running on an ordinary terminal.
9280
9281 Do not use this variable, except for GNU Emacs compatibility, as it
9282 gives wrong values in a multi-device environment. Use `console-type'
9283 instead.
9284 */ );
9285 Vwindow_system = Qnil;
9286
9287 /* #### Temporary shit until window-system is eliminated. */
9288 DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /*
9289 DON'T TOUCH
9290 */ );
9291 Vinitial_window_system = Qnil;
9292
9293 DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
9294 Non-nil means put cursor in minibuffer, at end of any message there.
9295 */ );
9296 cursor_in_echo_area = 0;
9297
9298 /* #### Shouldn't this be generalized as follows:
9299
9300 if nil, use block cursor.
9301 if a number, use a bar cursor of that width.
9302 Otherwise, use a 1-pixel bar cursor.
9303
9304 #### Or better yet, this variable should be trashed entirely
9305 (use a Lisp-magic variable to maintain compatibility)
9306 and a specifier `cursor-shape' added, which allows a block
9307 cursor, a bar cursor, a flashing block or bar cursor,
9308 maybe a caret cursor, etc. */
9309
9310 DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
9311 Use vertical bar cursor if non-nil. If t width is 1 pixel, otherwise 2.
9312 */ );
9313 Vbar_cursor = Qnil;
9314
9315 #ifndef INHIBIT_REDISPLAY_HOOKS
9316 xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
9317 Function or functions to run before every redisplay.
9318 Functions on this hook must be careful to avoid signalling errors!
9319 */ );
9320 Vpre_redisplay_hook = Qnil;
9321
9322 xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
9323 Function or functions to run after every redisplay.
9324 Functions on this hook must be careful to avoid signalling errors!
9325 */ );
9326 Vpost_redisplay_hook = Qnil;
9327 #endif /* INHIBIT_REDISPLAY_HOOKS */
9328
9329 DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
9330 Bump this to tell the C code to call `display-warning-buffer'
9331 at next redisplay. You should not normally change this; the function
9332 `display-warning' automatically does this at appropriate times.
9333 */ );
9334 display_warning_tick = 0;
9335
9336 DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
9337 Non-nil means inhibit display of warning messages.
9338 You should *bind* this, not set it. Any pending warning messages
9339 will be displayed when the binding no longer applies.
9340 */ );
9341 /* reset to 0 by startup.el after the splash screen has displayed.
9342 This way, the warnings don't obliterate the splash screen. */
9343 inhibit_warning_display = 1;
9344
9345 DEFVAR_LISP ("window-size-change-functions",
9346 &Vwindow_size_change_functions /*
9347 Not currently implemented.
9348 Functions called before redisplay, if window sizes have changed.
9349 The value should be a list of functions that take one argument.
9350 Just before redisplay, for each frame, if any of its windows have changed
9351 size since the last redisplay, or have been split or deleted,
9352 all the functions in the list are called, with the frame as argument.
9353 */ );
9354 Vwindow_size_change_functions = Qnil;
9355
9356 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
9357 Not currently implemented.
9358 Functions to call before redisplaying a window with scrolling.
9359 Each function is called with two arguments, the window
9360 and its new display-start position. Note that the value of `window-end'
9361 is not valid when these functions are called.
9362 */ );
9363 Vwindow_scroll_functions = Qnil;
9364
9365 DEFVAR_LISP ("redisplay-end-trigger-functions",
9366 &Vredisplay_end_trigger_functions /*
9367 See `set-window-redisplay-end-trigger'.
9368 */ );
9369 Vredisplay_end_trigger_functions = Qnil;
9370
9371 DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
9372 *Non-nil means column display number starts at 1.
9373 */ );
9374 column_number_start_at_one = 0;
9375 }
9376
9377 void
9378 specifier_vars_of_redisplay (void)
9379 {
9380 DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
9381 *Width of left margin.
9382 This is a specifier; use `set-specifier' to change it.
9383 */ );
9384 Vleft_margin_width = Fmake_specifier (Qnatnum);
9385 set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
9386 set_specifier_caching (Vleft_margin_width,
9387 slot_offset (struct window, left_margin_width),
9388 some_window_value_changed,
9389 slot_offset (struct frame, left_margin_width),
9390 margin_width_changed_in_frame);
9391
9392 DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
9393 *Width of right margin.
9394 This is a specifier; use `set-specifier' to change it.
9395 */ );
9396 Vright_margin_width = Fmake_specifier (Qnatnum);
9397 set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
9398 set_specifier_caching (Vright_margin_width,
9399 slot_offset (struct window, right_margin_width),
9400 some_window_value_changed,
9401 slot_offset (struct frame, right_margin_width),
9402 margin_width_changed_in_frame);
9403
9404 DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
9405 *Minimum ascent height of lines.
9406 This is a specifier; use `set-specifier' to change it.
9407 */ );
9408 Vminimum_line_ascent = Fmake_specifier (Qnatnum);
9409 set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
9410 set_specifier_caching (Vminimum_line_ascent,
9411 slot_offset (struct window, minimum_line_ascent),
9412 some_window_value_changed,
9413 0, 0);
9414
9415 DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
9416 *Minimum descent height of lines.
9417 This is a specifier; use `set-specifier' to change it.
9418 */ );
9419 Vminimum_line_descent = Fmake_specifier (Qnatnum);
9420 set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
9421 set_specifier_caching (Vminimum_line_descent,
9422 slot_offset (struct window, minimum_line_descent),
9423 some_window_value_changed,
9424 0, 0);
9425
9426 DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
9427 *Non-nil means use the left outside margin as extra whitespace when
9428 displaying 'whitespace or 'inside-margin glyphs.
9429 This is a specifier; use `set-specifier' to change it.
9430 */ );
9431 Vuse_left_overflow = Fmake_specifier (Qboolean);
9432 set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
9433 set_specifier_caching (Vuse_left_overflow,
9434 slot_offset (struct window, use_left_overflow),
9435 some_window_value_changed,
9436 0, 0);
9437
9438 DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
9439 *Non-nil means use the right outside margin as extra whitespace when
9440 displaying 'whitespace or 'inside-margin glyphs.
9441 This is a specifier; use `set-specifier' to change it.
9442 */ );
9443 Vuse_right_overflow = Fmake_specifier (Qboolean);
9444 set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
9445 set_specifier_caching (Vuse_right_overflow,
9446 slot_offset (struct window, use_right_overflow),
9447 some_window_value_changed,
9448 0, 0);
9449
9450 DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
9451 *Non-nil means the text cursor is visible (this is usually the case).
9452 This is a specifier; use `set-specifier' to change it.
9453 */ );
9454 Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
9455 set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
9456 set_specifier_caching (Vtext_cursor_visible_p,
9457 slot_offset (struct window, text_cursor_visible_p),
9458 text_cursor_visible_p_changed,
9459 0, 0);
9460
9461 }