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