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