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