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