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