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