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