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