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