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