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