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