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