95e171ee1a86e7658c9bb4dd24f1d8a1175ad379
[chise/xemacs-chise.git.1] / src / redisplay.c
1 /* Display generation from window structure and buffer text.
2    Copyright (C) 1994, 1995, 1996 Board of Trustees, University of Illinois.
3    Copyright (C) 1995 Free Software Foundation, Inc.
4    Copyright (C) 1995, 1996 Ben Wing.
5    Copyright (C) 1995 Sun Microsystems, Inc.
6    Copyright (C) 1996 Chuck Thompson.
7
8 This file is part of XEmacs.
9
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
14
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING.  If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.  */
24
25 /* Synched up with:  Not in FSF. */
26
27 /* Author: Chuck Thompson */
28
29 /* Fixed up by Ben Wing for Mule */
30
31 /* This file has been Mule-ized. */
32
33 /*****************************************************************************
34  The Golden Rules of Redisplay
35
36  First:         It Is Better To Be Correct Than Fast
37  Second:        Thou Shalt Not Run Elisp From Within Redisplay
38  Third:         It Is Better To Be Fast Than Not To Be
39  ****************************************************************************/
40
41 #include <config.h>
42 #include "lisp.h"
43 #include <limits.h>
44
45 #include "buffer.h"
46 #include "commands.h"
47 #include "debug.h"
48 #include "device.h"
49 #include "elhash.h"
50 #include "extents.h"
51 #include "faces.h"
52 #include "frame.h"
53 #include "glyphs.h"
54 #include "gutter.h"
55 #include "insdel.h"
56 #include "menubar.h"
57 #include "objects.h"
58 #include "process.h"
59 #include "redisplay.h"
60 #include "toolbar.h"
61 #include "window.h"
62 #include "line-number.h"
63 #ifdef FILE_CODING
64 #include "file-coding.h"
65 #endif
66
67 #ifdef HAVE_TTY
68 #include "console-tty.h"
69 #ifdef HAVE_UNISTD_H
70 #include <unistd.h> /* for isatty() */
71 #endif
72 #endif /* HAVE_TTY */
73
74 /* Note: We have to be careful throughout this code to properly handle
75    and differentiate between Bufbytes and Emchars.
76
77    Since strings are generally composed of Bufbytes, I've taken the tack
78    that any contiguous set of Bufbytes is called a "string", while
79    any contiguous set of Emchars is called an "array". */
80
81 /* Return value to indicate a failure by an add_*_rune routine to add
82    a rune, but no propagation information needs to be returned. */
83 #define ADD_FAILED (prop_block_dynarr *) 1
84
85 #define BEGIN_GLYPHS    0
86 #define END_GLYPHS      1
87 #define LEFT_GLYPHS     2
88 #define RIGHT_GLYPHS    3
89
90 #define VERTICAL_CLIP(w, display)                                       \
91     ((WINDOW_TTY_P (w) | (!display && scroll_on_clipped_lines))         \
92       ? INT_MAX                                                         \
93       : vertical_clip)
94
95 /* The following structures are completely private to redisplay.c so
96    we put them here instead of in a header file, for modularity. */
97
98 /* NOTE: Bytinds not Bufpos's in this structure. */
99
100 typedef struct position_redisplay_data_type
101 {
102   /* This information is normally filled in by the create_*_block
103      routines and is used by the add_*_rune routines. */
104   Lisp_Object window;
105   /* if we are working with strings rather than buffers we need a
106      handle to the string */
107   Lisp_Object string;
108   struct device *d;
109   struct display_block *db;
110   struct display_line *dl;
111   Emchar ch;            /* Character that is to be added.  This is
112                            used to communicate this information to
113                            add_emchar_rune(). */
114   Lisp_Object last_charset; /* The charset of the previous character.
115                                Used to optimize some lookups -- we
116                                only have to do some things when
117                                the charset changes. */
118   face_index last_findex;   /* The face index of the previous character.
119                                Needed to ensure the validity of the
120                                last_charset optimization. */
121
122   int last_char_width;  /* The width of the previous character. */
123   int font_is_bogus;    /* If true, it means we couldn't instantiate
124                            the font for this charset, so we substitute
125                            ~'s from the ASCII charset. */
126   Bytind bi_bufpos;
127   Bytind bi_endpos;
128   int pixpos;
129   int max_pixpos;
130   int blank_width;      /* Width of the blank that is to be added.
131                            This is used to communicate this information
132                            to add_blank_rune().
133
134                            This is also used rather cheesily to
135                            communicate the width of the eol-cursor-size
136                            blank that exists at the end of the line.
137                            add_emchar_rune() is called cheesily with
138                            the non-printing char '\n', which is stuck
139                            in the output routines with its width being
140                            BLANK_WIDTH. */
141   Bytind bi_cursor_bufpos;/* This stores the buffer position of the cursor. */
142   unsigned int cursor_type :3;
143   int cursor_x;         /* rune block cursor is at */
144   int start_col;        /* Number of character columns (each column has
145                            a width of the default char width) that still
146                            need to be skipped.  This is used for horizontal
147                            scrolling, where a certain number of columns
148                            (those off the left side of the screen) need
149                            to be skipped before anything is displayed. */
150   Bytind bi_start_col_enabled;
151   int start_col_xoffset;        /* Number of pixels that still need to
152                            be skipped.  This is used for
153                            horizontal scrolling of glyphs, where we want
154                            to be able to scroll over part of the glyph. */
155
156   int hscroll_glyph_width_adjust;  /* how much the width of the hscroll
157                                       glyph differs from space_width (w).
158                                       0 if no hscroll glyph was used,
159                                       i.e. the window is not scrolled
160                                       horizontally.  Used in tab
161                                       calculations. */
162
163   /* Information about the face the text should be displayed in and
164      any begin-glyphs and end-glyphs. */
165   struct extent_fragment *ef;
166   face_index findex;
167
168   /* The height of a pixmap may either be predetermined if the user
169      has set a baseline value, or it may be dependent on whatever the
170      line ascent and descent values end up being, based just on font
171      information.  In the first case we can immediately update the
172      values, thus their inclusion here.  In the last case we cannot
173      determine the actual contribution to the line height until we
174      have finished laying out all text on the line.  Thus we propagate
175      the max height of such pixmaps and do a final calculation after
176      all text has been added to the line. */
177   int new_ascent;
178   int new_descent;
179   int max_pixmap_height;
180
181   Lisp_Object result_str; /* String where we put the result of
182                              generating a formatted string in the modeline. */
183   int is_modeline; /* Non-zero if we're generating the modeline. */
184   Charcount modeline_charpos; /* Number of chars used in result_str so far;
185                                  corresponds to bytepos. */
186   Bytecount bytepos; /* Number of bytes used in result_str so far.
187                         We don't actually copy the bytes into result_str
188                         until the end because we don't know how big the
189                         string is going to be until then. */
190 } pos_data;
191
192 enum prop_type
193 {
194   PROP_STRING,
195   PROP_CHAR,
196   PROP_MINIBUF_PROMPT,
197   PROP_BLANK
198 };
199
200 /* Data that should be propagated to the next line.  Either a single
201    Emchar or a string of Bufbyte's.
202
203    The actual data that is propagated ends up as a Dynarr of these
204    blocks.
205
206    #### It's unclean that both Emchars and Bufbytes are here.
207    */
208
209 typedef struct prop_block prop_block;
210 struct prop_block
211 {
212   enum prop_type type;
213
214   union data
215   {
216     struct
217     {
218       Bufbyte *str;
219       Bytecount len; /* length of the string. */
220     } p_string;
221
222     struct
223     {
224       Emchar ch;
225       Bytind bi_cursor_bufpos; /* NOTE: is in Bytinds */
226       unsigned int cursor_type :3;
227     } p_char;
228
229     struct
230     {
231       int width;
232       face_index findex;
233     } p_blank;
234   } data;
235 };
236
237 typedef struct
238 {
239   Dynarr_declare (prop_block);
240 } prop_block_dynarr;
241
242
243 static Charcount generate_fstring_runes (struct window *w, pos_data *data,
244                                          Charcount pos, Charcount min_pos,
245                                          Charcount max_pos, Lisp_Object elt,
246                                          int depth, int max_pixsize,
247                                          face_index findex, int type,
248                                          Charcount *offset,
249                                          Lisp_Object cur_ext);
250 static prop_block_dynarr *add_glyph_rune (pos_data *data,
251                                           struct glyph_block *gb,
252                                           int pos_type, int allow_cursor,
253                                           struct glyph_cachel *cachel);
254 static Bytind create_text_block (struct window *w, struct display_line *dl,
255                                  Bytind bi_start_pos, prop_block_dynarr **prop,
256                                  int type);
257 static int create_overlay_glyph_block (struct window *w,
258                                        struct display_line *dl);
259 static void create_left_glyph_block (struct window *w,
260                                      struct display_line *dl,
261                                      int overlay_width);
262 static void create_right_glyph_block (struct window *w,
263                                       struct display_line *dl);
264 static void redisplay_windows (Lisp_Object window, int skip_selected);
265 static void decode_mode_spec (struct window *w, Emchar spec, int type);
266 static void free_display_line (struct display_line *dl);
267 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
268                                      Bufpos point, int no_regen);
269 static int point_visible (struct window *w, Bufpos point, int type);
270
271 /* This used to be 10 but 30 seems to give much better performance. */
272 #define INIT_MAX_PREEMPTS       30
273 static int max_preempts;
274
275 #define REDISPLAY_PREEMPTION_CHECK                                      \
276 ((void)                                                                 \
277  (preempted =                                                           \
278   (!disable_preemption &&                                               \
279    ((preemption_count < max_preempts) || !NILP (Vexecuting_macro)) &&   \
280    (!INTERACTIVE || detect_input_pending ()))))
281
282 /*
283  * Redisplay global variables.
284  */
285
286 /* We need a third set of display structures for the cursor motion
287    routines.  We used to just give each window a third set.  However,
288    we always fully regenerate the structures when needed so there
289    isn't any reason we need more than a single set. */
290 display_line_dynarr *cmotion_display_lines;
291
292 /* We store the extents that we need to generate in a Dynarr and then
293    frob them all on at the end of generating the string.  We do it
294    this way rather than adding them as we generate the string because
295    we don't store the text into the resulting string until we're done
296    (to avoid having to resize the string multiple times), and we don't
297    want to go around adding extents to a string when the extents might
298    stretch off the end of the string. */
299 static EXTENT_dynarr *formatted_string_extent_dynarr;
300 static Bytecount_dynarr *formatted_string_extent_start_dynarr;
301 static Bytecount_dynarr *formatted_string_extent_end_dynarr;
302
303
304 /* #### probably temporary */
305 int cache_adjustment;
306
307 /* This holds a string representing the text corresponding to a single
308    modeline % spec. */
309 static Bufbyte_dynarr *mode_spec_bufbyte_string;
310
311 int in_display;         /* 1 if in redisplay.  */
312
313 int disable_preemption; /* Used for debugging redisplay and for
314                            force-redisplay. */
315
316 /* We only allow max_preempts preemptions before we force a redisplay. */
317 static int preemption_count;
318
319 /* Minimum pixel height of clipped bottom display line. */
320 int vertical_clip;
321
322 /* Minimum visible pixel width of clipped glyphs at right margin. */
323 int horizontal_clip;
324
325 /* Nonzero means reading single-character input with prompt
326    so put cursor on minibuffer after the prompt.  */
327 int cursor_in_echo_area;
328 Lisp_Object Qcursor_in_echo_area;
329
330 /* Nonzero means truncate lines in all windows less wide than the frame */
331 int truncate_partial_width_windows;
332
333 /* non-nil if a buffer has changed since the last time redisplay completed */
334 int buffers_changed;
335 int buffers_changed_set;
336
337 /* non-nil if hscroll has changed somewhere or a buffer has been
338    narrowed or widened */
339 int clip_changed;
340 int clip_changed_set;
341
342 /* non-nil if any extent has changed since the last time redisplay completed */
343 int extents_changed;
344 int extents_changed_set;
345
346 /* non-nil if any face has changed since the last time redisplay completed */
347 int faces_changed;
348
349 /* Nonzero means some frames have been marked as garbaged */
350 int frame_changed;
351
352 /* non-zero if any of the builtin display glyphs (continuation,
353    hscroll, control-arrow, etc) is in need of updating
354    somewhere. */
355 int glyphs_changed;
356 int glyphs_changed_set;
357
358 /* non-zero if any subwindow has been deleted. */
359 int subwindows_changed;
360 int subwindows_changed_set;
361
362 /* non-zero if any displayed subwindow is in need of updating
363    somewhere. */
364 int subwindows_state_changed;
365 int subwindows_state_changed_set;
366
367 /* This variable is 1 if the icon has to be updated.
368  It is set to 1 when `frame-icon-glyph' changes. */
369 int icon_changed;
370 int icon_changed_set;
371
372 /* This variable is 1 if the menubar widget has to be updated.
373  It is set to 1 by set-menubar-dirty-flag and cleared when the widget
374  has been updated. */
375 int menubar_changed;
376 int menubar_changed_set;
377
378 /* true iff we should redraw the modelines on the next redisplay */
379 int modeline_changed;
380 int modeline_changed_set;
381
382 /* non-nil if point has changed in some buffer since the last time
383    redisplay completed */
384 int point_changed;
385 int point_changed_set;
386
387 /* non-nil if some frame has changed its size */
388 int size_changed;
389
390 /* non-nil if some device has signaled that it wants to change size */
391 int asynch_device_change_pending;
392
393 /* non-nil if any toolbar has changed */
394 int toolbar_changed;
395 int toolbar_changed_set;
396
397 /* non-nil if any gutter has changed */
398 int gutter_changed;
399 int gutter_changed_set;
400
401 /* non-nil if any window has changed since the last time redisplay completed */
402 int windows_changed;
403
404 /* non-nil if any frame's window structure has changed since the last
405    time redisplay completed */
406 int windows_structure_changed;
407
408 /* If non-nil, use vertical bar cursor. */
409 Lisp_Object Vbar_cursor;
410 Lisp_Object Qbar_cursor;
411
412 Lisp_Object Vvisible_bell;      /* If true and the terminal will support it
413                                    then the frame will flash instead of
414                                    beeping when an error occurs */
415
416 /* Nonzero means no need to redraw the entire frame on resuming
417    a suspended Emacs.  This is useful on terminals with multiple pages,
418    where one page is used for Emacs and another for all else. */
419 int no_redraw_on_reenter;
420
421 Lisp_Object Vwindow_system;     /* nil or a symbol naming the window system
422                                    under which emacs is running
423                                    ('x is the only current possibility) */
424 Lisp_Object Vinitial_window_system;
425
426 Lisp_Object Vglobal_mode_string;
427
428 /* The number of lines scroll a window by when point leaves the window; if
429   it is <=0 then point is centered in the window */
430 int scroll_step;
431
432 /* Scroll up to this many lines, to bring point back on screen. */
433 int scroll_conservatively;
434
435 /* Marker for where to display an arrow on top of the buffer text.  */
436 Lisp_Object Voverlay_arrow_position;
437 /* String to display for the arrow.  */
438 Lisp_Object Voverlay_arrow_string;
439
440 Lisp_Object Vwindow_size_change_functions;
441 Lisp_Object Vwindow_scroll_functions;
442 Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions;
443
444 Lisp_Object Qbuffer_list_changed_hook, Vbuffer_list_changed_hook;
445
446
447 #define INHIBIT_REDISPLAY_HOOKS  /* #### Until we've thought about
448                                     this more. */
449 #ifndef INHIBIT_REDISPLAY_HOOKS
450 /* #### Chuck says: I think this needs more thought.
451    Think about this for 19.14. */
452 Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook;
453 Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook;
454 #endif /* INHIBIT_REDISPLAY_HOOKS */
455
456 static int last_display_warning_tick, display_warning_tick;
457 Lisp_Object Qdisplay_warning_buffer;
458 int inhibit_warning_display;
459
460 Lisp_Object Vleft_margin_width, Vright_margin_width;
461 Lisp_Object Vminimum_line_ascent, Vminimum_line_descent;
462 Lisp_Object Vuse_left_overflow, Vuse_right_overflow;
463 Lisp_Object Vtext_cursor_visible_p;
464
465 int column_number_start_at_one;
466
467 Lisp_Object Qtop_bottom;
468
469 #define WINDOW_SCROLLED(w) \
470 (w->hscroll > 0 || w->left_xoffset)
471
472 \f
473 /***************************************************************************/
474 /*                                                                         */
475 /*              low-level interfaces onto device routines                  */
476 /*                                                                         */
477 /***************************************************************************/
478
479 static int
480 redisplay_text_width_emchar_string (struct window *w, int findex,
481                                     Emchar *str, Charcount len)
482 {
483   unsigned char charsets[NUM_LEADING_BYTES];
484   Lisp_Object window;
485
486   find_charsets_in_emchar_string (charsets, str, len);
487   XSETWINDOW (window, w);
488   ensure_face_cachel_complete (WINDOW_FACE_CACHEL (w, findex), window,
489                                charsets);
490   return DEVMETH (XDEVICE (FRAME_DEVICE (XFRAME (WINDOW_FRAME (w)))),
491                   text_width, (XFRAME (WINDOW_FRAME (w)),
492                                WINDOW_FACE_CACHEL (w, findex), str, len));
493 }
494
495 static Emchar_dynarr *rtw_emchar_dynarr;
496
497 int
498 redisplay_text_width_string (struct window *w, int findex,
499                              Bufbyte *nonreloc, Lisp_Object reloc,
500                              Bytecount offset, Bytecount len)
501 {
502   if (!rtw_emchar_dynarr)
503     rtw_emchar_dynarr = Dynarr_new (Emchar);
504   Dynarr_reset (rtw_emchar_dynarr);
505
506   fixup_internal_substring (nonreloc, reloc, offset, &len);
507   if (STRINGP (reloc))
508     nonreloc = XSTRING_DATA (reloc);
509   convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
510   return redisplay_text_width_emchar_string
511     (w, findex, Dynarr_atp (rtw_emchar_dynarr, 0),
512      Dynarr_length (rtw_emchar_dynarr));
513 }
514
515 int
516 redisplay_frame_text_width_string (struct frame *f, Lisp_Object face,
517                                    Bufbyte *nonreloc, Lisp_Object reloc,
518                                    Bytecount offset, Bytecount len)
519 {
520   unsigned char charsets[NUM_LEADING_BYTES];
521   Lisp_Object frame;
522   struct face_cachel cachel;
523
524   if (!rtw_emchar_dynarr)
525     rtw_emchar_dynarr = Dynarr_new (Emchar);
526   Dynarr_reset (rtw_emchar_dynarr);
527
528   fixup_internal_substring (nonreloc, reloc, offset, &len);
529   if (STRINGP (reloc))
530     nonreloc = XSTRING_DATA (reloc);
531   convert_bufbyte_string_into_emchar_dynarr (nonreloc, len, rtw_emchar_dynarr);
532   find_charsets_in_bufbyte_string (charsets, nonreloc, len);
533   reset_face_cachel (&cachel);
534   cachel.face = face;
535   XSETFRAME (frame, f);
536   ensure_face_cachel_complete (&cachel, frame, charsets);
537   return DEVMETH (XDEVICE (FRAME_DEVICE (f)),
538                   text_width, (f, &cachel, Dynarr_atp (rtw_emchar_dynarr, 0),
539                                Dynarr_length (rtw_emchar_dynarr)));
540 }
541
542 /* Return the display block from DL of the given TYPE.  A display line
543    can have only one display block of each possible type.  If DL does
544    not have a block of type TYPE, one will be created and added to DL. */
545
546 struct display_block *
547 get_display_block_from_line (struct display_line *dl, enum display_type type)
548 {
549   int elt;
550   struct display_block db;
551
552   /* Check if this display line already has a block of the desired type and
553      if so, return it. */
554   if (dl->display_blocks)
555     {
556       for (elt = 0; elt < Dynarr_length (dl->display_blocks); elt++)
557         {
558           if (Dynarr_at (dl->display_blocks, elt).type == type)
559             return Dynarr_atp (dl->display_blocks, elt);
560         }
561
562       /* There isn't an active block of the desired type, but there
563          might still be allocated blocks we need to reuse. */
564       if (elt < Dynarr_largest (dl->display_blocks))
565         {
566           struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
567
568           /* 'add' the block to the list */
569           Dynarr_increment (dl->display_blocks);
570
571           /* initialize and return */
572           dbp->type = type;
573           return dbp;
574         }
575     }
576   else
577     {
578       /* This line doesn't have any display blocks, so initialize the display
579          bock array. */
580       dl->display_blocks = Dynarr_new (display_block);
581     }
582
583   /* The line doesn't have a block of the desired type so go ahead and create
584      one and add it to the line. */
585   xzero (db);
586   db.type = type;
587   db.runes = Dynarr_new (rune);
588   Dynarr_add (dl->display_blocks, db);
589
590   /* Return the newly added display block. */
591   elt = Dynarr_length (dl->display_blocks) - 1;
592
593   return Dynarr_atp (dl->display_blocks, elt);
594 }
595
596 static int
597 tab_char_width (struct window *w)
598 {
599   struct buffer *b = XBUFFER (w->buffer);
600   int char_tab_width = XINT (b->tab_width);
601
602   if (char_tab_width <= 0 || char_tab_width > 1000) char_tab_width = 8;
603
604   return char_tab_width;
605 }
606
607 static int
608 space_width (struct window *w)
609 {
610   /* While tabs are traditional composed of spaces, for variable-width
611      fonts the space character tends to give too narrow a value.  So
612      we use 'n' instead.  Except that we don't.  We use the default
613      character width for the default face.  If this is actually
614      defined by the font then it is probably the best thing to
615      actually use.  If it isn't, we have assumed it is 'n' and have
616      already calculated its width.  Thus we can avoid a call to
617      XTextWidth on X frames by just querying the default width. */
618   return XFONT_INSTANCE
619     (WINDOW_FACE_CACHEL_FONT (w, DEFAULT_INDEX, Vcharset_ascii))->width;
620 }
621
622 static int
623 tab_pix_width (struct window *w)
624 {
625   return space_width (w) * tab_char_width (w);
626 }
627
628 /* Given a pixel position in a window, return the pixel location of
629    the next tabstop.  Tabs are calculated from the left window edge in
630    terms of spaces displayed in the default face.  Formerly the space
631    width was determined using the currently active face.  That method
632    leads to tabstops which do not line up. */
633
634 static int
635 next_tab_position (struct window *w, int start_pixpos, int left_pixpos)
636 {
637   int n_pos = left_pixpos;
638   int pix_tab_width = tab_pix_width (w);
639
640   /* Adjust n_pos for any hscrolling which has happened. */
641   if (WINDOW_SCROLLED (w))
642     n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset;
643
644   while (n_pos <= start_pixpos)
645     n_pos += pix_tab_width;
646
647   return n_pos;
648 }
649
650 /* For the given window, calculate the outside and margin boundaries for a
651    display line.  The whitespace boundaries must be calculated by the text
652    layout routines. */
653
654 layout_bounds
655 calculate_display_line_boundaries (struct window *w, int modeline)
656 {
657   layout_bounds bounds;
658
659   /* Set the outermost boundaries which are the boundaries of the
660      window itself minus the gutters (and minus the scrollbars if this
661      is for the modeline). */
662   if (!modeline)
663     {
664       bounds.left_out = WINDOW_TEXT_LEFT (w);
665       bounds.right_out = WINDOW_TEXT_RIGHT (w);
666     }
667   else
668     {
669       bounds.left_out = WINDOW_MODELINE_LEFT (w);
670       bounds.right_out = WINDOW_MODELINE_RIGHT (w);
671     }
672
673   /* The inner boundaries mark where the glyph margins are located. */
674   bounds.left_in = bounds.left_out + window_left_margin_width (w);
675   bounds.right_in = bounds.right_out - window_right_margin_width (w);
676
677   /* We cannot fully calculate the whitespace boundaries as they
678      depend on the contents of the line being displayed. */
679   bounds.left_white = bounds.left_in;
680   bounds.right_white = bounds.right_in;
681
682   return bounds;
683 }
684
685 /* Given a display line and a starting position, ensure that the
686    contents of the display line accurately represent the visual
687    representation of the buffer contents starting from the given
688    position when displayed in the given window.  The display line ends
689    when the contents of the line reach the right boundary of the given
690    window. */
691
692 static Bufpos
693 generate_display_line (struct window *w, struct display_line *dl, int bounds,
694                        Bufpos start_pos, prop_block_dynarr **prop,
695                        int type)
696 {
697   Bufpos ret_bufpos;
698   int overlay_width;
699   struct buffer *b = XBUFFER (WINDOW_BUFFER (w));
700
701   /* If our caller hasn't already set the boundaries, then do so now. */
702   if (!bounds)
703     dl->bounds = calculate_display_line_boundaries (w, 0);
704
705   /* Reset what this line is using. */
706   if (dl->display_blocks)
707     Dynarr_reset (dl->display_blocks);
708   if (dl->left_glyphs)
709     {
710       Dynarr_free (dl->left_glyphs);
711       dl->left_glyphs = 0;
712     }
713   if (dl->right_glyphs)
714     {
715       Dynarr_free (dl->right_glyphs);
716       dl->right_glyphs = 0;
717     }
718
719   /* We aren't generating a modeline at the moment. */
720   dl->modeline = 0;
721
722   /* Create a display block for the text region of the line. */
723   {
724     /* #### urk urk urk!!! Chuck fix this shit! */
725     Bytind hacked_up_bytind =
726       create_text_block (w, dl, bufpos_to_bytind (b, start_pos),
727                          prop, type);
728     if (hacked_up_bytind > BI_BUF_ZV (b))
729       ret_bufpos = BUF_ZV (b) + 1;
730     else
731       ret_bufpos = bytind_to_bufpos (b, hacked_up_bytind);
732   }
733   dl->bufpos = start_pos;
734   if (dl->end_bufpos < dl->bufpos)
735     dl->end_bufpos = dl->bufpos;
736
737   if (MARKERP (Voverlay_arrow_position)
738       && EQ (w->buffer, Fmarker_buffer (Voverlay_arrow_position))
739       && start_pos == marker_position (Voverlay_arrow_position)
740       && (STRINGP (Voverlay_arrow_string)
741           || GLYPHP (Voverlay_arrow_string)))
742     {
743       overlay_width = create_overlay_glyph_block (w, dl);
744     }
745   else
746     overlay_width = 0;
747
748   /* If there are left glyphs associated with any character in the
749      text block, then create a display block to handle them. */
750   if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
751     create_left_glyph_block (w, dl, overlay_width);
752
753   /* If there are right glyphs associated with any character in the
754      text block, then create a display block to handle them. */
755   if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
756     create_right_glyph_block (w, dl);
757
758   /* In the future additional types of display blocks may be generated
759      here. */
760
761   w->last_redisplay_pos = ret_bufpos;
762
763   return ret_bufpos;
764 }
765
766 /* Adds an hscroll glyph to a display block.  If this is called, then
767    the block had better be empty.
768
769    Yes, there are multiple places where this function is called but
770    that is the way it has to be.  Each calling function has to deal
771    with bi_start_col_enabled a little differently depending on the
772    object being worked with. */
773
774 static prop_block_dynarr *
775 add_hscroll_rune (pos_data *data)
776 {
777   struct glyph_block gb;
778   prop_block_dynarr *retval;
779   Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
780   unsigned int old_cursor_type = data->cursor_type;
781   Bytind bi_old_bufpos = data->bi_bufpos;
782
783   if (data->cursor_type == CURSOR_ON
784       && data->bi_cursor_bufpos >= data->bi_start_col_enabled
785       && data->bi_cursor_bufpos <= data->bi_bufpos)
786     {
787       data->bi_cursor_bufpos = data->bi_start_col_enabled;
788     }
789   else
790     {
791       data->cursor_type = NO_CURSOR;
792     }
793
794   data->bi_endpos = data->bi_bufpos;
795   data->bi_bufpos = data->bi_start_col_enabled;
796
797   gb.extent = Qnil;
798   gb.glyph = Vhscroll_glyph;
799   {
800     int oldpixpos = data->pixpos;
801     retval = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0,
802                              GLYPH_CACHEL (XWINDOW (data->window),
803                                            HSCROLL_GLYPH_INDEX));
804     data->hscroll_glyph_width_adjust =
805       data->pixpos - oldpixpos - space_width (XWINDOW (data->window));
806   }
807   data->bi_endpos = 0;
808   data->bi_cursor_bufpos = bi_old_cursor_bufpos;
809   data->cursor_type = old_cursor_type;
810   data->bi_bufpos = bi_old_bufpos;
811
812   data->bi_start_col_enabled = 0;
813   return retval;
814 }
815
816 /* Adds a character rune to a display block.  If there is not enough
817    room to fit the rune on the display block (as determined by the
818    MAX_PIXPOS) then it adds nothing and returns ADD_FAILED. */
819
820 static prop_block_dynarr *
821 add_emchar_rune (pos_data *data)
822 {
823   struct rune rb, *crb;
824   int width, local;
825
826   if (data->start_col)
827     {
828       data->start_col--;
829
830       if (data->start_col)
831         return NULL;
832     }
833
834   if (data->bi_start_col_enabled)
835     {
836       return add_hscroll_rune (data);
837     }
838
839   if (data->ch == '\n')
840     {
841       data->font_is_bogus = 0;
842       /* Cheesy end-of-line pseudo-character. */
843       width = data->blank_width;
844     }
845   else
846     {
847       Lisp_Object charset = CHAR_CHARSET (data->ch);
848       if (!EQ (charset, data->last_charset) ||
849           data->findex != data->last_findex)
850         {
851           /* OK, we need to do things the hard way. */
852           struct window *w = XWINDOW (data->window);
853           struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, data->findex);
854           Lisp_Object font_instance =
855             ensure_face_cachel_contains_charset (cachel, data->window,
856                                                  charset);
857           Lisp_Font_Instance *fi;
858
859           if (EQ (font_instance, Vthe_null_font_instance))
860             {
861               font_instance = FACE_CACHEL_FONT (cachel, Vcharset_ascii);
862               data->font_is_bogus = 1;
863             }
864           else
865             data->font_is_bogus = 0;
866
867           fi = XFONT_INSTANCE (font_instance);
868           if (!fi->proportional_p)
869             /* sweetness and light. */
870             data->last_char_width = fi->width;
871           else
872             data->last_char_width = -1;
873           data->new_ascent  = max (data->new_ascent,  (int) fi->ascent);
874           data->new_descent = max (data->new_descent, (int) fi->descent);
875           data->last_charset = charset;
876           data->last_findex = data->findex;
877         }
878
879       width = data->last_char_width;
880       if (width < 0)
881         {
882           /* bummer.  Proportional fonts. */
883           width = redisplay_text_width_emchar_string (XWINDOW (data->window),
884                                                       data->findex,
885                                                       &data->ch, 1);
886         }
887     }
888
889   if (data->max_pixpos != -1 && (data->pixpos + width > data->max_pixpos))
890     {
891       return ADD_FAILED;
892     }
893
894   if (Dynarr_length (data->db->runes) < Dynarr_largest (data->db->runes))
895     {
896       crb = Dynarr_atp (data->db->runes, Dynarr_length (data->db->runes));
897       local = 0;
898     }
899   else
900     {
901       crb = &rb;
902       local = 1;
903     }
904
905   crb->findex = data->findex;
906   crb->xpos = data->pixpos;
907   crb->width = width;
908   if (data->bi_bufpos)
909     {
910       if (NILP (data->string))
911         crb->bufpos =
912           bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
913                             data->bi_bufpos);
914       else
915         crb->bufpos =
916           bytecount_to_charcount (XSTRING_DATA (data->string), data->bi_bufpos);
917     }
918   else if (data->is_modeline)
919     crb->bufpos = data->modeline_charpos;
920   else
921     /* Text but not in buffer */
922     crb->bufpos = 0;
923   crb->type = RUNE_CHAR;
924   crb->object.chr.ch = data->font_is_bogus ? '~' : data->ch;
925   crb->endpos = 0;
926
927   if (data->cursor_type == CURSOR_ON)
928     {
929       if (data->bi_bufpos == data->bi_cursor_bufpos)
930         {
931           crb->cursor_type = CURSOR_ON;
932           data->cursor_x = Dynarr_length (data->db->runes);
933         }
934       else
935         crb->cursor_type = CURSOR_OFF;
936     }
937   else if (data->cursor_type == NEXT_CURSOR)
938     {
939       crb->cursor_type = CURSOR_ON;
940       data->cursor_x = Dynarr_length (data->db->runes);
941       data->cursor_type = NO_CURSOR;
942     }
943   else if (data->cursor_type == IGNORE_CURSOR)
944     crb->cursor_type = IGNORE_CURSOR;
945   else
946     crb->cursor_type = CURSOR_OFF;
947
948   if (local)
949     Dynarr_add (data->db->runes, *crb);
950   else
951     Dynarr_increment (data->db->runes);
952
953   data->pixpos += width;
954
955   return NULL;
956 }
957
958 /* Given a string C_STRING of length C_LENGTH, call add_emchar_rune
959    for each character in the string.  Propagate any left-over data
960    unless NO_PROP is non-zero. */
961
962 static prop_block_dynarr *
963 add_bufbyte_string_runes (pos_data *data, Bufbyte *c_string,
964                           Bytecount c_length, int no_prop)
965 {
966   Bufbyte *pos, *end = c_string + c_length;
967   prop_block_dynarr *prop;
968
969   /* #### This function is too simplistic.  It needs to do the same
970      sort of character interpretation (display-table lookup,
971      ctl-arrow checking), etc. that create_text_block() does.
972      The functionality to do this in that routine needs to be
973      modularized. */
974
975   for (pos = c_string; pos < end;)
976     {
977       data->ch = charptr_emchar (pos);
978
979       prop = add_emchar_rune (data);
980
981       if (prop)
982         {
983           if (no_prop)
984             return ADD_FAILED;
985           else
986             {
987               struct prop_block pb;
988               Bytecount len = end - pos;
989               prop = Dynarr_new (prop_block);
990
991               pb.type = PROP_STRING;
992               pb.data.p_string.str = xnew_array (Bufbyte, len);
993               strncpy ((char *) pb.data.p_string.str, (char *) pos, len);
994               pb.data.p_string.len = len;
995
996               Dynarr_add (prop, pb);
997               return prop;
998             }
999         }
1000       INC_CHARPTR (pos);
1001       assert (pos <= end);
1002     }
1003
1004   return NULL;
1005 }
1006
1007 /* Add a single rune of the specified width.  The area covered by this
1008    rune will be displayed in the foreground color of the associated
1009    face. */
1010
1011 static prop_block_dynarr *
1012 add_blank_rune (pos_data *data, struct window *w, int char_tab_width)
1013 {
1014   struct rune rb;
1015
1016   /* If data->start_col is not 0 then this call to add_blank_rune must have
1017      been to add it as a tab. */
1018   if (data->start_col)
1019     {
1020       /* assert (w != NULL) */
1021       prop_block_dynarr *retval;
1022
1023       /* If we have still not fully scrolled horizontally, subtract
1024          the width of this tab and return. */
1025       if (char_tab_width < data->start_col)
1026         {
1027           data->start_col -= char_tab_width;
1028           return NULL;
1029         }
1030       else if (char_tab_width == data->start_col)
1031         data->blank_width = 0;
1032       else
1033         {
1034           int spcwid = space_width (w);
1035
1036           if (spcwid >= data->blank_width)
1037             data->blank_width = 0;
1038           else
1039             data->blank_width -= spcwid;
1040         }
1041
1042       data->start_col = 0;
1043       retval = add_hscroll_rune (data);
1044
1045       /* Could be caused by the handling of the hscroll rune. */
1046       if (retval != NULL || !data->blank_width)
1047         return retval;
1048     }
1049
1050   /* Blank runes are always calculated to fit. */
1051   assert (data->pixpos + data->blank_width <= data->max_pixpos);
1052
1053   rb.findex = data->findex;
1054   rb.xpos = data->pixpos;
1055   rb.width = data->blank_width;
1056   if (data->bi_bufpos)
1057     rb.bufpos =
1058       bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (XWINDOW (data->window))),
1059                         data->bi_bufpos);
1060   else
1061     /* #### and this is really correct too? */
1062     rb.bufpos = 0;
1063   rb.endpos = 0;
1064   rb.type = RUNE_BLANK;
1065
1066   if (data->cursor_type == CURSOR_ON)
1067     {
1068       if (data->bi_bufpos == data->bi_cursor_bufpos)
1069         {
1070           rb.cursor_type = CURSOR_ON;
1071           data->cursor_x = Dynarr_length (data->db->runes);
1072         }
1073       else
1074         rb.cursor_type = CURSOR_OFF;
1075     }
1076   else if (data->cursor_type == NEXT_CURSOR)
1077     {
1078       rb.cursor_type = CURSOR_ON;
1079       data->cursor_x = Dynarr_length (data->db->runes);
1080       data->cursor_type = NO_CURSOR;
1081     }
1082   else
1083     rb.cursor_type = CURSOR_OFF;
1084
1085   Dynarr_add (data->db->runes, rb);
1086   data->pixpos += data->blank_width;
1087
1088   return NULL;
1089 }
1090
1091 /* Add runes representing a character in octal. */
1092
1093 #define ADD_NEXT_OCTAL_RUNE_CHAR do                             \
1094 {                                                               \
1095   if (add_failed || (add_failed = add_emchar_rune (data)))      \
1096     {                                                           \
1097       struct prop_block pb;                                     \
1098       if (!prop)                                                \
1099         prop = Dynarr_new (prop_block);                         \
1100                                                                 \
1101       pb.type = PROP_CHAR;                                      \
1102       pb.data.p_char.ch = data->ch;                             \
1103       pb.data.p_char.cursor_type = data->cursor_type;           \
1104       Dynarr_add (prop, pb);                                    \
1105     }                                                           \
1106 } while (0)
1107
1108 static prop_block_dynarr *
1109 add_octal_runes (pos_data *data)
1110 {
1111   prop_block_dynarr *prop, *add_failed;
1112   Emchar orig_char = data->ch;
1113   unsigned int orig_cursor_type = data->cursor_type;
1114
1115   /* Initialize */
1116   prop = NULL;
1117   add_failed = NULL;
1118
1119   if (data->start_col)
1120     data->start_col--;
1121
1122   if (!data->start_col)
1123     {
1124     if (data->bi_start_col_enabled)
1125       {
1126         add_failed = add_hscroll_rune (data);
1127       }
1128     else
1129       {
1130         struct glyph_block gb;
1131         struct window *w = XWINDOW (data->window);
1132
1133         gb.extent = Qnil;
1134         gb.glyph = Voctal_escape_glyph;
1135         add_failed =
1136           add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1137                           GLYPH_CACHEL (w, OCT_ESC_GLYPH_INDEX));
1138       }
1139     }
1140
1141   /* We only propagate information if the glyph was partially
1142      added. */
1143   if (add_failed)
1144     return add_failed;
1145
1146   data->cursor_type = IGNORE_CURSOR;
1147
1148   if (data->ch >= 0x100)
1149     {
1150       /* If the character is an extended Mule character, it could have
1151          up to 19 bits.  For the moment, we treat it as a seven-digit
1152          octal number.  This is not that pretty, but whatever. */
1153       data->ch = (7 & (orig_char >> 18)) + '0';
1154       ADD_NEXT_OCTAL_RUNE_CHAR;
1155
1156       data->ch = (7 & (orig_char >> 15)) + '0';
1157       ADD_NEXT_OCTAL_RUNE_CHAR;
1158
1159       data->ch = (7 & (orig_char >> 12)) + '0';
1160       ADD_NEXT_OCTAL_RUNE_CHAR;
1161
1162       data->ch = (7 & (orig_char >> 9)) + '0';
1163       ADD_NEXT_OCTAL_RUNE_CHAR;
1164     }
1165
1166   data->ch = (7 & (orig_char >> 6)) + '0';
1167   ADD_NEXT_OCTAL_RUNE_CHAR;
1168
1169   data->ch = (7 & (orig_char >> 3)) + '0';
1170   ADD_NEXT_OCTAL_RUNE_CHAR;
1171
1172   data->ch = (7 & orig_char) + '0';
1173   ADD_NEXT_OCTAL_RUNE_CHAR;
1174
1175   data->cursor_type = orig_cursor_type;
1176   return prop;
1177 }
1178
1179 #undef ADD_NEXT_OCTAL_RUNE_CHAR
1180
1181 /* Add runes representing a control character to a display block. */
1182
1183 static prop_block_dynarr *
1184 add_control_char_runes (pos_data *data, struct buffer *b)
1185 {
1186   if (!NILP (b->ctl_arrow))
1187     {
1188       prop_block_dynarr *prop;
1189       Emchar orig_char = data->ch;
1190       unsigned int old_cursor_type = data->cursor_type;
1191
1192       /* Initialize */
1193       prop = NULL;
1194
1195       if (data->start_col)
1196         data->start_col--;
1197
1198       if (!data->start_col)
1199         {
1200           if (data->bi_start_col_enabled)
1201             {
1202               prop_block_dynarr *retval;
1203
1204               retval = add_hscroll_rune (data);
1205               if (retval)
1206                 return retval;
1207             }
1208           else
1209             {
1210               struct glyph_block gb;
1211               struct window *w = XWINDOW (data->window);
1212
1213               gb.extent = Qnil;
1214               gb.glyph = Vcontrol_arrow_glyph;
1215
1216               /* We only propagate information if the glyph was partially
1217                  added. */
1218               if (add_glyph_rune (data, &gb, BEGIN_GLYPHS, 1,
1219                                   GLYPH_CACHEL (w, CONTROL_GLYPH_INDEX)))
1220                 return ADD_FAILED;
1221             }
1222         }
1223
1224       if (orig_char == 0177)
1225         data->ch = '?';
1226       else
1227         data->ch = orig_char ^ 0100;
1228       data->cursor_type = IGNORE_CURSOR;
1229
1230       if (add_emchar_rune (data))
1231         {
1232           struct prop_block pb;
1233           if (!prop)
1234             prop = Dynarr_new (prop_block);
1235
1236           pb.type = PROP_CHAR;
1237           pb.data.p_char.ch = data->ch;
1238           pb.data.p_char.cursor_type = data->cursor_type;
1239           Dynarr_add (prop, pb);
1240         }
1241
1242       data->cursor_type = old_cursor_type;
1243       return prop;
1244     }
1245   else
1246     {
1247       return add_octal_runes (data);
1248     }
1249 }
1250
1251 static prop_block_dynarr *
1252 add_disp_table_entry_runes_1 (pos_data *data, Lisp_Object entry)
1253 {
1254   prop_block_dynarr *prop = NULL;
1255
1256   if (STRINGP (entry))
1257     {
1258       prop = add_bufbyte_string_runes (data,
1259                                        XSTRING_DATA   (entry),
1260                                        XSTRING_LENGTH (entry),
1261                                        0);
1262     }
1263   else if (GLYPHP (entry))
1264     {
1265       if (data->start_col)
1266         data->start_col--;
1267
1268       if (!data->start_col && data->bi_start_col_enabled)
1269         {
1270           prop = add_hscroll_rune (data);
1271         }
1272       else
1273         {
1274           struct glyph_block gb;
1275
1276           gb.glyph = entry;
1277           gb.extent = Qnil;
1278           prop = add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
1279         }
1280     }
1281   else if (CHAR_OR_CHAR_INTP (entry))
1282     {
1283       data->ch = XCHAR_OR_CHAR_INT (entry);
1284       prop = add_emchar_rune (data);
1285     }
1286   else if (CONSP (entry))
1287     {
1288       if (EQ (XCAR (entry), Qformat)
1289           && CONSP (XCDR (entry))
1290           && STRINGP (XCAR (XCDR (entry))))
1291         {
1292           Lisp_Object format = XCAR (XCDR (entry));
1293           Bytind len = XSTRING_LENGTH (format);
1294           Bufbyte *src = XSTRING_DATA (format), *end = src + len;
1295           Bufbyte *result = alloca_array (Bufbyte, len);
1296           Bufbyte *dst = result;
1297
1298           while (src < end)
1299             {
1300               Emchar c = charptr_emchar (src);
1301               INC_CHARPTR (src);
1302               if (c != '%' || src == end)
1303                 dst += set_charptr_emchar (dst, c);
1304               else
1305                 {
1306                   c = charptr_emchar (src);
1307                   INC_CHARPTR (src);
1308                   switch (c)
1309                     {
1310                       /*case 'x':
1311                       dst += long_to_string_base ((char *)dst, data->ch, 16);
1312                       break;*/
1313                     case '%':
1314                       dst += set_charptr_emchar (dst, '%');
1315                       break;
1316                       /* #### unimplemented */
1317                     }
1318                 }
1319             }
1320           prop = add_bufbyte_string_runes (data, result, dst - result, 0);
1321         }
1322     }
1323
1324   /* Else blow it off because someone added a bad entry and we don't
1325      have any safe way of signaling an error. */
1326   return prop;
1327 }
1328
1329 /* Given a display table entry, call the appropriate functions to
1330    display each element of the entry. */
1331
1332 static prop_block_dynarr *
1333 add_disp_table_entry_runes (pos_data *data, Lisp_Object entry)
1334 {
1335   prop_block_dynarr *prop = NULL;
1336   if (VECTORP (entry))
1337     {
1338       Lisp_Vector *de = XVECTOR (entry);
1339       EMACS_INT len = vector_length (de);
1340       int elt;
1341
1342       for (elt = 0; elt < len; elt++)
1343         {
1344           if (NILP (vector_data (de)[elt]))
1345             continue;
1346           else
1347             prop = add_disp_table_entry_runes_1 (data, vector_data (de)[elt]);
1348           /* Else blow it off because someone added a bad entry and we
1349              don't have any safe way of signaling an error.  Hey, this
1350              comment sounds familiar. */
1351
1352           /* #### Still need to add any remaining elements to the
1353              propagation information. */
1354           if (prop)
1355             return prop;
1356         }
1357     }
1358   else
1359     prop = add_disp_table_entry_runes_1 (data, entry);
1360   return prop;
1361 }
1362
1363 /* Add runes which were propagated from the previous line. */
1364
1365 static prop_block_dynarr *
1366 add_propagation_runes (prop_block_dynarr **prop, pos_data *data)
1367 {
1368   /* #### Remember to handle start_col parameter of data when the rest of
1369      this is finished. */
1370   /* #### Chuck -- I've redone this function a bit.  It looked like the
1371      case of not all the propagation blocks being added was not handled
1372      well. */
1373   /* #### Chuck -- I also think the double indirection of PROP is kind
1374      of bogus.  A cleaner solution is just to check for
1375      Dynarr_length (prop) > 0. */
1376   /* #### This function also doesn't even pay attention to ADD_FAILED!
1377      This is seriously fucked!  Seven ####'s in 130 lines -- is that a
1378      record? */
1379   int elt;
1380   prop_block_dynarr *add_failed;
1381   Bytind bi_old_cursor_bufpos = data->bi_cursor_bufpos;
1382   unsigned int old_cursor_type = data->cursor_type;
1383
1384   for (elt = 0; elt < Dynarr_length (*prop); elt++)
1385     {
1386       struct prop_block *pb = Dynarr_atp (*prop, elt);
1387
1388       switch (pb->type)
1389         {
1390         case PROP_CHAR:
1391           data->ch = pb->data.p_char.ch;
1392           data->bi_cursor_bufpos = pb->data.p_char.bi_cursor_bufpos;
1393           data->cursor_type = pb->data.p_char.cursor_type;
1394           add_failed = add_emchar_rune (data);
1395
1396           if (add_failed)
1397             goto oops_no_more_space;
1398           break;
1399         case PROP_STRING:
1400           if (pb->data.p_string.str)
1401             xfree (pb->data.p_string.str);
1402           /* #### bogus bogus -- this doesn't do anything!
1403              Should probably call add_bufbyte_string_runes(),
1404              once that function is fixed. */
1405           break;
1406         case PROP_MINIBUF_PROMPT:
1407           {
1408             face_index old_findex = data->findex;
1409             Bytind bi_old_bufpos = data->bi_bufpos;
1410
1411             data->findex = DEFAULT_INDEX;
1412             data->bi_bufpos = 0;
1413             data->cursor_type = NO_CURSOR;
1414
1415             while (pb->data.p_string.len > 0)
1416               {
1417                 data->ch = charptr_emchar (pb->data.p_string.str);
1418                 add_failed = add_emchar_rune (data);
1419
1420                 if (add_failed)
1421                   {
1422                     data->findex = old_findex;
1423                     data->bi_bufpos = bi_old_bufpos;
1424                     goto oops_no_more_space;
1425                   }
1426                 else
1427                   {
1428                     /* Complicated equivalent of ptr++, len-- */
1429                     Bufbyte *oldpos = pb->data.p_string.str;
1430                     INC_CHARPTR (pb->data.p_string.str);
1431                     pb->data.p_string.len -= pb->data.p_string.str - oldpos;
1432                   }
1433               }
1434
1435             data->findex = old_findex;
1436             /* ##### FIXME FIXME FIXME -- Upon successful return from
1437                this function, data->bi_bufpos is automatically incremented.
1438                However, we don't want that to happen if we were adding
1439                the minibuffer prompt. */
1440             {
1441               struct buffer *buf =
1442                 XBUFFER (WINDOW_BUFFER (XWINDOW (data->window)));
1443               /* #### Chuck fix this shit or I'm gonna scream! */
1444               if (bi_old_bufpos > BI_BUF_BEGV (buf))
1445                 data->bi_bufpos = prev_bytind (buf, bi_old_bufpos);
1446               else
1447                 /* #### is this correct?  Does anyone know?
1448                    Does anyone care? Is this a cheesy hack or what? */
1449                 data->bi_bufpos = BI_BUF_BEGV (buf) - 1;
1450             }
1451           }
1452           break;
1453         case PROP_BLANK:
1454           {
1455             /* #### I think it's unnecessary and misleading to preserve
1456                the blank_width, as it implies that the value carries
1457                over from one rune to the next, which is wrong. */
1458             int old_width = data->blank_width;
1459             face_index old_findex = data->findex;
1460
1461             data->findex = pb->data.p_blank.findex;
1462             data->blank_width = pb->data.p_blank.width;
1463             data->bi_cursor_bufpos = 0;
1464             data->cursor_type = IGNORE_CURSOR;
1465
1466             if (data->pixpos + data->blank_width > data->max_pixpos)
1467               data->blank_width = data->max_pixpos - data->pixpos;
1468
1469             /* We pass a bogus value of char_tab_width.  It shouldn't
1470                matter because unless something is really screwed up
1471                this call won't cause that arg to be used. */
1472             add_failed = add_blank_rune (data, XWINDOW (data->window), 0);
1473
1474             /* This can happen in the case where we have a tab which
1475                is wider than the window. */
1476             if (data->blank_width != pb->data.p_blank.width)
1477               {
1478                 pb->data.p_blank.width -= data->blank_width;
1479                 add_failed = ADD_FAILED;
1480               }
1481
1482             data->findex = old_findex;
1483             data->blank_width = old_width;
1484
1485             if (add_failed)
1486               goto oops_no_more_space;
1487           }
1488           break;
1489         default:
1490           abort ();
1491         }
1492     }
1493
1494  oops_no_more_space:
1495
1496   data->bi_cursor_bufpos = bi_old_cursor_bufpos;
1497   data->cursor_type = old_cursor_type;
1498   if (elt < Dynarr_length (*prop))
1499     {
1500       Dynarr_delete_many (*prop, 0, elt);
1501       return *prop;
1502     }
1503   else
1504     {
1505       Dynarr_free (*prop);
1506       return NULL;
1507     }
1508 }
1509
1510 /* Add 'text layout glyphs at position POS_TYPE that are contained to
1511    the display block, but add all other types to the appropriate list
1512    of the display line.  They will be added later by different
1513    routines. */
1514
1515 static prop_block_dynarr *
1516 add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type,
1517                 int allow_cursor, struct glyph_cachel *cachel)
1518 {
1519   struct window *w = XWINDOW (data->window);
1520
1521   /* If window faces changed, and glyph instance is text, then
1522      glyph sizes might have changed too */
1523   invalidate_glyph_geometry_maybe (gb->glyph, w);
1524
1525   /* This makes sure the glyph is in the cachels.
1526
1527      #### We do this to make sure the glyph is in the glyph cachels,
1528      so that the dirty flag can be reset after redisplay has
1529      finished. We should do this some other way, maybe by iterating
1530      over the window cache of subwindows. */
1531   get_glyph_cachel_index (w, gb->glyph);
1532
1533   /* A nil extent indicates a special glyph (ex. truncator). */
1534   if (NILP (gb->extent)
1535       || (pos_type == BEGIN_GLYPHS &&
1536           extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1537       || (pos_type == END_GLYPHS &&
1538           extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_TEXT)
1539       || pos_type == LEFT_GLYPHS || pos_type == RIGHT_GLYPHS)
1540     {
1541       struct rune rb;
1542       int width;
1543       int xoffset = 0;
1544       int ascent, descent;
1545       Lisp_Object baseline;
1546       Lisp_Object face;
1547       Lisp_Object instance;
1548       face_index findex;
1549
1550       if (cachel)
1551         width = cachel->width;
1552       else
1553         width = glyph_width (gb->glyph, data->window);
1554
1555       if (!width)
1556         return NULL;
1557
1558       if (data->start_col || data->start_col_xoffset)
1559         {
1560           prop_block_dynarr *retval;
1561           int glyph_char_width = width / space_width (w);
1562
1563           /* If we still have not fully scrolled horizontally after
1564              taking into account the width of the glyph, subtract its
1565              width and return. */
1566           if (glyph_char_width < data->start_col)
1567             {
1568               data->start_col -= glyph_char_width;
1569               return NULL;
1570             }
1571           else if (glyph_char_width == data->start_col)
1572             width = 0;
1573           else
1574             {
1575               xoffset = space_width (w) * data->start_col;
1576               width -= xoffset;
1577
1578               /* #### Can this happen? */
1579               if (width < 0)
1580                 width = 0;
1581             }
1582
1583           data->start_col = 0;
1584           retval = add_hscroll_rune (data);
1585
1586           /* Could be caused by the handling of the hscroll rune. */
1587           if (retval != NULL || !width)
1588             return retval;
1589         }
1590       else
1591         xoffset = 0;
1592
1593       if (data->pixpos + width > data->max_pixpos)
1594         {
1595           /* If this is the first object we are attempting to add to
1596              the line then we ignore the horizontal_clip threshold.
1597              Otherwise we will loop until the bottom of the window
1598              continually failing to add this glyph because it is wider
1599              than the window.  We could alternatively just completely
1600              ignore the glyph and proceed from there but I think that
1601              this is a better solution. */
1602           if (Dynarr_length (data->db->runes)
1603               && data->max_pixpos - data->pixpos < horizontal_clip)
1604             return ADD_FAILED;
1605           else
1606             width = data->max_pixpos - data->pixpos;
1607         }
1608
1609       if (cachel)
1610         {
1611           ascent = cachel->ascent;
1612           descent = cachel->descent;
1613         }
1614       else
1615         {
1616           ascent = glyph_ascent (gb->glyph, data->window);
1617           descent = glyph_descent (gb->glyph, data->window);
1618         }
1619
1620       baseline = glyph_baseline (gb->glyph, data->window);
1621
1622       if (glyph_contrib_p (gb->glyph, data->window))
1623         {
1624           /* A pixmap that has not had a baseline explicitly set.  Its
1625              contribution will be determined later. */
1626           if (NILP (baseline))
1627             {
1628               int height = ascent + descent;
1629               data->max_pixmap_height = max (data->max_pixmap_height, height);
1630             }
1631
1632           /* A string so determine contribution normally. */
1633           else if (EQ (baseline, Qt))
1634             {
1635               data->new_ascent = max (data->new_ascent, ascent);
1636               data->new_descent = max (data->new_descent, descent);
1637             }
1638
1639           /* A pixmap with an explicitly set baseline.  We determine the
1640              contribution here. */
1641           else if (INTP (baseline))
1642             {
1643               int height = ascent + descent;
1644               int pix_ascent, pix_descent;
1645
1646               pix_ascent = height * XINT (baseline) / 100;
1647               pix_descent = height - pix_ascent;
1648
1649               data->new_ascent = max (data->new_ascent, pix_ascent);
1650               data->new_descent = max (data->new_descent, pix_descent);
1651             }
1652
1653           /* Otherwise something is screwed up. */
1654           else
1655             abort ();
1656         }
1657
1658       face = glyph_face (gb->glyph, data->window);
1659       if (NILP (face))
1660         findex = data->findex;
1661       else
1662         findex = get_builtin_face_cache_index (w, face);
1663
1664       instance = glyph_image_instance (gb->glyph, data->window, 
1665                                        ERROR_ME_NOT, 1);
1666       if (TEXT_IMAGE_INSTANCEP (instance))
1667         {
1668           Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance);
1669           face_index orig_findex = data->findex;
1670           Bytind orig_bufpos = data->bi_bufpos;
1671           Bytind orig_start_col_enabled = data->bi_start_col_enabled;
1672
1673           data->findex = findex;
1674           data->bi_start_col_enabled = 0;
1675           if (!allow_cursor)
1676             data->bi_bufpos = 0;
1677           add_bufbyte_string_runes (data, XSTRING_DATA (string),
1678                                     XSTRING_LENGTH (string), 0);
1679           data->findex = orig_findex;
1680           data->bi_bufpos = orig_bufpos;
1681           data->bi_start_col_enabled = orig_start_col_enabled;
1682           return NULL;
1683         }
1684
1685       rb.findex = findex;
1686       rb.xpos = data->pixpos;
1687       rb.width = width;
1688       rb.bufpos = 0;                    /* glyphs are never "at" anywhere */
1689       if (data->bi_endpos)
1690         /* #### is this necessary at all? */
1691         rb.endpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1692                                       data->bi_endpos);
1693       else
1694         rb.endpos = 0;
1695       rb.type = RUNE_DGLYPH;
1696       rb.object.dglyph.glyph = gb->glyph;
1697       rb.object.dglyph.extent = gb->extent;
1698       rb.object.dglyph.xoffset = xoffset;
1699
1700       if (allow_cursor)
1701         {
1702           rb.bufpos = bytind_to_bufpos (XBUFFER (WINDOW_BUFFER (w)),
1703                                         data->bi_bufpos);
1704
1705           if (data->cursor_type == CURSOR_ON)
1706             {
1707               if (data->bi_bufpos == data->bi_cursor_bufpos)
1708                 {
1709                   rb.cursor_type = CURSOR_ON;
1710                   data->cursor_x = Dynarr_length (data->db->runes);
1711                 }
1712               else
1713                 rb.cursor_type = CURSOR_OFF;
1714             }
1715           else if (data->cursor_type == NEXT_CURSOR)
1716             {
1717               rb.cursor_type = CURSOR_ON;
1718               data->cursor_x = Dynarr_length (data->db->runes);
1719               data->cursor_type = NO_CURSOR;
1720             }
1721           else if (data->cursor_type == IGNORE_CURSOR)
1722             rb.cursor_type = IGNORE_CURSOR;
1723           else if (data->cursor_type == NO_CURSOR)
1724             rb.cursor_type = NO_CURSOR;
1725           else
1726             rb.cursor_type = CURSOR_OFF;
1727         }
1728       else
1729         rb.cursor_type = CURSOR_OFF;
1730
1731       Dynarr_add (data->db->runes, rb);
1732       data->pixpos += width;
1733
1734       return NULL;
1735     }
1736   else
1737     {
1738       if (!NILP (glyph_face (gb->glyph, data->window)))
1739         gb->findex =
1740           get_builtin_face_cache_index (w, glyph_face (gb->glyph,
1741                                                        data->window));
1742       else
1743         gb->findex = data->findex;
1744
1745       if (pos_type == BEGIN_GLYPHS)
1746         {
1747           if (!data->dl->left_glyphs)
1748             data->dl->left_glyphs = Dynarr_new (glyph_block);
1749           Dynarr_add (data->dl->left_glyphs, *gb);
1750           return NULL;
1751         }
1752       else if (pos_type == END_GLYPHS)
1753         {
1754           if (!data->dl->right_glyphs)
1755             data->dl->right_glyphs = Dynarr_new (glyph_block);
1756           Dynarr_add (data->dl->right_glyphs, *gb);
1757           return NULL;
1758         }
1759       else
1760         abort ();       /* there are no unknown types */
1761     }
1762
1763   return NULL;  /* shut up compiler */
1764 }
1765
1766 /* Add all glyphs at position POS_TYPE that are contained in the given
1767    data. */
1768
1769 static prop_block_dynarr *
1770 add_glyph_runes (pos_data *data, int pos_type)
1771 {
1772   /* #### This still needs to handle the start_col parameter.  Duh, Chuck,
1773      why didn't you just modify add_glyph_rune in the first place? */
1774   int elt;
1775   glyph_block_dynarr *glyph_arr = (pos_type == BEGIN_GLYPHS
1776                                    ? data->ef->begin_glyphs
1777                                    : data->ef->end_glyphs);
1778   prop_block_dynarr *prop;
1779
1780   for (elt = 0; elt < Dynarr_length (glyph_arr); elt++)
1781     {
1782       prop = add_glyph_rune (data, Dynarr_atp (glyph_arr, elt), pos_type, 0,
1783                              0);
1784
1785       if (prop)
1786         {
1787           /* #### Add some propagation information. */
1788           return prop;
1789         }
1790     }
1791
1792   Dynarr_reset (glyph_arr);
1793
1794   return NULL;
1795 }
1796
1797 /* Given a position for a buffer in a window, ensure that the given
1798    display line DL accurately represents the text on a line starting
1799    at the given position.
1800
1801    NOTE NOTE NOTE NOTE: This function works with and returns Bytinds.
1802    You must do appropriate conversion. */
1803
1804 static Bytind
1805 create_text_block (struct window *w, struct display_line *dl,
1806                    Bytind bi_start_pos, prop_block_dynarr **prop,
1807                    int type)
1808 {
1809   struct frame *f = XFRAME (w->frame);
1810   struct buffer *b = XBUFFER (w->buffer);
1811   struct device *d = XDEVICE (f->device);
1812
1813   pos_data data;
1814
1815   /* Don't display anything in the minibuffer if this window is not on
1816      a selected frame.  We consider all other windows to be active
1817      minibuffers as it simplifies the coding. */
1818   int active_minibuffer = (!MINI_WINDOW_P (w) ||
1819                            (f == device_selected_frame (d)) ||
1820                            is_surrogate_for_selected_frame (f));
1821
1822   int truncate_win = window_truncation_on (w);
1823   int end_glyph_width;
1824
1825   /* If the buffer's value of selective_display is an integer then
1826      only lines that start with less than selective_display columns of
1827      space will be displayed.  If selective_display is t then all text
1828      after a ^M is invisible. */
1829   int selective = (INTP (b->selective_display)
1830                    ? XINT (b->selective_display)
1831                    : (!NILP (b->selective_display) ? -1 : 0));
1832
1833   /* The variable ctl-arrow allows the user to specify what characters
1834      can actually be displayed and which octal should be used for.
1835      #### This variable should probably have some rethought done to
1836      it.
1837
1838      #### It would also be really nice if you could specify that
1839      the characters come out in hex instead of in octal.  Mule
1840      does that by adding a ctl-hexa variable similar to ctl-arrow,
1841      but that's bogus -- we need a more general solution.  I
1842      think you need to extend the concept of display tables
1843      into a more general conversion mechanism.  Ideally you
1844      could specify a Lisp function that converts characters,
1845      but this violates the Second Golden Rule and besides would
1846      make things way way way way slow.
1847
1848      So instead, we extend the display-table concept, which was
1849      historically limited to 256-byte vectors, to one of the
1850      following:
1851
1852      a) A 256-entry vector, for backward compatibility;
1853      b) char-table, mapping characters to values;
1854      c) range-table, mapping ranges of characters to values;
1855      d) a list of the above.
1856
1857      The (d) option allows you to specify multiple display tables
1858      instead of just one.  Each display table can specify conversions
1859      for some characters and leave others unchanged.  The way the
1860      character gets displayed is determined by the first display table
1861      with a binding for that character.  This way, you could call a
1862      function `enable-hex-display' that adds a hex display-table to
1863      the list of display tables for the current buffer.
1864
1865      #### ...not yet implemented...  Also, we extend the concept of
1866      "mapping" to include a printf-like spec.  Thus you can make all
1867      extended characters show up as hex with a display table like
1868      this:
1869
1870          #s(range-table data ((256 524288) (format "%x")))
1871
1872      Since more than one display table is possible, you have
1873      great flexibility in mapping ranges of characters.  */
1874   Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow)
1875                           ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
1876                           : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
1877                              ? 255 : 160));
1878
1879   Lisp_Object face_dt, window_dt;
1880
1881   /* The text display block for this display line. */
1882   struct display_block *db = get_display_block_from_line (dl, TEXT);
1883
1884   /* The first time through the main loop we need to force the glyph
1885      data to be updated. */
1886   int initial = 1;
1887
1888   /* Apparently the new extent_fragment_update returns an end position
1889      equal to the position passed in if there are no more runs to be
1890      displayed. */
1891   int no_more_frags = 0;
1892
1893   Lisp_Object synch_minibuffers_value =
1894     symbol_value_in_buffer (Qsynchronize_minibuffers, w->buffer);
1895
1896   dl->used_prop_data = 0;
1897   dl->num_chars = 0;
1898   dl->line_continuation = 0;
1899
1900   xzero (data);
1901   data.ef = extent_fragment_new (w->buffer, f);
1902
1903   /* These values are used by all of the rune addition routines.  We add
1904      them to this structure for ease of passing. */
1905   data.d = d;
1906   XSETWINDOW (data.window, w);
1907   data.string = Qnil;
1908   data.db = db;
1909   data.dl = dl;
1910
1911   data.bi_bufpos = bi_start_pos;
1912   data.pixpos = dl->bounds.left_in;
1913   data.last_charset = Qunbound;
1914   data.last_findex = DEFAULT_INDEX;
1915   data.result_str = Qnil;
1916
1917   /* Set the right boundary adjusting it to take into account any end
1918      glyph.  Save the width of the end glyph for later use. */
1919   data.max_pixpos = dl->bounds.right_in;
1920   if (truncate_win)
1921     end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
1922   else
1923     end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
1924   data.max_pixpos -= end_glyph_width;
1925
1926   if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
1927     {
1928       data.bi_cursor_bufpos = BI_BUF_ZV (b);
1929       data.cursor_type = CURSOR_ON;
1930     }
1931   else if (MINI_WINDOW_P (w) && !active_minibuffer)
1932     data.cursor_type = NO_CURSOR;
1933   else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)) &&
1934            EQ(DEVICE_CONSOLE(d), Vselected_console) &&
1935            d == XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d))))&&
1936            f == XFRAME(DEVICE_SELECTED_FRAME(d)))
1937     {
1938       data.bi_cursor_bufpos = BI_BUF_PT (b);
1939       data.cursor_type = CURSOR_ON;
1940     }
1941   else if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
1942     {
1943       data.bi_cursor_bufpos = bi_marker_position (w->pointm[type]);
1944       data.cursor_type = CURSOR_ON;
1945     }
1946   else
1947     data.cursor_type = NO_CURSOR;
1948   data.cursor_x = -1;
1949
1950   data.start_col = w->hscroll;
1951   data.start_col_xoffset = w->left_xoffset;
1952   data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
1953   data.hscroll_glyph_width_adjust = 0;
1954
1955   /* We regenerate the line from the very beginning. */
1956   Dynarr_reset (db->runes);
1957
1958   /* Why is this less than or equal and not just less than?  If the
1959      starting position is already equal to the maximum we can't add
1960      anything else, right?  Wrong.  We might still have a newline to
1961      add.  A newline can use the room allocated for an end glyph since
1962      if we add it we know we aren't going to be adding any end
1963      glyph. */
1964
1965   /* #### Chuck -- I think this condition should be while (1).
1966      Otherwise if (e.g.) there is one begin-glyph and one end-glyph
1967      and the begin-glyph ends exactly at the end of the window, the
1968      end-glyph and text might not be displayed.  while (1) ensures
1969      that the loop terminates only when either (a) there is
1970      propagation data or (b) the end-of-line or end-of-buffer is hit.
1971
1972      #### Also I think you need to ensure that the operation
1973      "add begin glyphs; add end glyphs; add text" is atomic and
1974      can't get interrupted in the middle.  If you run off the end
1975      of the line during that operation, then you keep accumulating
1976      propagation data until you're done.  Otherwise, if the (e.g.)
1977      there's a begin glyph at a particular position and attempting
1978      to display that glyph results in window-end being hit and
1979      propagation data being generated, then the character at that
1980      position won't be displayed.
1981
1982      #### See also the comment after the end of this loop, below.
1983      */
1984   while (data.pixpos <= data.max_pixpos
1985          && (active_minibuffer || !NILP (synch_minibuffers_value)))
1986     {
1987       /* #### This check probably should not be necessary. */
1988       if (data.bi_bufpos > BI_BUF_ZV (b))
1989         {
1990           /* #### urk!  More of this lossage! */
1991           data.bi_bufpos--;
1992           goto done;
1993         }
1994
1995       /* If selective display was an integer and we aren't working on
1996          a continuation line then find the next line we are actually
1997          supposed to display. */
1998       if (selective > 0
1999           && (data.bi_bufpos == BI_BUF_BEGV (b)
2000               || BUF_FETCH_CHAR (b, prev_bytind (b, data.bi_bufpos)) == '\n'))
2001         {
2002           while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2003             {
2004               data.bi_bufpos =
2005                 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2006               if (data.bi_bufpos >= BI_BUF_ZV (b))
2007                 {
2008                   data.bi_bufpos = BI_BUF_ZV (b);
2009                   goto done;
2010                 }
2011             }
2012         }
2013
2014       /* Check for face changes. */
2015       if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
2016         {
2017           /* Now compute the face and begin/end-glyph information. */
2018           data.findex =
2019             /* Remember that the extent-fragment routines deal in Bytind's. */
2020             extent_fragment_update (w, data.ef, data.bi_bufpos);
2021
2022           get_display_tables (w, data.findex, &face_dt, &window_dt);
2023
2024           if (data.bi_bufpos == data.ef->end)
2025             no_more_frags = 1;
2026         }
2027       initial = 0;
2028
2029       /* Determine what is next to be displayed.  We first handle any
2030          glyphs returned by glyphs_at_bufpos.  If there are no glyphs to
2031          display then we determine what to do based on the character at the
2032          current buffer position. */
2033
2034       /* If the current position is covered by an invisible extent, do
2035          nothing (except maybe add some ellipses).
2036
2037          #### The behavior of begin and end-glyphs at the edge of an
2038          invisible extent should be investigated further.  This is
2039          fairly low priority though. */
2040       if (data.ef->invisible)
2041         {
2042           /* #### Chuck, perhaps you could look at this code?  I don't
2043              really know what I'm doing. */
2044           if (*prop)
2045             {
2046               Dynarr_free (*prop);
2047               *prop = 0;
2048             }
2049
2050           /* The extent fragment code only sets this when we should
2051              really display the ellipses.  It makes sure the ellipses
2052              don't get displayed more than once in a row. */
2053           if (data.ef->invisible_ellipses)
2054             {
2055               struct glyph_block gb;
2056
2057               data.ef->invisible_ellipses_already_displayed = 1;
2058               data.ef->invisible_ellipses = 0;
2059               gb.extent = Qnil;
2060               gb.glyph = Vinvisible_text_glyph;
2061               *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2062                                       GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2063               /* Perhaps they shouldn't propagate if the very next thing
2064                  is to display a newline (for compatibility with
2065                  selective-display-ellipses)?  Maybe that's too
2066                  abstruse. */
2067               if (*prop)
2068                 goto done;
2069             }
2070
2071           /* If point is in an invisible region we place it on the
2072              next visible character. */
2073           if (data.cursor_type == CURSOR_ON
2074               && data.bi_bufpos == data.bi_cursor_bufpos)
2075             {
2076               data.cursor_type = NEXT_CURSOR;
2077             }
2078
2079           /* #### What if we we're dealing with a display table? */
2080           if (data.start_col)
2081             data.start_col--;
2082
2083           if (data.bi_bufpos == BI_BUF_ZV (b))
2084             goto done;
2085           else
2086             INC_BYTIND (b, data.bi_bufpos);
2087         }
2088
2089       /* If there is propagation data, then it represents the current
2090          buffer position being displayed.  Add them and advance the
2091          position counter.  This might also add the minibuffer
2092          prompt. */
2093       else if (*prop)
2094         {
2095           dl->used_prop_data = 1;
2096           *prop = add_propagation_runes (prop, &data);
2097
2098           if (*prop)
2099             goto done;  /* gee, a really narrow window */
2100           else if (data.bi_bufpos == BI_BUF_ZV (b))
2101             goto done;
2102           else if (data.bi_bufpos < BI_BUF_BEGV (b))
2103             /* #### urk urk urk! Aborts are not very fun! Fix this please! */
2104             data.bi_bufpos = BI_BUF_BEGV (b);
2105           else
2106             INC_BYTIND (b, data.bi_bufpos);
2107         }
2108
2109       /* If there are end glyphs, add them to the line.  These are
2110          the end glyphs for the previous run of text.  We add them
2111          here rather than doing them at the end of handling the
2112          previous run so that glyphs at the beginning and end of
2113          a line are handled correctly. */
2114       else if (Dynarr_length (data.ef->end_glyphs) > 0)
2115         {
2116           *prop = add_glyph_runes (&data, END_GLYPHS);
2117           if (*prop)
2118             goto done;
2119         }
2120
2121       /* If there are begin glyphs, add them to the line. */
2122       else if (Dynarr_length (data.ef->begin_glyphs) > 0)
2123         {
2124           *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
2125           if (*prop)
2126             goto done;
2127         }
2128
2129       /* If at end-of-buffer, we've already processed begin and
2130          end-glyphs at this point and there's no text to process,
2131          so we're done. */
2132       else if (data.bi_bufpos == BI_BUF_ZV (b))
2133         goto done;
2134
2135       else
2136         {
2137           Lisp_Object entry = Qnil;
2138           /* Get the character at the current buffer position. */
2139           data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2140           if (!NILP (face_dt) || !NILP (window_dt))
2141             entry = display_table_entry (data.ch, face_dt, window_dt);
2142
2143           /* If there is a display table entry for it, hand it off to
2144              add_disp_table_entry_runes and let it worry about it. */
2145           if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
2146             {
2147               *prop = add_disp_table_entry_runes (&data, entry);
2148
2149               if (*prop)
2150                 goto done;
2151             }
2152
2153           /* Check if we have hit a newline character.  If so, add a marker
2154              to the line and end this loop. */
2155           else if (data.ch == '\n')
2156             {
2157               /* We aren't going to be adding an end glyph so give its
2158                  space back in order to make sure that the cursor can
2159                  fit. */
2160               data.max_pixpos += end_glyph_width;
2161
2162               if (selective > 0
2163                   && (bi_spaces_at_point
2164                       (b, next_bytind (b, data.bi_bufpos))
2165                       >= selective))
2166                 {
2167                   if (!NILP (b->selective_display_ellipses))
2168                     {
2169                       struct glyph_block gb;
2170
2171                       gb.extent = Qnil;
2172                       gb.glyph = Vinvisible_text_glyph;
2173                       add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2174                                       GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2175                     }
2176                   else
2177                     {
2178                       /* Cheesy, cheesy, cheesy.  We mark the end of the
2179                          line with a special "character rune" whose width
2180                          is the EOL cursor width and whose character is
2181                          the non-printing character '\n'. */
2182                       data.blank_width = DEVMETH (d, eol_cursor_width, ());
2183                       *prop = add_emchar_rune (&data);
2184                     }
2185
2186                   /* We need to set data.bi_bufpos to the start of the
2187                      next visible region in order to make this line
2188                      appear to contain all of the invisible area.
2189                      Otherwise, the line cache won't work
2190                      correctly. */
2191                   INC_BYTIND (b, data.bi_bufpos);
2192                   while (bi_spaces_at_point (b, data.bi_bufpos) >= selective)
2193                     {
2194                       data.bi_bufpos =
2195                         bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2196                       if (data.bi_bufpos >= BI_BUF_ZV (b))
2197                         {
2198                           data.bi_bufpos = BI_BUF_ZV (b);
2199                           break;
2200                         }
2201                     }
2202                   if (BI_BUF_FETCH_CHAR
2203                       (b, prev_bytind (b, data.bi_bufpos)) == '\n')
2204                     DEC_BYTIND (b, data.bi_bufpos);
2205                 }
2206               else
2207                 {
2208                   data.blank_width = DEVMETH (d, eol_cursor_width, ());
2209                   *prop = add_emchar_rune (&data);
2210                 }
2211
2212               goto done;
2213             }
2214
2215           /* If the current character is ^M, and selective display is
2216              enabled, then add the invisible-text-glyph if
2217              selective-display-ellipses is set.  In any case, this
2218              line is done. */
2219           else if (data.ch == (('M' & 037)) && selective == -1)
2220             {
2221               Bytind bi_next_bufpos;
2222
2223               /* Find the buffer position at the end of the line. */
2224               bi_next_bufpos =
2225                 bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2226               if (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_next_bufpos))
2227                   == '\n')
2228                 DEC_BYTIND (b, bi_next_bufpos);
2229
2230               /* If the cursor is somewhere in the elided text make
2231                  sure that the cursor gets drawn appropriately. */
2232               if (data.cursor_type == CURSOR_ON
2233                   && (data.bi_cursor_bufpos >= data.bi_bufpos &&
2234                       data.bi_cursor_bufpos < bi_next_bufpos))
2235                 {
2236                     data.cursor_type = NEXT_CURSOR;
2237                 }
2238
2239               /* We won't be adding a truncation or continuation glyph
2240                  so give up the room allocated for them. */
2241               data.max_pixpos += end_glyph_width;
2242
2243               if (!NILP (b->selective_display_ellipses))
2244                 {
2245                   /* We don't propagate anything from the invisible
2246                      text glyph if it fails to fit.  This is
2247                      intentional. */
2248                   struct glyph_block gb;
2249
2250                   gb.extent = Qnil;
2251                   gb.glyph = Vinvisible_text_glyph;
2252                   add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 1,
2253                                   GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
2254                 }
2255
2256               /* Set the buffer position to the end of the line.  We
2257                  need to do this before potentially adding a newline
2258                  so that the cursor flag will get set correctly (if
2259                  needed). */
2260               data.bi_bufpos = bi_next_bufpos;
2261
2262               if (NILP (b->selective_display_ellipses)
2263                   || data.bi_cursor_bufpos == bi_next_bufpos)
2264                 {
2265                   /* We have to at least add a newline character so
2266                      that the cursor shows up properly. */
2267                   data.ch = '\n';
2268                   data.blank_width = DEVMETH (d, eol_cursor_width, ());
2269                   data.findex = DEFAULT_INDEX;
2270                   data.start_col = 0;
2271                   data.start_col_xoffset = 0;
2272                   data.bi_start_col_enabled = 0;
2273
2274                   add_emchar_rune (&data);
2275                 }
2276
2277               /* This had better be a newline but doing it this way
2278                  we'll see obvious incorrect results if it isn't.  No
2279                  need to abort here. */
2280               data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
2281
2282               goto done;
2283             }
2284
2285           /* If the current character is considered to be printable, then
2286              just add it. */
2287           else if (data.ch >= printable_min)
2288             {
2289               *prop = add_emchar_rune (&data);
2290               if (*prop)
2291                 goto done;
2292             }
2293
2294           /* If the current character is a tab, determine the next tab
2295              starting position and add a blank rune which extends from the
2296              current pixel position to that starting position. */
2297           else if (data.ch == '\t')
2298             {
2299               int tab_start_pixpos = data.pixpos;
2300               int next_tab_start;
2301               int char_tab_width;
2302               int prop_width = 0;
2303
2304               if (data.start_col > 1)
2305                 tab_start_pixpos -= (space_width (w) * (data.start_col - 1))
2306                   + data.start_col_xoffset;
2307
2308               next_tab_start =
2309                 next_tab_position (w, tab_start_pixpos,
2310                                    dl->bounds.left_in +
2311                                    data.hscroll_glyph_width_adjust);
2312               if (next_tab_start > data.max_pixpos)
2313                 {
2314                   prop_width = next_tab_start - data.max_pixpos;
2315                   next_tab_start = data.max_pixpos;
2316                 }
2317               data.blank_width = next_tab_start - data.pixpos;
2318               char_tab_width =
2319                 (next_tab_start - tab_start_pixpos) / space_width (w);
2320
2321               *prop = add_blank_rune (&data, w, char_tab_width);
2322
2323               /* add_blank_rune is only supposed to be called with
2324                  sizes guaranteed to fit in the available space. */
2325               assert (!(*prop));
2326
2327               if (prop_width)
2328                 {
2329                   struct prop_block pb;
2330                   *prop = Dynarr_new (prop_block);
2331
2332                   pb.type = PROP_BLANK;
2333                   pb.data.p_blank.width = prop_width;
2334                   pb.data.p_blank.findex = data.findex;
2335                   Dynarr_add (*prop, pb);
2336
2337                   goto done;
2338                 }
2339             }
2340
2341           /* If character is a control character, pass it off to
2342              add_control_char_runes.
2343
2344              The is_*() routines have undefined results on
2345              arguments outside of the range [-1, 255].  (This
2346              often bites people who carelessly use `char' instead
2347              of `unsigned char'.)
2348              */
2349           else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
2350             {
2351               *prop = add_control_char_runes (&data, b);
2352
2353               if (*prop)
2354                 goto done;
2355             }
2356
2357           /* If the character is above the ASCII range and we have not
2358              already handled it, then print it as an octal number. */
2359           else if (data.ch >= 0200)
2360             {
2361               *prop = add_octal_runes (&data);
2362
2363               if (*prop)
2364                 goto done;
2365             }
2366
2367           /* Assume the current character is considered to be printable,
2368              then just add it. */
2369           else
2370             {
2371               *prop = add_emchar_rune (&data);
2372               if (*prop)
2373                 goto done;
2374             }
2375
2376           INC_BYTIND (b, data.bi_bufpos);
2377         }
2378     }
2379
2380 done:
2381
2382   /* Determine the starting point of the next line if we did not hit the
2383      end of the buffer. */
2384   if (data.bi_bufpos < BI_BUF_ZV (b)
2385       && (active_minibuffer || !NILP (synch_minibuffers_value)))
2386     {
2387       /* #### This check is not correct.  If the line terminated
2388          due to a begin-glyph or end-glyph hitting window-end, then
2389          data.ch will not point to the character at data.bi_bufpos.  If
2390          you make the two changes mentioned at the top of this loop,
2391          you should be able to say '(if (*prop))'.  That should also
2392          make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
2393          check. */
2394
2395       /* The common case is that the line ended because we hit a newline.
2396          In that case, the next character is just the next buffer
2397          position. */
2398       if (data.ch == '\n')
2399         {
2400           /* If data.start_col_enabled is still true, then the window is
2401              scrolled far enough so that nothing on this line is visible.
2402              We need to stick a truncation glyph at the beginning of the
2403              line in that case unless the line is completely blank. */
2404           if (data.bi_start_col_enabled)
2405             {
2406               if (data.cursor_type == CURSOR_ON)
2407                 {
2408                   if (data.bi_cursor_bufpos >= bi_start_pos
2409                       && data.bi_cursor_bufpos <= data.bi_bufpos)
2410                     data.bi_cursor_bufpos = data.bi_bufpos;
2411                 }
2412               data.findex = DEFAULT_INDEX;
2413               data.start_col = 0;
2414               data.bi_start_col_enabled = 0;
2415
2416               if (data.bi_bufpos != bi_start_pos)
2417                 {
2418                   struct glyph_block gb;
2419
2420                   gb.extent = Qnil;
2421                   gb.glyph = Vhscroll_glyph;
2422                   add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
2423                                   GLYPH_CACHEL (w, HSCROLL_GLYPH_INDEX));
2424                 }
2425               else
2426                 {
2427                   /* This duplicates code down below to add a newline to
2428                      the end of an otherwise empty line.*/
2429                   data.ch = '\n';
2430                   data.blank_width = DEVMETH (d, eol_cursor_width, ());
2431
2432                   add_emchar_rune (&data);
2433                 }
2434             }
2435
2436           INC_BYTIND (b, data.bi_bufpos);
2437         }
2438
2439       /* Otherwise we have a buffer line which cannot fit on one display
2440          line. */
2441       else
2442         {
2443           struct glyph_block gb;
2444           struct glyph_cachel *cachel;
2445
2446           /* If the line is to be truncated then we actually have to look
2447              for the next newline.  We also add the end-of-line glyph which
2448              we know will fit because we adjusted the right border before
2449              we starting laying out the line. */
2450           data.max_pixpos += end_glyph_width;
2451           data.findex = DEFAULT_INDEX;
2452           gb.extent = Qnil;
2453
2454           if (truncate_win)
2455             {
2456               Bytind bi_pos;
2457
2458               /* Now find the start of the next line. */
2459               bi_pos = bi_find_next_newline_no_quit (b, data.bi_bufpos, 1);
2460
2461               /* If the cursor is past the truncation line then we
2462                  make it appear on the truncation glyph.  If we've hit
2463                  the end of the buffer then we also make the cursor
2464                  appear unless eob is immediately preceded by a
2465                  newline.  In that case the cursor should actually
2466                  appear on the next line. */
2467               if (data.cursor_type == CURSOR_ON
2468                   && data.bi_cursor_bufpos >= data.bi_bufpos
2469                   && (data.bi_cursor_bufpos < bi_pos ||
2470                       (bi_pos == BI_BUF_ZV (b)
2471                        && (bi_pos == BI_BUF_BEGV (b)
2472                            || (BI_BUF_FETCH_CHAR (b, prev_bytind (b, bi_pos))
2473                                != '\n')))))
2474                 data.bi_cursor_bufpos = bi_pos;
2475               else
2476                 data.cursor_type = NO_CURSOR;
2477
2478               data.bi_bufpos = bi_pos;
2479               gb.glyph = Vtruncation_glyph;
2480               cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
2481             }
2482           else
2483             {
2484               /* The cursor can never be on the continuation glyph. */
2485               data.cursor_type = NO_CURSOR;
2486
2487               /* data.bi_bufpos is already at the start of the next line. */
2488
2489               dl->line_continuation = 1;
2490               gb.glyph = Vcontinuation_glyph;
2491               cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
2492             }
2493
2494           add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
2495
2496           if (truncate_win && data.bi_bufpos == BI_BUF_ZV (b)
2497               && BI_BUF_FETCH_CHAR (b, prev_bytind (b, BI_BUF_ZV (b))) != '\n')
2498             /* #### Damn this losing shit. */
2499             data.bi_bufpos++;
2500         }
2501     }
2502   else if ((active_minibuffer || !NILP (synch_minibuffers_value))
2503            && (!echo_area_active (f) || data.bi_bufpos == BI_BUF_ZV (b)))
2504     {
2505       /* We need to add a marker to the end of the line since there is no
2506          newline character in order for the cursor to get drawn.  We label
2507          it as a newline so that it gets handled correctly by the
2508          whitespace routines below. */
2509
2510       data.ch = '\n';
2511       data.blank_width = DEVMETH (d, eol_cursor_width, ());
2512       data.findex = DEFAULT_INDEX;
2513       data.start_col = 0;
2514       data.start_col_xoffset = 0;
2515       data.bi_start_col_enabled = 0;
2516
2517       data.max_pixpos += data.blank_width;
2518       add_emchar_rune (&data);
2519       data.max_pixpos -= data.blank_width;
2520
2521       /* #### urk!  Chuck, this shit is bad news.  Going around
2522          manipulating invalid positions is guaranteed to result in
2523          trouble sooner or later. */
2524       data.bi_bufpos = BI_BUF_ZV (b) + 1;
2525     }
2526
2527   /* Calculate left whitespace boundary. */
2528   {
2529     int elt = 0;
2530
2531     /* Whitespace past a newline is considered right whitespace. */
2532     while (elt < Dynarr_length (db->runes))
2533       {
2534         struct rune *rb = Dynarr_atp (db->runes, elt);
2535
2536         if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
2537             || rb->type == RUNE_BLANK)
2538           {
2539             dl->bounds.left_white += rb->width;
2540             elt++;
2541           }
2542         else
2543           elt = Dynarr_length (db->runes);
2544       }
2545   }
2546
2547   /* Calculate right whitespace boundary. */
2548   {
2549     int elt = Dynarr_length (db->runes) - 1;
2550     int done = 0;
2551
2552     while (!done && elt >= 0)
2553       {
2554         struct rune *rb = Dynarr_atp (db->runes, elt);
2555
2556         if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
2557             && isspace (rb->object.chr.ch))
2558             && !rb->type == RUNE_BLANK)
2559           {
2560             dl->bounds.right_white = rb->xpos + rb->width;
2561             done = 1;
2562           }
2563
2564         elt--;
2565
2566       }
2567
2568     /* The line is blank so everything is considered to be right
2569        whitespace. */
2570     if (!done)
2571       dl->bounds.right_white = dl->bounds.left_in;
2572   }
2573
2574   /* Set the display blocks bounds. */
2575   db->start_pos = dl->bounds.left_in;
2576   if (Dynarr_length (db->runes))
2577     {
2578       struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
2579
2580       db->end_pos = rb->xpos + rb->width;
2581     }
2582   else
2583     db->end_pos = dl->bounds.right_white;
2584
2585   /* update line height parameters */
2586   if (!data.new_ascent && !data.new_descent)
2587     {
2588       /* We've got a blank line so initialize these values from the default
2589          face. */
2590       default_face_font_info (data.window, &data.new_ascent,
2591                               &data.new_descent, 0, 0, 0);
2592     }
2593
2594   if (data.max_pixmap_height)
2595     {
2596       int height = data.new_ascent + data.new_descent;
2597       int pix_ascent, pix_descent;
2598
2599       pix_descent = data.max_pixmap_height * data.new_descent / height;
2600       pix_ascent = data.max_pixmap_height - pix_descent;
2601
2602       data.new_ascent = max (data.new_ascent, pix_ascent);
2603       data.new_descent = max (data.new_descent, pix_descent);
2604     }
2605
2606   dl->ascent = data.new_ascent;
2607   dl->descent = data.new_descent;
2608
2609   {
2610     unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
2611
2612     if (dl->ascent < ascent)
2613       dl->ascent = ascent;
2614   }
2615   {
2616     unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
2617
2618     if (dl->descent < descent)
2619       dl->descent = descent;
2620   }
2621
2622   dl->cursor_elt = data.cursor_x;
2623   /* #### lossage lossage lossage! Fix this shit! */
2624   if (data.bi_bufpos > BI_BUF_ZV (b))
2625     dl->end_bufpos = BUF_ZV (b);
2626   else
2627     dl->end_bufpos = bytind_to_bufpos (b, data.bi_bufpos) - 1;
2628   if (truncate_win)
2629     data.dl->num_chars = column_at_point (b, dl->end_bufpos, 0);
2630   else
2631     /* This doesn't correctly take into account tabs and control
2632        characters but if the window isn't being truncated then this
2633        value isn't going to end up being used anyhow. */
2634     data.dl->num_chars = dl->end_bufpos - dl->bufpos;
2635
2636   /* #### handle horizontally scrolled line with text none of which
2637      was actually laid out. */
2638
2639   /* #### handle any remainder of overlay arrow */
2640
2641   if (*prop == ADD_FAILED)
2642     *prop = NULL;
2643
2644   if (truncate_win && *prop)
2645     {
2646       Dynarr_free (*prop);
2647       *prop = NULL;
2648     }
2649
2650   extent_fragment_delete (data.ef);
2651
2652   /* #### If we started at EOB, then make sure we return a value past
2653      it so that regenerate_window will exit properly.  This is bogus.
2654      The main loop should get fixed so that it isn't necessary to call
2655      this function if we are already at EOB. */
2656
2657   if (data.bi_bufpos == BI_BUF_ZV (b) && bi_start_pos == BI_BUF_ZV (b))
2658     return data.bi_bufpos + 1; /* Yuck! */
2659   else
2660     return data.bi_bufpos;
2661 }
2662
2663 /* Display the overlay arrow at the beginning of the given line. */
2664
2665 static int
2666 create_overlay_glyph_block (struct window *w, struct display_line *dl)
2667 {
2668   struct frame *f = XFRAME (w->frame);
2669   struct device *d = XDEVICE (f->device);
2670   pos_data data;
2671
2672   /* If Voverlay_arrow_string isn't valid then just fail silently. */
2673   if (!STRINGP (Voverlay_arrow_string) && !GLYPHP (Voverlay_arrow_string))
2674     return 0;
2675
2676   xzero (data);
2677   data.ef = NULL;
2678   data.d = d;
2679   XSETWINDOW (data.window, w);
2680   data.db = get_display_block_from_line (dl, OVERWRITE);
2681   data.dl = dl;
2682   data.pixpos = dl->bounds.left_in;
2683   data.max_pixpos = dl->bounds.right_in;
2684   data.cursor_type = NO_CURSOR;
2685   data.cursor_x = -1;
2686   data.findex = DEFAULT_INDEX;
2687   data.last_charset = Qunbound;
2688   data.last_findex = DEFAULT_INDEX;
2689   data.result_str = Qnil;
2690   data.string = Qnil;
2691
2692   Dynarr_reset (data.db->runes);
2693
2694   if (STRINGP (Voverlay_arrow_string))
2695     {
2696       add_bufbyte_string_runes
2697         (&data,
2698          XSTRING_DATA   (Voverlay_arrow_string),
2699          XSTRING_LENGTH (Voverlay_arrow_string),
2700          1);
2701     }
2702   else if (GLYPHP (Voverlay_arrow_string))
2703     {
2704       struct glyph_block gb;
2705
2706       gb.glyph = Voverlay_arrow_string;
2707       gb.extent = Qnil;
2708       add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
2709     }
2710
2711   if (data.max_pixmap_height)
2712     {
2713       int height = data.new_ascent + data.new_descent;
2714       int pix_ascent, pix_descent;
2715
2716       pix_descent = data.max_pixmap_height * data.new_descent / height;
2717       pix_ascent = data.max_pixmap_height - pix_descent;
2718
2719       data.new_ascent = max (data.new_ascent, pix_ascent);
2720       data.new_descent = max (data.new_descent, pix_descent);
2721     }
2722
2723   dl->ascent = data.new_ascent;
2724   dl->descent = data.new_descent;
2725
2726   data.db->start_pos = dl->bounds.left_in;
2727   data.db->end_pos = data.pixpos;
2728
2729   return data.pixpos - dl->bounds.left_in;
2730 }
2731
2732 /* Add a type of glyph to a margin display block. */
2733
2734 static int
2735 add_margin_runes (struct display_line *dl, struct display_block *db, int start,
2736                   int count, enum glyph_layout layout, int side, Lisp_Object window)
2737 {
2738   glyph_block_dynarr *gbd = (side == LEFT_GLYPHS
2739                              ? dl->left_glyphs
2740                              : dl->right_glyphs);
2741   int elt, end;
2742   int reverse;
2743   struct window *w = XWINDOW (window);
2744   struct frame *f = XFRAME (w->frame);
2745   struct device *d = XDEVICE (f->device);
2746   pos_data data;
2747
2748   xzero (data);
2749   data.d = d;
2750   data.window = window;
2751   data.db = db;
2752   data.dl = dl;
2753   data.pixpos = start;
2754   data.cursor_type = NO_CURSOR;
2755   data.cursor_x = -1;
2756   data.last_charset = Qunbound;
2757   data.last_findex = DEFAULT_INDEX;
2758   data.result_str = Qnil;
2759   data.string = Qnil;
2760   data.new_ascent = dl->ascent;
2761   data.new_descent = dl->descent;
2762
2763   if ((layout == GL_WHITESPACE && side == LEFT_GLYPHS)
2764       || (layout == GL_INSIDE_MARGIN && side == RIGHT_GLYPHS))
2765     {
2766       reverse = 1;
2767       elt = Dynarr_length (gbd) - 1;
2768       end = 0;
2769     }
2770   else
2771     {
2772       reverse = 0;
2773       elt = 0;
2774       end = Dynarr_length (gbd);
2775     }
2776
2777   while (count && ((!reverse && elt < end) || (reverse && elt >= end)))
2778     {
2779       struct glyph_block *gb = Dynarr_atp (gbd, elt);
2780
2781       if (NILP (gb->extent))
2782         abort ();       /* these should have been handled in add_glyph_rune */
2783
2784       if (gb->active &&
2785           ((side == LEFT_GLYPHS &&
2786             extent_begin_glyph_layout (XEXTENT (gb->extent)) == layout)
2787            || (side == RIGHT_GLYPHS &&
2788                extent_end_glyph_layout (XEXTENT (gb->extent)) == layout)))
2789         {
2790           data.findex = gb->findex;
2791           data.max_pixpos = data.pixpos + gb->width;
2792           add_glyph_rune (&data, gb, side, 0, NULL);
2793           count--;
2794           gb->active = 0;
2795         }
2796
2797       (reverse ? elt-- : elt++);
2798     }
2799
2800   if (data.max_pixmap_height)
2801     {
2802       int height = data.new_ascent + data.new_descent;
2803       int pix_ascent, pix_descent;
2804
2805       pix_descent = data.max_pixmap_height * data.new_descent / height;
2806       pix_ascent = data.max_pixmap_height - pix_descent;
2807       data.new_ascent = max (data.new_ascent, pix_ascent);
2808       data.new_descent = max (data.new_descent, pix_descent);
2809     }
2810
2811   dl->ascent = data.new_ascent;
2812   dl->descent = data.new_descent;
2813
2814   return data.pixpos;
2815 }
2816
2817 /* Add a blank to a margin display block. */
2818
2819 static void
2820 add_margin_blank (struct display_line *dl, struct display_block *db,
2821                   struct window *w, int xpos, int width, int side)
2822 {
2823   struct rune rb;
2824
2825   rb.findex = (side == LEFT_GLYPHS
2826                ? get_builtin_face_cache_index (w, Vleft_margin_face)
2827                : get_builtin_face_cache_index (w, Vright_margin_face));
2828   rb.xpos = xpos;
2829   rb.width = width;
2830   rb.bufpos = -1;
2831   rb.endpos = 0;
2832   rb.type = RUNE_BLANK;
2833   rb.cursor_type = CURSOR_OFF;
2834
2835   Dynarr_add (db->runes, rb);
2836 }
2837
2838 /* Display glyphs in the left outside margin, left inside margin and
2839    left whitespace area. */
2840
2841 static void
2842 create_left_glyph_block (struct window *w, struct display_line *dl,
2843                          int overlay_width)
2844 {
2845   Lisp_Object window;
2846
2847   int use_overflow = (NILP (w->use_left_overflow) ? 0 : 1);
2848   int elt, end_xpos;
2849   int out_end, in_out_start, in_in_end, white_out_start, white_in_start;
2850   int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
2851   int left_in_start = dl->bounds.left_in;
2852   int left_in_end = dl->bounds.left_in + overlay_width;
2853
2854   struct display_block *odb, *idb;
2855
2856   XSETWINDOW (window, w);
2857
2858   /* We have to add the glyphs to the line in the order outside,
2859      inside, whitespace.  However the precedence dictates that we
2860      determine how many will fit in the reverse order. */
2861
2862   /* Determine how many whitespace glyphs we can display and where
2863      they should start. */
2864   white_in_start = dl->bounds.left_white;
2865   white_out_start = left_in_start;
2866   white_out_cnt = white_in_cnt = 0;
2867   elt = 0;
2868
2869   while (elt < Dynarr_length (dl->left_glyphs))
2870     {
2871       struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2872
2873       if (NILP (gb->extent))
2874         abort ();       /* these should have been handled in add_glyph_rune */
2875
2876       if (extent_begin_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
2877         {
2878           int width;
2879
2880           width = glyph_width (gb->glyph, window);
2881
2882           if (white_in_start - width >= left_in_end)
2883             {
2884               white_in_cnt++;
2885               white_in_start -= width;
2886               gb->width = width;
2887               gb->active = 1;
2888             }
2889           else if (use_overflow
2890                    && (white_out_start - width > dl->bounds.left_out))
2891             {
2892               white_out_cnt++;
2893               white_out_start -= width;
2894               gb->width = width;
2895               gb->active = 1;
2896             }
2897           else
2898             gb->active = 0;
2899         }
2900
2901       elt++;
2902     }
2903
2904   /* Determine how many inside margin glyphs we can display and where
2905      they should start.  The inside margin glyphs get whatever space
2906      is left after the whitespace glyphs have been displayed.  These
2907      are tricky to calculate since if we decide to use the overflow
2908      area we basically have to start over.  So for these we build up a
2909      list of just the inside margin glyphs and manipulate it to
2910      determine the needed info. */
2911   {
2912     glyph_block_dynarr *ib;
2913     int avail_in, avail_out;
2914     int done = 0;
2915     int marker = 0;
2916     int used_in, used_out;
2917
2918     elt = 0;
2919     used_in = used_out = 0;
2920     ib = Dynarr_new (glyph_block);
2921     while (elt < Dynarr_length (dl->left_glyphs))
2922       {
2923         struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2924
2925         if (NILP (gb->extent))
2926           abort ();     /* these should have been handled in add_glyph_rune */
2927
2928         if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2929             GL_INSIDE_MARGIN)
2930           {
2931             gb->width = glyph_width (gb->glyph, window);
2932             used_in += gb->width;
2933             Dynarr_add (ib, *gb);
2934           }
2935
2936         elt++;
2937       }
2938
2939     if (white_out_cnt)
2940       avail_in = 0;
2941     else
2942       {
2943         avail_in = white_in_start - left_in_end;
2944         if (avail_in < 0)
2945           avail_in = 0;
2946       }
2947
2948     if (!use_overflow)
2949       avail_out = 0;
2950     else
2951       avail_out = white_out_start - dl->bounds.left_out;
2952
2953     marker = 0;
2954     while (!done && marker < Dynarr_length (ib))
2955       {
2956         int width = Dynarr_atp (ib, marker)->width;
2957
2958         /* If everything now fits in the available inside margin
2959            space, we're done. */
2960         if (used_in <= avail_in)
2961           done = 1;
2962         else
2963           {
2964             /* Otherwise see if we have room to move a glyph to the
2965                outside. */
2966             if (used_out + width <= avail_out)
2967               {
2968                 used_out += width;
2969                 used_in -= width;
2970               }
2971             else
2972               done = 1;
2973           }
2974
2975         if (!done)
2976           marker++;
2977       }
2978
2979     /* At this point we now know that everything from marker on goes in
2980        the inside margin and everything before it goes in the outside
2981        margin.  The stuff going into the outside margin is guaranteed
2982        to fit, but we may have to trim some stuff from the inside. */
2983
2984     in_in_end = left_in_end;
2985     in_out_start = white_out_start;
2986     in_out_cnt = in_in_cnt = 0;
2987
2988     Dynarr_free (ib);
2989     elt = 0;
2990     while (elt < Dynarr_length (dl->left_glyphs))
2991       {
2992         struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
2993
2994         if (NILP (gb->extent))
2995           abort ();     /* these should have been handled in add_glyph_rune */
2996
2997         if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
2998             GL_INSIDE_MARGIN)
2999           {
3000             int width = glyph_width (gb->glyph, window);
3001
3002             if (used_out)
3003               {
3004                 in_out_cnt++;
3005                 in_out_start -= width;
3006                 gb->width = width;
3007                 gb->active = 1;
3008                 used_out -= width;
3009               }
3010             else if (in_in_end + width < white_in_start)
3011               {
3012                 in_in_cnt++;
3013                 in_in_end += width;
3014                 gb->width = width;
3015                 gb->active = 1;
3016               }
3017             else
3018               gb->active = 0;
3019           }
3020
3021         elt++;
3022       }
3023   }
3024
3025   /* Determine how many outside margin glyphs we can display.  They
3026      always start at the left outside margin and can only use the
3027      outside margin space. */
3028   out_end = dl->bounds.left_out;
3029   out_cnt = 0;
3030   elt = 0;
3031
3032   while (elt < Dynarr_length (dl->left_glyphs))
3033     {
3034       struct glyph_block *gb = Dynarr_atp (dl->left_glyphs, elt);
3035
3036       if (NILP (gb->extent))
3037         abort ();       /* these should have been handled in add_glyph_rune */
3038
3039       if (extent_begin_glyph_layout (XEXTENT (gb->extent)) ==
3040           GL_OUTSIDE_MARGIN)
3041         {
3042           int width = glyph_width (gb->glyph, window);
3043
3044           if (out_end + width <= in_out_start)
3045             {
3046               out_cnt++;
3047               out_end += width;
3048               gb->width = width;
3049               gb->active = 1;
3050             }
3051           else
3052             gb->active = 0;
3053         }
3054
3055       elt++;
3056     }
3057
3058   /* Now that we know where everything goes, we add the glyphs as
3059      runes to the appropriate display blocks. */
3060   if (out_cnt || in_out_cnt || white_out_cnt)
3061     {
3062       odb = get_display_block_from_line (dl, LEFT_OUTSIDE_MARGIN);
3063       odb->start_pos = dl->bounds.left_out;
3064       /* #### We should stop adding a blank to account for the space
3065          between the end of the glyphs and the margin and instead set
3066          this accordingly. */
3067       odb->end_pos = dl->bounds.left_in;
3068       Dynarr_reset (odb->runes);
3069     }
3070   else
3071     odb = 0;
3072
3073   if (in_in_cnt || white_in_cnt)
3074     {
3075       idb = get_display_block_from_line (dl, LEFT_INSIDE_MARGIN);
3076       idb->start_pos = dl->bounds.left_in;
3077       /* #### See above comment for odb->end_pos */
3078       idb->end_pos = dl->bounds.left_white;
3079       Dynarr_reset (idb->runes);
3080     }
3081   else
3082     idb = 0;
3083
3084   /* First add the outside margin glyphs. */
3085   if (out_cnt)
3086     end_xpos = add_margin_runes (dl, odb, dl->bounds.left_out, out_cnt,
3087                                  GL_OUTSIDE_MARGIN, LEFT_GLYPHS, window);
3088   else
3089     end_xpos = dl->bounds.left_out;
3090
3091   /* There may be blank space between the outside margin glyphs and
3092      the inside margin glyphs.  If so, add a blank. */
3093   if (in_out_cnt && (in_out_start - end_xpos))
3094     {
3095       add_margin_blank (dl, odb, w, end_xpos, in_out_start - end_xpos,
3096                         LEFT_GLYPHS);
3097     }
3098
3099   /* Next add the inside margin glyphs which are actually in the
3100      outside margin. */
3101   if (in_out_cnt)
3102     {
3103       end_xpos = add_margin_runes (dl, odb, in_out_start, in_out_cnt,
3104                                    GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3105     }
3106
3107   /* If we didn't add any inside margin glyphs to the outside margin,
3108      but are adding whitespace glyphs, then we need to add a blank
3109      here. */
3110   if (!in_out_cnt && white_out_cnt && (white_out_start - end_xpos))
3111     {
3112       add_margin_blank (dl, odb, w, end_xpos, white_out_start - end_xpos,
3113                         LEFT_GLYPHS);
3114     }
3115
3116   /* Next add the whitespace margin glyphs which are actually in the
3117      outside margin. */
3118   if (white_out_cnt)
3119     {
3120       end_xpos = add_margin_runes (dl, odb, white_out_start, white_out_cnt,
3121                                    GL_WHITESPACE, LEFT_GLYPHS, window);
3122     }
3123
3124   /* We take care of clearing between the end of the glyphs and the
3125      start of the inside margin for lines which have glyphs.  */
3126   if (odb && (left_in_start - end_xpos))
3127     {
3128       add_margin_blank (dl, odb, w, end_xpos, left_in_start - end_xpos,
3129                         LEFT_GLYPHS);
3130     }
3131
3132   /* Next add the inside margin glyphs which are actually in the
3133      inside margin. */
3134   if (in_in_cnt)
3135     {
3136       end_xpos = add_margin_runes (dl, idb, left_in_end, in_in_cnt,
3137                                    GL_INSIDE_MARGIN, LEFT_GLYPHS, window);
3138     }
3139   else
3140     end_xpos = left_in_end;
3141
3142   /* Make sure that the area between the end of the inside margin
3143      glyphs and the whitespace glyphs is cleared. */
3144   if (idb && (white_in_start - end_xpos > 0))
3145     {
3146       add_margin_blank (dl, idb, w, end_xpos, white_in_start - end_xpos,
3147                         LEFT_GLYPHS);
3148     }
3149
3150   /* Next add the whitespace margin glyphs which are actually in the
3151      inside margin. */
3152   if (white_in_cnt)
3153     {
3154       add_margin_runes (dl, idb, white_in_start, white_in_cnt, GL_WHITESPACE,
3155                         LEFT_GLYPHS, window);
3156     }
3157
3158   /* Whitespace glyphs always end right next to the text block so
3159      there is nothing we have to make sure is cleared after them. */
3160 }
3161
3162 /* Display glyphs in the right outside margin, right inside margin and
3163    right whitespace area. */
3164
3165 static void
3166 create_right_glyph_block (struct window *w, struct display_line *dl)
3167 {
3168   Lisp_Object window;
3169
3170   int use_overflow = (NILP (w->use_right_overflow) ? 0 : 1);
3171   int elt, end_xpos;
3172   int out_start, in_out_end, in_in_start, white_out_end, white_in_end;
3173   int out_cnt, in_out_cnt, in_in_cnt, white_out_cnt, white_in_cnt;
3174
3175   struct display_block *odb, *idb;
3176
3177   XSETWINDOW (window, w);
3178
3179   /* We have to add the glyphs to the line in the order outside,
3180      inside, whitespace.  However the precedence dictates that we
3181      determine how many will fit in the reverse order. */
3182
3183   /* Determine how many whitespace glyphs we can display and where
3184      they should start. */
3185   white_in_end = dl->bounds.right_white;
3186   white_out_end = dl->bounds.right_in;
3187   white_out_cnt = white_in_cnt = 0;
3188   elt = 0;
3189
3190   while (elt < Dynarr_length (dl->right_glyphs))
3191     {
3192       struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3193
3194       if (NILP (gb->extent))
3195         abort ();       /* these should have been handled in add_glyph_rune */
3196
3197       if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_WHITESPACE)
3198         {
3199           int width = glyph_width (gb->glyph, window);
3200
3201           if (white_in_end + width <= dl->bounds.right_in)
3202             {
3203               white_in_cnt++;
3204               white_in_end += width;
3205               gb->width = width;
3206               gb->active = 1;
3207             }
3208           else if (use_overflow
3209                    && (white_out_end + width <= dl->bounds.right_out))
3210             {
3211               white_out_cnt++;
3212               white_out_end += width;
3213               gb->width = width;
3214               gb->active = 1;
3215             }
3216           else
3217             gb->active = 0;
3218         }
3219
3220       elt++;
3221     }
3222
3223   /* Determine how many inside margin glyphs we can display and where
3224      they should start.  The inside margin glyphs get whatever space
3225      is left after the whitespace glyphs have been displayed.  These
3226      are tricky to calculate since if we decide to use the overflow
3227      area we basically have to start over.  So for these we build up a
3228      list of just the inside margin glyphs and manipulate it to
3229      determine the needed info. */
3230   {
3231     glyph_block_dynarr *ib;
3232     int avail_in, avail_out;
3233     int done = 0;
3234     int marker = 0;
3235     int used_in, used_out;
3236
3237     elt = 0;
3238     used_in = used_out = 0;
3239     ib = Dynarr_new (glyph_block);
3240     while (elt < Dynarr_length (dl->right_glyphs))
3241       {
3242         struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3243
3244         if (NILP (gb->extent))
3245           abort ();     /* these should have been handled in add_glyph_rune */
3246
3247         if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3248           {
3249             gb->width = glyph_width (gb->glyph, window);
3250             used_in += gb->width;
3251             Dynarr_add (ib, *gb);
3252           }
3253
3254         elt++;
3255       }
3256
3257     if (white_out_cnt)
3258       avail_in = 0;
3259     else
3260       avail_in = dl->bounds.right_in - white_in_end;
3261
3262     if (!use_overflow)
3263       avail_out = 0;
3264     else
3265       avail_out = dl->bounds.right_out - white_out_end;
3266
3267     marker = 0;
3268     while (!done && marker < Dynarr_length (ib))
3269       {
3270         int width = Dynarr_atp (ib, marker)->width;
3271
3272         /* If everything now fits in the available inside margin
3273            space, we're done. */
3274         if (used_in <= avail_in)
3275           done = 1;
3276         else
3277           {
3278             /* Otherwise see if we have room to move a glyph to the
3279                outside. */
3280             if (used_out + width <= avail_out)
3281               {
3282                 used_out += width;
3283                 used_in -= width;
3284               }
3285             else
3286               done = 1;
3287           }
3288
3289         if (!done)
3290           marker++;
3291       }
3292
3293     /* At this point we now know that everything from marker on goes in
3294        the inside margin and everything before it goes in the outside
3295        margin.  The stuff going into the outside margin is guaranteed
3296        to fit, but we may have to trim some stuff from the inside. */
3297
3298     in_in_start = dl->bounds.right_in;
3299     in_out_end = dl->bounds.right_in;
3300     in_out_cnt = in_in_cnt = 0;
3301
3302     Dynarr_free (ib);
3303     elt = 0;
3304     while (elt < Dynarr_length (dl->right_glyphs))
3305       {
3306         struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3307
3308         if (NILP (gb->extent))
3309           abort ();     /* these should have been handled in add_glyph_rune */
3310
3311         if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_INSIDE_MARGIN)
3312           {
3313             int width = glyph_width (gb->glyph, window);
3314
3315             if (used_out)
3316               {
3317                 in_out_cnt++;
3318                 in_out_end += width;
3319                 gb->width = width;
3320                 gb->active = 1;
3321                 used_out -= width;
3322               }
3323             else if (in_in_start - width >= white_in_end)
3324               {
3325                 in_in_cnt++;
3326                 in_in_start -= width;
3327                 gb->width = width;
3328                 gb->active = 1;
3329               }
3330             else
3331               gb->active = 0;
3332           }
3333
3334         elt++;
3335       }
3336   }
3337
3338   /* Determine how many outside margin glyphs we can display.  They
3339      always start at the right outside margin and can only use the
3340      outside margin space. */
3341   out_start = dl->bounds.right_out;
3342   out_cnt = 0;
3343   elt = 0;
3344
3345   while (elt < Dynarr_length (dl->right_glyphs))
3346     {
3347       struct glyph_block *gb = Dynarr_atp (dl->right_glyphs, elt);
3348
3349       if (NILP (gb->extent))
3350         abort ();       /* these should have been handled in add_glyph_rune */
3351
3352       if (extent_end_glyph_layout (XEXTENT (gb->extent)) == GL_OUTSIDE_MARGIN)
3353         {
3354           int width = glyph_width (gb->glyph, window);
3355
3356           if (out_start - width >= in_out_end)
3357             {
3358               out_cnt++;
3359               out_start -= width;
3360               gb->width = width;
3361               gb->active = 1;
3362             }
3363           else
3364             gb->active = 0;
3365         }
3366
3367       elt++;
3368     }
3369
3370   /* Now that we now where everything goes, we add the glyphs as runes
3371      to the appropriate display blocks. */
3372   if (out_cnt || in_out_cnt || white_out_cnt)
3373     {
3374       odb = get_display_block_from_line (dl, RIGHT_OUTSIDE_MARGIN);
3375       /* #### See comments before odb->start_pos init in
3376          create_left_glyph_block */
3377       odb->start_pos = dl->bounds.right_in;
3378       odb->end_pos = dl->bounds.right_out;
3379       Dynarr_reset (odb->runes);
3380     }
3381   else
3382     odb = 0;
3383
3384   if (in_in_cnt || white_in_cnt)
3385     {
3386       idb = get_display_block_from_line (dl, RIGHT_INSIDE_MARGIN);
3387       idb->start_pos = dl->bounds.right_white;
3388       /* #### See comments before odb->start_pos init in
3389          create_left_glyph_block */
3390       idb->end_pos = dl->bounds.right_in;
3391       Dynarr_reset (idb->runes);
3392     }
3393   else
3394     idb = 0;
3395
3396   /* First add the whitespace margin glyphs which are actually in the
3397      inside margin. */
3398   if (white_in_cnt)
3399     {
3400       end_xpos = add_margin_runes (dl, idb, dl->bounds.right_white,
3401                                    white_in_cnt, GL_WHITESPACE, RIGHT_GLYPHS,
3402                                    window);
3403     }
3404   else
3405     end_xpos = dl->bounds.right_white;
3406
3407   /* Make sure that the area between the end of the whitespace glyphs
3408      and the inside margin glyphs is cleared. */
3409   if (in_in_cnt && (in_in_start - end_xpos))
3410     {
3411       add_margin_blank (dl, idb, w, end_xpos, in_in_start - end_xpos,
3412                         RIGHT_GLYPHS);
3413     }
3414
3415   /* Next add the inside margin glyphs which are actually in the
3416      inside margin. */
3417   if (in_in_cnt)
3418     {
3419       end_xpos = add_margin_runes (dl, idb, in_in_start, in_in_cnt,
3420                                    GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3421     }
3422
3423   /* If we didn't add any inside margin glyphs then make sure the rest
3424      of the inside margin area gets cleared. */
3425   if (idb && (dl->bounds.right_in - end_xpos))
3426     {
3427       add_margin_blank (dl, idb, w, end_xpos, dl->bounds.right_in - end_xpos,
3428                         RIGHT_GLYPHS);
3429     }
3430
3431   /* Next add any whitespace glyphs in the outside margin. */
3432   if (white_out_cnt)
3433     {
3434       end_xpos = add_margin_runes (dl, odb, dl->bounds.right_in, white_out_cnt,
3435                                    GL_WHITESPACE, RIGHT_GLYPHS, window);
3436     }
3437   else
3438     end_xpos = dl->bounds.right_in;
3439
3440   /* Next add any inside margin glyphs in the outside margin. */
3441   if (in_out_cnt)
3442     {
3443       end_xpos = add_margin_runes (dl, odb, end_xpos, in_out_cnt,
3444                                    GL_INSIDE_MARGIN, RIGHT_GLYPHS, window);
3445     }
3446
3447   /* There may be space between any whitespace or inside margin glyphs
3448      in the outside margin and the actual outside margin glyphs. */
3449   if (odb && (out_start - end_xpos))
3450     {
3451       add_margin_blank (dl, odb, w, end_xpos, out_start - end_xpos,
3452                         RIGHT_GLYPHS);
3453     }
3454
3455   /* Finally, add the outside margin glyphs. */
3456   if (out_cnt)
3457     {
3458       add_margin_runes (dl, odb, out_start, out_cnt, GL_OUTSIDE_MARGIN,
3459                         RIGHT_GLYPHS, window);
3460     }
3461 }
3462
3463 \f
3464 /***************************************************************************/
3465 /*                                                                         */
3466 /*                            modeline routines                            */
3467 /*                                                                         */
3468 /***************************************************************************/
3469
3470 /* This function is also used in frame.c by `generate_title_string' */
3471 void
3472 generate_formatted_string_db (Lisp_Object format_str, Lisp_Object result_str,
3473                               struct window *w, struct display_line *dl,
3474                               struct display_block *db, face_index findex,
3475                               int min_pixpos, int max_pixpos, int type)
3476 {
3477   struct frame *f = XFRAME (w->frame);
3478   struct device *d = XDEVICE (f->device);
3479
3480   pos_data data;
3481   int c_pixpos;
3482   Charcount offset = 0;
3483
3484   xzero (data);
3485   data.d = d;
3486   data.db = db;
3487   data.dl = dl;
3488   data.findex = findex;
3489   data.pixpos = min_pixpos;
3490   data.max_pixpos = max_pixpos;
3491   data.cursor_type = NO_CURSOR;
3492   data.last_charset = Qunbound;
3493   data.last_findex = DEFAULT_INDEX;
3494   data.result_str = result_str;
3495   data.is_modeline = 1;
3496   data.string = Qnil;
3497   XSETWINDOW (data.window, w);
3498
3499   Dynarr_reset (formatted_string_extent_dynarr);
3500   Dynarr_reset (formatted_string_extent_start_dynarr);
3501   Dynarr_reset (formatted_string_extent_end_dynarr);
3502
3503   /* result_str is nil when we're building a frame or icon title. Otherwise,
3504      we're building a modeline, so the offset starts at the modeline
3505      horizontal scrolling ammount */
3506   if (! NILP (result_str))
3507     offset = w->modeline_hscroll;
3508   generate_fstring_runes (w, &data, 0, 0, -1, format_str, 0,
3509                           max_pixpos - min_pixpos, findex, type, &offset,
3510                           Qnil);
3511
3512   if (Dynarr_length (db->runes))
3513     {
3514       struct rune *rb =
3515         Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
3516       c_pixpos = rb->xpos + rb->width;
3517     }
3518   else
3519     c_pixpos = min_pixpos;
3520
3521   /* If we don't reach the right side of the window, add a blank rune
3522      to make up the difference.  This usually only occurs if the
3523      modeline face is using a proportional width font or a fixed width
3524      font of a different size from the default face font. */
3525
3526   if (c_pixpos < max_pixpos)
3527     {
3528       data.pixpos = c_pixpos;
3529       data.blank_width = max_pixpos - data.pixpos;
3530
3531       add_blank_rune (&data, NULL, 0);
3532     }
3533
3534   /* Now create the result string and frob the extents into it. */
3535   if (!NILP (result_str))
3536     {
3537       int elt;
3538       Bytecount len;
3539       Bufbyte *strdata;
3540       struct buffer *buf = XBUFFER (WINDOW_BUFFER (w));
3541
3542       in_modeline_generation = 1;
3543
3544       detach_all_extents (result_str);
3545       resize_string (XSTRING (result_str), -1,
3546                      data.bytepos - XSTRING_LENGTH (result_str));
3547
3548       strdata = XSTRING_DATA (result_str);
3549
3550       for (elt = 0, len = 0; elt < Dynarr_length (db->runes); elt++)
3551         {
3552           if (Dynarr_atp (db->runes, elt)->type == RUNE_CHAR)
3553             {
3554               len += (set_charptr_emchar
3555                       (strdata + len, Dynarr_atp (db->runes,
3556                                                   elt)->object.chr.ch));
3557             }
3558         }
3559
3560       for (elt = 0; elt < Dynarr_length (formatted_string_extent_dynarr);
3561            elt++)
3562         {
3563           Lisp_Object extent = Qnil;
3564           Lisp_Object child;
3565
3566           XSETEXTENT (extent, Dynarr_at (formatted_string_extent_dynarr, elt));
3567           child = Fgethash (extent, buf->modeline_extent_table, Qnil);
3568           if (NILP (child))
3569             {
3570               child = Fmake_extent (Qnil, Qnil, result_str);
3571               Fputhash (extent, child, buf->modeline_extent_table);
3572             }
3573           Fset_extent_parent (child, extent);
3574           set_extent_endpoints
3575             (XEXTENT (child),
3576              Dynarr_at (formatted_string_extent_start_dynarr, elt),
3577              Dynarr_at (formatted_string_extent_end_dynarr, elt),
3578              result_str);
3579         }
3580
3581       in_modeline_generation = 0;
3582     }
3583 }
3584
3585 /* Ensure that the given display line DL accurately represents the
3586    modeline for the given window. */
3587 static void
3588 generate_modeline (struct window *w, struct display_line *dl, int type)
3589 {
3590   struct buffer *b = XBUFFER (w->buffer);
3591   struct frame *f = XFRAME (w->frame);
3592   struct device *d = XDEVICE (f->device);
3593
3594   /* Unlike display line and rune pointers, this one can't change underneath
3595      our feet. */
3596   struct display_block *db = get_display_block_from_line (dl, TEXT);
3597   int max_pixpos, min_pixpos, ypos_adj;
3598   Lisp_Object font_inst;
3599
3600   /* This will actually determine incorrect inside boundaries for the
3601      modeline since it ignores the margins.  However being aware of this fact
3602      we never use those values anywhere so it doesn't matter. */
3603   dl->bounds = calculate_display_line_boundaries (w, 1);
3604
3605   /* We are generating a modeline. */
3606   dl->modeline = 1;
3607   dl->cursor_elt = -1;
3608
3609   /* Reset the runes on the modeline. */
3610   Dynarr_reset (db->runes);
3611
3612   if (!WINDOW_HAS_MODELINE_P (w))
3613     {
3614       struct rune rb;
3615
3616       /* If there is a horizontal scrollbar, don't add anything. */
3617       if (window_scrollbar_height (w))
3618         return;
3619
3620       dl->ascent = DEVMETH (d, divider_height, ());
3621       dl->descent = 0;
3622       /* The modeline is at the bottom of the gutters. */
3623       dl->ypos = WINDOW_BOTTOM (w);
3624
3625       rb.findex = MODELINE_INDEX;
3626       rb.xpos = dl->bounds.left_out;
3627       rb.width = dl->bounds.right_out - dl->bounds.left_out;
3628       rb.bufpos = 0;
3629       rb.endpos = 0;
3630       rb.type = RUNE_HLINE;
3631       rb.object.hline.thickness = 1;
3632       rb.object.hline.yoffset = 0;
3633       rb.cursor_type = NO_CURSOR;
3634
3635       if (!EQ (Qzero, w->modeline_shadow_thickness)
3636           && FRAME_WIN_P (f))
3637         {
3638           int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3639
3640           dl->ypos -= shadow_thickness;
3641           rb.xpos += shadow_thickness;
3642           rb.width -= 2 * shadow_thickness;
3643         }
3644
3645       Dynarr_add (db->runes, rb);
3646       return;
3647     }
3648
3649   /* !!#### not right; needs to compute the max height of
3650      all the charsets */
3651   font_inst = WINDOW_FACE_CACHEL_FONT (w, MODELINE_INDEX, Vcharset_ascii);
3652
3653   dl->ascent = XFONT_INSTANCE (font_inst)->ascent;
3654   dl->descent = XFONT_INSTANCE (font_inst)->descent;
3655
3656   min_pixpos = dl->bounds.left_out;
3657   max_pixpos = dl->bounds.right_out;
3658
3659   if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f))
3660     {
3661       int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
3662
3663       ypos_adj = shadow_thickness;
3664       min_pixpos += shadow_thickness;
3665       max_pixpos -= shadow_thickness;
3666     }
3667   else
3668     ypos_adj = 0;
3669
3670   generate_formatted_string_db (b->modeline_format,
3671                                 b->generated_modeline_string, w, dl, db,
3672                                 MODELINE_INDEX, min_pixpos, max_pixpos, type);
3673
3674   /* The modeline is at the bottom of the gutters.  We have to wait to
3675      set this until we've generated the modeline in order to account
3676      for any embedded faces. */
3677   dl->ypos = WINDOW_BOTTOM (w) - dl->descent - ypos_adj;
3678 }
3679
3680 static Charcount
3681 add_string_to_fstring_db_runes (pos_data *data, const Bufbyte *str,
3682                                 Charcount pos, Charcount min_pos, Charcount max_pos)
3683 {
3684   /* This function has been Mule-ized. */
3685   Charcount end;
3686   const Bufbyte *cur_pos = str;
3687   struct display_block *db = data->db;
3688
3689   data->blank_width = space_width (XWINDOW (data->window));
3690   while (Dynarr_length (db->runes) < pos)
3691     add_blank_rune (data, NULL, 0);
3692
3693   end = (Dynarr_length (db->runes) +
3694          bytecount_to_charcount (str, strlen ((const char *) str)));
3695   if (max_pos != -1)
3696     end = min (max_pos, end);
3697
3698   while (pos < end && *cur_pos)
3699     {
3700       const Bufbyte *old_cur_pos = cur_pos;
3701       int succeeded;
3702
3703       data->ch = charptr_emchar (cur_pos);
3704       succeeded = (add_emchar_rune (data) != ADD_FAILED);
3705       INC_CHARPTR (cur_pos);
3706       if (succeeded)
3707         {
3708           pos++;
3709           data->modeline_charpos++;
3710           data->bytepos += cur_pos - old_cur_pos;
3711         }
3712     }
3713
3714   while (Dynarr_length (db->runes) < min_pos &&
3715          (data->pixpos + data->blank_width <= data->max_pixpos))
3716     add_blank_rune (data, NULL, 0);
3717
3718   return Dynarr_length (db->runes);
3719 }
3720
3721 /* #### Urk!  Should also handle begin-glyphs and end-glyphs in
3722    modeline extents. */
3723 static Charcount
3724 add_glyph_to_fstring_db_runes (pos_data *data, Lisp_Object glyph,
3725                                Charcount pos, Charcount min_pos,
3726                                Charcount max_pos, Lisp_Object extent)
3727 {
3728   /* This function has been Mule-ized. */
3729   Charcount end;
3730   struct display_block *db = data->db;
3731   struct glyph_block gb;
3732
3733   data->blank_width = space_width (XWINDOW (data->window));
3734   while (Dynarr_length (db->runes) < pos)
3735     add_blank_rune (data, NULL, 0);
3736
3737   end = Dynarr_length (db->runes) + 1;
3738   if (max_pos != -1)
3739     end = min (max_pos, end);
3740
3741   gb.glyph = glyph;
3742   gb.extent = extent;
3743   add_glyph_rune (data, &gb, BEGIN_GLYPHS, 0, 0);
3744   pos++;
3745
3746   while (Dynarr_length (db->runes) < pos &&
3747          (data->pixpos + data->blank_width <= data->max_pixpos))
3748     add_blank_rune (data, NULL, 0);
3749
3750   return Dynarr_length (db->runes);
3751 }
3752
3753 /* If max_pos is == -1, it is considered to be infinite.  The same is
3754    true of max_pixsize. */
3755 #define SET_CURRENT_MODE_CHARS_PIXSIZE                                  \
3756   if (Dynarr_length (data->db->runes))                                  \
3757     cur_pixsize = data->pixpos - Dynarr_atp (data->db->runes, 0)->xpos; \
3758   else                                                                  \
3759     cur_pixsize = 0;
3760
3761 /* Note that this function does "positions" in terms of characters and
3762    not in terms of columns.  This is necessary to make the formatting
3763    work correctly when proportional width fonts are used in the
3764    modeline. */
3765 static Charcount
3766 generate_fstring_runes (struct window *w, pos_data *data, Charcount pos,
3767                         Charcount min_pos, Charcount max_pos,
3768                         Lisp_Object elt, int depth, int max_pixsize,
3769                         face_index findex, int type, Charcount *offset,
3770                         Lisp_Object cur_ext)
3771 {
3772   /* This function has been Mule-ized. */
3773   /* #### The other losing things in this function are:
3774
3775      -- C zero-terminated-string lossage.
3776      -- Non-printable characters should be converted into something
3777         appropriate (e.g. ^F) instead of blindly being printed anyway.
3778    */
3779
3780 tail_recurse:
3781   if (depth > 10)
3782     goto invalid;
3783
3784   depth++;
3785
3786   if (STRINGP (elt))
3787     {
3788       /* A string.  Add to the display line and check for %-constructs
3789          within it. */
3790
3791       Bufbyte *this = XSTRING_DATA (elt);
3792
3793       while ((pos < max_pos || max_pos == -1) && *this)
3794         {
3795           Bufbyte *last = this;
3796
3797           while (*this && *this != '%')
3798             this++;
3799
3800           if (this != last)
3801             {
3802               /* No %-construct */
3803               Charcount size =
3804                 bytecount_to_charcount (last, this - last);
3805
3806               if (size <= *offset)
3807                 *offset -= size;
3808               else
3809                 {
3810                   Charcount tmp_max = (max_pos == -1 ? pos + size - *offset :
3811                                        min (pos + size - *offset, max_pos));
3812                   const Bufbyte *tmp_last = charptr_n_addr (last, *offset);
3813
3814                   pos = add_string_to_fstring_db_runes (data, tmp_last,
3815                                                         pos, pos, tmp_max);
3816                   *offset = 0;
3817                 }
3818             }
3819           else /* *this == '%' */
3820             {
3821               Charcount spec_width = 0;
3822
3823               this++; /* skip over '%' */
3824
3825               /* We can't allow -ve args due to the "%-" construct.
3826                * Argument specifies minwidth but not maxwidth
3827                * (maxwidth can be specified by
3828                * (<negative-number> . <stuff>) modeline elements)
3829                */
3830               while (isdigit (*this))
3831                 {
3832                   spec_width = spec_width * 10 + (*this - '0');
3833                   this++;
3834                 }
3835               spec_width += pos;
3836
3837               if (*this == 'M')
3838                 {
3839                   pos = generate_fstring_runes (w, data, pos, spec_width,
3840                                                 max_pos, Vglobal_mode_string,
3841                                                 depth, max_pixsize, findex,
3842                                                 type, offset, cur_ext);
3843                 }
3844               else if (*this == '-')
3845                 {
3846                   Charcount num_to_add;
3847
3848                   if (max_pixsize < 0)
3849                     num_to_add = 0;
3850                   else if (max_pos != -1)
3851                     num_to_add = max_pos - pos;
3852                   else
3853                     {
3854                       int cur_pixsize;
3855                       int dash_pixsize;
3856                       Bufbyte ch = '-';
3857                       SET_CURRENT_MODE_CHARS_PIXSIZE;
3858
3859                       dash_pixsize =
3860                         redisplay_text_width_string (w, findex, &ch, Qnil, 0,
3861                                                      1);
3862
3863                       num_to_add = (max_pixsize - cur_pixsize) / dash_pixsize;
3864                       num_to_add++;
3865                     }
3866
3867                   while (num_to_add--)
3868                     pos = add_string_to_fstring_db_runes
3869                       (data, (const Bufbyte *) "-", pos, pos, max_pos);
3870                 }
3871               else if (*this != 0)
3872                 {
3873                   Emchar ch = charptr_emchar (this);
3874                   Bufbyte *str;
3875                   Charcount size;
3876
3877                   decode_mode_spec (w, ch, type);
3878
3879                   str = Dynarr_atp (mode_spec_bufbyte_string, 0);
3880                   size = bytecount_to_charcount
3881                     /* Skip the null character added by `decode_mode_spec' */
3882                     (str, Dynarr_length (mode_spec_bufbyte_string)) - 1;
3883
3884                   if (size <= *offset)
3885                     *offset -= size;
3886                   else
3887                     {
3888                       const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3889
3890                       /* #### NOTE: I don't understand why a tmp_max is not
3891                          computed and used here as in the plain string case
3892                          above. -- dv */
3893                       pos = add_string_to_fstring_db_runes (data, tmp_str,
3894                                                             pos, pos,
3895                                                             max_pos);
3896                       *offset = 0;
3897                     }
3898                 }
3899
3900               /* NOT this++.  There could be any sort of character at
3901                  the current position. */
3902               INC_CHARPTR (this);
3903             }
3904
3905           if (max_pixsize > 0)
3906             {
3907               int cur_pixsize;
3908               SET_CURRENT_MODE_CHARS_PIXSIZE;
3909
3910               if (cur_pixsize >= max_pixsize)
3911                 break;
3912             }
3913         }
3914     }
3915   else if (SYMBOLP (elt))
3916     {
3917       /* A symbol: process the value of the symbol recursively
3918          as if it appeared here directly. */
3919       Lisp_Object tem = symbol_value_in_buffer (elt, w->buffer);
3920
3921       if (!UNBOUNDP (tem))
3922         {
3923           /* If value is a string, output that string literally:
3924              don't check for % within it.  */
3925           if (STRINGP (tem))
3926             {
3927               Bufbyte *str = XSTRING_DATA (tem);
3928               Charcount size = XSTRING_CHAR_LENGTH (tem);
3929
3930               if (size <= *offset)
3931                 *offset -= size;
3932               else
3933                 {
3934                   const Bufbyte *tmp_str = charptr_n_addr (str, *offset);
3935
3936                   /* #### NOTE: I don't understand why a tmp_max is not
3937                      computed and used here as in the plain string case
3938                      above. -- dv */
3939                   pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
3940                                                         min_pos, max_pos);
3941                   *offset = 0;
3942                 }
3943             }
3944           /* Give up right away for nil or t.  */
3945           else if (!EQ (tem, elt))
3946             {
3947               elt = tem;
3948               goto tail_recurse;
3949             }
3950         }
3951     }
3952   else if (GENERIC_SPECIFIERP (elt))
3953     {
3954       Lisp_Object window, tem;
3955       XSETWINDOW (window, w);
3956       tem = specifier_instance_no_quit (elt, Qunbound, window,
3957                                         ERROR_ME_NOT, 0, Qzero);
3958       if (!UNBOUNDP (tem))
3959         {
3960           elt = tem;
3961           goto tail_recurse;
3962         }
3963     }
3964   else if (CONSP (elt))
3965     {
3966       /* A cons cell: four distinct cases.
3967        * - If first element is a string or a cons, process all the elements
3968        *   and effectively concatenate them.
3969        * - If first element is a negative number, truncate displaying cdr to
3970        *   at most that many characters.  If positive, pad (with spaces)
3971        *   to at least that many characters.
3972        * - If first element is another symbol, process the cadr or caddr
3973        *   recursively according to whether the symbol's value is non-nil or
3974        *   nil.
3975        * - If first element is an extent, process the cdr recursively
3976        *   and handle the extent's face.
3977        */
3978
3979       Lisp_Object car, tem;
3980
3981       car = XCAR (elt);
3982       if (SYMBOLP (car))
3983         {
3984           elt = XCDR (elt);
3985           if (!CONSP (elt))
3986             goto invalid;
3987
3988           tem = symbol_value_in_buffer (car, w->buffer);
3989           /* elt is now the cdr, and we know it is a cons cell.
3990              Use its car if CAR has a non-nil value.  */
3991           if (!UNBOUNDP (tem))
3992             {
3993               if (!NILP (tem))
3994                 {
3995                   elt = XCAR (elt);
3996                   goto tail_recurse;
3997                 }
3998             }
3999           /* Symbol's value is nil (or symbol is unbound)
4000            * Get the cddr of the original list
4001            * and if possible find the caddr and use that.
4002            */
4003           elt = XCDR (elt);
4004           if (NILP (elt))
4005             ;
4006           else if (!CONSP (elt))
4007             goto invalid;
4008           else
4009             {
4010               elt = XCAR (elt);
4011               goto tail_recurse;
4012             }
4013         }
4014       else if (INTP (car))
4015         {
4016           Charcount lim = XINT (car);
4017
4018           elt = XCDR (elt);
4019
4020           if (lim < 0)
4021             {
4022               /* Negative int means reduce maximum width.
4023                * DO NOT change MIN_PIXPOS here!
4024                * (20 -10 . foo) should truncate foo to 10 col
4025                * and then pad to 20.
4026                */
4027               if (max_pos == -1)
4028                 max_pos = pos - lim;
4029               else
4030                 max_pos = min (max_pos, pos - lim);
4031             }
4032           else if (lim > 0)
4033             {
4034               /* Padding specified.  Don't let it be more than
4035                * current maximum.
4036                */
4037               lim += pos;
4038               if (max_pos != -1 && lim > max_pos)
4039                 lim = max_pos;
4040               /* If that's more padding than already wanted, queue it.
4041                * But don't reduce padding already specified even if
4042                * that is beyond the current truncation point.
4043                */
4044               if (lim > min_pos)
4045                 min_pos = lim;
4046             }
4047           goto tail_recurse;
4048         }
4049       else if (STRINGP (car) || CONSP (car))
4050         {
4051           int limit = 50;
4052
4053           /* LIMIT is to protect against circular lists.  */
4054           while (CONSP (elt) && --limit > 0
4055                  && (pos < max_pos || max_pos == -1))
4056             {
4057               pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4058                                             XCAR (elt), depth, max_pixsize,
4059                                             findex, type, offset, cur_ext);
4060               elt = XCDR (elt);
4061             }
4062         }
4063       else if (EXTENTP (car))
4064         {
4065           struct extent *ext = XEXTENT (car);
4066
4067           if (EXTENT_LIVE_P (ext))
4068             {
4069               face_index old_findex = data->findex;
4070               Lisp_Object face;
4071               Lisp_Object font_inst;
4072               face_index new_findex;
4073               Bytecount start = data->bytepos;
4074
4075               face = extent_face (ext);
4076               if (FACEP (face))
4077                 {
4078                   /* #### needs to merge faces, sigh */
4079                   /* #### needs to handle list of faces */
4080                   new_findex = get_builtin_face_cache_index (w, face);
4081                   /* !!#### not right; needs to compute the max height of
4082                      all the charsets */
4083                   font_inst = WINDOW_FACE_CACHEL_FONT (w, new_findex,
4084                                                        Vcharset_ascii);
4085
4086                   data->dl->ascent = max (data->dl->ascent,
4087                                           XFONT_INSTANCE (font_inst)->ascent);
4088                   data->dl->descent = max (data->dl->descent,
4089                                            XFONT_INSTANCE (font_inst)->
4090                                            descent);
4091                 }
4092               else
4093                 new_findex = old_findex;
4094
4095               data->findex = new_findex;
4096               pos = generate_fstring_runes (w, data, pos, pos, max_pos,
4097                                             XCDR (elt), depth - 1,
4098                                             max_pixsize, new_findex, type,
4099                                             offset, car);
4100               data->findex = old_findex;
4101               Dynarr_add (formatted_string_extent_dynarr, ext);
4102               Dynarr_add (formatted_string_extent_start_dynarr, start);
4103               Dynarr_add (formatted_string_extent_end_dynarr, data->bytepos);
4104             }
4105         }
4106     }
4107   else if (GLYPHP (elt))
4108     {
4109       /* Glyphs are considered as one character with respect to the modeline
4110          horizontal scrolling facility. -- dv */
4111       if (*offset > 0)
4112         *offset -= 1;
4113       else
4114         pos = add_glyph_to_fstring_db_runes (data, elt, pos, pos, max_pos,
4115                                              cur_ext);
4116     }
4117   else
4118     {
4119     invalid:
4120       {
4121         char *str = GETTEXT ("*invalid*");
4122         Charcount size = (Charcount) strlen (str); /* is this ok ?? -- dv */
4123
4124         if (size <= *offset)
4125           *offset -= size;
4126         else
4127           {
4128             const Bufbyte *tmp_str =
4129               charptr_n_addr ((const Bufbyte *) str, *offset);
4130
4131             /* #### NOTE: I don't understand why a tmp_max is not computed and
4132                used here as in the plain string case above. -- dv */
4133             pos = add_string_to_fstring_db_runes (data, tmp_str, pos,
4134                                                   min_pos, max_pos);
4135             *offset = 0;
4136           }
4137       }
4138     }
4139
4140   if (min_pos > pos)
4141     {
4142       add_string_to_fstring_db_runes (data, (const Bufbyte *) "", pos,
4143                                       min_pos, -1);
4144     }
4145
4146   return pos;
4147 }
4148
4149 /* Update just the modeline.  Assumes the desired display structs.  If
4150    they do not have a modeline block, it does nothing. */
4151 static void
4152 regenerate_modeline (struct window *w)
4153 {
4154   display_line_dynarr *dla = window_display_lines (w, DESIRED_DISP);
4155
4156   if (!Dynarr_length (dla) || !Dynarr_atp (dla, 0)->modeline)
4157     return;
4158   else
4159     {
4160       generate_modeline (w, Dynarr_atp (dla, 0), DESIRED_DISP);
4161       redisplay_update_line (w, 0, 0, 0);
4162     }
4163 }
4164
4165 /* Make sure that modeline display line is present in the given
4166    display structs if the window has a modeline and update that
4167    line.  Returns true if a modeline was needed. */
4168 static int
4169 ensure_modeline_generated (struct window *w, int type)
4170 {
4171   int need_modeline;
4172
4173   /* minibuffer windows don't have modelines */
4174   if (MINI_WINDOW_P (w))
4175     need_modeline = 0;
4176   /* windows which haven't had it turned off do */
4177   else if (WINDOW_HAS_MODELINE_P (w))
4178     need_modeline = 1;
4179   /* windows which have it turned off don't have a divider if there is
4180      a horizontal scrollbar */
4181   else if (window_scrollbar_height (w))
4182     need_modeline = 0;
4183   /* and in this case there is none */
4184   else
4185     need_modeline = 1;
4186
4187   if (need_modeline)
4188     {
4189       display_line_dynarr *dla;
4190
4191       dla = window_display_lines (w, type);
4192
4193       /* We don't care if there is a display line which is not
4194          currently a modeline because it is definitely going to become
4195          one if we have gotten to this point. */
4196       if (Dynarr_length (dla) == 0)
4197         {
4198           if (Dynarr_largest (dla) > 0)
4199             {
4200               struct display_line *mlp = Dynarr_atp (dla, 0);
4201               Dynarr_add (dla, *mlp);
4202             }
4203           else
4204             {
4205               struct display_line modeline;
4206               xzero (modeline);
4207               Dynarr_add (dla, modeline);
4208             }
4209         }
4210
4211       /* If we're adding a new place marker go ahead and generate the
4212          modeline so that it is available for use by
4213          window_modeline_height. */
4214       generate_modeline (w, Dynarr_atp (dla, 0), type);
4215     }
4216
4217   return need_modeline;
4218 }
4219
4220 /* #### Kludge or not a kludge.  I tend towards the former. */
4221 int
4222 real_current_modeline_height (struct window *w)
4223 {
4224   Fset_marker (w->start[CMOTION_DISP],  w->start[CURRENT_DISP],  w->buffer);
4225   Fset_marker (w->pointm[CMOTION_DISP], w->pointm[CURRENT_DISP], w->buffer);
4226
4227   if (ensure_modeline_generated (w, CMOTION_DISP))
4228     {
4229       display_line_dynarr *dla = window_display_lines (w, CMOTION_DISP);
4230
4231       if (Dynarr_length (dla))
4232         {
4233           if (Dynarr_atp (dla, 0)->modeline)
4234             return (Dynarr_atp (dla, 0)->ascent +
4235                     Dynarr_atp (dla, 0)->descent);
4236         }
4237     }
4238   return 0;
4239 }
4240
4241 \f
4242 /***************************************************************************/
4243 /*                                                              */
4244 /*                            displayable string routines                       */
4245 /*                                                              */
4246 /***************************************************************************/
4247
4248 /* Given a position for a string in a window, ensure that the given
4249    display line DL accurately represents the text on a line starting
4250    at the given position.
4251
4252    Yes, this is duplicating the code of create_text_block, but it
4253    looked just too hard to change create_text_block to handle strings
4254    *and* buffers. We already make a distinction between the two
4255    elsewhere in the code so I think unifying them would require a
4256    complete MULE rewrite. Besides, the other distinction is that these
4257    functions cover text that the user *cannot edit* so we can remove
4258    everything to do with cursors, minibuffers etc. Eventually the
4259    modeline routines should be modified to use this code as it copes
4260    with many more types of display situation. */
4261
4262 static Bufpos
4263 create_string_text_block (struct window *w, Lisp_Object disp_string,
4264                           struct display_line *dl,
4265                           Bufpos start_pos,
4266                           prop_block_dynarr **prop,
4267                           face_index default_face)
4268 {
4269   struct frame *f = XFRAME (w->frame);
4270   /* Note that a lot of the buffer controlled stuff has been left in
4271      because you might well want to make use of it (selective display
4272      etc), its just the buffer text that we do not use. However, it
4273      seems to be possible for buffer to be nil sometimes so protect
4274      against this case. */
4275   struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0;
4276   struct device *d = XDEVICE (f->device);
4277   Lisp_String* s = XSTRING (disp_string);
4278
4279   /* we're working with these a lot so precalculate them */
4280   Bytecount slen = XSTRING_LENGTH (disp_string);
4281   Bytecount bi_string_zv = slen;
4282   Bytind bi_start_pos = charcount_to_bytecount (string_data (s), start_pos);
4283
4284   pos_data data;
4285
4286   int truncate_win = b ? window_truncation_on (w) : 0;
4287   int end_glyph_width = 0;
4288
4289   /* we're going to ditch selective display for static text, its an
4290      FSF thing and invisble extents are the way to go
4291      here. Implementing it also relies on a number of buffer-specific
4292      functions that we don't have the luxury of being able to use
4293      here. */
4294
4295   /* The variable ctl-arrow allows the user to specify what characters
4296      can actually be displayed and which octal should be used for.
4297      #### This variable should probably have some rethought done to
4298      it.
4299
4300      #### It would also be really nice if you could specify that
4301      the characters come out in hex instead of in octal.  Mule
4302      does that by adding a ctl-hexa variable similar to ctl-arrow,
4303      but that's bogus -- we need a more general solution.  I
4304      think you need to extend the concept of display tables
4305      into a more general conversion mechanism.  Ideally you
4306      could specify a Lisp function that converts characters,
4307      but this violates the Second Golden Rule and besides would
4308      make things way way way way slow.
4309
4310      So instead, we extend the display-table concept, which was
4311      historically limited to 256-byte vectors, to one of the
4312      following:
4313
4314      a) A 256-entry vector, for backward compatibility;
4315      b) char-table, mapping characters to values;
4316      c) range-table, mapping ranges of characters to values;
4317      d) a list of the above.
4318
4319      The (d) option allows you to specify multiple display tables
4320      instead of just one.  Each display table can specify conversions
4321      for some characters and leave others unchanged.  The way the
4322      character gets displayed is determined by the first display table
4323      with a binding for that character.  This way, you could call a
4324      function `enable-hex-display' that adds a hex display-table to
4325      the list of display tables for the current buffer.
4326
4327      #### ...not yet implemented...  Also, we extend the concept of
4328      "mapping" to include a printf-like spec.  Thus you can make all
4329      extended characters show up as hex with a display table like
4330      this:
4331
4332          #s(range-table data ((256 524288) (format "%x")))
4333
4334      Since more than one display table is possible, you have
4335      great flexibility in mapping ranges of characters.  */
4336   Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow)
4337                           ? XCHAR_OR_CHAR_INT (b->ctl_arrow)
4338                           : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil))
4339                              ? 255 : 160)) : 255;
4340
4341   Lisp_Object face_dt, window_dt;
4342
4343   /* The text display block for this display line. */
4344   struct display_block *db = get_display_block_from_line (dl, TEXT);
4345
4346   /* The first time through the main loop we need to force the glyph
4347      data to be updated. */
4348   int initial = 1;
4349
4350   /* Apparently the new extent_fragment_update returns an end position
4351      equal to the position passed in if there are no more runs to be
4352      displayed. */
4353   int no_more_frags = 0;
4354
4355   dl->used_prop_data = 0;
4356   dl->num_chars = 0;
4357   dl->line_continuation = 0;
4358
4359   /* set up faces to use for clearing areas, used by
4360      output_display_line */
4361   dl->default_findex = default_face;
4362   if (default_face)
4363     {
4364       dl->left_margin_findex = default_face;
4365       dl->right_margin_findex = default_face;
4366     }
4367   else
4368     {
4369       dl->left_margin_findex =
4370         get_builtin_face_cache_index (w, Vleft_margin_face);
4371       dl->right_margin_findex =
4372         get_builtin_face_cache_index (w, Vright_margin_face);
4373     }
4374
4375   xzero (data);
4376   data.ef = extent_fragment_new (disp_string, f);
4377
4378   /* These values are used by all of the rune addition routines.  We add
4379      them to this structure for ease of passing. */
4380   data.d = d;
4381   XSETWINDOW (data.window, w);
4382   data.db = db;
4383   data.dl = dl;
4384
4385   data.bi_bufpos = bi_start_pos;
4386   data.pixpos = dl->bounds.left_in;
4387   data.last_charset = Qunbound;
4388   data.last_findex = default_face;
4389   data.result_str = Qnil;
4390   data.string = disp_string;
4391
4392   /* Set the right boundary adjusting it to take into account any end
4393      glyph.  Save the width of the end glyph for later use. */
4394   data.max_pixpos = dl->bounds.right_in;
4395 #if 0
4396   if (truncate_win)
4397     end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
4398   else
4399     end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
4400 #endif
4401   data.max_pixpos -= end_glyph_width;
4402
4403   data.cursor_type = NO_CURSOR;
4404   data.cursor_x = -1;
4405
4406   data.start_col = 0;
4407   /* I don't think we want this, string areas should not scroll with
4408      the window
4409   data.start_col = w->hscroll;
4410   data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0);
4411   */
4412   data.bi_start_col_enabled = 0;
4413   data.hscroll_glyph_width_adjust = 0;
4414
4415   /* We regenerate the line from the very beginning. */
4416   Dynarr_reset (db->runes);
4417
4418   /* Why is this less than or equal and not just less than?  If the
4419      starting position is already equal to the maximum we can't add
4420      anything else, right?  Wrong.  We might still have a newline to
4421      add.  A newline can use the room allocated for an end glyph since
4422      if we add it we know we aren't going to be adding any end
4423      glyph. */
4424
4425   /* #### Chuck -- I think this condition should be while (1).
4426      Otherwise if (e.g.) there is one begin-glyph and one end-glyph
4427      and the begin-glyph ends exactly at the end of the window, the
4428      end-glyph and text might not be displayed.  while (1) ensures
4429      that the loop terminates only when either (a) there is
4430      propagation data or (b) the end-of-line or end-of-buffer is hit.
4431
4432      #### Also I think you need to ensure that the operation
4433      "add begin glyphs; add end glyphs; add text" is atomic and
4434      can't get interrupted in the middle.  If you run off the end
4435      of the line during that operation, then you keep accumulating
4436      propagation data until you're done.  Otherwise, if the (e.g.)
4437      there's a begin glyph at a particular position and attempting
4438      to display that glyph results in window-end being hit and
4439      propagation data being generated, then the character at that
4440      position won't be displayed.
4441
4442      #### See also the comment after the end of this loop, below.
4443      */
4444   while (data.pixpos <= data.max_pixpos)
4445     {
4446       /* #### This check probably should not be necessary. */
4447       if (data.bi_bufpos > bi_string_zv)
4448         {
4449           /* #### urk!  More of this lossage! */
4450           data.bi_bufpos--;
4451           goto done;
4452         }
4453
4454       /* Check for face changes. */
4455       if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
4456         {
4457           /* Now compute the face and begin/end-glyph information. */
4458           data.findex =
4459             /* Remember that the extent-fragment routines deal in Bytind's. */
4460             extent_fragment_update (w, data.ef, data.bi_bufpos);
4461           /* This is somewhat cheesy but the alternative is to
4462              propagate default_face into extent_fragment_update. */
4463           if (data.findex == DEFAULT_INDEX)
4464             data.findex = default_face;
4465
4466           get_display_tables (w, data.findex, &face_dt, &window_dt);
4467
4468           if (data.bi_bufpos == data.ef->end)
4469             no_more_frags = 1;
4470         }
4471       initial = 0;
4472
4473       /* Determine what is next to be displayed.  We first handle any
4474          glyphs returned by glyphs_at_bufpos.  If there are no glyphs to
4475          display then we determine what to do based on the character at the
4476          current buffer position. */
4477
4478       /* If the current position is covered by an invisible extent, do
4479          nothing (except maybe add some ellipses).
4480
4481          #### The behavior of begin and end-glyphs at the edge of an
4482          invisible extent should be investigated further.  This is
4483          fairly low priority though. */
4484       if (data.ef->invisible)
4485         {
4486           /* #### Chuck, perhaps you could look at this code?  I don't
4487              really know what I'm doing. */
4488           if (*prop)
4489             {
4490               Dynarr_free (*prop);
4491               *prop = 0;
4492             }
4493
4494           /* The extent fragment code only sets this when we should
4495              really display the ellipses.  It makes sure the ellipses
4496              don't get displayed more than once in a row. */
4497           if (data.ef->invisible_ellipses)
4498             {
4499               struct glyph_block gb;
4500
4501               data.ef->invisible_ellipses_already_displayed = 1;
4502               data.ef->invisible_ellipses = 0;
4503               gb.extent = Qnil;
4504               gb.glyph = Vinvisible_text_glyph;
4505               *prop = add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0,
4506                                       GLYPH_CACHEL (w, INVIS_GLYPH_INDEX));
4507               /* Perhaps they shouldn't propagate if the very next thing
4508                  is to display a newline (for compatibility with
4509                  selective-display-ellipses)?  Maybe that's too
4510                  abstruse. */
4511               if (*prop)
4512                 goto done;
4513             }
4514
4515           /* #### What if we we're dealing with a display table? */
4516           if (data.start_col)
4517             data.start_col--;
4518
4519           if (data.bi_bufpos == bi_string_zv)
4520             goto done;
4521           else
4522             INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4523         }
4524
4525       /* If there is propagation data, then it represents the current
4526          buffer position being displayed.  Add them and advance the
4527          position counter.  This might also add the minibuffer
4528          prompt. */
4529       else if (*prop)
4530         {
4531           dl->used_prop_data = 1;
4532           *prop = add_propagation_runes (prop, &data);
4533
4534           if (*prop)
4535             goto done;  /* gee, a really narrow window */
4536           else if (data.bi_bufpos == bi_string_zv)
4537             goto done;
4538           else if (data.bi_bufpos < 0)
4539             /* #### urk urk urk! Aborts are not very fun! Fix this please! */
4540             data.bi_bufpos = 0;
4541           else
4542             INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4543         }
4544
4545       /* If there are end glyphs, add them to the line.  These are
4546          the end glyphs for the previous run of text.  We add them
4547          here rather than doing them at the end of handling the
4548          previous run so that glyphs at the beginning and end of
4549          a line are handled correctly. */
4550       else if (Dynarr_length (data.ef->end_glyphs) > 0)
4551         {
4552           *prop = add_glyph_runes (&data, END_GLYPHS);
4553           if (*prop)
4554             goto done;
4555         }
4556
4557       /* If there are begin glyphs, add them to the line. */
4558       else if (Dynarr_length (data.ef->begin_glyphs) > 0)
4559         {
4560           *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
4561           if (*prop)
4562             goto done;
4563         }
4564
4565       /* If at end-of-buffer, we've already processed begin and
4566          end-glyphs at this point and there's no text to process,
4567          so we're done. */
4568       else if (data.bi_bufpos == bi_string_zv)
4569         goto done;
4570
4571       else
4572         {
4573           Lisp_Object entry = Qnil;
4574           /* Get the character at the current buffer position. */
4575           data.ch = string_char (s, data.bi_bufpos);
4576           if (!NILP (face_dt) || !NILP (window_dt))
4577             entry = display_table_entry (data.ch, face_dt, window_dt);
4578
4579           /* If there is a display table entry for it, hand it off to
4580              add_disp_table_entry_runes and let it worry about it. */
4581           if (!NILP (entry) && !EQ (entry, make_char (data.ch)))
4582             {
4583               *prop = add_disp_table_entry_runes (&data, entry);
4584
4585               if (*prop)
4586                 goto done;
4587             }
4588
4589           /* Check if we have hit a newline character.  If so, add a marker
4590              to the line and end this loop. */
4591           else if (data.ch == '\n')
4592             {
4593               /* We aren't going to be adding an end glyph so give its
4594                  space back in order to make sure that the cursor can
4595                  fit. */
4596               data.max_pixpos += end_glyph_width;
4597               goto done;
4598             }
4599
4600           /* If the current character is considered to be printable, then
4601              just add it. */
4602           else if (data.ch >= printable_min)
4603             {
4604               *prop = add_emchar_rune (&data);
4605               if (*prop)
4606                 goto done;
4607             }
4608
4609           /* If the current character is a tab, determine the next tab
4610              starting position and add a blank rune which extends from the
4611              current pixel position to that starting position. */
4612           else if (data.ch == '\t')
4613             {
4614               int tab_start_pixpos = data.pixpos;
4615               int next_tab_start;
4616               int char_tab_width;
4617               int prop_width = 0;
4618
4619               if (data.start_col > 1)
4620                 tab_start_pixpos -= (space_width (w) * (data.start_col - 1));
4621
4622               next_tab_start =
4623                 next_tab_position (w, tab_start_pixpos,
4624                                    dl->bounds.left_in +
4625                                    data.hscroll_glyph_width_adjust);
4626               if (next_tab_start > data.max_pixpos)
4627                 {
4628                   prop_width = next_tab_start - data.max_pixpos;
4629                   next_tab_start = data.max_pixpos;
4630                 }
4631               data.blank_width = next_tab_start - data.pixpos;
4632               char_tab_width =
4633                 (next_tab_start - tab_start_pixpos) / space_width (w);
4634
4635               *prop = add_blank_rune (&data, w, char_tab_width);
4636
4637               /* add_blank_rune is only supposed to be called with
4638                  sizes guaranteed to fit in the available space. */
4639               assert (!(*prop));
4640
4641               if (prop_width)
4642                 {
4643                   struct prop_block pb;
4644                   *prop = Dynarr_new (prop_block);
4645
4646                   pb.type = PROP_BLANK;
4647                   pb.data.p_blank.width = prop_width;
4648                   pb.data.p_blank.findex = data.findex;
4649                   Dynarr_add (*prop, pb);
4650
4651                   goto done;
4652                 }
4653             }
4654
4655           /* If character is a control character, pass it off to
4656              add_control_char_runes.
4657
4658              The is_*() routines have undefined results on
4659              arguments outside of the range [-1, 255].  (This
4660              often bites people who carelessly use `char' instead
4661              of `unsigned char'.)
4662              */
4663           else if (data.ch < 0x100 && iscntrl ((Bufbyte) data.ch))
4664             {
4665               *prop = add_control_char_runes (&data, b);
4666
4667               if (*prop)
4668                 goto done;
4669             }
4670
4671           /* If the character is above the ASCII range and we have not
4672              already handled it, then print it as an octal number. */
4673           else if (data.ch >= 0200)
4674             {
4675               *prop = add_octal_runes (&data);
4676
4677               if (*prop)
4678                 goto done;
4679             }
4680
4681           /* Assume the current character is considered to be printable,
4682              then just add it. */
4683           else
4684             {
4685               *prop = add_emchar_rune (&data);
4686               if (*prop)
4687                 goto done;
4688             }
4689
4690           INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4691         }
4692     }
4693
4694 done:
4695
4696   /* Determine the starting point of the next line if we did not hit the
4697      end of the buffer. */
4698   if (data.bi_bufpos < bi_string_zv)
4699     {
4700       /* #### This check is not correct.  If the line terminated
4701          due to a begin-glyph or end-glyph hitting window-end, then
4702          data.ch will not point to the character at data.bi_bufpos.  If
4703          you make the two changes mentioned at the top of this loop,
4704          you should be able to say '(if (*prop))'.  That should also
4705          make it possible to eliminate the data.bi_bufpos < BI_BUF_ZV (b)
4706          check. */
4707
4708       /* The common case is that the line ended because we hit a newline.
4709          In that case, the next character is just the next buffer
4710          position. */
4711       if (data.ch == '\n')
4712         {
4713           INC_CHARBYTIND (string_data (s), data.bi_bufpos);
4714         }
4715
4716       /* Otherwise we have a buffer line which cannot fit on one display
4717          line. */
4718       else
4719         {
4720           struct glyph_block gb;
4721           struct glyph_cachel *cachel;
4722
4723           /* If the line is to be truncated then we actually have to look
4724              for the next newline.  We also add the end-of-line glyph which
4725              we know will fit because we adjusted the right border before
4726              we starting laying out the line. */
4727           data.max_pixpos += end_glyph_width;
4728           data.findex = default_face;
4729           gb.extent = Qnil;
4730
4731           if (truncate_win)
4732             {
4733               Bytind bi_pos;
4734
4735               /* Now find the start of the next line. */
4736               bi_pos = bi_find_next_emchar_in_string (s, '\n', data.bi_bufpos, 1);
4737
4738               data.cursor_type = NO_CURSOR;
4739               data.bi_bufpos = bi_pos;
4740               gb.glyph = Vtruncation_glyph;
4741               cachel = GLYPH_CACHEL (w, TRUN_GLYPH_INDEX);
4742             }
4743           else
4744             {
4745               /* The cursor can never be on the continuation glyph. */
4746               data.cursor_type = NO_CURSOR;
4747
4748               /* data.bi_bufpos is already at the start of the next line. */
4749
4750               dl->line_continuation = 1;
4751               gb.glyph = Vcontinuation_glyph;
4752               cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
4753             }
4754
4755           if (end_glyph_width)
4756             add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
4757
4758           if (truncate_win && data.bi_bufpos == bi_string_zv)
4759             {
4760               const Bufbyte* endb = charptr_n_addr (string_data (s), bi_string_zv);
4761               DEC_CHARPTR (endb);
4762               if (charptr_emchar (endb) != '\n')
4763                 {
4764                   /* #### Damn this losing shit. */
4765                   data.bi_bufpos++;
4766                 }
4767             }
4768         }
4769     }
4770   else if (data.bi_bufpos == bi_string_zv)
4771     {
4772       /* create_text_block () adds a bogus \n marker here which screws
4773          up subwindow display. Since we never have a cursor in the
4774          gutter we can safely ignore it. */
4775     }
4776   /* Calculate left whitespace boundary. */
4777   {
4778     int elt = 0;
4779
4780     /* Whitespace past a newline is considered right whitespace. */
4781     while (elt < Dynarr_length (db->runes))
4782       {
4783         struct rune *rb = Dynarr_atp (db->runes, elt);
4784
4785         if ((rb->type == RUNE_CHAR && rb->object.chr.ch == ' ')
4786             || rb->type == RUNE_BLANK)
4787           {
4788             dl->bounds.left_white += rb->width;
4789             elt++;
4790           }
4791         else
4792           elt = Dynarr_length (db->runes);
4793       }
4794   }
4795
4796   /* Calculate right whitespace boundary. */
4797   {
4798     int elt = Dynarr_length (db->runes) - 1;
4799     int done = 0;
4800
4801     while (!done && elt >= 0)
4802       {
4803         struct rune *rb = Dynarr_atp (db->runes, elt);
4804
4805         if (!(rb->type == RUNE_CHAR && rb->object.chr.ch < 0x100
4806             && isspace (rb->object.chr.ch))
4807             && !rb->type == RUNE_BLANK)
4808           {
4809             dl->bounds.right_white = rb->xpos + rb->width;
4810             done = 1;
4811           }
4812
4813         elt--;
4814
4815       }
4816
4817     /* The line is blank so everything is considered to be right
4818        whitespace. */
4819     if (!done)
4820       dl->bounds.right_white = dl->bounds.left_in;
4821   }
4822
4823   /* Set the display blocks bounds. */
4824   db->start_pos = dl->bounds.left_in;
4825   if (Dynarr_length (db->runes))
4826     {
4827       struct rune *rb = Dynarr_atp (db->runes, Dynarr_length (db->runes) - 1);
4828
4829       db->end_pos = rb->xpos + rb->width;
4830     }
4831   else
4832     db->end_pos = dl->bounds.right_white;
4833
4834   /* update line height parameters */
4835   if (!data.new_ascent && !data.new_descent)
4836     {
4837       /* We've got a blank line so initialize these values from the default
4838          face. */
4839       default_face_font_info (data.window, &data.new_ascent,
4840                               &data.new_descent, 0, 0, 0);
4841     }
4842
4843   if (data.max_pixmap_height)
4844     {
4845       int height = data.new_ascent + data.new_descent;
4846       int pix_ascent, pix_descent;
4847
4848       pix_descent = data.max_pixmap_height * data.new_descent / height;
4849       pix_ascent = data.max_pixmap_height - pix_descent;
4850
4851       data.new_ascent = max (data.new_ascent, pix_ascent);
4852       data.new_descent = max (data.new_descent, pix_descent);
4853     }
4854
4855   dl->ascent = data.new_ascent;
4856   dl->descent = data.new_descent;
4857
4858   {
4859     unsigned short ascent = (unsigned short) XINT (w->minimum_line_ascent);
4860
4861     if (dl->ascent < ascent)
4862       dl->ascent = ascent;
4863   }
4864   {
4865     unsigned short descent = (unsigned short) XINT (w->minimum_line_descent);
4866
4867     if (dl->descent < descent)
4868       dl->descent = descent;
4869   }
4870
4871   dl->cursor_elt = data.cursor_x;
4872   /* #### lossage lossage lossage! Fix this shit! */
4873   if (data.bi_bufpos > bi_string_zv)
4874     dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, bi_string_zv);
4875   else
4876     dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1;
4877   if (truncate_win)
4878     data.dl->num_chars =
4879       string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8);
4880   else
4881     /* This doesn't correctly take into account tabs and control
4882        characters but if the window isn't being truncated then this
4883        value isn't going to end up being used anyhow. */
4884     data.dl->num_chars = dl->end_bufpos - dl->bufpos;
4885
4886   /* #### handle horizontally scrolled line with text none of which
4887      was actually laid out. */
4888
4889   /* #### handle any remainder of overlay arrow */
4890
4891   if (*prop == ADD_FAILED)
4892     *prop = NULL;
4893
4894   if (truncate_win && *prop)
4895     {
4896       Dynarr_free (*prop);
4897       *prop = NULL;
4898     }
4899
4900   extent_fragment_delete (data.ef);
4901
4902   /* #### If we started at EOB, then make sure we return a value past
4903      it so that regenerate_window will exit properly.  This is bogus.
4904      The main loop should get fixed so that it isn't necessary to call
4905      this function if we are already at EOB. */
4906
4907   if (data.bi_bufpos == bi_string_zv && bi_start_pos == bi_string_zv)
4908     return bytecount_to_charcount (string_data (s), data.bi_bufpos) + 1; /* Yuck! */
4909   else
4910     return bytecount_to_charcount (string_data (s), data.bi_bufpos);
4911 }
4912
4913 /* Given a display line and a starting position, ensure that the
4914    contents of the display line accurately represent the visual
4915    representation of the buffer contents starting from the given
4916    position when displayed in the given window.  The display line ends
4917    when the contents of the line reach the right boundary of the given
4918    window.
4919
4920    This is very similar to generate_display_line but with the same
4921    limitations as create_string_text_block. I have taken the liberty
4922    of fixing the bytind stuff though.*/
4923
4924 static Bufpos
4925 generate_string_display_line (struct window *w, Lisp_Object disp_string,
4926                               struct display_line *dl,
4927                               Bufpos start_pos,
4928                               prop_block_dynarr **prop,
4929                               face_index default_face)
4930 {
4931   Bufpos ret_bufpos;
4932
4933   /* you must set bounds before calling this. */
4934
4935   /* Reset what this line is using. */
4936   if (dl->display_blocks)
4937     Dynarr_reset (dl->display_blocks);
4938   if (dl->left_glyphs)
4939     {
4940       Dynarr_free (dl->left_glyphs);
4941       dl->left_glyphs = 0;
4942     }
4943   if (dl->right_glyphs)
4944     {
4945       Dynarr_free (dl->right_glyphs);
4946       dl->right_glyphs = 0;
4947     }
4948
4949   /* We aren't generating a modeline at the moment. */
4950   dl->modeline = 0;
4951
4952   /* Create a display block for the text region of the line. */
4953   ret_bufpos = create_string_text_block (w, disp_string, dl, start_pos,
4954                                          prop, default_face);
4955   dl->bufpos = start_pos;
4956   if (dl->end_bufpos < dl->bufpos)
4957     dl->end_bufpos = dl->bufpos;
4958
4959   /* If there are left glyphs associated with any character in the
4960      text block, then create a display block to handle them. */
4961   if (dl->left_glyphs != NULL && Dynarr_length (dl->left_glyphs))
4962     create_left_glyph_block (w, dl, 0);
4963
4964   /* If there are right glyphs associated with any character in the
4965      text block, then create a display block to handle them. */
4966   if (dl->right_glyphs != NULL && Dynarr_length (dl->right_glyphs))
4967     create_right_glyph_block (w, dl);
4968
4969   return ret_bufpos;
4970 }
4971
4972 /* This is ripped off from regenerate_window. All we want to do is
4973    loop through elements in the string creating display lines until we
4974    have covered the provided area. Simple really.  */
4975 void
4976 generate_displayable_area (struct window *w, Lisp_Object disp_string,
4977                            int xpos, int ypos, int width, int height,
4978                            display_line_dynarr* dla,
4979                            Bufpos start_pos,
4980                            face_index default_face)
4981 {
4982   int yend = ypos + height;
4983   Charcount s_zv;
4984
4985   prop_block_dynarr *prop = 0;
4986   layout_bounds bounds;
4987   assert (dla);
4988
4989   Dynarr_reset (dla);
4990   /* if there's nothing to do then do nothing. code after this assumes
4991      there is something to do. */
4992   if (NILP (disp_string))
4993     return;
4994
4995   s_zv = XSTRING_CHAR_LENGTH (disp_string);
4996
4997   bounds.left_out = xpos;
4998   bounds.right_out = xpos + width;
4999   /* The inner boundaries mark where the glyph margins are located. */
5000   bounds.left_in = bounds.left_out + window_left_margin_width (w);
5001   bounds.right_in = bounds.right_out - window_right_margin_width (w);
5002   /* We cannot fully calculate the whitespace boundaries as they
5003      depend on the contents of the line being displayed. */
5004   bounds.left_white = bounds.left_in;
5005   bounds.right_white = bounds.right_in;
5006
5007   while (ypos < yend)
5008     {
5009       struct display_line dl;
5010       struct display_line *dlp;
5011       Bufpos next_pos;
5012       int local;
5013
5014       if (Dynarr_length (dla) < Dynarr_largest (dla))
5015         {
5016           dlp = Dynarr_atp (dla, Dynarr_length (dla));
5017           local = 0;
5018         }
5019       else
5020         {
5021
5022           xzero (dl);
5023           dlp = &dl;
5024           local = 1;
5025         }
5026
5027       dlp->bounds = bounds;
5028       dlp->offset = 0;
5029       next_pos = generate_string_display_line (w, disp_string, dlp, start_pos,
5030                                                &prop, default_face);
5031       /* we need to make sure that we continue along the line if there
5032          is more left to display otherwise we just end up redisplaying
5033          the same chunk over and over again. */
5034       if (next_pos == start_pos && next_pos < s_zv)
5035         start_pos++;
5036       else
5037         start_pos = next_pos;
5038
5039       dlp->ypos = ypos + dlp->ascent;
5040       ypos = dlp->ypos + dlp->descent;
5041
5042       if (ypos > yend)
5043         {
5044           int visible_height = dlp->ascent + dlp->descent;
5045
5046           dlp->clip = (ypos - yend);
5047           visible_height -= dlp->clip;
5048
5049           if (visible_height < VERTICAL_CLIP (w, 1))
5050             {
5051               if (local)
5052                 free_display_line (dlp);
5053               break;
5054             }
5055         }
5056       else
5057         dlp->clip = 0;
5058
5059       Dynarr_add (dla, *dlp);
5060
5061       /* #### This type of check needs to be done down in the
5062          generate_display_line call. */
5063       if (start_pos >= s_zv)
5064         break;
5065     }
5066
5067   if (prop)
5068     Dynarr_free (prop);
5069 }
5070
5071 \f
5072 /***************************************************************************/
5073 /*                                                                         */
5074 /*                        window-regeneration routines                     */
5075 /*                                                                         */
5076 /***************************************************************************/
5077
5078 /* For a given window and starting position in the buffer it contains,
5079    ensure that the TYPE display lines accurately represent the
5080    presentation of the window.  We pass the buffer instead of getting
5081    it from the window since redisplay_window may have temporarily
5082    changed it to the echo area buffer. */
5083
5084 static void
5085 regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type)
5086 {
5087   struct frame *f = XFRAME (w->frame);
5088   struct buffer *b = XBUFFER (w->buffer);
5089   int ypos = WINDOW_TEXT_TOP (w);
5090   int yend;     /* set farther down */
5091   int yclip = WINDOW_TEXT_TOP_CLIP (w);
5092   int force;
5093
5094   prop_block_dynarr *prop;
5095   layout_bounds bounds;
5096   display_line_dynarr *dla;
5097   int need_modeline;
5098
5099   /* The lines had better exist by this point. */
5100   if (!(dla = window_display_lines (w, type)))
5101     abort ();
5102   Dynarr_reset (dla);
5103   w->max_line_len = 0;
5104
5105   /* Normally these get updated in redisplay_window but it is possible
5106      for this function to get called from some other points where that
5107      update may not have occurred.  This acts as a safety check. */
5108   if (!Dynarr_length (w->face_cachels))
5109     reset_face_cachels (w);
5110   if (!Dynarr_length (w->glyph_cachels))
5111     reset_glyph_cachels (w);
5112
5113   Fset_marker (w->start[type], make_int (start_pos), w->buffer);
5114   Fset_marker (w->pointm[type], make_int (point), w->buffer);
5115   w->last_point_x[type] = -1;
5116   w->last_point_y[type] = -1;
5117
5118   /* Make sure a modeline is in the structs if needed. */
5119   need_modeline = ensure_modeline_generated (w, type);
5120
5121   /* Wait until here to set this so that the structs have a modeline
5122      generated in the case where one didn't exist. */
5123   yend = WINDOW_TEXT_BOTTOM (w);
5124
5125   bounds = calculate_display_line_boundaries (w, 0);
5126
5127   /* 97/3/14 jhod: stuff added here to support pre-prompts (used for input systems) */
5128   if (MINI_WINDOW_P (w)
5129       && (!NILP (Vminibuf_prompt) || !NILP (Vminibuf_preprompt))
5130       && !echo_area_active (f)
5131       && start_pos == BUF_BEGV (b))
5132     {
5133       struct prop_block pb;
5134       Lisp_Object string;
5135       prop = Dynarr_new (prop_block);
5136
5137       string = concat2(Vminibuf_preprompt, Vminibuf_prompt);
5138       pb.type = PROP_MINIBUF_PROMPT;
5139       pb.data.p_string.str = XSTRING_DATA(string);
5140       pb.data.p_string.len = XSTRING_LENGTH(string);
5141       Dynarr_add (prop, pb);
5142     }
5143   else
5144     prop = 0;
5145
5146   /* When we are computing things for scrolling purposes, make
5147      sure at least one line is always generated */
5148   force = (type == CMOTION_DISP);
5149
5150   /* Make sure this is set always */
5151   /* Note the conversion at end */
5152   w->window_end_pos[type] = start_pos;
5153   while (ypos < yend || force)
5154     {
5155       struct display_line dl;
5156       struct display_line *dlp;
5157       int local;
5158
5159       if (Dynarr_length (dla) < Dynarr_largest (dla))
5160         {
5161           dlp = Dynarr_atp (dla, Dynarr_length (dla));
5162           local = 0;
5163         }
5164       else
5165         {
5166
5167           xzero (dl);
5168           dlp = &dl;
5169           local = 1;
5170         }
5171
5172       dlp->bounds = bounds;
5173       dlp->offset = 0;
5174       start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type);
5175
5176       if (yclip > dlp->ascent)
5177         {
5178           /* this should never happen, but if it does just display the
5179              whole line */
5180           yclip = 0;
5181         }
5182
5183       dlp->ypos = (ypos + dlp->ascent) - yclip;
5184       ypos = dlp->ypos + dlp->descent;
5185
5186       /* See if we've been asked to start midway through a line, for
5187          partial display line scrolling. */
5188       if (yclip)
5189         {
5190           dlp->top_clip = yclip;
5191           yclip = 0;
5192         }
5193       else
5194         dlp->top_clip = 0;
5195
5196       if (ypos > yend)
5197         {
5198           int visible_height = dlp->ascent + dlp->descent;
5199
5200           dlp->clip = (ypos - yend);
5201           /* Although this seems strange we could have a single very
5202              tall line visible for which we need to account for both
5203              the top clip and the bottom clip. */
5204           visible_height -= (dlp->clip + dlp->top_clip);
5205
5206           if (visible_height < VERTICAL_CLIP (w, 1) && !force)
5207             {
5208               if (local)
5209                 free_display_line (dlp);
5210               break;
5211             }
5212         }
5213       else
5214         dlp->clip = 0;
5215
5216       if (dlp->cursor_elt != -1)
5217         {
5218           /* #### This check is steaming crap.  Have to get things
5219              fixed so when create_text_block hits EOB, we're done,
5220              period. */
5221           if (w->last_point_x[type] == -1)
5222             {
5223               w->last_point_x[type] = dlp->cursor_elt;
5224               w->last_point_y[type] = Dynarr_length (dla);
5225             }
5226           else
5227             {
5228               /* #### This means that we've added a cursor at EOB
5229                  twice.  Yuck oh yuck. */
5230               struct display_block *db =
5231                 get_display_block_from_line (dlp, TEXT);
5232
5233               Dynarr_atp (db->runes, dlp->cursor_elt)->cursor_type = NO_CURSOR;
5234               dlp->cursor_elt = -1;
5235             }
5236         }
5237
5238       if (dlp->num_chars > w->max_line_len)
5239         w->max_line_len = dlp->num_chars;
5240
5241       Dynarr_add (dla, *dlp);
5242
5243       /* #### This isn't right, but it is close enough for now. */
5244       w->window_end_pos[type] = start_pos;
5245
5246       /* #### This type of check needs to be done down in the
5247          generate_display_line call. */
5248       if (start_pos > BUF_ZV (b))
5249         break;
5250
5251       force = 0;
5252     }
5253
5254   if (prop)
5255     Dynarr_free (prop);
5256
5257   /* #### More not quite right, but close enough. */
5258   /* Ben sez: apparently window_end_pos[] is measured
5259      as the number of characters between the window end and the
5260      end of the buffer?  This seems rather weirdo.  What's
5261      the justification for this?
5262
5263      JV sez: Because BUF_Z (b) would be a good initial value, however
5264      that can change. This representation allows initalizing with 0.
5265   */
5266   w->window_end_pos[type] = BUF_Z (b) - w->window_end_pos[type];
5267
5268   if (need_modeline)
5269     {
5270       /* We know that this is the right thing to use because we put it
5271          there when we first started working in this function. */
5272       generate_modeline (w, Dynarr_atp (dla, 0), type);
5273     }
5274 }
5275
5276 #define REGEN_INC_FIND_START_END                \
5277   do {                                          \
5278     /* Determine start and end of lines. */     \
5279     if (!Dynarr_length (cdla))                  \
5280       return 0;                                 \
5281     else                                        \
5282       {                                         \
5283         if (Dynarr_atp (cdla, 0)->modeline && Dynarr_atp (ddla, 0)->modeline) \
5284           {                                     \
5285             dla_start = 1;                      \
5286           }                                     \
5287         else if (!Dynarr_atp (cdla, 0)->modeline \
5288                  && !Dynarr_atp (ddla, 0)->modeline) \
5289           {                                     \
5290             dla_start = 0;                      \
5291           }                                     \
5292         else                                    \
5293           abort ();     /* structs differ */    \
5294                                                 \
5295         dla_end = Dynarr_length (cdla) - 1;     \
5296       }                                         \
5297                                                 \
5298     start_pos = (Dynarr_atp (cdla, dla_start)->bufpos \
5299                  + Dynarr_atp (cdla, dla_start)->offset); \
5300     /* If this isn't true, then startp has changed and we need to do a \
5301        full regen. */                           \
5302     if (startp != start_pos)                    \
5303       return 0;                                 \
5304                                                 \
5305     /* Point is outside the visible region so give up. */ \
5306     if (pointm < start_pos)                     \
5307       return 0;                                 \
5308                                                 \
5309   } while (0)
5310
5311 /* This attempts to incrementally update the display structures.  It
5312    returns a boolean indicating success or failure.  This function is
5313    very similar to regenerate_window_incrementally and is in fact only
5314    called from that function.  However, because of the nature of the
5315    changes it deals with it sometimes makes different assumptions
5316    which can lead to success which are much more difficult to make
5317    when dealing with buffer changes. */
5318
5319 static int
5320 regenerate_window_extents_only_changed (struct window *w, Bufpos startp,
5321                                         Bufpos pointm,
5322                                         Charcount beg_unchanged,
5323                                         Charcount end_unchanged)
5324 {
5325   struct buffer *b = XBUFFER (w->buffer);
5326   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5327   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5328
5329   int dla_start = 0;
5330   int dla_end, line;
5331   int first_line, last_line;
5332   Bufpos start_pos;
5333   /* Don't define this in the loop where it is used because we
5334      definitely want its value to survive between passes. */
5335   prop_block_dynarr *prop = NULL;
5336
5337   /* If we don't have any buffer change recorded but the modiff flag has
5338      been incremented, then fail.  I'm not sure of the exact circumstances
5339      under which this can happen, but I believe that it is probably a
5340      reasonable happening. */
5341   if (!point_visible (w, pointm, CURRENT_DISP)
5342       || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b))
5343     return 0;
5344
5345   /* If the cursor is moved we attempt to update it.  If we succeed we
5346      go ahead and proceed with the optimization attempt. */
5347   if (!EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5348       || pointm != marker_position (w->last_point[CURRENT_DISP]))
5349     {
5350       struct frame *f = XFRAME (w->frame);
5351       struct device *d = XDEVICE (f->device);
5352       struct frame *sel_f = device_selected_frame (d);
5353       int success = 0;
5354
5355       if (w->last_point_x[CURRENT_DISP] != -1
5356           && w->last_point_y[CURRENT_DISP] != -1)
5357         {
5358
5359           if (redisplay_move_cursor (w, pointm, WINDOW_TTY_P (w)))
5360             {
5361               /* Always regenerate the modeline in case it is
5362                  displaying the current line or column. */
5363               regenerate_modeline (w);
5364               success = 1;
5365             }
5366         }
5367       else if (w != XWINDOW (FRAME_SELECTED_WINDOW (sel_f)))
5368         {
5369           if (f->modeline_changed)
5370             regenerate_modeline (w);
5371           success = 1;
5372         }
5373
5374       if (!success)
5375         return 0;
5376     }
5377
5378   if (beg_unchanged == -1 && end_unchanged == -1)
5379     return 1;
5380
5381   /* assert: There are no buffer modifications or they are all below the
5382      visible region.  We assume that regenerate_window_incrementally has
5383      not called us unless this is true.  */
5384
5385   REGEN_INC_FIND_START_END;
5386
5387   /* If the changed are starts before the visible area, give up. */
5388   if (beg_unchanged < startp)
5389     return 0;
5390
5391   /* Find what display line the extent changes first affect. */
5392   line = dla_start;
5393   while (line <= dla_end)
5394     {
5395       struct display_line *dl = Dynarr_atp (cdla, line);
5396       Bufpos lstart = dl->bufpos + dl->offset;
5397       Bufpos lend = dl->end_bufpos + dl->offset;
5398
5399       if (beg_unchanged >= lstart && beg_unchanged <= lend)
5400         break;
5401
5402       line++;
5403     }
5404
5405   /* If the changes are below the visible area then if point hasn't
5406      moved return success otherwise fail in order to be safe. */
5407   if (line > dla_end)
5408     {
5409       if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
5410           && pointm == marker_position (w->last_point[CURRENT_DISP]))
5411         return 1;
5412       else
5413         return 0;
5414     }
5415
5416   /* At this point we know what line the changes first affect.  We now
5417      begin redrawing lines as long as we are still in the affected
5418      region and the line's size and positioning don't change.
5419      Otherwise we fail.  If we fail we will have altered the desired
5420      structs which could lead to an assertion failure.  However, if we
5421      fail the next thing that is going to happen is a full regen so we
5422      will actually end up being safe. */
5423   w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5424   w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5425   Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
5426   Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
5427
5428   first_line = last_line = line;
5429   while (line <= dla_end)
5430     {
5431       Bufpos old_start, old_end, new_start;
5432       struct display_line *cdl = Dynarr_atp (cdla, line);
5433       struct display_line *ddl = Dynarr_atp (ddla, line);
5434       struct display_block *db;
5435       int initial_size;
5436
5437       assert (cdl->bufpos == ddl->bufpos);
5438       assert (cdl->end_bufpos == ddl->end_bufpos);
5439       assert (cdl->offset == ddl->offset);
5440
5441       db = get_display_block_from_line (ddl, TEXT);
5442       initial_size = Dynarr_length (db->runes);
5443       old_start = ddl->bufpos + ddl->offset;
5444       old_end = ddl->end_bufpos + ddl->offset;
5445
5446       /* If this is the first line being updated and it used
5447          propagation data, fail.  Otherwise we'll be okay because
5448          we'll have the necessary propagation data. */
5449       if (line == first_line && ddl->used_prop_data)
5450         return 0;
5451
5452       new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5453                                          &prop, DESIRED_DISP);
5454       ddl->offset = 0;
5455
5456       /* #### If there is propagated stuff the fail.  We could
5457          probably actually deal with this if the line had propagated
5458          information when originally created by a full
5459          regeneration. */
5460       if (prop)
5461         {
5462           Dynarr_free (prop);
5463           return 0;
5464         }
5465
5466       /* If any line position parameters have changed or a
5467          cursor has disappeared or disappeared, fail.  */
5468       db = get_display_block_from_line (ddl, TEXT);
5469       if (cdl->ypos != ddl->ypos
5470           || cdl->ascent != ddl->ascent
5471           || cdl->descent != ddl->descent
5472           || cdl->top_clip != ddl->top_clip
5473           || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5474           || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
5475           || old_start != ddl->bufpos
5476           || old_end != ddl->end_bufpos
5477           || initial_size != Dynarr_length (db->runes))
5478         {
5479           return 0;
5480         }
5481
5482       if (ddl->cursor_elt != -1)
5483         {
5484           w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5485           w->last_point_y[DESIRED_DISP] = line;
5486         }
5487
5488       last_line = line;
5489
5490       /* If the extent changes end on the line we just updated then
5491          we're done.  Otherwise go on to the next line. */
5492       if (end_unchanged <= ddl->end_bufpos)
5493         break;
5494       else
5495         line++;
5496     }
5497
5498   redisplay_update_line (w, first_line, last_line, 1);
5499   return 1;
5500 }
5501
5502 /* Attempt to update the display data structures based on knowledge of
5503    the changed region in the buffer.  Returns a boolean indicating
5504    success or failure.  If this function returns a failure then a
5505    regenerate_window _must_ be performed next in order to maintain
5506    invariants located here. */
5507
5508 static int
5509 regenerate_window_incrementally (struct window *w, Bufpos startp,
5510                                  Bufpos pointm)
5511 {
5512   struct buffer *b = XBUFFER (w->buffer);
5513   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
5514   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
5515   Charcount beg_unchanged, end_unchanged;
5516   Charcount extent_beg_unchanged, extent_end_unchanged;
5517
5518   int dla_start = 0;
5519   int dla_end, line;
5520   Bufpos start_pos;
5521
5522   /* If this function is called, the current and desired structures
5523      had better be identical.  If they are not, then that is a bug. */
5524   assert (Dynarr_length (cdla) == Dynarr_length (ddla));
5525
5526   /* We don't handle minibuffer windows yet.  The minibuffer prompt
5527      screws us up. */
5528   if (MINI_WINDOW_P (w))
5529     return 0;
5530
5531   extent_beg_unchanged = BUF_EXTENT_BEGIN_UNCHANGED (b);
5532   extent_end_unchanged = (BUF_EXTENT_END_UNCHANGED (b) == -1
5533                           ? -1
5534                           : BUF_Z (b) - BUF_EXTENT_END_UNCHANGED (b));
5535
5536   /* If nothing has changed in the buffer, then make sure point is ok
5537      and succeed. */
5538   if (BUF_BEGIN_UNCHANGED (b) == -1 && BUF_END_UNCHANGED (b) == -1)
5539     return regenerate_window_extents_only_changed (w, startp, pointm,
5540                                                    extent_beg_unchanged,
5541                                                    extent_end_unchanged);
5542
5543   /* We can't deal with deleted newlines. */
5544   if (BUF_NEWLINE_WAS_DELETED (b))
5545     return 0;
5546
5547   beg_unchanged = BUF_BEGIN_UNCHANGED (b);
5548   end_unchanged = (BUF_END_UNCHANGED (b) == -1
5549                    ? -1
5550                    : BUF_Z (b) - BUF_END_UNCHANGED (b));
5551
5552   REGEN_INC_FIND_START_END;
5553
5554   /* If the changed area starts before the visible area, give up. */
5555   if (beg_unchanged < startp)
5556     return 0;
5557
5558   /* Find what display line the buffer changes first affect. */
5559   line = dla_start;
5560   while (line <= dla_end)
5561     {
5562       struct display_line *dl = Dynarr_atp (cdla, line);
5563       Bufpos lstart = dl->bufpos + dl->offset;
5564       Bufpos lend = dl->end_bufpos + dl->offset;
5565
5566       if (beg_unchanged >= lstart && beg_unchanged <= lend)
5567         break;
5568
5569       line++;
5570     }
5571
5572   /* If the changes are below the visible area then if point hasn't
5573      moved return success otherwise fail in order to be safe. */
5574   if (line > dla_end)
5575     return regenerate_window_extents_only_changed (w, startp, pointm,
5576                                                    extent_beg_unchanged,
5577                                                    extent_end_unchanged);
5578   else
5579     /* At this point we know what line the changes first affect.  We
5580        now redraw that line.  If the changes are contained within it
5581        we are going to succeed and can update just that one line.
5582        Otherwise we fail.  If we fail we will have altered the desired
5583        structs which could lead to an assertion failure.  However, if
5584        we fail the next thing that is going to happen is a full regen
5585        so we will actually end up being safe. */
5586     {
5587       Bufpos new_start;
5588       prop_block_dynarr *prop = NULL;
5589       struct display_line *cdl = Dynarr_atp (cdla, line);
5590       struct display_line *ddl = Dynarr_atp (ddla, line);
5591
5592       assert (cdl->bufpos == ddl->bufpos);
5593       assert (cdl->end_bufpos == ddl->end_bufpos);
5594       assert (cdl->offset == ddl->offset);
5595
5596       /* If the line continues to next display line, fail. */
5597       if (ddl->line_continuation)
5598         return 0;
5599
5600       /* If the line was generated using propagation data, fail. */
5601       if (ddl->used_prop_data)
5602         return 0;
5603
5604       new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset,
5605                                          &prop, DESIRED_DISP);
5606       ddl->offset = 0;
5607
5608       /* If there is propagated stuff then it is pretty much a
5609          guarantee that more than just the one line is affected. */
5610       if (prop)
5611         {
5612           Dynarr_free (prop);
5613           return 0;
5614         }
5615
5616       /* If the line continues to next display line, fail. */
5617       if (ddl->line_continuation)
5618         return 0;
5619
5620       /* If any line position parameters have changed or a
5621          cursor has disappeared or disappeared, fail. */
5622       if (cdl->ypos != ddl->ypos
5623           || cdl->ascent != ddl->ascent
5624           || cdl->descent != ddl->descent
5625           || cdl->top_clip != ddl->top_clip
5626           || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)
5627           || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1))
5628         {
5629           return 0;
5630         }
5631
5632       /* If the changed area also ends on this line, then we may be in
5633          business.  Update everything and return success. */
5634       if (end_unchanged >= ddl->bufpos && end_unchanged <= ddl->end_bufpos)
5635         {
5636           w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
5637           w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
5638           Fset_marker (w->last_start[DESIRED_DISP], make_int (startp),
5639                        w->buffer);
5640           Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm),
5641                        w->buffer);
5642
5643           if (ddl->cursor_elt != -1)
5644             {
5645               w->last_point_x[DESIRED_DISP] = ddl->cursor_elt;
5646               w->last_point_y[DESIRED_DISP] = line;
5647             }
5648
5649           redisplay_update_line (w, line, line, 1);
5650           regenerate_modeline (w);
5651
5652           /* #### For now we just flush the cache until this has been
5653              tested.  After that is done, this should correct the
5654              cache directly. */
5655           Dynarr_reset (w->line_start_cache);
5656
5657           /* Adjust the extent changed boundaries to remove any
5658              overlap with the buffer changes since we've just
5659              successfully updated that area. */
5660           if (extent_beg_unchanged != -1
5661               && extent_beg_unchanged >= beg_unchanged
5662               && extent_beg_unchanged < end_unchanged)
5663             extent_beg_unchanged = end_unchanged;
5664
5665           if (extent_end_unchanged != -1
5666               && extent_end_unchanged >= beg_unchanged
5667               && extent_end_unchanged < end_unchanged)
5668             extent_end_unchanged = beg_unchanged - 1;
5669
5670           if (extent_end_unchanged <= extent_beg_unchanged)
5671             extent_beg_unchanged = extent_end_unchanged = -1;
5672
5673           /* This could lead to odd results if it fails, but since the
5674              buffer changes update succeeded this probably will to.
5675              We already know that the extent changes start at or after
5676              the line because we checked before entering the loop. */
5677           if (extent_beg_unchanged != -1
5678               && extent_end_unchanged != -1
5679               && ((extent_beg_unchanged < ddl->bufpos)
5680                   || (extent_end_unchanged > ddl->end_bufpos)))
5681             return regenerate_window_extents_only_changed (w, startp, pointm,
5682                                                            extent_beg_unchanged,
5683                                                            extent_end_unchanged);
5684           else
5685             return 1;
5686         }
5687     }
5688
5689   /* Oh, well. */
5690   return 0;
5691 }
5692
5693 /* Given a window and a point, update the given display lines such
5694    that point is displayed in the middle of the window.
5695    Return the window's new start position. */
5696
5697 static Bufpos
5698 regenerate_window_point_center (struct window *w, Bufpos point, int type)
5699 {
5700   Bufpos startp;
5701
5702   /* We need to make sure that the modeline is generated so that the
5703      window height can be calculated correctly. */
5704   ensure_modeline_generated (w, type);
5705
5706   startp = start_with_line_at_pixpos (w, point, window_half_pixpos (w));
5707   regenerate_window (w, startp, point, type);
5708   Fset_marker (w->start[type], make_int (startp), w->buffer);
5709
5710   return startp;
5711 }
5712
5713 /* Given a window and a set of display lines, return a boolean
5714    indicating whether the given point is contained within. */
5715
5716 static int
5717 point_visible (struct window *w, Bufpos point, int type)
5718 {
5719   struct buffer *b = XBUFFER (w->buffer);
5720   display_line_dynarr *dla = window_display_lines (w, type);
5721   int first_line;
5722
5723   if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline)
5724     first_line = 1;
5725   else
5726     first_line = 0;
5727
5728   if (Dynarr_length (dla) > first_line)
5729     {
5730       Bufpos start, end;
5731       struct display_line *dl = Dynarr_atp (dla, first_line);
5732
5733       start = dl->bufpos;
5734       end = BUF_Z (b) - w->window_end_pos[type] - 1;
5735
5736       if (point >= start && point <= end)
5737         {
5738           if (!MINI_WINDOW_P (w) && scroll_on_clipped_lines)
5739             {
5740               dl = Dynarr_atp (dla, Dynarr_length (dla) - 1);
5741
5742               if (point >= (dl->bufpos + dl->offset)
5743                   && point <= (dl->end_bufpos + dl->offset))
5744                 return !dl->clip;
5745               else
5746                 return 1;
5747             }
5748           else
5749             return 1;
5750         }
5751       else
5752         return 0;
5753     }
5754   else
5755     return 0;
5756 }
5757
5758 /* Return pixel position the middle of the window, not including the
5759    modeline and any potential horizontal scrollbar. */
5760
5761 int
5762 window_half_pixpos (struct window *w)
5763 {
5764   return WINDOW_TEXT_TOP (w) + (WINDOW_TEXT_HEIGHT (w) >> 1);
5765 }
5766
5767 /* Return the display line which is currently in the middle of the
5768    window W for display lines TYPE. */
5769
5770 int
5771 line_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5772 {
5773   display_line_dynarr *dla;
5774   int half;
5775   int elt;
5776   int first_elt = (MINI_WINDOW_P (w) ? 0 : 1);
5777
5778   if (type == CMOTION_DISP)
5779     regenerate_window (w, start, point, type);
5780
5781   dla = window_display_lines (w, type);
5782   half = window_half_pixpos (w);
5783
5784   for (elt = first_elt; elt < Dynarr_length (dla); elt++)
5785     {
5786       struct display_line *dl = Dynarr_atp (dla, elt);
5787       int line_bot = dl->ypos + dl->descent;
5788
5789       if (line_bot > half)
5790         return elt;
5791     }
5792
5793   /* We may not have a line at the middle if the end of the buffer is
5794      being displayed. */
5795   return -1;
5796 }
5797
5798 /* Return a value for point that would place it at the beginning of
5799    the line which is in the middle of the window. */
5800
5801 Bufpos
5802 point_at_center (struct window *w, int type, Bufpos start, Bufpos point)
5803 {
5804   /* line_at_center will regenerate the display structures, if necessary. */
5805   int line = line_at_center (w, type, start, point);
5806
5807   if (line == -1)
5808     return BUF_ZV (XBUFFER (w->buffer));
5809   else
5810     {
5811       display_line_dynarr *dla = window_display_lines (w, type);
5812       struct display_line *dl = Dynarr_atp (dla, line);
5813
5814       return dl->bufpos;
5815     }
5816 }
5817
5818 /* For a given window, ensure that the current visual representation
5819    is accurate. */
5820
5821 static void
5822 redisplay_window (Lisp_Object window, int skip_selected)
5823 {
5824   struct window *w = XWINDOW (window);
5825   struct frame *f = XFRAME (w->frame);
5826   struct device *d = XDEVICE (f->device);
5827   Lisp_Object old_buffer = w->buffer;
5828   Lisp_Object the_buffer = w->buffer;
5829   struct buffer *b;
5830   int echo_active = 0;
5831   int startp = 1;
5832   int pointm;
5833   int old_startp = 1;
5834   int old_pointm = 1;
5835   int selected_in_its_frame;
5836   int selected_globally;
5837   int skip_output = 0;
5838   int truncation_changed;
5839   int inactive_minibuffer =
5840     (MINI_WINDOW_P (w) &&
5841      (f != device_selected_frame (d)) &&
5842      !is_surrogate_for_selected_frame (f));
5843
5844   /* #### In the new world this function actually does a bunch of
5845      optimizations such as buffer-based scrolling, but none of that is
5846      implemented yet. */
5847
5848   /* If this is a combination window, do its children; that's all.
5849      The selected window is always a leaf so we don't check for
5850      skip_selected here. */
5851   if (!NILP (w->vchild))
5852     {
5853       redisplay_windows (w->vchild, skip_selected);
5854       return;
5855     }
5856   if (!NILP (w->hchild))
5857     {
5858       redisplay_windows (w->hchild, skip_selected);
5859       return;
5860     }
5861
5862   /* Is this window the selected window on its frame? */
5863   selected_in_its_frame = (w == XWINDOW (FRAME_SELECTED_WINDOW (f)));
5864   selected_globally =
5865       selected_in_its_frame &&
5866       EQ(DEVICE_CONSOLE(d), Vselected_console) &&
5867       XDEVICE(CONSOLE_SELECTED_DEVICE(XCONSOLE(DEVICE_CONSOLE(d)))) == d &&
5868       XFRAME(DEVICE_SELECTED_FRAME(d)) == f;
5869   if (skip_selected && selected_in_its_frame)
5870     return;
5871
5872   /* It is possible that the window is not fully initialized yet. */
5873   if (NILP (w->buffer))
5874     return;
5875
5876   if (MINI_WINDOW_P (w) && echo_area_active (f))
5877     {
5878       w->buffer = the_buffer = Vecho_area_buffer;
5879       echo_active = 1;
5880     }
5881
5882   b = XBUFFER (w->buffer);
5883
5884   if (echo_active)
5885     {
5886       old_pointm = selected_globally
5887                    ? BUF_PT (b)
5888                    : marker_position (w->pointm[CURRENT_DISP]);
5889       pointm = 1;
5890     }
5891   else
5892     {
5893       if (selected_globally)
5894         {
5895           pointm = BUF_PT (b);
5896         }
5897       else
5898         {
5899           pointm = marker_position (w->pointm[CURRENT_DISP]);
5900
5901           if (pointm < BUF_BEGV (b))
5902             pointm = BUF_BEGV (b);
5903           else if (pointm > BUF_ZV (b))
5904             pointm = BUF_ZV (b);
5905         }
5906     }
5907   Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm), the_buffer);
5908
5909   /* If the buffer has changed we have to invalidate all of our face
5910      cache elements. */
5911   if ((!echo_active && b != window_display_buffer (w))
5912       || !Dynarr_length (w->face_cachels)
5913       || f->faces_changed)
5914     reset_face_cachels (w);
5915   else
5916     mark_face_cachels_as_not_updated (w);
5917
5918   /* Ditto the glyph cache elements, although we do *not* invalidate
5919      the cache purely because glyphs have changed - this is now
5920      handled by the dirty flag.*/
5921   if ((!echo_active && b != window_display_buffer (w))
5922       || !Dynarr_length (w->glyph_cachels) || f->faces_changed)
5923     reset_glyph_cachels (w);
5924   else
5925     mark_glyph_cachels_as_not_updated (w);
5926
5927   /* If the marker's buffer is not the window's buffer, then we need
5928      to find a new starting position. */
5929   if (!MINI_WINDOW_P (w)
5930       && !EQ (Fmarker_buffer (w->start[CURRENT_DISP]), w->buffer))
5931     {
5932       startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
5933
5934       goto regeneration_done;
5935     }
5936
5937   if (echo_active)
5938     {
5939       old_startp = marker_position (w->start[CURRENT_DISP]);
5940       startp = 1;
5941     }
5942   else
5943     {
5944       startp = marker_position (w->start[CURRENT_DISP]);
5945       if (startp < BUF_BEGV (b))
5946         startp = BUF_BEGV (b);
5947       else if (startp > BUF_ZV (b))
5948         startp = BUF_ZV (b);
5949     }
5950   Fset_marker (w->start[DESIRED_DISP], make_int (startp), the_buffer);
5951
5952   truncation_changed = (find_window_mirror (w)->truncate_win !=
5953                         window_truncation_on (w));
5954
5955   /* If w->force_start is set, then some function set w->start and we
5956      should display from there and change point, if necessary, to
5957      ensure that it is visible. */
5958   if (w->force_start || inactive_minibuffer)
5959     {
5960       w->force_start = 0;
5961       w->last_modified[DESIRED_DISP] = Qzero;
5962       w->last_facechange[DESIRED_DISP] = Qzero;
5963
5964       regenerate_window (w, startp, pointm, DESIRED_DISP);
5965
5966       if (!point_visible (w, pointm, DESIRED_DISP) && !inactive_minibuffer)
5967         {
5968           pointm = point_at_center (w, DESIRED_DISP, 0, 0);
5969
5970           if (selected_globally)
5971             BUF_SET_PT (b, pointm);
5972
5973           Fset_marker (w->pointm[DESIRED_DISP], make_int (pointm),
5974                        the_buffer);
5975
5976           /* #### BUFU amounts of overkill just to get the cursor
5977              location marked properly.  FIX ME FIX ME FIX ME */
5978           regenerate_window (w, startp, pointm, DESIRED_DISP);
5979         }
5980
5981       goto regeneration_done;
5982     }
5983
5984   /* If nothing has changed since the last redisplay, then we just
5985      need to make sure that point is still visible. */
5986   if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b)
5987       && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)
5988       && pointm >= startp
5989       /* This check is to make sure we restore the minibuffer after a
5990          temporary change to the echo area. */
5991       && !(MINI_WINDOW_P (w) && f->buffers_changed)
5992       && !f->frame_changed
5993       && !truncation_changed
5994       /* check whether start is really at the begining of a line  GE */
5995       && (!w->start_at_line_beg || beginning_of_line_p (b, startp))
5996       )
5997     {
5998       /* Check if the cursor has actually moved. */
5999       if (EQ (Fmarker_buffer (w->last_point[CURRENT_DISP]), w->buffer)
6000           && pointm == marker_position (w->last_point[CURRENT_DISP])
6001           && selected_globally
6002           && !w->windows_changed
6003           && !f->clip_changed
6004           && !f->extents_changed
6005           && !f->faces_changed
6006           && !f->glyphs_changed
6007           && !f->subwindows_changed
6008           /*      && !f->subwindows_state_changed*/
6009           && !f->point_changed
6010           && !f->windows_structure_changed)
6011         {
6012           /* If not, we're done. */
6013           if (f->modeline_changed)
6014             regenerate_modeline (w);
6015
6016           skip_output = 1;
6017           goto regeneration_done;
6018         }
6019       else
6020         {
6021           /* If the new point is visible in the redisplay structures,
6022              then let the output update routines handle it, otherwise
6023              do things the hard way. */
6024           if (!w->windows_changed
6025               && !f->clip_changed
6026               && !f->extents_changed
6027               && !f->faces_changed
6028               && !f->glyphs_changed
6029               && !f->subwindows_changed
6030               /*              && !f->subwindows_state_changed*/
6031               && !f->windows_structure_changed)
6032             {
6033               if (point_visible (w, pointm, CURRENT_DISP)
6034                   && w->last_point_x[CURRENT_DISP] != -1
6035                   && w->last_point_y[CURRENT_DISP] != -1)
6036                 {
6037                   if (redisplay_move_cursor (w, pointm, FRAME_TTY_P (f)))
6038                     {
6039                       /* Always regenerate in case it is displaying
6040                          the current line or column. */
6041                       regenerate_modeline (w);
6042
6043                       skip_output = 1;
6044                       goto regeneration_done;
6045                     }
6046                 }
6047               else if (!selected_in_its_frame && !f->point_changed)
6048                 {
6049                   if (f->modeline_changed)
6050                     regenerate_modeline (w);
6051
6052                   skip_output = 1;
6053                   goto regeneration_done;
6054                 }
6055             }
6056
6057           /* If we weren't able to take the shortcut method, then use
6058              the brute force method. */
6059           regenerate_window (w, startp, pointm, DESIRED_DISP);
6060
6061           if (point_visible (w, pointm, DESIRED_DISP))
6062             goto regeneration_done;
6063         }
6064     }
6065
6066   /* Check if the starting point is no longer at the beginning of a
6067      line, in which case find a new starting point.  We also recenter
6068      if our start position is equal to point-max.  Otherwise we'll end
6069      up with a blank window. */
6070   else if (((w->start_at_line_beg || MINI_WINDOW_P (w))
6071             && !(startp == BUF_BEGV (b)
6072                  || BUF_FETCH_CHAR (b, startp - 1) == '\n'))
6073            || (pointm == startp &&
6074                EQ (Fmarker_buffer (w->last_start[CURRENT_DISP]), w->buffer) &&
6075                startp < marker_position (w->last_start[CURRENT_DISP]))
6076            || (startp == BUF_ZV (b)))
6077     {
6078       startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6079
6080       goto regeneration_done;
6081     }
6082   /* See if we can update the data structures locally based on
6083      knowledge of what changed in the buffer. */
6084   else if (!w->windows_changed
6085            && !f->clip_changed
6086            && !f->faces_changed
6087            && !f->glyphs_changed
6088            && !f->subwindows_changed
6089            /*      && !f->subwindows_state_changed*/
6090            && !f->windows_structure_changed
6091            && !f->frame_changed
6092            && !truncation_changed
6093            && pointm >= startp
6094            && regenerate_window_incrementally (w, startp, pointm))
6095     {
6096       if (f->modeline_changed
6097           || XINT (w->last_modified[CURRENT_DISP]) < BUF_MODIFF (b)
6098           || XINT (w->last_facechange[CURRENT_DISP]) < BUF_FACECHANGE (b))
6099         regenerate_modeline (w);
6100
6101       skip_output = 1;
6102       goto regeneration_done;
6103     }
6104   /* #### This is where a check for structure based scrolling would go. */
6105   /* If all else fails, try just regenerating and see what happens. */
6106   else
6107     {
6108       regenerate_window (w, startp, pointm, DESIRED_DISP);
6109
6110       if (point_visible (w, pointm, DESIRED_DISP))
6111         goto regeneration_done;
6112     }
6113
6114   /* We still haven't gotten the window regenerated with point
6115      visible.  Next we try scrolling a little and see if point comes
6116      back onto the screen. */
6117   if (scroll_step > 0)
6118     {
6119       int scrolled = scroll_conservatively;
6120       for (; scrolled >= 0; scrolled -= scroll_step)
6121         {
6122           startp = vmotion (w, startp,
6123                             (pointm < startp) ? -scroll_step : scroll_step, 0);
6124           regenerate_window (w, startp, pointm, DESIRED_DISP);
6125
6126           if (point_visible (w, pointm, DESIRED_DISP))
6127             goto regeneration_done;
6128         }
6129     }
6130
6131   /* We still haven't managed to get the screen drawn with point on
6132      the screen, so just center it and be done with it. */
6133   startp = regenerate_window_point_center (w, pointm, DESIRED_DISP);
6134
6135
6136 regeneration_done:
6137
6138   /* If the window's frame is changed then reset the current display
6139      lines in order to force a full repaint. */
6140   if (f->frame_changed)
6141     {
6142       display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
6143
6144       Dynarr_reset (cla);
6145     }
6146
6147   /* Must do this before calling redisplay_output_window because it
6148      sets some markers on the window. */
6149   if (echo_active)
6150     {
6151       w->buffer = old_buffer;
6152       Fset_marker (w->pointm[DESIRED_DISP], make_int (old_pointm), old_buffer);
6153       Fset_marker (w->start[DESIRED_DISP], make_int (old_startp), old_buffer);
6154     }
6155
6156   /* These also have to be set before calling redisplay_output_window
6157      since it sets the CURRENT_DISP values based on them. */
6158   w->last_modified[DESIRED_DISP] = make_int (BUF_MODIFF (b));
6159   w->last_facechange[DESIRED_DISP] = make_int (BUF_FACECHANGE (b));
6160   Fset_marker (w->last_start[DESIRED_DISP], make_int (startp), w->buffer);
6161   Fset_marker (w->last_point[DESIRED_DISP], make_int (pointm), w->buffer);
6162
6163   if (!skip_output)
6164     {
6165       Bufpos start = marker_position (w->start[DESIRED_DISP]);
6166       Bufpos end = (w->window_end_pos[DESIRED_DISP] == -1
6167                     ? BUF_ZV (b)
6168                     : BUF_Z (b) - w->window_end_pos[DESIRED_DISP] - 1);
6169       /* Don't pollute the cache if not sure if we are correct */
6170       if (w->start_at_line_beg)
6171         update_line_start_cache (w, start, end, pointm, 1);
6172       redisplay_output_window (w);
6173       /*
6174        * If we just displayed the echo area, the line start cache is
6175        * no longer valid, because the minibuffer window is associated
6176        * with the window now.
6177        */
6178       if (echo_active)
6179         w->line_cache_last_updated = make_int (-1);
6180     }
6181
6182   /* #### This should be dependent on face changes and will need to be
6183      somewhere else once tty updates occur on a per-frame basis. */
6184   mark_face_cachels_as_clean (w);
6185
6186   /* The glyph cachels only get dirty if someone changed something.
6187    Since redisplay has now effectively ended we can reset the dirty
6188    flag since everything must be up-to-date. */
6189   if (glyphs_changed)
6190     mark_glyph_cachels_as_clean (w);
6191
6192   w->windows_changed = 0;
6193 }
6194
6195 /* Call buffer_reset_changes for all buffers present in any window
6196    currently visible in all frames on all devices.  #### There has to
6197    be a better way to do this. */
6198
6199 static int
6200 reset_buffer_changes_mapfun (struct window *w, void *ignored_closure)
6201 {
6202   buffer_reset_changes (XBUFFER (w->buffer));
6203   return 0;
6204 }
6205
6206 static void
6207 reset_buffer_changes (void)
6208 {
6209   Lisp_Object frmcons, devcons, concons;
6210
6211   FRAME_LOOP_NO_BREAK (frmcons, devcons, concons)
6212     {
6213       struct frame *f = XFRAME (XCAR (frmcons));
6214
6215       if (FRAME_REPAINT_P (f))
6216         map_windows (f, reset_buffer_changes_mapfun, 0);
6217     }
6218 }
6219
6220 /* Ensure that all windows underneath the given window in the window
6221    hierarchy are correctly displayed. */
6222
6223 static void
6224 redisplay_windows (Lisp_Object window, int skip_selected)
6225 {
6226   for (; !NILP (window) ; window = XWINDOW (window)->next)
6227     {
6228       redisplay_window (window, skip_selected);
6229     }
6230 }
6231
6232 static int
6233 call_redisplay_end_triggers (struct window *w, void *closure)
6234 {
6235   Bufpos lrpos = w->last_redisplay_pos;
6236   w->last_redisplay_pos = 0;
6237   if (!NILP (w->buffer)
6238       && !NILP (w->redisplay_end_trigger)
6239       && lrpos > 0)
6240     {
6241       Bufpos pos;
6242
6243       if (MARKERP (w->redisplay_end_trigger)
6244           && XMARKER (w->redisplay_end_trigger)->buffer != 0)
6245         pos = marker_position (w->redisplay_end_trigger);
6246       else if (INTP (w->redisplay_end_trigger))
6247         pos = XINT (w->redisplay_end_trigger);
6248       else
6249         {
6250           w->redisplay_end_trigger = Qnil;
6251           return 0;
6252         }
6253
6254       if (lrpos >= pos)
6255         {
6256           Lisp_Object window;
6257           XSETWINDOW (window, w);
6258           va_run_hook_with_args_in_buffer (XBUFFER (w->buffer),
6259                                            Qredisplay_end_trigger_functions,
6260                                            2, window,
6261                                            w->redisplay_end_trigger);
6262           w->redisplay_end_trigger = Qnil;
6263         }
6264     }
6265
6266   return 0;
6267 }
6268
6269 /* Ensure that all windows on the given frame are correctly displayed. */
6270
6271 int
6272 redisplay_frame (struct frame *f, int preemption_check)
6273 {
6274   struct device *d = XDEVICE (f->device);
6275
6276   if (preemption_check)
6277     {
6278       /* The preemption check itself takes a lot of time,
6279          so normally don't do it here.  We do it if called
6280          from Lisp, though (`redisplay-frame'). */
6281       int preempted;
6282
6283       REDISPLAY_PREEMPTION_CHECK;
6284       if (preempted)
6285         return 1;
6286     }
6287
6288   if (!internal_equal (f->old_buffer_alist, f->buffer_alist, 0))
6289     {
6290       Lisp_Object frame;
6291
6292       f->old_buffer_alist = Freplace_list (f->old_buffer_alist,
6293                                            f->buffer_alist);
6294       XSETFRAME (frame, f);
6295       va_run_hook_with_args (Qbuffer_list_changed_hook, 1, frame);
6296     }
6297
6298   /* Before we put a hold on frame size changes, attempt to process
6299      any which are already pending. */
6300   if (f->size_change_pending)
6301     change_frame_size (f, f->new_height, f->new_width, 0);
6302
6303   /* If frame size might need to be changed, due to changed size
6304      of toolbars, scrollbars etc, change it now */
6305   if (f->size_slipped)
6306     {
6307       adjust_frame_size (f);
6308       assert (!f->size_slipped);
6309     }
6310
6311   /* The menubar, toolbar, and icon updates must be done before
6312      hold_frame_size_changes is called and we are officially
6313      'in_display'.  They may eval lisp code which may call Fsignal.
6314      If in_display is set Fsignal will abort. */
6315
6316 #ifdef HAVE_MENUBARS
6317   /* Update the menubar.  It is done first since it could change
6318      the menubar's visibility.  This way we avoid having flashing
6319      caused by an Expose event generated by the visibility change
6320      being handled. */
6321   update_frame_menubars (f);
6322 #endif /* HAVE_MENUBARS */
6323 #ifdef HAVE_TOOLBARS
6324   /* Update the toolbars. */
6325   update_frame_toolbars (f);
6326 #endif /* HAVE_TOOLBARS */
6327   /* Gutter update proper has to be done inside display when no frame
6328      size changes can occur, thus we separately update the gutter
6329      geometry here if it needs it. */
6330   update_frame_gutter_geometry (f);
6331
6332   /* If we clear the frame we have to force its contents to be redrawn. */
6333   if (f->clear)
6334     f->frame_changed = 1;
6335
6336   /* Invalidate the subwindow cache. We use subwindows_changed here to
6337      cause subwindows to get instantiated. This is because
6338      subwindows_state_changed is less strict - dealing with things
6339      like the clicked state of button. We have to do this before
6340      redisplaying the gutters as subwindows get unmapped in the
6341      process.*/
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 rediplay 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 flafs 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);
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);
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);
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);
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);
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);
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);
9523
9524 }