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