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