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