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