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