XEmacs 21.2.14.
[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       /* Don't pollute the cache if not sure if we are correct */
5257       if (w->start_at_line_beg)
5258         update_line_start_cache (w, start, end, pointm, 1);
5259       redisplay_output_window (w);
5260       /*
5261        * If we just displayed the echo area, the line start cache is
5262        * no longer valid, because the minibuffer window is associated
5263        * with the window now.
5264        */
5265       if (echo_active)
5266         w->line_cache_last_updated = make_int (-1);
5267     }
5268
5269   /* #### This should be dependent on face changes and will need to be
5270      somewhere else once tty updates occur on a per-frame basis. */
5271   mark_face_cachels_as_clean (w);
5272
5273   w->windows_changed = 0;
5274 }
5275
5276 /* Call buffer_reset_changes for all buffers present in any window
5277    currently visible in all frames on all devices.  #### There has to
5278    be a better way to do this. */
5279
5280 static int
5281 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
5282 {
5283   buffer_reset_changes (XBUFFER (w->buffer));
5284   return 0;
5285 }
5286
5287 static void
5288 reset_buffer_changes (void)
5289 {
5290   Lisp_Object frmcons, devcons, concons;
5291
5292   FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
5293     {
5294       struct frame *f = XFRAME (XCAR (frmcons));
5295
5296       if (FRAME_REPAINT_P (f))
5297         map_windows (f, reset_buffer_changes_mapfun, 0);
5298     }
5299 }
5300
5301 /* Ensure that all windows underneath the given window in the window
5302    hierarchy are correctly displayed. */
5303
5304 static void
5305 redisplay_windows (Lisp_Object window, int skip_selected)
5306 {
5307   for (; !NILP (window) ; window = XWINDOW (window)->next)
5308     {
5309       redisplay_window (window, skip_selected);
5310     }
5311 }
5312
5313 static int
5314 call_redisplay_end_triggers (struct window *w, void *closure)
5315 {
5316   Bufpos lrpos = w->last_redisplay_pos;
5317   w->last_redisplay_pos = 0;
5318   if (!NILP (w->buffer)
5319       && !NILP (w->redisplay_end_trigger)
5320       && lrpos > 0)
5321     {
5322       Bufpos pos;
5323
5324       if (MARKERP (w->redisplay_end_trigger)
5325           && XMARKER (w->redisplay_end_trigger)->buffer != 0)
5326         pos = marker_position (w->redisplay_end_trigger);
5327       else if (INTP (w->redisplay_end_trigger))
5328         pos = XINT (w->redisplay_end_trigger);
5329       else
5330         {
5331           w->redisplay_end_trigger = Qnil;
5332           return 0;
5333         }
5334
5335       if (lrpos >= pos)
5336         {
5337           Lisp_Object window;
5338           XSETWINDOW (window, w);
5339           va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
5340                                            Qredisplay_end_trigger_functions,
5341                                            2, window,
5342                                            w->redisplay_end_trigger);
5343           w->redisplay_end_trigger = Qnil;
5344         }
5345     }
5346
5347   return 0;
5348 }
5349
5350 /* Ensure that all windows on the given frame are correctly displayed. */
5351
5352 static int
5353 redisplay_frame (struct frame *f, int preemption_check)
5354 {
5355   struct device *d = XDEVICE (f->device);
5356
5357   if (preemption_check)
5358     {
5359       /* The preemption check itself takes a lot of time,
5360          so normally don't do it here.  We do it if called
5361          from Lisp, though (`redisplay-frame'). */
5362       int preempted;
5363
5364       REDISPLAY_PREEMPTION_CHECK;
5365       if (preempted)
5366         return 1;
5367     }
5368
5369   /* Before we put a hold on frame size changes, attempt to process
5370      any which are already pending. */
5371   if (f->size_change_pending)
5372     change_frame_size (f, f->new_height, f->new_width, 0);
5373
5374   /* If frame size might need to be changed, due to changed size
5375      of toolbars, scrollbars etc, change it now */
5376   if (f->size_slipped)
5377     {
5378       adjust_frame_size (f);
5379       assert (!f->size_slipped);
5380     }
5381
5382   /* The menubar, toolbar, and icon updates must be done before
5383      hold_frame_size_changes is called and we are officially
5384      'in_display'.  They may eval lisp code which may call Fsignal.
5385      If in_display is set Fsignal will abort. */
5386
5387 #ifdef HAVE_MENUBARS
5388   /* Update the menubar.  It is done first since it could change
5389      the menubar's visibility.  This way we avoid having flashing
5390      caused by an Expose event generated by the visibility change
5391      being handled. */
5392   update_frame_menubars (f);
5393 #endif /* HAVE_MENUBARS */
5394   /* widgets are similar to menus in that they can call lisp to
5395      determine activation etc. Therefore update them before we get
5396      into redisplay. This is primarily for connected widgets such as
5397      radio buttons. */
5398   update_frame_subwindows (f);
5399 #ifdef HAVE_TOOLBARS
5400   /* Update the toolbars. */
5401   update_frame_toolbars (f);
5402 #endif /* HAVE_TOOLBARS */
5403
5404   hold_frame_size_changes ();
5405
5406   /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */
5407   /* Within this section, we are defenseless and assume that the
5408      following cannot happen:
5409
5410      1) garbage collection
5411      2) Lisp code evaluation
5412      3) frame size changes
5413
5414      We ensure (3) by calling hold_frame_size_changes(), which
5415      will cause any pending frame size changes to get put on hold
5416      till after the end of the critical section.  (1) follows
5417      automatically if (2) is met.  #### Unfortunately, there are
5418      some places where Lisp code can be called within this section.
5419      We need to remove them.
5420
5421      If Fsignal() is called during this critical section, we
5422      will abort().
5423
5424      If garbage collection is called during this critical section,
5425      we simply return. #### We should abort instead.
5426
5427      #### If a frame-size change does occur we should probably
5428      actually be preempting redisplay. */
5429
5430   /* If we clear the frame we have to force its contents to be redrawn. */
5431   if (f->clear)
5432     f->frame_changed = 1;
5433
5434   /* Erase the frame before outputting its contents. */
5435   if (f->clear)
5436     {
5437       DEVMETH (d, clear_frame, (f));
5438     }
5439
5440   /* invalidate the subwindow cache. we are going to reuse the glyphs
5441      flag here to cause subwindows to get instantiated. This is
5442      because subwindows changed is less strict - dealing with things
5443      like the clicked state of button. */
5444   if (!Dynarr_length (f->subwindow_cachels)
5445       || f->glyphs_changed
5446       || f->frame_changed)
5447     reset_subwindow_cachels (f);
5448   else
5449     mark_subwindow_cachels_as_not_updated (f);
5450
5451   /* Do the selected window first. */
5452   redisplay_window (FRAME_SELECTED_WINDOW (f), 0);
5453
5454   /* Then do the rest. */
5455   redisplay_windows (f->root_window, 1);
5456
5457   /* We now call the output_end routine for tty frames.  We delay
5458      doing so in order to avoid cursor flicker.  So much for 100%
5459      encapsulation. */
5460   if (FRAME_TTY_P (f))
5461     DEVMETH (d, output_end, (d));
5462
5463   update_frame_title (f);
5464
5465   f->buffers_changed  = 0;
5466   f->clip_changed     = 0;
5467   f->extents_changed  = 0;
5468   f->faces_changed    = 0;
5469   f->frame_changed    = 0;
5470   f->glyphs_changed   = 0;
5471   f->subwindows_changed   = 0;
5472   f->icon_changed     = 0;
5473   f->menubar_changed  = 0;
5474   f->modeline_changed = 0;
5475   f->point_changed    = 0;
5476   f->toolbar_changed  = 0;
5477   f->windows_changed  = 0;
5478   f->windows_structure_changed = 0;
5479   f->window_face_cache_reset = 0;
5480   f->echo_area_garbaged = 0;
5481
5482   f->clear = 0;
5483
5484   if (!f->size_change_pending)
5485     f->size_changed = 0;
5486
5487   /* ----------------- END CRITICAL REDISPLAY SECTION ---------------- */
5488
5489   /* Allow frame size changes to occur again.
5490
5491      #### what happens if changes to other frames happen? */
5492   unhold_one_frame_size_changes (f);
5493
5494   map_windows (f, call_redisplay_end_triggers, 0);
5495   return 0;
5496 }
5497
5498 /* Ensure that all frames on the given device are correctly displayed. */
5499
5500 static int
5501 redisplay_device (struct device *d)
5502 {
5503   Lisp_Object frame, frmcons;
5504   int preempted = 0;
5505   int size_change_failed = 0;
5506   struct frame *f;
5507
5508   if (DEVICE_STREAM_P (d)) /* nothing to do */
5509     return 0;
5510
5511   /* It is possible that redisplay has been called before the
5512      device is fully initialized.  If so then continue with the
5513      next device. */
5514   if (NILP (DEVICE_SELECTED_FRAME (d)))
5515     return 0;
5516
5517   REDISPLAY_PREEMPTION_CHECK;
5518   if (preempted)
5519     return 1;
5520
5521   /* Always do the selected frame first. */
5522   frame = DEVICE_SELECTED_FRAME (d);
5523
5524   f = XFRAME (frame);
5525
5526   if (f->icon_changed || f->windows_changed)
5527     update_frame_icon (f);
5528
5529   if (FRAME_REPAINT_P (f))
5530     {
5531       if (f->buffers_changed  || f->clip_changed  || f->extents_changed ||
5532           f->faces_changed    || f->frame_changed || f->menubar_changed ||
5533           f->modeline_changed || f->point_changed || f->size_changed    ||
5534           f->toolbar_changed  || f->windows_changed || f->size_slipped  ||
5535           f->windows_structure_changed || f->glyphs_changed || f->subwindows_changed)
5536         {
5537           preempted = redisplay_frame (f, 0);
5538         }
5539
5540       if (preempted)
5541         return 1;
5542
5543       /* If the frame redisplay did not get preempted, then this flag
5544          should have gotten set to 0.  It might be possible for that
5545          not to happen if a size change event were to occur at an odd
5546          time.  To make sure we don't miss anything we simply don't
5547          reset the top level flags until the condition ends up being
5548          in the right state. */
5549       if (f->size_changed)
5550         size_change_failed = 1;
5551     }
5552
5553   DEVICE_FRAME_LOOP (frmcons, d)
5554     {
5555       f = XFRAME (XCAR (frmcons));
5556
5557       if (f == XFRAME (DEVICE_SELECTED_FRAME (d)))
5558         continue;
5559
5560       if (f->icon_changed || f->windows_changed)
5561         update_frame_icon (f);
5562
5563       if (FRAME_REPAINT_P (f))
5564         {
5565           if (f->buffers_changed  || f->clip_changed  || f->extents_changed ||
5566               f->faces_changed    || f->frame_changed || f->menubar_changed ||
5567               f->modeline_changed || f->point_changed || f->size_changed    ||
5568               f->toolbar_changed  || f->windows_changed ||
5569               f->windows_structure_changed ||
5570               f->glyphs_changed || f->subwindows_changed)
5571             {
5572               preempted = redisplay_frame (f, 0);
5573             }
5574
5575           if (preempted)
5576             return 1;
5577
5578           if (f->size_change_pending)
5579             size_change_failed = 1;
5580         }
5581     }
5582
5583   /* If we get here then we redisplayed all of our frames without
5584      getting preempted so mark ourselves as clean. */
5585   d->buffers_changed  = 0;
5586   d->clip_changed     = 0;
5587   d->extents_changed  = 0;
5588   d->faces_changed    = 0;
5589   d->frame_changed    = 0;
5590   d->glyphs_changed   = 0;
5591   d->subwindows_changed   = 0;
5592   d->icon_changed     = 0;
5593   d->menubar_changed  = 0;
5594   d->modeline_changed = 0;
5595   d->point_changed    = 0;
5596   d->toolbar_changed  = 0;
5597   d->windows_changed  = 0;
5598   d->windows_structure_changed = 0;
5599
5600   if (!size_change_failed)
5601     d->size_changed = 0;
5602
5603   return 0;
5604 }
5605
5606 static Lisp_Object
5607 restore_profiling_redisplay_flag (Lisp_Object val)
5608 {
5609   profiling_redisplay_flag = XINT (val);
5610   return Qnil;
5611 }
5612
5613 /* Ensure that all windows on all frames on all devices are displaying
5614    the current contents of their respective buffers. */
5615
5616 static void
5617 redisplay_without_hooks (void)
5618 {
5619   Lisp_Object devcons, concons;
5620   int size_change_failed = 0;
5621   int count = specpdl_depth ();
5622
5623   if (profiling_active)
5624     {
5625       record_unwind_protect (restore_profiling_redisplay_flag,
5626                              make_int (profiling_redisplay_flag));
5627       profiling_redisplay_flag = 1;
5628     }
5629
5630   if (asynch_device_change_pending)
5631     handle_asynch_device_change ();
5632
5633   if (!buffers_changed && !clip_changed     && !extents_changed &&
5634       !faces_changed   && !frame_changed    && !icon_changed    &&
5635       !menubar_changed && !modeline_changed && !point_changed   &&
5636       !size_changed    && !toolbar_changed  && !windows_changed &&
5637       !glyphs_changed  && !subwindows_changed &&
5638       !windows_structure_changed && !disable_preemption &&
5639       preemption_count < max_preempts)
5640     goto done;
5641
5642   DEVICE_LOOP_NO_BREAK (devcons, concons)
5643     {
5644       struct device *d = XDEVICE (XCAR (devcons));
5645       int preempted;
5646
5647       if (d->buffers_changed  || d->clip_changed     || d->extents_changed ||
5648           d->faces_changed    || d->frame_changed    || d->icon_changed    ||
5649           d->menubar_changed  || d->modeline_changed || d->point_changed   ||
5650           d->size_changed     || d->toolbar_changed  || d->windows_changed ||
5651           d->windows_structure_changed ||
5652           d->glyphs_changed || d->subwindows_changed)
5653         {
5654           preempted = redisplay_device (d);
5655
5656           if (preempted)
5657             {
5658               preemption_count++;
5659               RESET_CHANGED_SET_FLAGS;
5660               goto done;
5661             }
5662
5663           /* See comment in redisplay_device. */
5664           if (d->size_changed)
5665             size_change_failed = 1;
5666         }
5667     }
5668   preemption_count = 0;
5669
5670   /* Mark redisplay as accurate */
5671   buffers_changed  = 0;
5672   clip_changed     = 0;
5673   extents_changed  = 0;
5674   frame_changed    = 0;
5675   glyphs_changed   = 0;
5676   subwindows_changed   = 0;
5677   icon_changed     = 0;
5678   menubar_changed  = 0;
5679   modeline_changed = 0;
5680   point_changed    = 0;
5681   toolbar_changed  = 0;
5682   windows_changed  = 0;
5683   windows_structure_changed = 0;
5684   RESET_CHANGED_SET_FLAGS;
5685
5686   if (faces_changed)
5687     {
5688       mark_all_faces_as_clean ();
5689       faces_changed = 0;
5690     }
5691
5692   if (!size_change_failed)
5693     size_changed = 0;
5694
5695   reset_buffer_changes ();
5696
5697  done:
5698   unbind_to (count, Qnil);
5699 }
5700
5701 void
5702 redisplay (void)
5703 {
5704   if (last_display_warning_tick != display_warning_tick &&
5705       !inhibit_warning_display)
5706     {
5707       /* If an error occurs during this function, oh well.
5708          If we report another warning, we could get stuck in an
5709          infinite loop reporting warnings. */
5710       call0_trapping_errors (0, Qdisplay_warning_buffer);
5711       last_display_warning_tick = display_warning_tick;
5712     }
5713   /* The run_hook_trapping_errors functions are smart enough not
5714      to do any evalling if the hook function is empty, so there
5715      should not be any significant time loss.  All places in the
5716      C code that call redisplay() are prepared to handle GCing,
5717      so we should be OK. */
5718 #ifndef INHIBIT_REDISPLAY_HOOKS
5719   run_hook_trapping_errors ("Error in pre-redisplay-hook",
5720                             Qpre_redisplay_hook);
5721 #endif /* INHIBIT_REDISPLAY_HOOKS */
5722
5723   redisplay_without_hooks ();
5724
5725 #ifndef INHIBIT_REDISPLAY_HOOKS
5726   run_hook_trapping_errors ("Error in post-redisplay-hook",
5727                             Qpost_redisplay_hook);
5728 #endif /* INHIBIT_REDISPLAY_HOOKS */
5729 }
5730
5731
5732 static char window_line_number_buf[32];
5733
5734 /* Efficiently determine the window line number, and return a pointer
5735    to its printed representation.  Do this regardless of whether
5736    line-number-mode is on.  The first line in the buffer is counted as
5737    1.  If narrowing is in effect, the lines are counted from the
5738    beginning of the visible portion of the buffer.  */
5739 static char *
5740 window_line_number (struct window *w, int type)
5741 {
5742   struct device *d = XDEVICE (XFRAME (w->frame)->device);
5743   struct buffer *b = XBUFFER (w->buffer);
5744   /* Be careful in the order of these tests. The first clause will
5745      fail if DEVICE_SELECTED_FRAME == Qnil (since w->frame cannot be).
5746      This can occur when the frame title is computed really early */
5747   Bufpos pos =
5748     ((EQ(DEVICE_SELECTED_FRAME(d), w->frame) &&
5749        (w == XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame(d)))) &&
5750       EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5751       XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d )
5752      ? BUF_PT (b)
5753      : marker_position (w->pointm[type]));
5754   EMACS_INT line;
5755
5756   line = buffer_line_number (b, pos, 1);
5757
5758   long_to_string (window_line_number_buf, line + 1);
5759
5760   return window_line_number_buf;
5761 }
5762
5763
5764 /* Given a character representing an object in a modeline
5765    specification, return a string (stored into the global array
5766    `mode_spec_bufbyte_string') with the information that object
5767    represents.
5768
5769    This function is largely unchanged from previous versions of the
5770    redisplay engine.
5771
5772    Warning! This code is also used for frame titles and can be called
5773    very early in the device/frame update process!  JV
5774 */
5775
5776 static void
5777 decode_mode_spec (struct window *w, Emchar spec, int type)
5778 {
5779   Lisp_Object obj = Qnil;
5780   CONST char *str = NULL;
5781   struct buffer *b = XBUFFER (w->buffer);
5782
5783   Dynarr_reset (mode_spec_bufbyte_string);
5784
5785   switch (spec)
5786     {
5787       /* print buffer name */
5788     case 'b':
5789       obj = b->name;
5790       break;
5791
5792       /* print visited file name */
5793     case 'f':
5794       obj = b->filename;
5795       break;
5796
5797       /* print the current column */
5798     case 'c':
5799       {
5800         Bufpos pt = (w == XWINDOW (Fselected_window (Qnil)))
5801                     ? BUF_PT (b)
5802                     : marker_position (w->pointm[type]);
5803         int col = column_at_point (b, pt, 1) + !!column_number_start_at_one;
5804         char buf[32];
5805
5806         long_to_string (buf, col);
5807
5808         Dynarr_add_many (mode_spec_bufbyte_string,
5809                          (CONST Bufbyte *) buf, strlen (buf));
5810
5811         goto decode_mode_spec_done;
5812       }
5813       /* print the file coding system */
5814     case 'C':
5815 #ifdef FILE_CODING
5816       {
5817         Lisp_Object codesys = b->buffer_file_coding_system;
5818         /* Be very careful here not to get an error. */
5819         if (NILP (codesys) || SYMBOLP (codesys) || CODING_SYSTEMP (codesys))
5820           {
5821             codesys = Ffind_coding_system (codesys);
5822             if (CODING_SYSTEMP (codesys))
5823               obj = XCODING_SYSTEM_MNEMONIC (codesys);
5824           }
5825       }
5826 #endif /* FILE_CODING */
5827       break;
5828
5829       /* print the current line number */
5830     case 'l':
5831       str = window_line_number (w, type);
5832       break;
5833
5834       /* print value of mode-name (obsolete) */
5835     case 'm':
5836       obj = b->mode_name;
5837       break;
5838
5839       /* print hyphen and frame number, if != 1 */
5840     case 'N':
5841 #ifdef HAVE_TTY
5842       {
5843         struct frame *f = XFRAME (w->frame);
5844         if (FRAME_TTY_P (f) && f->order_count > 1 && f->order_count <= 99999999)
5845           {
5846             /* Naughty, naughty */
5847             char * writable_str = alloca_array (char, 10);
5848             sprintf (writable_str, "-%d", f->order_count);
5849             str = writable_str;
5850           }
5851       }
5852 #endif /* HAVE_TTY */
5853       break;
5854
5855       /* print Narrow if appropriate */
5856     case 'n':
5857       if (BUF_BEGV (b) > BUF_BEG (b)
5858           || BUF_ZV (b) < BUF_Z (b))
5859         str = " Narrow";
5860       break;
5861
5862       /* print %, * or hyphen, if buffer is read-only, modified or neither */
5863     case '*':
5864       str = (!NILP (b->read_only)
5865              ? "%"
5866              : ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5867                 ? "*"
5868                 : "-"));
5869       break;
5870
5871       /* print * or hyphen -- XEmacs change to allow a buffer to be
5872          read-only but still indicate whether it is modified. */
5873     case '+':
5874       str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5875              ? "*"
5876              : (!NILP (b->read_only)
5877                 ? "%"
5878                 : "-"));
5879       break;
5880
5881       /* #### defined in 19.29 decode_mode_spec, but not in
5882          modeline-format doc string. */
5883       /* This differs from %* in that it ignores read-only-ness. */
5884     case '&':
5885       str = ((BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
5886              ? "*"
5887              : "-");
5888       break;
5889
5890       /* print process status */
5891     case 's':
5892       obj = Fget_buffer_process (w->buffer);
5893       if (NILP (obj))
5894         str = GETTEXT ("no process");
5895       else
5896         obj = Fsymbol_name (Fprocess_status (obj));
5897       break;
5898
5899       /* Print name of selected frame.  */
5900     case 'S':
5901       obj = XFRAME (w->frame)->name;
5902       break;
5903
5904       /* indicate TEXT or BINARY */
5905     case 't':
5906       /* #### NT does not use this any more. Now what? */
5907       str = "T";
5908       break;
5909
5910       /* print percent of buffer above top of window, or Top, Bot or All */
5911     case 'p':
5912     {
5913       Bufpos pos = marker_position (w->start[type]);
5914       Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5915
5916       /* This had better be while the desired lines are being done. */
5917       if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b))
5918         {
5919           if (pos <= BUF_BEGV (b))
5920             str = "All";
5921           else
5922             str = "Bottom";
5923         }
5924       else if (pos <= BUF_BEGV (b))
5925         str = "Top";
5926       else
5927         {
5928           /* This hard limit is ok since the string it will hold has a
5929              fixed maximum length of 3.  But just to be safe... */
5930           char buf[10];
5931
5932           total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
5933
5934           /* We can't normally display a 3-digit number, so get us a
5935              2-digit number that is close. */
5936           if (total == 100)
5937             total = 99;
5938
5939           sprintf (buf, "%2d%%", total);
5940           Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5941                            strlen (buf));
5942
5943           goto decode_mode_spec_done;
5944         }
5945       break;
5946     }
5947
5948     /* print percent of buffer above bottom of window, perhaps plus
5949        Top, or print Bottom or All */
5950     case 'P':
5951     {
5952       Bufpos toppos = marker_position (w->start[type]);
5953       Bufpos botpos = BUF_Z (b) - w->window_end_pos[type];
5954       Charcount total = BUF_ZV (b) - BUF_BEGV (b);
5955
5956       /* botpos is only accurate as of the last redisplay, so we can
5957          only treat it as a hint.  In particular, after erase-buffer,
5958          botpos may be negative. */
5959       if (botpos < toppos)
5960         botpos = toppos;
5961
5962       if (botpos >= BUF_ZV (b))
5963         {
5964           if (toppos <= BUF_BEGV (b))
5965             str = "All";
5966           else
5967             str = "Bottom";
5968         }
5969       else
5970         {
5971           /* This hard limit is ok since the string it will hold has a
5972              fixed maximum length of around 6.  But just to be safe... */
5973           char buf[10];
5974
5975           total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
5976
5977           /* We can't normally display a 3-digit number, so get us a
5978              2-digit number that is close. */
5979           if (total == 100)
5980             total = 99;
5981
5982           if (toppos <= BUF_BEGV (b))
5983             sprintf (buf, "Top%2d%%", total);
5984           else
5985             sprintf (buf, "%2d%%", total);
5986
5987           Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf,
5988                            strlen (buf));
5989
5990           goto decode_mode_spec_done;
5991         }
5992       break;
5993     }
5994
5995     /* print % */
5996     case '%':
5997       str = "%";
5998       break;
5999
6000       /* print one [ for each recursive editing level. */
6001     case '[':
6002     {
6003       int i;
6004
6005       if (command_loop_level > 5)
6006         {
6007           str = "[[[... ";
6008           break;
6009         }
6010
6011       for (i = 0; i < command_loop_level; i++)
6012         Dynarr_add (mode_spec_bufbyte_string, '[');
6013
6014       goto decode_mode_spec_done;
6015     }
6016
6017     /* print one ] for each recursive editing level. */
6018     case ']':
6019     {
6020       int i;
6021
6022       if (command_loop_level > 5)
6023         {
6024           str = "...]]]";
6025           break;
6026         }
6027
6028       for (i = 0; i < command_loop_level; i++)
6029         Dynarr_add (mode_spec_bufbyte_string, ']');
6030
6031       goto decode_mode_spec_done;
6032     }
6033
6034     /* print infinitely many dashes -- handle at top level now */
6035     case '-':
6036       break;
6037
6038     }
6039
6040   if (STRINGP (obj))
6041     Dynarr_add_many (mode_spec_bufbyte_string,
6042                      XSTRING_DATA   (obj),
6043                      XSTRING_LENGTH (obj));
6044   else if (str)
6045     Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) str, strlen (str));
6046
6047 decode_mode_spec_done:
6048   Dynarr_add (mode_spec_bufbyte_string, '\0');
6049 }
6050
6051 /* Given a display line, free all of its data structures. */
6052
6053 static void
6054 free_display_line (struct display_line *dl)
6055 {
6056   int block;
6057
6058   if (dl->display_blocks)
6059     {
6060       for (block = 0; block < Dynarr_largest (dl->display_blocks); block++)
6061         {
6062           struct display_block *db = Dynarr_atp (dl->display_blocks, block);
6063
6064           Dynarr_free (db->runes);
6065         }
6066
6067       Dynarr_free (dl->display_blocks);
6068       dl->display_blocks = NULL;
6069     }
6070
6071   if (dl->left_glyphs)
6072     {
6073       Dynarr_free (dl->left_glyphs);
6074       dl->left_glyphs = NULL;
6075     }
6076
6077   if (dl->right_glyphs)
6078     {
6079       Dynarr_free (dl->right_glyphs);
6080       dl->right_glyphs = NULL;
6081     }
6082 }
6083
6084
6085 /* Given an array of display lines, free them and all data structures
6086    contained within them. */
6087
6088 static void
6089 free_display_lines (display_line_dynarr *dla)
6090 {
6091   int line;
6092
6093   for (line = 0; line < Dynarr_largest (dla); line++)
6094     {
6095       free_display_line (Dynarr_atp (dla, line));
6096     }
6097
6098   Dynarr_free (dla);
6099 }
6100
6101 /* Call internal free routine for each set of display lines. */
6102
6103 void
6104 free_display_structs (struct window_mirror *mir)
6105 {
6106   if (mir->current_display_lines)
6107     {
6108       free_display_lines (mir->current_display_lines);
6109       mir->current_display_lines = 0;
6110     }
6111
6112   if (mir->desired_display_lines)
6113     {
6114       free_display_lines (mir->desired_display_lines);
6115       mir->desired_display_lines = 0;
6116     }
6117 }
6118 \f
6119
6120 static void
6121 mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object))
6122 {
6123   if (gba)
6124     {
6125       glyph_block *gb = Dynarr_atp (gba, 0);
6126       glyph_block *gb_last = Dynarr_atp (gba, Dynarr_length (gba));
6127
6128       for (; gb < gb_last; gb++)
6129         {
6130           if (!NILP (gb->glyph))
6131             markobj (gb->glyph);
6132           if (!NILP (gb->extent))
6133             markobj (gb->extent);
6134         }
6135     }
6136 }
6137
6138 static void
6139 mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object))
6140 {
6141   display_line *dl = Dynarr_atp (dla, 0);
6142   display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla));
6143
6144   for (; dl < dl_last; dl++)
6145     {
6146       display_block_dynarr *dba = dl->display_blocks;
6147       display_block *db = Dynarr_atp (dba, 0);
6148       display_block *db_last = Dynarr_atp (dba, Dynarr_length (dba));
6149
6150       for (; db < db_last; db++)
6151         {
6152           rune_dynarr *ra = db->runes;
6153           rune *r = Dynarr_atp (ra, 0);
6154           rune *r_last = Dynarr_atp (ra, Dynarr_length (ra));
6155
6156           for (; r < r_last; r++)
6157             {
6158               if (r->type == RUNE_DGLYPH)
6159                 {
6160                   if (!NILP (r->object.dglyph.glyph))
6161                     markobj (r->object.dglyph.glyph);
6162                   if (!NILP (r->object.dglyph.extent))
6163                     markobj (r->object.dglyph.extent);
6164                 }
6165             }
6166         }
6167
6168       mark_glyph_block_dynarr (dl->left_glyphs,  markobj);
6169       mark_glyph_block_dynarr (dl->right_glyphs, markobj);
6170     }
6171 }
6172
6173 static void
6174 mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object))
6175 {
6176   mark_redisplay_structs (mir->current_display_lines, markobj);
6177   mark_redisplay_structs (mir->desired_display_lines, markobj);
6178
6179   if (mir->next)
6180     mark_window_mirror (mir->next, markobj);
6181
6182   if (mir->hchild)
6183     mark_window_mirror (mir->hchild, markobj);
6184   else if (mir->vchild)
6185     mark_window_mirror (mir->vchild, markobj);
6186 }
6187
6188 void
6189 mark_redisplay (void (*markobj)(Lisp_Object))
6190 {
6191   Lisp_Object frmcons, devcons, concons;
6192
6193   FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6194     {
6195       struct frame *f = XFRAME (XCAR (frmcons));
6196       update_frame_window_mirror (f);
6197       mark_window_mirror (f->root_mirror, markobj);
6198     }
6199 }
6200 \f
6201 /*****************************************************************************
6202  Line Start Cache Description and Rationale
6203
6204  The traditional scrolling code in Emacs breaks in a variable height world.
6205  It depends on the key assumption that the number of lines that can be
6206  displayed at any given time is fixed.  This led to a complete separation
6207  of the scrolling code from the redisplay code.  In order to fully support
6208  variable height lines, the scrolling code must actually be tightly
6209  integrated with redisplay.  Only redisplay can determine how many lines
6210  will be displayed on a screen for any given starting point.
6211
6212  What is ideally wanted is a complete list of the starting buffer position
6213  for every possible display line of a buffer along with the height of that
6214  display line.  Maintaining such a full list would be very expensive.  We
6215  settle for having it include information for all areas which we happen to
6216  generate anyhow (i.e. the region currently being displayed) and for those
6217  areas we need to work with.
6218
6219  In order to ensure that the cache accurately represents what redisplay
6220  would actually show, it is necessary to invalidate it in many situations.
6221  If the buffer changes, the starting positions may no longer be correct.
6222  If a face or an extent has changed then the line heights may have altered.
6223  These events happen frequently enough that the cache can end up being
6224  constantly disabled.  With this potentially constant invalidation when is
6225  the cache ever useful?
6226
6227  Even if the cache is invalidated before every single usage, it is
6228  necessary.  Scrolling often requires knowledge about display lines which
6229  are actually above or below the visible region.  The cache provides a
6230  convenient light-weight method of storing this information for multiple
6231  display regions.  This knowledge is necessary for the scrolling code to
6232  always obey the First Golden Rule of Redisplay.
6233
6234  If the cache already contains all of the information that the scrolling
6235  routines happen to need so that it doesn't have to go generate it, then we
6236  are able to obey the Third Golden Rule of Redisplay.  The first thing we
6237  do to help out the cache is to always add the displayed region.  This
6238  region had to be generated anyway, so the cache ends up getting the
6239  information basically for free.  In those cases where a user is simply
6240  scrolling around viewing a buffer there is a high probability that this is
6241  sufficient to always provide the needed information.  The second thing we
6242  can do is be smart about invalidating the cache.
6243
6244  TODO -- Be smart about invalidating the cache.  Potential places:
6245
6246  + Insertions at end-of-line which don't cause line-wraps do not alter the
6247    starting positions of any display lines.  These types of buffer
6248    modifications should not invalidate the cache.  This is actually a large
6249    optimization for redisplay speed as well.
6250
6251  + Buffer modifications frequently only affect the display of lines at and
6252    below where they occur.  In these situations we should only invalidate
6253    the part of the cache starting at where the modification occurs.
6254
6255  In case you're wondering, the Second Golden Rule of Redisplay is not
6256  applicable.
6257  ****************************************************************************/
6258
6259 /* This will get used quite a bit so we don't want to be constantly
6260    allocating and freeing it. */
6261 line_start_cache_dynarr *internal_cache;
6262
6263 /* Makes internal_cache represent the TYPE display structs and only
6264    the TYPE display structs. */
6265
6266 static void
6267 update_internal_cache_list (struct window *w, int type)
6268 {
6269   int line;
6270   display_line_dynarr *dla = window_display_lines (w, type);
6271
6272   Dynarr_reset (internal_cache);
6273   for (line = 0; line < Dynarr_length (dla); line++)
6274     {
6275       struct display_line *dl = Dynarr_atp (dla, line);
6276
6277       if (dl->modeline)
6278         continue;
6279       else
6280         {
6281           struct line_start_cache lsc;
6282           
6283           lsc.start = dl->bufpos;
6284           lsc.end = dl->end_bufpos;
6285           lsc.height = dl->ascent + dl->descent;
6286
6287           Dynarr_add (internal_cache, lsc);
6288         }
6289     }
6290 }
6291
6292 /* Reset the line cache if necessary.  This should be run at the
6293    beginning of any function which access the cache. */
6294
6295 static void
6296 validate_line_start_cache (struct window *w)
6297 {
6298   struct buffer *b = XBUFFER (w->buffer);
6299   struct frame *f = XFRAME (w->frame);
6300
6301   if (!w->line_cache_validation_override)
6302     {
6303       /* f->extents_changed used to be in here because extent face and
6304          size changes can cause text shifting.  However, the extent
6305          covering the region is constantly having its face set and
6306          priority altered by the mouse code.  This means that the line
6307          start cache is constantly being invalidated.  This is bad
6308          since the mouse code also triggers heavy usage of the cache.
6309          Since it is an unlikely that f->extents being changed
6310          indicates that the cache really needs to be updated and if it
6311          does redisplay will catch it pretty quickly we no longer
6312          invalidate the cache if it is set.  This greatly speeds up
6313          dragging out regions with the mouse. */
6314       if (XINT (w->line_cache_last_updated) < BUF_MODIFF (b)
6315           || f->faces_changed
6316           || f->clip_changed)
6317         {
6318           Dynarr_reset (w->line_start_cache);
6319         }
6320     }
6321 }
6322
6323 /* Return the very first buffer position contained in the given
6324    window's cache, or -1 if the cache is empty.  Assumes that the
6325    cache is valid. */
6326
6327 static Bufpos
6328 line_start_cache_start (struct window *w)
6329 {
6330   line_start_cache_dynarr *cache = w->line_start_cache;
6331
6332   if (!Dynarr_length (cache))
6333     return -1;
6334   else
6335     return Dynarr_atp (cache, 0)->start;
6336 }
6337
6338 /* Return the very last buffer position contained in the given
6339    window's cache, or -1 if the cache is empty.  Assumes that the
6340    cache is valid. */
6341
6342 static Bufpos
6343 line_start_cache_end (struct window *w)
6344 {
6345   line_start_cache_dynarr *cache = w->line_start_cache;
6346
6347   if (!Dynarr_length (cache))
6348     return -1;
6349   else
6350     return Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
6351 }
6352
6353 /* Return the index of the line POINT is contained within in window
6354    W's line start cache.  It will enlarge the cache or move the cache
6355    window in order to have POINT be present in the cache.  MIN_PAST is
6356    a guarantee of the number of entries in the cache present on either
6357    side of POINT (unless a buffer boundary is hit).  If MIN_PAST is -1
6358    then it will be treated as 0, but the cache window will not be
6359    allowed to shift.  Returns -1 if POINT cannot be found in the cache
6360    for any reason. */
6361
6362 int
6363 point_in_line_start_cache (struct window *w, Bufpos point, int min_past)
6364 {
6365   struct buffer *b = XBUFFER (w->buffer);
6366   line_start_cache_dynarr *cache = w->line_start_cache;
6367   unsigned int top, bottom, pos;
6368
6369   validate_line_start_cache (w);
6370   w->line_cache_validation_override++;
6371
6372   /* Let functions pass in negative values, but we still treat -1
6373      specially. */
6374   /* #### bogosity alert */
6375   if (min_past < 0 && min_past != -1)
6376     min_past = -min_past;
6377
6378   if (!Dynarr_length (cache) || line_start_cache_start (w) > point
6379       || line_start_cache_end (w) < point)
6380     {
6381       int loop;
6382       int win_char_height = window_char_height (w, 1);
6383
6384       /* Occasionally we get here with a 0 height
6385          window. find_next_newline_no_quit will abort if we pass it a
6386          count of 0 so handle that case. */
6387       if (!win_char_height)
6388         win_char_height = 1;
6389
6390       if (!Dynarr_length (cache))
6391         {
6392           Bufpos from = find_next_newline_no_quit (b, point, -1);
6393           Bufpos to = find_next_newline_no_quit (b, from, win_char_height);
6394
6395           update_line_start_cache (w, from, to, point, 0);
6396
6397           if (!Dynarr_length (cache))
6398             {
6399               w->line_cache_validation_override--;
6400               return -1;
6401             }
6402         }
6403
6404       assert (Dynarr_length (cache));
6405
6406       loop = 0;
6407       while (line_start_cache_start (w) > point
6408              && (loop < cache_adjustment || min_past == -1))
6409         {
6410           Bufpos from, to;
6411
6412           from = line_start_cache_start (w);
6413           if (from <= BUF_BEGV (b))
6414             break;
6415
6416           from = find_next_newline_no_quit (b, from, -win_char_height);
6417           to = line_start_cache_end (w);
6418
6419           update_line_start_cache (w, from, to, point, 0);
6420           loop++;
6421         }
6422
6423       if (line_start_cache_start (w) > point)
6424         {
6425           Bufpos from, to;
6426
6427           from = find_next_newline_no_quit (b, point, -1);
6428           if (from >= BUF_ZV (b))
6429             {
6430               to = find_next_newline_no_quit (b, from, -win_char_height);
6431               from = to;
6432               to = BUF_ZV (b);
6433             }
6434           else
6435             to = find_next_newline_no_quit (b, from, win_char_height);
6436
6437           update_line_start_cache (w, from, to, point, 0);
6438         }
6439
6440       loop = 0;
6441       while (line_start_cache_end (w) < point
6442              && (loop < cache_adjustment || min_past == -1))
6443         {
6444           Bufpos from, to;
6445
6446           to = line_start_cache_end (w);
6447           if (to >= BUF_ZV (b))
6448             break;
6449
6450           from = line_start_cache_end (w);
6451           to = find_next_newline_no_quit (b, from, win_char_height);
6452
6453           update_line_start_cache (w, from, to, point, 0);
6454           loop++;
6455         }
6456
6457       if (line_start_cache_end (w) < point)
6458         {
6459           Bufpos from, to;
6460
6461           from = find_next_newline_no_quit (b, point, -1);
6462           if (from >= BUF_ZV (b))
6463             {
6464               to = find_next_newline_no_quit (b, from, -win_char_height);
6465               from = to;
6466               to = BUF_ZV (b);
6467             }
6468           else
6469             to = find_next_newline_no_quit (b, from, win_char_height);
6470
6471           update_line_start_cache (w, from, to, point, 0);
6472         }
6473     }
6474
6475   assert (Dynarr_length (cache));
6476
6477   if (min_past == -1)
6478     min_past = 0;
6479
6480   /* This could happen if the buffer is narrowed. */
6481   if (line_start_cache_start (w) > point
6482       || line_start_cache_end (w) < point)
6483     {
6484       w->line_cache_validation_override--;
6485       return -1;
6486     }
6487
6488 find_point_loop:
6489
6490   top = Dynarr_length (cache) - 1;
6491   bottom = 0;
6492
6493   while (1)
6494     {
6495       unsigned int new_pos;
6496       Bufpos start, end;
6497
6498       pos = (bottom + top + 1) >> 1;
6499       start = Dynarr_atp (cache, pos)->start;
6500       end = Dynarr_atp (cache, pos)->end;
6501
6502       if (point >= start && point <= end)
6503         {
6504           if (pos < min_past && line_start_cache_start (w) > BUF_BEGV (b))
6505             {
6506               Bufpos from =
6507                 find_next_newline_no_quit (b, line_start_cache_start (w),
6508                                            -min_past - 1);
6509               Bufpos to = line_start_cache_end (w);
6510
6511               update_line_start_cache (w, from, to, point, 0);
6512               goto find_point_loop;
6513             }
6514           else if ((Dynarr_length (cache) - pos - 1) < min_past
6515                    && line_start_cache_end (w) < BUF_ZV (b))
6516             {
6517               Bufpos from = line_start_cache_end (w);
6518               Bufpos to = find_next_newline_no_quit (b, from,
6519                                                      (min_past
6520                                                       ? min_past
6521                                                       : 1));
6522
6523               update_line_start_cache (w, from, to, point, 0);
6524               goto find_point_loop;
6525             }
6526           else
6527             {
6528               w->line_cache_validation_override--;
6529               return pos;
6530             }
6531         }
6532       else if (point > end)
6533         bottom = pos + 1;
6534       else if (point < start)
6535         top = pos - 1;
6536       else
6537         abort ();
6538
6539       new_pos = (bottom + top + 1) >> 1;
6540       if (pos == new_pos)
6541         {
6542           w->line_cache_validation_override--;
6543           return -1;
6544         }
6545     }
6546 }
6547
6548 /* Return a boolean indicating if POINT would be visible in window W
6549    if display of the window was to begin at STARTP. */
6550
6551 int
6552 point_would_be_visible (struct window *w, Bufpos startp, Bufpos point)
6553 {
6554   struct buffer *b = XBUFFER (w->buffer);
6555   int pixpos = 0;
6556   int bottom = WINDOW_TEXT_HEIGHT (w);
6557   int start_elt;
6558
6559   /* If point is before the intended start it obviously can't be visible. */
6560   if (point < startp)
6561     return 0;
6562
6563   /* If point or start are not in the accessible buffer range, then
6564      fail. */
6565   if (startp < BUF_BEGV (b) || startp > BUF_ZV (b)
6566       || point < BUF_BEGV (b) || point > BUF_ZV (b))
6567     return 0;
6568
6569   validate_line_start_cache (w);
6570   w->line_cache_validation_override++;
6571
6572   start_elt = point_in_line_start_cache (w, startp, 0);
6573   if (start_elt == -1)
6574     {
6575       w->line_cache_validation_override--;
6576       return 0;
6577     }
6578
6579   assert (line_start_cache_start (w) <= startp
6580           && line_start_cache_end (w) >= startp);
6581
6582   while (1)
6583     {
6584       int height;
6585
6586       /* Expand the cache if necessary. */
6587       if (start_elt == Dynarr_length (w->line_start_cache))
6588         {
6589           Bufpos old_startp =
6590             Dynarr_atp (w->line_start_cache, start_elt - 1)->start;
6591
6592           start_elt = point_in_line_start_cache (w, old_startp,
6593                                                  window_char_height (w, 0));
6594
6595           /* We've already actually processed old_startp, so increment
6596              immediately. */
6597           start_elt++;
6598
6599           /* If this happens we didn't add any extra elements.  Bummer. */
6600           if (start_elt == Dynarr_length (w->line_start_cache))
6601             {
6602               w->line_cache_validation_override--;
6603               return 0;
6604             }
6605         }
6606
6607       height = Dynarr_atp (w->line_start_cache, start_elt)->height;
6608
6609       if (pixpos + height > bottom)
6610         {
6611           if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6612             {
6613               w->line_cache_validation_override--;
6614               return 0;
6615             }
6616         }
6617
6618       pixpos += height;
6619       if (point <= Dynarr_atp (w->line_start_cache, start_elt)->end)
6620         {
6621           w->line_cache_validation_override--;
6622           return 1;
6623         }
6624
6625       start_elt++;
6626     }
6627 }
6628
6629 /* For the given window W, if display starts at STARTP, what will be
6630    the buffer position at the beginning or end of the last line
6631    displayed.  The end of the last line is also know as the window end
6632    position.
6633
6634    #### With a little work this could probably be reworked as just a
6635    call to start_with_line_at_pixpos. */
6636
6637 static Bufpos
6638 start_end_of_last_line (struct window *w, Bufpos startp, int end)
6639 {
6640   struct buffer *b = XBUFFER (w->buffer);
6641   line_start_cache_dynarr *cache = w->line_start_cache;
6642   int pixpos = 0;
6643   int bottom = WINDOW_TEXT_HEIGHT (w);
6644   Bufpos cur_start;
6645   int start_elt;
6646
6647   validate_line_start_cache (w);
6648   w->line_cache_validation_override++;
6649
6650   if (startp < BUF_BEGV (b))
6651     startp = BUF_BEGV (b);
6652   else if (startp > BUF_ZV (b))
6653     startp = BUF_ZV (b);
6654   cur_start = startp;
6655
6656   start_elt = point_in_line_start_cache (w, cur_start, 0);
6657   if (start_elt == -1)
6658     abort ();   /* this had better never happen */
6659
6660   while (1)
6661     {
6662       int height = Dynarr_atp (cache, start_elt)->height;
6663
6664       cur_start = Dynarr_atp (cache, start_elt)->start;
6665
6666       if (pixpos + height > bottom)
6667         {
6668           /* Adjust for any possible clip. */
6669           if (bottom - pixpos < VERTICAL_CLIP (w, 0))
6670             start_elt--;
6671
6672           if (start_elt < 0)
6673             {
6674               w->line_cache_validation_override--;
6675               if (end)
6676                 return BUF_ZV (b);
6677               else
6678                 return BUF_BEGV (b);
6679             }
6680           else
6681             {
6682               w->line_cache_validation_override--;
6683               if (end)
6684                 return Dynarr_atp (cache, start_elt)->end;
6685               else
6686                 return Dynarr_atp (cache, start_elt)->start;
6687             }
6688         }
6689
6690       pixpos += height;
6691       start_elt++;
6692       if (start_elt == Dynarr_length (cache))
6693         {
6694           Bufpos from = line_start_cache_end (w);
6695           int win_char_height = window_char_height (w, 0);
6696           Bufpos to = find_next_newline_no_quit (b, from,
6697                                                  (win_char_height
6698                                                   ? win_char_height
6699                                                   : 1));
6700
6701           /* We've hit the end of the bottom so that's what it is. */
6702           if (from >= BUF_ZV (b))
6703             {
6704               w->line_cache_validation_override--;
6705               return BUF_ZV (b);
6706             }
6707
6708           update_line_start_cache (w, from, to, BUF_PT (b), 0);
6709
6710           /* Updating the cache invalidates any current indexes. */
6711           start_elt = point_in_line_start_cache (w, cur_start, -1) + 1;
6712         }
6713     }
6714 }
6715
6716 /* For the given window W, if display starts at STARTP, what will be
6717    the buffer position at the beginning of the last line displayed. */
6718
6719 Bufpos
6720 start_of_last_line (struct window *w, Bufpos startp)
6721 {
6722   return start_end_of_last_line (w, startp, 0);
6723 }
6724
6725 /* For the given window W, if display starts at STARTP, what will be
6726    the buffer position at the end of the last line displayed.  This is
6727    also know as the window end position. */
6728
6729 Bufpos
6730 end_of_last_line (struct window *w, Bufpos startp)
6731 {
6732   return start_end_of_last_line (w, startp, 1);
6733 }
6734
6735 /* For window W, what does the starting position have to be so that
6736    the line containing POINT will cover pixel position PIXPOS. */
6737
6738 Bufpos
6739 start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos)
6740 {
6741   struct buffer *b = XBUFFER (w->buffer);
6742   int cur_elt;
6743   Bufpos cur_pos, prev_pos = point;
6744   int point_line_height;
6745   int pixheight = pixpos - WINDOW_TEXT_TOP (w);
6746
6747   validate_line_start_cache (w);
6748   w->line_cache_validation_override++;
6749
6750   cur_elt = point_in_line_start_cache (w, point, 0);
6751   /* #### See comment in update_line_start_cache about big minibuffers. */
6752   if (cur_elt < 0)
6753     {
6754       w->line_cache_validation_override--;
6755       return point;
6756     }
6757
6758   point_line_height = Dynarr_atp (w->line_start_cache, cur_elt)->height;
6759
6760   while (1)
6761     {
6762       cur_pos = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6763
6764       pixheight -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6765
6766       /* Do not take into account the value of vertical_clip here.
6767          That is the responsibility of the calling functions. */
6768       if (pixheight < 0)
6769         {
6770           w->line_cache_validation_override--;
6771           if (-pixheight > point_line_height)
6772             /* We can't make the target line cover pixpos, so put it
6773                above pixpos.  That way it will at least be visible. */
6774             return prev_pos;
6775           else
6776             return cur_pos;
6777         }
6778
6779       cur_elt--;
6780       if (cur_elt < 0)
6781         {
6782           Bufpos from, to;
6783           int win_char_height;
6784
6785           if (cur_pos <= BUF_BEGV (b))
6786             {
6787               w->line_cache_validation_override--;
6788               return BUF_BEGV (b);
6789             }
6790
6791           win_char_height = window_char_height (w, 0);
6792           if (!win_char_height)
6793             win_char_height = 1;
6794
6795           from = find_next_newline_no_quit (b, cur_pos, -win_char_height);
6796           to = line_start_cache_end (w);
6797           update_line_start_cache (w, from, to, point, 0);
6798
6799           cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1;
6800           assert (cur_elt >= 0);
6801         }
6802       prev_pos = cur_pos;
6803     }
6804 }
6805
6806 /* For window W, what does the starting position have to be so that
6807    the line containing point is on display line LINE.  If LINE is
6808    positive it is considered to be the number of lines from the top of
6809    the window (0 is the top line).  If it is negative the number is
6810    considered to be the number of lines from the bottom (-1 is the
6811    bottom line). */
6812
6813 Bufpos
6814 start_with_point_on_display_line (struct window *w, Bufpos point, int line)
6815 {
6816   validate_line_start_cache (w);
6817   w->line_cache_validation_override++;
6818
6819   if (line >= 0)
6820     {
6821       int cur_elt = point_in_line_start_cache (w, point, line);
6822
6823       if (cur_elt - line < 0)
6824         cur_elt = 0;            /* Hit the top */
6825       else
6826         cur_elt -= line;
6827
6828       w->line_cache_validation_override--;
6829       return Dynarr_atp (w->line_start_cache, cur_elt)->start;
6830     }
6831   else
6832     {
6833       /* The calculated value of pixpos is correct for the bottom line
6834          or what we want when line is -1.  Therefore we subtract one
6835          because we have already handled one line. */
6836       int new_line = -line - 1;
6837       int cur_elt = point_in_line_start_cache (w, point, new_line);
6838       int pixpos = WINDOW_TEXT_BOTTOM (w);
6839       Bufpos retval, search_point;
6840
6841       /* If scroll_on_clipped_lines is false, the last "visible" line of
6842          the window covers the pixel at WINDOW_TEXT_BOTTOM (w) - 1.
6843          If s_o_c_l is true, then we don't want to count a clipped
6844          line, so back up from the bottom by the height of the line
6845          containing point. */
6846       if (scroll_on_clipped_lines)
6847         pixpos -= Dynarr_atp (w->line_start_cache, cur_elt)->height;
6848       else
6849         pixpos -= 1;
6850
6851       if (cur_elt + new_line >= Dynarr_length (w->line_start_cache))
6852         {
6853           /* Hit the bottom of the buffer. */
6854           int adjustment =
6855             (cur_elt + new_line) - Dynarr_length (w->line_start_cache) + 1;
6856           Lisp_Object window;
6857           int defheight;
6858
6859           XSETWINDOW (window, w);
6860           default_face_height_and_width (window, &defheight, 0);
6861
6862           cur_elt = Dynarr_length (w->line_start_cache) - 1;
6863
6864           pixpos -= (adjustment * defheight);
6865           if (pixpos < WINDOW_TEXT_TOP (w))
6866             pixpos = WINDOW_TEXT_TOP (w);
6867         }
6868       else
6869         cur_elt = cur_elt + new_line;
6870
6871       search_point = Dynarr_atp (w->line_start_cache, cur_elt)->start;
6872
6873       retval = start_with_line_at_pixpos (w, search_point, pixpos);
6874       w->line_cache_validation_override--;
6875       return retval;
6876     }
6877 }
6878
6879 /* This is used to speed up vertical scrolling by caching the known
6880    buffer starting positions for display lines.  This allows the
6881    scrolling routines to avoid costly calls to regenerate_window.  If
6882    NO_REGEN is true then it will only add the values in the DESIRED
6883    display structs which are in the given range.
6884
6885    Note also that the FROM/TO values are minimums.  It is possible
6886    that this function will actually add information outside of the
6887    lines containing those positions.  This can't hurt but it could
6888    possibly help.
6889
6890    #### We currently force the cache to have only 1 contiguous region.
6891    It might help to make the cache a dynarr of caches so that we can
6892    cover more areas.  This might, however, turn out to be a lot of
6893    overhead for too little gain. */
6894
6895 static void
6896 update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
6897                          Bufpos point, int no_regen)
6898 {
6899   struct buffer *b = XBUFFER (w->buffer);
6900   line_start_cache_dynarr *cache = w->line_start_cache;
6901   Bufpos low_bound, high_bound;
6902
6903   validate_line_start_cache (w);
6904   w->line_cache_validation_override++;
6905   updating_line_start_cache = 1;
6906
6907   if (from < BUF_BEGV (b))
6908     from = BUF_BEGV (b);
6909   if (to > BUF_ZV (b))
6910     to = BUF_ZV (b);
6911
6912   if (from > to)
6913     {
6914       updating_line_start_cache = 0;
6915       w->line_cache_validation_override--;
6916       return;
6917     }
6918
6919   if (Dynarr_length (cache))
6920     {
6921       low_bound = line_start_cache_start (w);
6922       high_bound = line_start_cache_end (w);
6923
6924       /* Check to see if the desired range is already in the cache. */
6925       if (from >= low_bound && to <= high_bound)
6926         {
6927           updating_line_start_cache = 0;
6928           w->line_cache_validation_override--;
6929           return;
6930         }
6931
6932       /* Check to make sure that the desired range is adjacent to the
6933          current cache.  If not, invalidate the cache. */
6934       if (to < low_bound || from > high_bound)
6935         {
6936           Dynarr_reset (cache);
6937           low_bound = high_bound = -1;
6938         }
6939     }
6940   else
6941     {
6942       low_bound = high_bound = -1;
6943     }
6944
6945   w->line_cache_last_updated = make_int (BUF_MODIFF (b));
6946
6947   /* This could be integrated into the next two sections, but it is easier
6948      to follow what's going on by having it separate. */
6949   if (no_regen)
6950     {
6951       Bufpos start, end;
6952
6953       update_internal_cache_list (w, DESIRED_DISP);
6954       if (!Dynarr_length (internal_cache))
6955         {
6956           updating_line_start_cache = 0;
6957           w->line_cache_validation_override--;
6958           return;
6959         }
6960
6961       start = Dynarr_atp (internal_cache, 0)->start;
6962       end =
6963         Dynarr_atp (internal_cache, Dynarr_length (internal_cache) - 1)->end;
6964
6965       /* We aren't allowed to generate additional information to fill in
6966          gaps, so if the DESIRED structs don't overlap the cache, reset the
6967          cache. */
6968       if (Dynarr_length (cache))
6969         {
6970           if (end < low_bound || start > high_bound)
6971             Dynarr_reset (cache);
6972
6973           /* #### What should really happen if what we are doing is
6974              extending a line (the last line)? */
6975           if (Dynarr_length (cache) == 1
6976               && Dynarr_length (internal_cache) == 1)
6977             Dynarr_reset (cache);
6978         }
6979
6980       if (!Dynarr_length (cache))
6981         {
6982           Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
6983                            Dynarr_length (internal_cache));
6984           updating_line_start_cache = 0;
6985           w->line_cache_validation_override--;
6986           return;
6987         }
6988
6989       /* An extra check just in case the calling function didn't pass in
6990          the bounds of the DESIRED structs in the first place. */
6991       if (start >= low_bound && end <= high_bound)
6992         {
6993           updating_line_start_cache = 0;
6994           w->line_cache_validation_override--;
6995           return;
6996         }
6997
6998       /* At this point we know that the internal cache partially overlaps
6999          the main cache. */
7000       if (start < low_bound)
7001         {
7002           int ic_elt = Dynarr_length (internal_cache) - 1;
7003           while (ic_elt >= 0)
7004             {
7005               if (Dynarr_atp (internal_cache, ic_elt)->start < low_bound)
7006                 break;
7007               else
7008                 ic_elt--;
7009             }
7010
7011           if (!(ic_elt >= 0))
7012             {
7013               Dynarr_reset (cache);
7014               Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7015                                Dynarr_length (internal_cache));
7016               updating_line_start_cache = 0;
7017               w->line_cache_validation_override--;
7018               return;
7019             }
7020
7021           Dynarr_insert_many_at_start (cache, Dynarr_atp (internal_cache, 0),
7022                               ic_elt + 1);
7023         }
7024
7025       if (end > high_bound)
7026         {
7027           int ic_elt = 0;
7028
7029           while (ic_elt < Dynarr_length (internal_cache))
7030             {
7031               if (Dynarr_atp (internal_cache, ic_elt)->start > high_bound)
7032                 break;
7033               else
7034                 ic_elt++;
7035             }
7036
7037           if (!(ic_elt < Dynarr_length (internal_cache)))
7038             {
7039               Dynarr_reset (cache);
7040               Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7041                                Dynarr_length (internal_cache));
7042               updating_line_start_cache = 0;
7043               w->line_cache_validation_override--;
7044               return;
7045             }
7046
7047           Dynarr_add_many (cache, Dynarr_atp (internal_cache, ic_elt),
7048                            Dynarr_length (internal_cache) - ic_elt);
7049         }
7050
7051       updating_line_start_cache = 0;
7052       w->line_cache_validation_override--;
7053       return;
7054     }
7055
7056   if (!Dynarr_length (cache) || from < low_bound)
7057     {
7058       Bufpos startp = find_next_newline_no_quit (b, from, -1);
7059       int marker = 0;
7060       int old_lb = low_bound;
7061
7062       while (startp < old_lb || low_bound == -1)
7063         {
7064           int ic_elt;
7065           Bufpos new_startp;
7066
7067           regenerate_window (w, startp, point, CMOTION_DISP);
7068           update_internal_cache_list (w, CMOTION_DISP);
7069
7070           /* If this assert is triggered then regenerate_window failed
7071              to layout a single line.  That is not supposed to be
7072              possible because we impose a minimum height on the buffer
7073              and override vertical clip when we are in here. */
7074           /* #### Ah, but it is because the window may temporarily
7075              exist but not have any lines at all if the minibuffer is
7076              real big.  Look into that situation better. */
7077           if (!Dynarr_length (internal_cache))
7078             {
7079               if (old_lb == -1 && low_bound == -1)
7080                 {
7081                   updating_line_start_cache = 0;
7082                   w->line_cache_validation_override--;
7083                   return;
7084                 }
7085
7086               assert (Dynarr_length (internal_cache));
7087             }
7088           assert (startp == Dynarr_atp (internal_cache, 0)->start);
7089
7090           ic_elt = Dynarr_length (internal_cache) - 1;
7091           if (low_bound != -1)
7092             {
7093               while (ic_elt >= 0)
7094                 {
7095                   if (Dynarr_atp (internal_cache, ic_elt)->start < old_lb)
7096                     break;
7097                   else
7098                     ic_elt--;
7099                 }
7100             }
7101           assert (ic_elt >= 0);
7102
7103           new_startp = Dynarr_atp (internal_cache, ic_elt)->end + 1;
7104
7105           /*
7106            * Handle invisible text properly:
7107            * If the last line we're inserting has the same end as the
7108            * line before which it will be added, merge the two lines.
7109            */
7110           if (Dynarr_length (cache)  &&
7111               Dynarr_atp (internal_cache, ic_elt)->end ==
7112               Dynarr_atp (cache, marker)->end)
7113             {
7114               Dynarr_atp (cache, marker)->start
7115                 = Dynarr_atp (internal_cache, ic_elt)->start;
7116               Dynarr_atp (cache, marker)->height
7117                 = Dynarr_atp (internal_cache, ic_elt)->height;
7118               ic_elt--;
7119             }
7120
7121           if (ic_elt >= 0)       /* we still have lines to add.. */
7122             {
7123               Dynarr_insert_many (cache, Dynarr_atp (internal_cache, 0),
7124                                   ic_elt + 1, marker);
7125               marker += (ic_elt + 1);
7126             }
7127
7128           if (startp < low_bound || low_bound == -1)
7129             low_bound = startp;
7130           startp = new_startp;
7131           if (startp > BUF_ZV (b))
7132             {
7133               updating_line_start_cache = 0;
7134               w->line_cache_validation_override--;
7135               return;
7136             }
7137         }
7138     }
7139
7140   assert (Dynarr_length (cache));
7141   assert (from >= low_bound);
7142
7143   /* Readjust the high_bound to account for any changes made while
7144      correcting the low_bound. */
7145   high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7146
7147   if (to > high_bound)
7148     {
7149       Bufpos startp = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end + 1;
7150
7151       do
7152         {
7153           regenerate_window (w, startp, point, CMOTION_DISP);
7154           update_internal_cache_list (w, CMOTION_DISP);
7155
7156           /* See comment above about regenerate_window failing. */
7157           assert (Dynarr_length (internal_cache));
7158
7159           Dynarr_add_many (cache, Dynarr_atp (internal_cache, 0),
7160                            Dynarr_length (internal_cache));
7161           high_bound = Dynarr_atp (cache, Dynarr_length (cache) - 1)->end;
7162           startp = high_bound + 1;
7163         }
7164       while (to > high_bound);
7165     }
7166
7167   updating_line_start_cache = 0;
7168   w->line_cache_validation_override--;
7169   assert (to <= high_bound);
7170 }
7171
7172 \f
7173 /* Given x and y coordinates in characters, relative to a window,
7174    return the pixel location corresponding to those coordinates.  The
7175    pixel location returned is the center of the given character
7176    position.  The pixel values are generated relative to the window,
7177    not the frame.
7178
7179    The modeline is considered to be part of the window. */
7180
7181 void
7182 glyph_to_pixel_translation (struct window *w, int char_x, int char_y,
7183                             int *pix_x, int *pix_y)
7184 {
7185   display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
7186   int num_disp_lines, modeline;
7187   Lisp_Object window;
7188   int defheight, defwidth;
7189
7190   XSETWINDOW (window, w);
7191   default_face_height_and_width (window, &defheight, &defwidth);
7192
7193   /* If we get a bogus value indicating somewhere above or to the left of
7194      the window, use the first window line or character position
7195      instead. */
7196   if (char_y < 0)
7197     char_y = 0;
7198   if (char_x < 0)
7199     char_x = 0;
7200
7201   num_disp_lines = Dynarr_length (dla);
7202   modeline = 0;
7203   if (num_disp_lines)
7204     {
7205       if (Dynarr_atp (dla, 0)->modeline)
7206         {
7207           num_disp_lines--;
7208           modeline = 1;
7209         }
7210     }
7211
7212   /* First check if the y position intersects the display lines. */
7213   if (char_y < num_disp_lines)
7214     {
7215       struct display_line *dl = Dynarr_atp (dla, char_y + modeline);
7216       struct display_block *db = get_display_block_from_line (dl, TEXT);
7217
7218       *pix_y = (dl->ypos - dl->ascent +
7219                 ((unsigned int) (dl->ascent + dl->descent - dl->clip) >> 1));
7220
7221       if (char_x < Dynarr_length (db->runes))
7222         {
7223           struct rune *rb = Dynarr_atp (db->runes, char_x);
7224
7225           *pix_x = rb->xpos + (rb->width >> 1);
7226         }
7227       else
7228         {
7229           int last_rune = Dynarr_length (db->runes) - 1;
7230           struct rune *rb = Dynarr_atp (db->runes, last_rune);
7231
7232           char_x -= last_rune;
7233
7234           *pix_x = rb->xpos + rb->width;
7235           *pix_x += ((char_x - 1) * defwidth);
7236           *pix_x += (defwidth >> 1);
7237         }
7238     }
7239   else
7240     {
7241       /* It didn't intersect, so extrapolate.  #### For now, we include the
7242          modeline in this since we don't have true character positions in
7243          it. */
7244
7245       if (!Dynarr_length (w->face_cachels))
7246         reset_face_cachels (w);
7247
7248       char_y -= num_disp_lines;
7249
7250       if (Dynarr_length (dla))
7251         {
7252           struct display_line *dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
7253           *pix_y = dl->ypos + dl->descent - dl->clip;
7254         }
7255       else
7256         *pix_y = WINDOW_TEXT_TOP (w);
7257
7258       *pix_y += (char_y * defheight);
7259       *pix_y += (defheight >> 1);
7260
7261       *pix_x = WINDOW_TEXT_LEFT (w);
7262       /* Don't adjust by one because this is still the unadjusted value. */
7263       *pix_x += (char_x * defwidth);
7264       *pix_x += (defwidth >> 1);
7265     }
7266
7267   if (*pix_x > w->pixel_left + w->pixel_width)
7268       *pix_x = w->pixel_left + w->pixel_width;
7269   if (*pix_y > w->pixel_top + w->pixel_height)
7270       *pix_y = w->pixel_top + w->pixel_height;
7271
7272   *pix_x -= w->pixel_left;
7273   *pix_y -= w->pixel_top;
7274 }
7275
7276 /* Given a display line and a position, determine if there is a glyph
7277    there and return information about it if there is. */
7278
7279 static void
7280 get_position_object (struct display_line *dl, Lisp_Object *obj1,
7281                      Lisp_Object *obj2, int x_coord, int *low_x_coord,
7282                      int *high_x_coord)
7283 {
7284   struct display_block *db;
7285   int elt;
7286   int block =
7287     get_next_display_block (dl->bounds, dl->display_blocks, x_coord, 0);
7288
7289   /* We use get_next_display_block to get the actual display block
7290      that would be displayed at x_coord. */
7291
7292   if (block == NO_BLOCK)
7293     return;
7294   else
7295     db = Dynarr_atp (dl->display_blocks, block);
7296
7297   for (elt = 0; elt < Dynarr_length (db->runes); elt++)
7298     {
7299       struct rune *rb = Dynarr_atp (db->runes, elt);
7300
7301       if (rb->xpos <= x_coord && x_coord < (rb->xpos + rb->width))
7302         {
7303           if (rb->type == RUNE_DGLYPH)
7304             {
7305               *obj1 = rb->object.dglyph.glyph;
7306               *obj2 = rb->object.dglyph.extent;
7307             }
7308           else
7309             {
7310               *obj1 = Qnil;
7311               *obj2 = Qnil;
7312             }
7313
7314           if (low_x_coord)
7315             *low_x_coord = rb->xpos;
7316           if (high_x_coord)
7317             *high_x_coord = rb->xpos + rb->width;
7318
7319           return;
7320         }
7321     }
7322 }
7323
7324 #define UPDATE_CACHE_RETURN                                             \
7325   do {                                                                  \
7326     d->pixel_to_glyph_cache.valid = 1;                                  \
7327     d->pixel_to_glyph_cache.low_x_coord = low_x_coord;                  \
7328     d->pixel_to_glyph_cache.high_x_coord = high_x_coord;                \
7329     d->pixel_to_glyph_cache.low_y_coord = low_y_coord;                  \
7330     d->pixel_to_glyph_cache.high_y_coord = high_y_coord;                \
7331     d->pixel_to_glyph_cache.frame = f;                                  \
7332     d->pixel_to_glyph_cache.col = *col;                                 \
7333     d->pixel_to_glyph_cache.row = *row;                                 \
7334     d->pixel_to_glyph_cache.obj_x = *obj_x;                             \
7335     d->pixel_to_glyph_cache.obj_y = *obj_y;                             \
7336     d->pixel_to_glyph_cache.w = *w;                                     \
7337     d->pixel_to_glyph_cache.bufpos = *bufpos;                           \
7338     d->pixel_to_glyph_cache.closest = *closest;                         \
7339     d->pixel_to_glyph_cache.modeline_closest = *modeline_closest;       \
7340     d->pixel_to_glyph_cache.obj1 = *obj1;                               \
7341     d->pixel_to_glyph_cache.obj2 = *obj2;                               \
7342     d->pixel_to_glyph_cache.retval = position;                          \
7343     RETURN_SANS_WARNINGS position;                                      \
7344   } while (0)
7345
7346 /* Given x and y coordinates in pixels relative to a frame, return
7347    information about what is located under those coordinates.
7348
7349    The return value will be one of:
7350
7351      OVER_TOOLBAR:      over one of the 4 frame toolbars
7352      OVER_MODELINE:     over a modeline
7353      OVER_BORDER:       over an internal border
7354      OVER_NOTHING:      over the text area, but not over text
7355      OVER_OUTSIDE:      outside of the frame border
7356      OVER_TEXT:         over text in the text area
7357
7358    OBJ1 is one of
7359
7360      -- a toolbar button
7361      -- a glyph
7362      -- nil if the coordinates are not over a glyph or a toolbar button.
7363
7364    OBJ2 is one of
7365
7366      -- an extent, if the coordinates are over a glyph in the text area
7367      -- nil otherwise.
7368
7369    If the coordinates are over a glyph, OBJ_X and OBJ_Y give the
7370    equivalent coordinates relative to the upper-left corner of the glyph.
7371
7372    If the coordinates are over a character, OBJ_X and OBJ_Y give the
7373    equivalent coordinates relative to the upper-left corner of the character.
7374
7375    Otherwise, OBJ_X and OBJ_Y are undefined.
7376    */
7377
7378 int
7379 pixel_to_glyph_translation (struct frame *f, int x_coord, int y_coord,
7380                             int *col, int *row, int *obj_x, int *obj_y,
7381                             struct window **w, Bufpos *bufpos,
7382                             Bufpos *closest, Charcount *modeline_closest,
7383                             Lisp_Object *obj1, Lisp_Object *obj2)
7384 {
7385   struct device *d;
7386   struct pixel_to_glyph_translation_cache *cache;
7387   Lisp_Object window;
7388   int frm_left, frm_right, frm_top, frm_bottom;
7389   int low_x_coord, high_x_coord, low_y_coord, high_y_coord;
7390   int position = OVER_NOTHING;
7391   int device_check_failed = 0;
7392   display_line_dynarr *dla;
7393
7394   /* This is a safety valve in case this got called with a frame in
7395      the middle of being deleted. */
7396   if (!DEVICEP (f->device) || !DEVICE_LIVE_P (XDEVICE (f->device)))
7397     {
7398       device_check_failed = 1;
7399       d = NULL, cache = NULL; /* Warning suppression */
7400     }
7401   else
7402     {
7403       d = XDEVICE (f->device);
7404       cache = &d->pixel_to_glyph_cache;
7405     }
7406
7407   if (!device_check_failed
7408       && cache->valid
7409       && cache->frame == f
7410       && cache->low_x_coord <= x_coord
7411       && cache->high_x_coord > x_coord
7412       && cache->low_y_coord <= y_coord
7413       && cache->high_y_coord > y_coord)
7414     {
7415       *col = cache->col;
7416       *row = cache->row;
7417       *obj_x = cache->obj_x;
7418       *obj_y = cache->obj_y;
7419       *w = cache->w;
7420       *bufpos = cache->bufpos;
7421       *closest = cache->closest;
7422       *modeline_closest = cache->modeline_closest;
7423       *obj1 = cache->obj1;
7424       *obj2 = cache->obj2;
7425
7426       return cache->retval;
7427     }
7428   else
7429     {
7430       *col = 0;
7431       *row = 0;
7432       *obj_x = 0;
7433       *obj_y = 0;
7434       *w = 0;
7435       *bufpos = 0;
7436       *closest = 0;
7437       *modeline_closest = -1;
7438       *obj1 = Qnil;
7439       *obj2 = Qnil;
7440
7441       low_x_coord = x_coord;
7442       high_x_coord = x_coord + 1;
7443       low_y_coord = y_coord;
7444       high_y_coord = y_coord + 1;
7445     }
7446
7447   if (device_check_failed)
7448     return OVER_NOTHING;
7449
7450   frm_left = FRAME_LEFT_BORDER_END (f);
7451   frm_right = FRAME_RIGHT_BORDER_START (f);
7452   frm_top = FRAME_TOP_BORDER_END (f);
7453   frm_bottom = FRAME_BOTTOM_BORDER_START (f);
7454
7455   /* Check if the mouse is outside of the text area actually used by
7456      redisplay. */
7457   if (y_coord < frm_top)
7458     {
7459       if (y_coord >= FRAME_TOP_BORDER_START (f))
7460         {
7461           low_y_coord = FRAME_TOP_BORDER_START (f);
7462           high_y_coord = frm_top;
7463           position = OVER_BORDER;
7464         }
7465       else if (y_coord >= 0)
7466         {
7467           low_y_coord = 0;
7468           high_y_coord = FRAME_TOP_BORDER_START (f);
7469           position = OVER_TOOLBAR;
7470         }
7471       else
7472         {
7473           low_y_coord = y_coord;
7474           high_y_coord = 0;
7475           position = OVER_OUTSIDE;
7476         }
7477     }
7478   else if (y_coord >= frm_bottom)
7479     {
7480       if (y_coord < FRAME_BOTTOM_BORDER_END (f))
7481         {
7482           low_y_coord = frm_bottom;
7483           high_y_coord = FRAME_BOTTOM_BORDER_END (f);
7484           position = OVER_BORDER;
7485         }
7486       else if (y_coord < FRAME_PIXHEIGHT (f))
7487         {
7488           low_y_coord = FRAME_BOTTOM_BORDER_END (f);
7489           high_y_coord = FRAME_PIXHEIGHT (f);
7490           position = OVER_TOOLBAR;
7491         }
7492       else
7493         {
7494           low_y_coord = FRAME_PIXHEIGHT (f);
7495           high_y_coord = y_coord;
7496           position = OVER_OUTSIDE;
7497         }
7498     }
7499
7500   if (position != OVER_TOOLBAR && position != OVER_BORDER)
7501     {
7502       if (x_coord < frm_left)
7503         {
7504           if (x_coord >= FRAME_LEFT_BORDER_START (f))
7505             {
7506               low_x_coord = FRAME_LEFT_BORDER_START (f);
7507               high_x_coord = frm_left;
7508               position = OVER_BORDER;
7509             }
7510           else if (x_coord >= 0)
7511             {
7512               low_x_coord = 0;
7513               high_x_coord = FRAME_LEFT_BORDER_START (f);
7514               position = OVER_TOOLBAR;
7515             }
7516           else
7517             {
7518               low_x_coord = x_coord;
7519               high_x_coord = 0;
7520               position = OVER_OUTSIDE;
7521             }
7522         }
7523       else if (x_coord >= frm_right)
7524         {
7525           if (x_coord < FRAME_RIGHT_BORDER_END (f))
7526             {
7527               low_x_coord = frm_right;
7528               high_x_coord = FRAME_RIGHT_BORDER_END (f);
7529               position = OVER_BORDER;
7530             }
7531           else if (x_coord < FRAME_PIXWIDTH (f))
7532             {
7533               low_x_coord = FRAME_RIGHT_BORDER_END (f);
7534               high_x_coord = FRAME_PIXWIDTH (f);
7535               position = OVER_TOOLBAR;
7536             }
7537           else
7538             {
7539               low_x_coord = FRAME_PIXWIDTH (f);
7540               high_x_coord = x_coord;
7541               position = OVER_OUTSIDE;
7542             }
7543         }
7544     }
7545
7546 #ifdef HAVE_TOOLBARS
7547   if (position == OVER_TOOLBAR)
7548     {
7549       *obj1 = toolbar_button_at_pixpos (f, x_coord, y_coord);
7550       *obj2 = Qnil;
7551       *w = 0;
7552       UPDATE_CACHE_RETURN;
7553     }
7554 #endif /* HAVE_TOOLBARS */
7555
7556   /* We still have to return the window the pointer is next to and its
7557      relative y position even if it is outside the x boundary. */
7558   if (x_coord < frm_left)
7559     x_coord = frm_left;
7560   else if (x_coord > frm_right)
7561     x_coord = frm_right;
7562
7563   /* Same in reverse. */
7564   if (y_coord < frm_top)
7565     y_coord = frm_top;
7566   else if (y_coord > frm_bottom)
7567     y_coord = frm_bottom;
7568
7569   /* Find what window the given coordinates are actually in. */
7570   window = f->root_window;
7571   *w = find_window_by_pixel_pos (x_coord, y_coord, window);
7572
7573   /* If we didn't find a window, we're done. */
7574   if (!*w)
7575     {
7576       UPDATE_CACHE_RETURN;
7577     }
7578   else if (position != OVER_NOTHING)
7579     {
7580       *closest = 0;
7581       *modeline_closest = -1;
7582
7583       if (high_y_coord <= frm_top || high_y_coord >= frm_bottom)
7584         {
7585           *w = 0;
7586           UPDATE_CACHE_RETURN;
7587         }
7588     }
7589
7590   /* Check if the window is a minibuffer but isn't active. */
7591   if (MINI_WINDOW_P (*w) && !minibuf_level)
7592     {
7593       /* Must reset the window value since some callers will ignore
7594          the return value if it is set. */
7595       *w = 0;
7596       UPDATE_CACHE_RETURN;
7597     }
7598
7599   /* See if the point is over window vertical divider */
7600   if (window_needs_vertical_divider (*w))
7601     {
7602       int div_x_high = WINDOW_RIGHT (*w);
7603       int div_x_low  = div_x_high - window_divider_width (*w);
7604       int div_y_high = WINDOW_BOTTOM (*w);
7605       int div_y_low  = WINDOW_TOP (*w);
7606
7607       if (div_x_low < x_coord && x_coord <= div_x_high &&
7608           div_y_low < y_coord && y_coord <= div_y_high)
7609         {
7610           low_x_coord = div_x_low;
7611           high_x_coord = div_x_high;
7612           low_y_coord = div_y_low;
7613           high_y_coord = div_y_high;
7614           position = OVER_V_DIVIDER;
7615           UPDATE_CACHE_RETURN;
7616         }
7617     }
7618
7619   dla = window_display_lines (*w, CURRENT_DISP);
7620
7621   for (*row = 0; *row < Dynarr_length (dla); (*row)++)
7622     {
7623       int really_over_nothing = 0;
7624       struct display_line *dl = Dynarr_atp (dla, *row);
7625
7626       if ((int) (dl->ypos - dl->ascent) <= y_coord
7627           && y_coord <= (int) (dl->ypos + dl->descent))
7628         {
7629           int check_margin_glyphs = 0;
7630           struct display_block *db = get_display_block_from_line (dl, TEXT);
7631           struct rune *rb = 0;
7632
7633           if (x_coord < dl->bounds.left_white
7634               || x_coord >= dl->bounds.right_white)
7635             check_margin_glyphs = 1;
7636
7637           low_y_coord = dl->ypos - dl->ascent;
7638           high_y_coord = dl->ypos + dl->descent + 1;
7639
7640           if (position == OVER_BORDER
7641               || position == OVER_OUTSIDE
7642               || check_margin_glyphs)
7643             {
7644               int x_check, left_bound;
7645
7646               if (check_margin_glyphs)
7647                 {
7648                   x_check = x_coord;
7649                   left_bound = dl->bounds.left_white;
7650                 }
7651               else
7652                 {
7653                   x_check = high_x_coord;
7654                   left_bound = frm_left;
7655                 }
7656
7657               if (Dynarr_length (db->runes))
7658                 {
7659                   if (x_check <= left_bound)
7660                     {
7661                       if (dl->modeline)
7662                         *modeline_closest = Dynarr_atp (db->runes, 0)->bufpos;
7663                       else
7664                         *closest = Dynarr_atp (db->runes, 0)->bufpos;
7665                     }
7666                   else
7667                     {
7668                       if (dl->modeline)
7669                         *modeline_closest =
7670                           Dynarr_atp (db->runes,
7671                                       Dynarr_length (db->runes) - 1)->bufpos;
7672                       else
7673                         *closest =
7674                           Dynarr_atp (db->runes,
7675                                       Dynarr_length (db->runes) - 1)->bufpos;
7676                     }
7677
7678                   if (dl->modeline)
7679                     *modeline_closest += dl->offset;
7680                   else
7681                     *closest += dl->offset;
7682                 }
7683               else
7684                 {
7685                   /* #### What should be here. */
7686                   if (dl->modeline)
7687                     *modeline_closest = 0;
7688                   else
7689                     *closest = 0;
7690                 }
7691
7692               if (check_margin_glyphs)
7693                 {
7694                   if (x_coord < dl->bounds.left_in
7695                       || x_coord >= dl->bounds.right_in)
7696                     {
7697                       /* If we are over the outside margins then we
7698                          know the loop over the text block isn't going
7699                          to accomplish anything.  So we go ahead and
7700                          set what information we can right here and
7701                          return. */
7702                       (*row)--;
7703                       *obj_y = y_coord - (dl->ypos - dl->ascent);
7704                       get_position_object (dl, obj1, obj2, x_coord,
7705                                            &low_x_coord, &high_x_coord);
7706
7707                       UPDATE_CACHE_RETURN;
7708                     }
7709                 }
7710               else
7711                 UPDATE_CACHE_RETURN;
7712             }
7713
7714           for (*col = 0; *col <= Dynarr_length (db->runes); (*col)++)
7715             {
7716               int past_end = (*col == Dynarr_length (db->runes));
7717
7718               if (!past_end)
7719                 rb = Dynarr_atp (db->runes, *col);
7720
7721               if (past_end ||
7722                   (rb->xpos <= x_coord && x_coord < rb->xpos + rb->width))
7723                 {
7724                   if (past_end)
7725                     {
7726                       (*col)--;
7727                       rb = Dynarr_atp (db->runes, *col);
7728                     }
7729
7730                   *bufpos = rb->bufpos + dl->offset;
7731                   low_x_coord = rb->xpos;
7732                   high_x_coord = rb->xpos + rb->width;
7733
7734                   if (rb->type == RUNE_DGLYPH)
7735                     {
7736                       int elt = *col + 1;
7737
7738                       /* Find the first character after the glyph. */
7739                       while (elt < Dynarr_length (db->runes))
7740                         {
7741                           if (Dynarr_atp (db->runes, elt)->type != RUNE_DGLYPH)
7742                             {
7743                               if (dl->modeline)
7744                                 *modeline_closest =
7745                                   (Dynarr_atp (db->runes, elt)->bufpos +
7746                                    dl->offset);
7747                               else
7748                                 *closest =
7749                                   (Dynarr_atp (db->runes, elt)->bufpos +
7750                                    dl->offset);
7751                               break;
7752                             }
7753
7754                           elt++;
7755                         }
7756
7757                       /* In this case we failed to find a non-glyph
7758                          character so we return the last position
7759                          displayed on the line. */
7760                       if (elt == Dynarr_length (db->runes))
7761                         {
7762                           if (dl->modeline)
7763                             *modeline_closest = dl->end_bufpos + dl->offset;
7764                           else
7765                             *closest = dl->end_bufpos + dl->offset;
7766                           really_over_nothing = 1;
7767                         }
7768                     }
7769                   else
7770                     {
7771                       if (dl->modeline)
7772                         *modeline_closest = rb->bufpos + dl->offset;
7773                       else
7774                         *closest = rb->bufpos + dl->offset;
7775                     }
7776
7777                   if (dl->modeline)
7778                     {
7779                       *row = window_displayed_height (*w);
7780
7781                       if (position == OVER_NOTHING)
7782                         position = OVER_MODELINE;
7783
7784                       if (rb->type == RUNE_DGLYPH)
7785                         {
7786                           *obj1 = rb->object.dglyph.glyph;
7787                           *obj2 = rb->object.dglyph.extent;
7788                         }
7789                       else if (rb->type == RUNE_CHAR)
7790                         {
7791                           *obj1 = Qnil;
7792                           *obj2 = Qnil;
7793                         }
7794                       else
7795                         {
7796                           *obj1 = Qnil;
7797                           *obj2 = Qnil;
7798                         }
7799
7800                       UPDATE_CACHE_RETURN;
7801                     }
7802                   else if (past_end
7803                            || (rb->type == RUNE_CHAR
7804                                && rb->object.chr.ch == '\n'))
7805                     {
7806                       (*row)--;
7807                       /* At this point we may have glyphs in the right
7808                          inside margin. */
7809                       if (check_margin_glyphs)
7810                         get_position_object (dl, obj1, obj2, x_coord,
7811                                              &low_x_coord, &high_x_coord);
7812                       UPDATE_CACHE_RETURN;
7813                     }
7814                   else
7815                     {
7816                       (*row)--;
7817                       if (rb->type == RUNE_DGLYPH)
7818                         {
7819                           *obj1 = rb->object.dglyph.glyph;
7820                           *obj2 = rb->object.dglyph.extent;
7821                         }
7822                       else if (rb->type == RUNE_CHAR)
7823                         {
7824                           *obj1 = Qnil;
7825                           *obj2 = Qnil;
7826                         }
7827                       else
7828                         {
7829                           *obj1 = Qnil;
7830                           *obj2 = Qnil;
7831                         }
7832
7833                       *obj_x = x_coord - rb->xpos;
7834                       *obj_y = y_coord - (dl->ypos - dl->ascent);
7835
7836                       /* At this point we may have glyphs in the left
7837                          inside margin. */
7838                       if (check_margin_glyphs)
7839                         get_position_object (dl, obj1, obj2, x_coord, 0, 0);
7840
7841                       if (position == OVER_NOTHING && !really_over_nothing)
7842                         position = OVER_TEXT;
7843
7844                       UPDATE_CACHE_RETURN;
7845                     }
7846                 }
7847             }
7848         }
7849     }
7850
7851   *row = Dynarr_length (dla) - 1;
7852   if (FRAME_WIN_P (f))
7853     {
7854       int bot_elt = Dynarr_length (dla) - 1;
7855
7856       if (bot_elt >= 0)
7857         {
7858           struct display_line *dl = Dynarr_atp (dla, bot_elt);
7859           int adj_area = y_coord - (dl->ypos + dl->descent);
7860           Lisp_Object lwin;
7861           int defheight;
7862
7863           XSETWINDOW (lwin, *w);
7864           default_face_height_and_width (lwin, 0, &defheight);
7865
7866           *row += (adj_area / defheight);
7867         }
7868     }
7869
7870   /* #### This should be checked out some more to determine what
7871      should really be going on. */
7872   if (!MARKERP ((*w)->start[CURRENT_DISP]))
7873     *closest = 0;
7874   else
7875     *closest = end_of_last_line (*w,
7876                                  marker_position ((*w)->start[CURRENT_DISP]));
7877   *col = 0;
7878   UPDATE_CACHE_RETURN;
7879 }
7880 #undef UPDATE_CACHE_RETURN
7881
7882 \f
7883 /***************************************************************************/
7884 /*                                                                         */
7885 /*                             Lisp functions                              */
7886 /*                                                                         */
7887 /***************************************************************************/
7888
7889 DEFUN ("redisplay-echo-area", Fredisplay_echo_area, 0, 0, 0, /*
7890 Ensure that all minibuffers are correctly showing the echo area.
7891 */
7892        ())
7893 {
7894   Lisp_Object devcons, concons;
7895
7896   DEVICE_LOOP_NO_BREAK (devcons, concons)
7897     {
7898       struct device *d = XDEVICE (XCAR (devcons));
7899       Lisp_Object frmcons;
7900
7901       DEVICE_FRAME_LOOP (frmcons, d)
7902         {
7903           struct frame *f = XFRAME (XCAR (frmcons));
7904
7905           if (FRAME_REPAINT_P (f) && FRAME_HAS_MINIBUF_P (f))
7906             {
7907               Lisp_Object window = FRAME_MINIBUF_WINDOW (f);
7908               /*
7909                * If the frame size has changed, there may be random
7910                * chud on the screen left from previous messages
7911                * because redisplay_frame hasn't been called yet.
7912                * Clear the screen to get rid of the potential mess.
7913                */
7914               if (f->echo_area_garbaged)
7915                 {
7916                   DEVMETH (d, clear_frame, (f));
7917                   f->echo_area_garbaged = 0;
7918                 }
7919               redisplay_window (window, 0);
7920               call_redisplay_end_triggers (XWINDOW (window), 0);
7921             }
7922         }
7923
7924       /* We now call the output_end routine for tty frames.  We delay
7925          doing so in order to avoid cursor flicker.  So much for 100%
7926          encapsulation. */
7927       if (DEVICE_TTY_P (d))
7928         DEVMETH (d, output_end, (d));
7929     }
7930
7931   return Qnil;
7932 }
7933
7934 static Lisp_Object
7935 restore_disable_preemption_value (Lisp_Object value)
7936 {
7937   disable_preemption = XINT (value);
7938   return Qnil;
7939 }
7940
7941 DEFUN ("redraw-frame", Fredraw_frame, 0, 2, 0, /*
7942 Clear frame FRAME and output again what is supposed to appear on it.
7943 FRAME defaults to the selected frame if omitted.
7944 Normally, redisplay is preempted as normal if input arrives.  However,
7945 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7946 input and is guaranteed to proceed to completion.
7947 */
7948        (frame, no_preempt))
7949 {
7950   struct frame *f = decode_frame (frame);
7951   int count = specpdl_depth ();
7952
7953   if (!NILP (no_preempt))
7954     {
7955       record_unwind_protect (restore_disable_preemption_value,
7956                              make_int (disable_preemption));
7957       disable_preemption++;
7958     }
7959
7960   f->clear = 1;
7961   redisplay_frame (f, 1);
7962
7963   return unbind_to (count, Qnil);
7964 }
7965
7966 DEFUN ("redisplay-frame", Fredisplay_frame, 0, 2, 0, /*
7967 Ensure that FRAME's contents are correctly displayed.
7968 This differs from `redraw-frame' in that it only redraws what needs to
7969 be updated, as opposed to unconditionally clearing and redrawing
7970 the frame.
7971 FRAME defaults to the selected frame if omitted.
7972 Normally, redisplay is preempted as normal if input arrives.  However,
7973 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7974 input and is guaranteed to proceed to completion.
7975 */
7976        (frame, no_preempt))
7977 {
7978   struct frame *f = decode_frame (frame);
7979   int count = specpdl_depth ();
7980
7981   if (!NILP (no_preempt))
7982     {
7983       record_unwind_protect (restore_disable_preemption_value,
7984                              make_int (disable_preemption));
7985       disable_preemption++;
7986     }
7987
7988   redisplay_frame (f, 1);
7989
7990   return unbind_to (count, Qnil);
7991 }
7992
7993 DEFUN ("redraw-device", Fredraw_device, 0, 2, 0, /*
7994 Clear device DEVICE and output again what is supposed to appear on it.
7995 DEVICE defaults to the selected device if omitted.
7996 Normally, redisplay is preempted as normal if input arrives.  However,
7997 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
7998 input and is guaranteed to proceed to completion.
7999 */
8000      (device, no_preempt))
8001 {
8002   struct device *d = decode_device (device);
8003   Lisp_Object frmcons;
8004   int count = specpdl_depth ();
8005
8006   if (!NILP (no_preempt))
8007     {
8008       record_unwind_protect (restore_disable_preemption_value,
8009                              make_int (disable_preemption));
8010       disable_preemption++;
8011     }
8012
8013   DEVICE_FRAME_LOOP (frmcons, d)
8014     {
8015       XFRAME (XCAR (frmcons))->clear = 1;
8016     }
8017   redisplay_device (d);
8018
8019   return unbind_to (count, Qnil);
8020 }
8021
8022 DEFUN ("redisplay-device", Fredisplay_device, 0, 2, 0, /*
8023 Ensure that DEVICE's contents are correctly displayed.
8024 This differs from `redraw-device' in that it only redraws what needs to
8025 be updated, as opposed to unconditionally clearing and redrawing
8026 the device.
8027 DEVICE defaults to the selected device if omitted.
8028 Normally, redisplay is preempted as normal if input arrives.  However,
8029 if optional second arg NO-PREEMPT is non-nil, redisplay will not stop for
8030 input and is guaranteed to proceed to completion.
8031 */
8032        (device, no_preempt))
8033 {
8034   struct device *d = decode_device (device);
8035   int count = specpdl_depth ();
8036
8037   if (!NILP (no_preempt))
8038     {
8039       record_unwind_protect (restore_disable_preemption_value,
8040                              make_int (disable_preemption));
8041       disable_preemption++;
8042     }
8043
8044   redisplay_device (d);
8045
8046   return unbind_to (count, Qnil);
8047 }
8048
8049 /* Big lie.  Big lie.  This will force all modelines to be updated
8050    regardless if the all flag is set or not.  It remains in existence
8051    solely for backwards compatibility. */
8052 DEFUN ("redraw-modeline", Fredraw_modeline, 0, 1, 0, /*
8053 Force the modeline of the current buffer to be redisplayed.
8054 With optional non-nil ALL, force redisplay of all modelines.
8055 */
8056        (all))
8057 {
8058   MARK_MODELINE_CHANGED;
8059   return Qnil;
8060 }
8061
8062 DEFUN ("force-cursor-redisplay", Fforce_cursor_redisplay, 0, 1, 0, /*
8063 Force an immediate update of the cursor on FRAME.
8064 FRAME defaults to the selected frame if omitted.
8065 */
8066   (frame))
8067 {
8068   redisplay_redraw_cursor (decode_frame (frame), 1);
8069   return Qnil;
8070 }
8071
8072 \f
8073 /***************************************************************************/
8074 /*                                                                         */
8075 /*                     Lisp-variable change triggers                       */
8076 /*                                                                         */
8077 /***************************************************************************/
8078
8079 static void
8080 margin_width_changed_in_frame (Lisp_Object specifier, struct frame *f,
8081                                Lisp_Object oldval)
8082 {
8083   /* Nothing to be done? */
8084 }
8085
8086 int
8087 redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val,
8088                             Lisp_Object in_object, int flags)
8089 {
8090   /* #### clip_changed should really be renamed something like
8091      global_redisplay_change. */
8092   MARK_CLIP_CHANGED;
8093   return 0;
8094 }
8095
8096 void
8097 redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property,
8098                          Lisp_Object locale)
8099 {
8100   if (WINDOWP (locale))
8101     {
8102       MARK_FRAME_GLYPHS_CHANGED (XFRAME (WINDOW_FRAME (XWINDOW (locale))));
8103     }
8104   else if (FRAMEP (locale))
8105     {
8106       MARK_FRAME_GLYPHS_CHANGED (XFRAME (locale));
8107     }
8108   else if (DEVICEP (locale))
8109     {
8110       Lisp_Object frmcons;
8111       DEVICE_FRAME_LOOP (frmcons, XDEVICE (locale))
8112         MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8113     }
8114   else if (CONSOLEP (locale))
8115     {
8116       Lisp_Object frmcons, devcons;
8117       CONSOLE_FRAME_LOOP_NO_BREAK (frmcons, devcons, XCONSOLE (locale))
8118         MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8119     }
8120   else /* global or buffer */
8121     {
8122       Lisp_Object frmcons, devcons, concons;
8123       FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
8124         MARK_FRAME_GLYPHS_CHANGED (XFRAME (XCAR (frmcons)));
8125     }
8126 }
8127
8128 static void
8129 text_cursor_visible_p_changed (Lisp_Object specifier, struct window *w,
8130                                Lisp_Object oldval)
8131 {
8132   if (XFRAME (w->frame)->init_finished)
8133     Fforce_cursor_redisplay (w->frame);
8134 }
8135
8136 #ifdef MEMORY_USAGE_STATS
8137
8138 \f
8139 /***************************************************************************/
8140 /*                                                                         */
8141 /*                        memory usage computation                         */
8142 /*                                                                         */
8143 /***************************************************************************/
8144
8145 static int
8146 compute_rune_dynarr_usage (rune_dynarr *dyn, struct overhead_stats *ovstats)
8147 {
8148   return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8149 }
8150
8151 static int
8152 compute_display_block_dynarr_usage (display_block_dynarr *dyn,
8153                                     struct overhead_stats *ovstats)
8154 {
8155   int total, i;
8156
8157   if (!dyn)
8158     return 0;
8159
8160   total = Dynarr_memory_usage (dyn, ovstats);
8161   for (i = 0; i < Dynarr_largest (dyn); i++)
8162     total += compute_rune_dynarr_usage (Dynarr_at (dyn, i).runes, ovstats);
8163
8164   return total;
8165 }
8166
8167 static int
8168 compute_glyph_block_dynarr_usage (glyph_block_dynarr *dyn,
8169                                   struct overhead_stats *ovstats)
8170 {
8171   return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8172 }
8173
8174 int
8175 compute_display_line_dynarr_usage (display_line_dynarr *dyn,
8176                                    struct overhead_stats *ovstats)
8177 {
8178   int total, i;
8179
8180   if (!dyn)
8181     return 0;
8182
8183   total = Dynarr_memory_usage (dyn, ovstats);
8184   for (i = 0; i < Dynarr_largest (dyn); i++)
8185     {
8186       struct display_line *dl = &Dynarr_at (dyn, i);
8187       total += compute_display_block_dynarr_usage(dl->display_blocks, ovstats);
8188       total += compute_glyph_block_dynarr_usage  (dl->left_glyphs,    ovstats);
8189       total += compute_glyph_block_dynarr_usage  (dl->right_glyphs,   ovstats);
8190     }
8191
8192   return total;
8193 }
8194
8195 int
8196 compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn,
8197                                        struct overhead_stats *ovstats)
8198 {
8199   return dyn ? Dynarr_memory_usage (dyn, ovstats) : 0;
8200 }
8201
8202 #endif /* MEMORY_USAGE_STATS */
8203
8204 \f
8205 /***************************************************************************/
8206 /*                                                                         */
8207 /*                              initialization                             */
8208 /*                                                                         */
8209 /***************************************************************************/
8210
8211 void
8212 init_redisplay (void)
8213 {
8214   disable_preemption = 0;
8215   preemption_count = 0;
8216   max_preempts = INIT_MAX_PREEMPTS;
8217
8218   if (!initialized)
8219     {
8220       cmotion_display_lines = Dynarr_new (display_line);
8221       mode_spec_bufbyte_string = Dynarr_new (Bufbyte);
8222       formatted_string_emchar_dynarr = Dynarr_new (Emchar);
8223       formatted_string_extent_dynarr = Dynarr_new (EXTENT);
8224       formatted_string_extent_start_dynarr = Dynarr_new (Bytecount);
8225       formatted_string_extent_end_dynarr = Dynarr_new (Bytecount);
8226       internal_cache = Dynarr_new (line_start_cache);
8227       xzero (formatted_string_display_line);
8228     }
8229
8230   /* window system is nil when in -batch mode */
8231   if (!initialized || noninteractive)
8232     return;
8233
8234   /* If the user wants to use a window system, we shouldn't bother
8235      initializing the terminal.  This is especially important when the
8236      terminal is so dumb that emacs gives up before and doesn't bother
8237      using the window system.
8238
8239      If the DISPLAY environment variable is set, try to use X, and die
8240      with an error message if that doesn't work.  */
8241
8242 #ifdef HAVE_X_WINDOWS
8243   if (!strcmp (display_use, "x"))
8244     {
8245       /* Some stuff checks this way early. */
8246       Vwindow_system = Qx;
8247       Vinitial_window_system = Qx;
8248       return;
8249     }
8250 #endif /* HAVE_X_WINDOWS */
8251
8252 #ifdef HAVE_MS_WINDOWS
8253   if (!strcmp (display_use, "mswindows"))
8254     {
8255       /* Some stuff checks this way early. */
8256       Vwindow_system = Qmswindows;
8257       Vinitial_window_system = Qmswindows;
8258       return;
8259     }
8260 #endif /* HAVE_MS_WINDOWS */
8261
8262 #ifdef HAVE_TTY
8263   /* If no window system has been specified, try to use the terminal.  */
8264   if (!isatty (0))
8265     {
8266       stderr_out ("XEmacs: standard input is not a tty\n");
8267       exit (1);
8268     }
8269
8270   /* Look at the TERM variable */
8271   if (!getenv ("TERM"))
8272     {
8273       stderr_out ("Please set the environment variable TERM; see tset(1).\n");
8274       exit (1);
8275     }
8276
8277   Vinitial_window_system = Qtty;
8278   return;
8279 #else  /* not HAVE_TTY */
8280   /* No DISPLAY specified, and no TTY support. */
8281   stderr_out ("XEmacs: Cannot open display.\n\
8282 Please set the environmental variable DISPLAY to an appropriate value.\n");
8283   exit (1);
8284 #endif
8285   /* Unreached. */
8286 }
8287
8288 void
8289 syms_of_redisplay (void)
8290 {
8291   defsymbol (&Qcursor_in_echo_area, "cursor-in-echo-area");
8292 #ifndef INHIBIT_REDISPLAY_HOOKS
8293   defsymbol (&Qpre_redisplay_hook, "pre-redisplay-hook");
8294   defsymbol (&Qpost_redisplay_hook, "post-redisplay-hook");
8295 #endif /* INHIBIT_REDISPLAY_HOOKS */
8296   defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer");
8297   defsymbol (&Qbar_cursor, "bar-cursor");
8298   defsymbol (&Qwindow_scroll_functions, "window-scroll-functions");
8299   defsymbol (&Qredisplay_end_trigger_functions,
8300              "redisplay-end-trigger-functions");
8301
8302   DEFSUBR (Fredisplay_echo_area);
8303   DEFSUBR (Fredraw_frame);
8304   DEFSUBR (Fredisplay_frame);
8305   DEFSUBR (Fredraw_device);
8306   DEFSUBR (Fredisplay_device);
8307   DEFSUBR (Fredraw_modeline);
8308   DEFSUBR (Fforce_cursor_redisplay);
8309 }
8310
8311 void
8312 vars_of_redisplay (void)
8313 {
8314 #if 0
8315   staticpro (&last_arrow_position);
8316   staticpro (&last_arrow_string);
8317   last_arrow_position = Qnil;
8318   last_arrow_string = Qnil;
8319 #endif /* 0 */
8320
8321   updating_line_start_cache = 0;
8322
8323   /* #### Probably temporary */
8324   DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /*
8325 \(Temporary) Setting this will impact the performance of the internal
8326 line start cache.
8327 */ );
8328   cache_adjustment = 2;
8329
8330   DEFVAR_INT_MAGIC ("pixel-vertical-clip-threshold", &vertical_clip /*
8331 Minimum pixel height for clipped bottom display line.
8332 A clipped line shorter than this won't be displayed.
8333 */ ,
8334                     redisplay_variable_changed);
8335   vertical_clip = 5;
8336
8337   DEFVAR_INT_MAGIC ("pixel-horizontal-clip-threshold", &horizontal_clip /*
8338 Minimum visible area for clipped glyphs at right boundary.
8339 Clipped glyphs shorter than this won't be displayed.
8340 Only pixmap glyph instances are currently allowed to be clipped.
8341 */ ,
8342                     redisplay_variable_changed);
8343   horizontal_clip = 5;
8344
8345   DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string /*
8346 String displayed by modeline-format's "%m" specification.
8347 */ );
8348   Vglobal_mode_string = Qnil;
8349
8350   DEFVAR_LISP_MAGIC ("overlay-arrow-position", &Voverlay_arrow_position /*
8351 Marker for where to display an arrow on top of the buffer text.
8352 This must be the beginning of a line in order to work.
8353 See also `overlay-arrow-string'.
8354 */ ,
8355                      redisplay_variable_changed);
8356   Voverlay_arrow_position = Qnil;
8357
8358   DEFVAR_LISP_MAGIC ("overlay-arrow-string", &Voverlay_arrow_string /*
8359 String to display as an arrow.  See also `overlay-arrow-position'.
8360 */ ,
8361                      redisplay_variable_changed);
8362   Voverlay_arrow_string = Qnil;
8363
8364   DEFVAR_INT ("scroll-step", &scroll_step /*
8365 *The number of lines to try scrolling a window by when point moves out.
8366 If that fails to bring point back on frame, point is centered instead.
8367 If this is zero, point is always centered after it moves off screen.
8368 */ );
8369   scroll_step = 0;
8370
8371   DEFVAR_INT ("scroll-conservatively", &scroll_conservatively /*
8372 *Scroll up to this many lines, to bring point back on screen.
8373 */ );
8374   scroll_conservatively = 0;
8375
8376   DEFVAR_BOOL_MAGIC ("truncate-partial-width-windows",
8377                      &truncate_partial_width_windows /*
8378 *Non-nil means truncate lines in all windows less than full frame wide.
8379 */ ,
8380                      redisplay_variable_changed);
8381   truncate_partial_width_windows = 1;
8382
8383   DEFVAR_BOOL ("visible-bell", &visible_bell /*
8384 *Non-nil means try to flash the frame to represent a bell.
8385 */ );
8386   visible_bell = 0;
8387
8388   DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter /*
8389 *Non-nil means no need to redraw entire frame after suspending.
8390 A non-nil value is useful if the terminal can automatically preserve
8391 Emacs's frame display when you reenter Emacs.
8392 It is up to you to set this variable if your terminal can do that.
8393 */ );
8394   no_redraw_on_reenter = 0;
8395
8396   DEFVAR_LISP ("window-system", &Vwindow_system /*
8397 A symbol naming the window-system under which Emacs is running,
8398 such as `x', or nil if emacs is running on an ordinary terminal.
8399
8400 Do not use this variable, except for GNU Emacs compatibility, as it
8401 gives wrong values in a multi-device environment.  Use `console-type'
8402 instead.
8403 */ );
8404   Vwindow_system = Qnil;
8405
8406   /* #### Temporary shit until window-system is eliminated. */
8407   DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /*
8408 DON'T TOUCH
8409 */ );
8410   Vinitial_window_system = Qnil;
8411
8412   DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area /*
8413 Non-nil means put cursor in minibuffer, at end of any message there.
8414 */ );
8415   cursor_in_echo_area = 0;
8416
8417   /* #### Shouldn't this be generalized as follows:
8418
8419      if nil, use block cursor.
8420      if a number, use a bar cursor of that width.
8421      Otherwise, use a 1-pixel bar cursor.
8422
8423      #### Or better yet, this variable should be trashed entirely
8424      (use a Lisp-magic variable to maintain compatibility)
8425      and a specifier `cursor-shape' added, which allows a block
8426      cursor, a bar cursor, a flashing block or bar cursor,
8427      maybe a caret cursor, etc. */
8428
8429   DEFVAR_LISP ("bar-cursor", &Vbar_cursor /*
8430 Use vertical bar cursor if non-nil.  If t width is 1 pixel, otherwise 2.
8431 */ );
8432   Vbar_cursor = Qnil;
8433
8434 #ifndef INHIBIT_REDISPLAY_HOOKS
8435   xxDEFVAR_LISP ("pre-redisplay-hook", &Vpre_redisplay_hook /*
8436 Function or functions to run before every redisplay.
8437 Functions on this hook must be careful to avoid signalling errors!
8438 */ );
8439   Vpre_redisplay_hook = Qnil;
8440
8441   xxDEFVAR_LISP ("post-redisplay-hook", &Vpost_redisplay_hook /*
8442 Function or functions to run after every redisplay.
8443 Functions on this hook must be careful to avoid signalling errors!
8444 */ );
8445   Vpost_redisplay_hook = Qnil;
8446 #endif /* INHIBIT_REDISPLAY_HOOKS */
8447
8448   DEFVAR_INT ("display-warning-tick", &display_warning_tick /*
8449 Bump this to tell the C code to call `display-warning-buffer'
8450 at next redisplay.  You should not normally change this; the function
8451 `display-warning' automatically does this at appropriate times.
8452 */ );
8453   display_warning_tick = 0;
8454
8455   DEFVAR_BOOL ("inhibit-warning-display", &inhibit_warning_display /*
8456 Non-nil means inhibit display of warning messages.
8457 You should *bind* this, not set it.  Any pending warning messages
8458 will be displayed when the binding no longer applies.
8459 */ );
8460   /* reset to 0 by startup.el after the splash screen has displayed.
8461      This way, the warnings don't obliterate the splash screen. */
8462   inhibit_warning_display = 1;
8463
8464   DEFVAR_LISP ("window-size-change-functions",
8465                &Vwindow_size_change_functions /*
8466 Not currently implemented.
8467 Functions called before redisplay, if window sizes have changed.
8468 The value should be a list of functions that take one argument.
8469 Just before redisplay, for each frame, if any of its windows have changed
8470 size since the last redisplay, or have been split or deleted,
8471 all the functions in the list are called, with the frame as argument.
8472 */ );
8473   Vwindow_size_change_functions = Qnil;
8474
8475   DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions /*
8476 Not currently implemented.
8477 Functions to call before redisplaying a window with scrolling.
8478 Each function is called with two arguments, the window
8479 and its new display-start position.  Note that the value of `window-end'
8480 is not valid when these functions are called.
8481 */ );
8482   Vwindow_scroll_functions = Qnil;
8483
8484   DEFVAR_LISP ("redisplay-end-trigger-functions",
8485                &Vredisplay_end_trigger_functions /*
8486 See `set-window-redisplay-end-trigger'.
8487 */ );
8488   Vredisplay_end_trigger_functions = Qnil;
8489
8490   DEFVAR_BOOL ("column-number-start-at-one", &column_number_start_at_one /*
8491 *Non-nil means column display number starts at 1.
8492 */ );
8493   column_number_start_at_one = 0;
8494 }
8495
8496 void
8497 specifier_vars_of_redisplay (void)
8498 {
8499   DEFVAR_SPECIFIER ("left-margin-width", &Vleft_margin_width /*
8500 *Width of left margin.
8501 This is a specifier; use `set-specifier' to change it.
8502 */ );
8503   Vleft_margin_width = Fmake_specifier (Qnatnum);
8504   set_specifier_fallback (Vleft_margin_width, list1 (Fcons (Qnil, Qzero)));
8505   set_specifier_caching (Vleft_margin_width,
8506                          slot_offset (struct window, left_margin_width),
8507                          some_window_value_changed,
8508                          slot_offset (struct frame, left_margin_width),
8509                          margin_width_changed_in_frame);
8510
8511   DEFVAR_SPECIFIER ("right-margin-width", &Vright_margin_width /*
8512 *Width of right margin.
8513 This is a specifier; use `set-specifier' to change it.
8514 */ );
8515   Vright_margin_width = Fmake_specifier (Qnatnum);
8516   set_specifier_fallback (Vright_margin_width, list1 (Fcons (Qnil, Qzero)));
8517   set_specifier_caching (Vright_margin_width,
8518                          slot_offset (struct window, right_margin_width),
8519                          some_window_value_changed,
8520                          slot_offset (struct frame, right_margin_width),
8521                          margin_width_changed_in_frame);
8522
8523   DEFVAR_SPECIFIER ("minimum-line-ascent", &Vminimum_line_ascent /*
8524 *Minimum ascent height of lines.
8525 This is a specifier; use `set-specifier' to change it.
8526 */ );
8527   Vminimum_line_ascent = Fmake_specifier (Qnatnum);
8528   set_specifier_fallback (Vminimum_line_ascent, list1 (Fcons (Qnil, Qzero)));
8529   set_specifier_caching (Vminimum_line_ascent,
8530                          slot_offset (struct window, minimum_line_ascent),
8531                          some_window_value_changed,
8532                          0, 0);
8533
8534   DEFVAR_SPECIFIER ("minimum-line-descent", &Vminimum_line_descent /*
8535 *Minimum descent height of lines.
8536 This is a specifier; use `set-specifier' to change it.
8537 */ );
8538   Vminimum_line_descent = Fmake_specifier (Qnatnum);
8539   set_specifier_fallback (Vminimum_line_descent, list1 (Fcons (Qnil, Qzero)));
8540   set_specifier_caching (Vminimum_line_descent,
8541                          slot_offset (struct window, minimum_line_descent),
8542                          some_window_value_changed,
8543                          0, 0);
8544
8545   DEFVAR_SPECIFIER ("use-left-overflow", &Vuse_left_overflow /*
8546 *Non-nil means use the left outside margin as extra whitespace when
8547 displaying 'whitespace or 'inside-margin glyphs.
8548 This is a specifier; use `set-specifier' to change it.
8549 */ );
8550   Vuse_left_overflow = Fmake_specifier (Qboolean);
8551   set_specifier_fallback (Vuse_left_overflow, list1 (Fcons (Qnil, Qnil)));
8552   set_specifier_caching (Vuse_left_overflow,
8553                          slot_offset (struct window, use_left_overflow),
8554                          some_window_value_changed,
8555                          0, 0);
8556
8557   DEFVAR_SPECIFIER ("use-right-overflow", &Vuse_right_overflow /*
8558 *Non-nil means use the right outside margin as extra whitespace when
8559 displaying 'whitespace or 'inside-margin glyphs.
8560 This is a specifier; use `set-specifier' to change it.
8561 */ );
8562   Vuse_right_overflow = Fmake_specifier (Qboolean);
8563   set_specifier_fallback (Vuse_right_overflow, list1 (Fcons (Qnil, Qnil)));
8564   set_specifier_caching (Vuse_right_overflow,
8565                          slot_offset (struct window, use_right_overflow),
8566                          some_window_value_changed,
8567                          0, 0);
8568
8569   DEFVAR_SPECIFIER ("text-cursor-visible-p", &Vtext_cursor_visible_p /*
8570 *Non-nil means the text cursor is visible (this is usually the case).
8571 This is a specifier; use `set-specifier' to change it.
8572 */ );
8573   Vtext_cursor_visible_p = Fmake_specifier (Qboolean);
8574   set_specifier_fallback (Vtext_cursor_visible_p, list1 (Fcons (Qnil, Qt)));
8575   set_specifier_caching (Vtext_cursor_visible_p,
8576                          slot_offset (struct window, text_cursor_visible_p),
8577                          text_cursor_visible_p_changed,
8578                          0, 0);
8579
8580 }