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