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