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