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