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