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