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