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