XEmacs 21.2.29 "Hestia".
[chise/xemacs-chise.git.1] / src / redisplay-output.c
1 /* Synchronize redisplay structures and output changes.
2    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3    Copyright (C) 1995, 1996 Ben Wing.
4    Copyright (C) 1996 Chuck Thompson.
5    Copyright (C) 1999 Andy Piper.
6
7 This file is part of XEmacs.
8
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING.  If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 /* Synched up with: Not in FSF. */
25
26 /* This file has been Mule-ized. */
27
28 /* Author: Chuck Thompson */
29
30 /* Heavily hacked for modularity, gutter and subwindow support by Andy
31    Piper. */
32
33 #include <config.h>
34 #include "lisp.h"
35
36 #include "buffer.h"
37 #include "window.h"
38 #include "frame.h"
39 #include "device.h"
40 #include "glyphs.h"
41 #include "redisplay.h"
42 #include "faces.h"
43
44 static int compare_runes (struct window *w, struct rune *crb,
45                           struct rune *drb);
46 static void redraw_cursor_in_window (struct window *w,
47                                      int run_end_begin_glyphs);
48 static void redisplay_output_display_block (struct window *w, struct display_line *dl,
49                                             int block, int start, int end, int start_pixpos,
50                                             int cursor_start, int cursor_width,
51                                             int cursor_height);
52 static void redisplay_normalize_display_box (struct display_box* dest,
53                                              struct display_glyph_area* src);
54 static int redisplay_display_boxes_in_window_p (struct window* w,
55                                                 struct display_box* db,
56                                                 struct display_glyph_area* dga);
57 static void redisplay_clear_clipped_region (Lisp_Object locale, face_index findex,
58                                             struct display_box* dest,
59                                             struct display_glyph_area* glyphsrc,
60                                             int fullheight_p, Lisp_Object);
61
62 /*****************************************************************************
63  sync_rune_structs
64
65  Synchronize the given rune blocks.
66  ****************************************************************************/
67 static void
68 sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra)
69 {
70   int rune_elt;
71   int max_move = ((Dynarr_length (dra) > Dynarr_largest (cra))
72                   ? Dynarr_largest (cra)
73                   : Dynarr_length (dra));
74
75   if (max_move)
76     {
77       /* #### Doing this directly breaks the encapsulation.  But, the
78          running time of this function has a measurable impact on
79          redisplay performance so avoiding all excess overhead is a
80          good thing.  Is all of this true? */
81       memcpy (cra->base, dra->base, sizeof (struct rune) * max_move);
82       Dynarr_set_size (cra, max_move);
83     }
84   else
85     Dynarr_reset (cra);
86
87   for (rune_elt = max_move; rune_elt < Dynarr_length (dra); rune_elt++)
88     {
89       struct rune rb, *crb;
90       struct rune *drb = Dynarr_atp (dra, rune_elt);
91
92       crb = &rb;
93       memcpy (crb, drb, sizeof (struct rune));
94       Dynarr_add (cra, *crb);
95     }
96 }
97
98 /*****************************************************************************
99  sync_display_line_structs
100
101  For the given LINE in window W, make the current display line equal
102  the desired display line.
103  ****************************************************************************/
104 static void
105 sync_display_line_structs (struct window *w, int line, int do_blocks,
106                            display_line_dynarr *cdla,
107                            display_line_dynarr *ddla)
108 {
109   int cdla_len = Dynarr_length (cdla);
110
111   struct display_line dl, *clp, *dlp;
112   int db_elt;
113
114   dlp = Dynarr_atp (ddla, line);
115   if (line >= Dynarr_largest (cdla))
116     {
117       clp = &dl;
118       clp->display_blocks = Dynarr_new (display_block);
119     }
120   else
121     {
122       clp = Dynarr_atp (cdla, line);
123       if (clp->display_blocks)
124         Dynarr_reset (clp->display_blocks);
125       if (clp->left_glyphs)
126         {
127           Dynarr_free (clp->left_glyphs);
128           clp->left_glyphs = 0;
129         }
130       if (clp->right_glyphs)
131         {
132           Dynarr_free (clp->right_glyphs);
133           clp->right_glyphs = 0;
134         }
135     }
136   {
137     display_block_dynarr *tdb = clp->display_blocks;
138
139     memcpy (clp, dlp, sizeof (struct display_line));
140     clp->display_blocks = tdb;
141     clp->left_glyphs = 0;
142     clp->right_glyphs = 0;
143   }
144
145   if (!do_blocks && line >= cdla_len)
146     {
147       Dynarr_add (cdla, *clp);
148       return;
149     }
150
151   for (db_elt = 0; db_elt < Dynarr_length (dlp->display_blocks); db_elt++)
152     {
153       struct display_block db, *cdb;
154       struct display_block *ddb = Dynarr_atp (dlp->display_blocks, db_elt);
155
156       if (db_elt >= Dynarr_largest (clp->display_blocks))
157         {
158           cdb = &db;
159           memcpy (cdb, ddb, sizeof (struct display_block));
160           cdb->runes = Dynarr_new (rune);
161           Dynarr_add (clp->display_blocks, *cdb);
162         }
163       else
164         {
165           rune_dynarr *tr;
166
167           cdb = Dynarr_atp (clp->display_blocks, db_elt);
168           tr = cdb->runes;
169           memcpy (cdb, ddb, sizeof (struct display_block));
170           cdb->runes = tr;
171           Dynarr_increment (clp->display_blocks);
172         }
173
174       sync_rune_structs (w, cdb->runes, ddb->runes);
175     }
176
177   if (line >= cdla_len)
178     Dynarr_add (cdla, *clp);
179 }
180
181 /*****************************************************************************
182  compare_runes
183
184  Compare to runes to see if each of their fields is equal.  If so,
185  return true otherwise return false.
186  ****************************************************************************/
187 static int
188 compare_runes (struct window *w, struct rune *crb, struct rune *drb)
189 {
190   /* Do not compare the values of bufpos and endpos.  They do not
191      affect the display characteristics. */
192
193   /* Note: (hanoi 6) spends 95% of its time in redisplay, and about
194      30% here. Not using bitfields for rune.type alone gives a redisplay
195      speed up of 10%.
196
197      #### In profile arcs run of a normal Gnus session this function
198      is run 6.76 million times, only to return 1 in 6.73 million of
199      those.
200
201      In addition a quick look GCC sparc assembly shows that GCC is not
202      doing a good job here.
203      1. The function is not inlined (too complicated?)
204      2. It seems to be reloading the crb and drb variables all the
205      time.
206      3. It doesn't seem to notice that the second half of these if's
207      are really a switch statement.
208
209      So I (JV) conjecture
210
211      #### It would really be worth it to arrange for this function to
212      be (almost) a single call to memcmp. */
213
214   if ((crb->findex != drb->findex) ||
215       (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
216     return 0;
217   else if (crb->xpos != drb->xpos)
218     return 0;
219   else if (crb->width != drb->width)
220     return 0;
221   else if (crb->cursor_type != drb->cursor_type)
222     return 0;
223   else if (crb->type != drb->type)
224     return 0;
225   else if (crb->type == RUNE_CHAR &&
226            (crb->object.chr.ch != drb->object.chr.ch))
227     return 0;
228   else if (crb->type == RUNE_HLINE &&
229            (crb->object.hline.thickness != drb->object.hline.thickness ||
230             crb->object.hline.yoffset != drb->object.hline.yoffset))
231     return 0;
232   else if (crb->type == RUNE_DGLYPH &&
233            (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
234             !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
235             crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
236     return 0;
237   /* Only check dirtiness if we know something has changed. */
238   else if (crb->type == RUNE_DGLYPH &&
239            XFRAME (w->frame)->glyphs_changed)
240     {
241       glyph_index gindex = get_glyph_cachel_index (w, drb->object.dglyph.glyph);
242       /* Although doing the cachel lookup for every comparison is
243          very expensive.we have to do it to make sure the cache is
244          up-to-date. */
245       if (GLYPH_CACHEL_DIRTYP (w, gindex))
246         return 0;
247       else
248         return 1;
249     }
250   else
251     return 1;
252 }
253
254 /*****************************************************************************
255  get_next_display_block
256
257  Return the next display starting at or overlapping START_POS.  Return
258  the start of the next region in NEXT_START.
259  ****************************************************************************/
260 int
261 get_next_display_block (layout_bounds bounds, display_block_dynarr *dba,
262                         int start_pos, int *next_start)
263 {
264   int next_display_block = NO_BLOCK;
265   int priority = -1;
266   int block;
267
268   /* If we don't find a display block covering or starting at
269      start_pos, then we return the starting point of the next display
270      block or the next division boundary, whichever is closer to
271      start_pos. */
272   if (next_start)
273     {
274       if (start_pos >= bounds.left_out && start_pos < bounds.left_in)
275         *next_start = bounds.left_in;
276       else if (start_pos < bounds.left_white)
277         *next_start = bounds.left_white;
278       else if (start_pos < bounds.right_white)
279         *next_start = bounds.right_white;
280       else if (start_pos < bounds.right_in)
281         *next_start = bounds.right_in;
282       else if (start_pos <= bounds.right_out)
283         *next_start = bounds.right_out;
284       else
285         abort ();
286     }
287
288   for (block = 0; block < Dynarr_length (dba); block++)
289     {
290       struct display_block *db = Dynarr_atp (dba, block);
291
292       if (db->start_pos <= start_pos && db->end_pos > start_pos)
293         {
294           if ((int) db->type > priority)
295             {
296               priority = db->type;
297               next_display_block = block;
298               if (next_start)
299                 *next_start = db->end_pos;
300             }
301         }
302       else if (next_start && db->start_pos > start_pos)
303         {
304           if (db->start_pos < *next_start)
305             *next_start = db->start_pos;
306         }
307     }
308
309   return next_display_block;
310 }
311
312 /*****************************************************************************
313  get_cursor_size_and_location
314
315  Return the information defining the pixel location of the cursor.
316  ****************************************************************************/
317 static void
318 get_cursor_size_and_location (struct window *w, struct display_block *db,
319                               int cursor_location,
320                               int *cursor_start, int *cursor_width,
321                               int *cursor_height)
322 {
323   struct rune *rb;
324   Lisp_Object window;
325   int defheight, defwidth;
326
327   if (Dynarr_length (db->runes) <= cursor_location)
328     abort ();
329
330   XSETWINDOW (window, w);
331
332   rb = Dynarr_atp (db->runes, cursor_location);
333   *cursor_start = rb->xpos;
334
335   default_face_height_and_width (window, &defheight, &defwidth);
336   *cursor_height = defheight;
337
338   if (rb->type == RUNE_BLANK)
339     *cursor_width = defwidth;
340   else
341     *cursor_width = rb->width;
342 }
343
344 /*****************************************************************************
345  compare_display_blocks
346
347  Given two display blocks, output only those areas where they differ.
348  ****************************************************************************/
349 static int
350 compare_display_blocks (struct window *w, struct display_line *cdl,
351                         struct display_line *ddl, int c_block, int d_block,
352                         int start_pixpos, int cursor_start, int cursor_width,
353                         int cursor_height)
354 {
355   struct frame *f = XFRAME (w->frame);
356   struct display_block *cdb, *ddb;
357   int start_pos;
358   int stop_pos;
359   int force = 0;
360   int block_end;
361
362   cdb = Dynarr_atp (cdl->display_blocks, c_block);
363   ddb = Dynarr_atp (ddl->display_blocks, d_block);
364
365   assert (cdb->type == ddb->type);
366
367   start_pos = -1;
368   stop_pos = min (Dynarr_length (cdb->runes), Dynarr_length (ddb->runes));
369
370   block_end =
371     (!Dynarr_length (ddb->runes)
372      ? 0
373      : (Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->xpos +
374         Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->width));
375
376   /* If the new block type is not text and the cursor status is
377      changing and it overlaps the position of this block then force a
378      full redraw of the block in order to make sure that the cursor is
379      updated properly. */
380   if (ddb->type != TEXT
381 #if 0
382       /* I'm not sure exactly what this code wants to do, but it's
383        * not right--it doesn't update when cursor_elt changes from, e.g.,
384        * 0 to 8, and the new or old cursor loc overlaps this block.
385        * I've replaced it with the more conservative test below.
386        * -dkindred@cs.cmu.edu 23-Mar-1997 */
387       && ((cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
388           || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1))
389       && (ddl->cursor_elt == -1 ||
390           (cursor_start
391            && cursor_width
392            && (cursor_start + cursor_width) >= start_pixpos
393            && cursor_start <= block_end))
394 #else
395       && (cdl->cursor_elt != ddl->cursor_elt)
396 #endif
397       )
398     force = 1;
399
400   if (f->windows_structure_changed ||
401       /* #### Why is this so? We have face cachels so that we don't
402          have to recalculate all the display blocks when faces
403          change. I have fixed this for glyphs and am inclined to think
404          that faces should "Just Work", but I'm not feeling brave
405          today. Maybe its because the face cachels represent merged
406          faces rather than simply instantiations in a particular
407          domain. */
408       f->faces_changed ||
409       cdl->ypos != ddl->ypos ||
410       cdl->ascent != ddl->ascent ||
411       cdl->descent != ddl->descent ||
412       cdl->clip != ddl->clip ||
413       force)
414     {
415       start_pos = 0;
416       force = 1;
417     }
418   else
419     {
420       int elt = 0;
421
422       while (start_pos < 0 && elt < stop_pos)
423         {
424           if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
425                               Dynarr_atp (ddb->runes, elt)))
426             {
427               start_pos = elt;
428             }
429           else
430             {
431               elt++;
432             }
433         }
434
435       /* If nothing has changed in the area where the blocks overlap, but
436          there are new blocks in the desired block, then adjust the start
437          point accordingly. */
438       if (elt == stop_pos && stop_pos < Dynarr_length (ddb->runes))
439         start_pos = stop_pos;
440     }
441
442   if (start_pos >= 0)
443     {
444       if ((Dynarr_length (ddb->runes) != Dynarr_length (cdb->runes))
445           || force)
446         {
447           stop_pos = Dynarr_length (ddb->runes);
448         }
449       else
450         {
451           /* If the lines have the same number of runes and we are not
452              forcing a full redraw because the display line has
453              changed position then we try and optimize how much of the
454              line we actually redraw by scanning backwards from the
455              end for the first changed rune.  This optimization is
456              almost always triggered by face changes. */
457
458           int elt = Dynarr_length (ddb->runes) - 1;
459
460           while (elt > start_pos)
461             {
462               if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
463                                   Dynarr_atp (ddb->runes, elt)))
464                 break;
465               else
466                 elt--;
467             }
468           stop_pos = elt + 1;
469         }
470
471       redisplay_output_display_block (w, ddl, d_block, start_pos,
472                                       stop_pos, start_pixpos,
473                                       cursor_start, cursor_width,
474                                       cursor_height);
475       return 1;
476     }
477
478   return 0;
479 }
480
481 /*****************************************************************************
482  clear_left_border
483
484  Clear the lefthand outside border.
485  ****************************************************************************/
486 static void
487 clear_left_border (struct window *w, int y, int height)
488 {
489   struct frame *f = XFRAME (w->frame);
490   Lisp_Object window;
491
492   XSETWINDOW (window, w);
493   redisplay_clear_region (window, DEFAULT_INDEX,
494                 FRAME_LEFT_BORDER_START (f), y,
495                 FRAME_BORDER_WIDTH (f), height);
496 }
497
498 /*****************************************************************************
499  clear_right_border
500
501  Clear the righthand outside border.
502  ****************************************************************************/
503 static void
504 clear_right_border (struct window *w, int y, int height)
505 {
506   struct frame *f = XFRAME (w->frame);
507   Lisp_Object window;
508
509   XSETWINDOW (window, w);
510   redisplay_clear_region (window, DEFAULT_INDEX,
511                 FRAME_RIGHT_BORDER_START (f),
512                 y, FRAME_BORDER_WIDTH (f), height);
513 }
514
515 /*****************************************************************************
516  output_display_line
517
518  Ensure that the contents of the given display line is correct
519  on-screen.  The force_ parameters are used by redisplay_move_cursor
520  to correctly update cursor locations and only cursor locations.
521  ****************************************************************************/
522 void
523 output_display_line (struct window *w, display_line_dynarr *cdla,
524                      display_line_dynarr *ddla, int line, int force_start,
525                      int force_end)
526
527 {
528   struct frame *f = XFRAME (w->frame);
529   struct buffer *b = XBUFFER (w->buffer);
530   struct buffer *old_b = window_display_buffer (w);
531   struct display_line *cdl, *ddl;
532   display_block_dynarr *cdba, *ddba;
533   int start_pixpos, end_pixpos;
534   int cursor_start, cursor_width, cursor_height;
535
536   int force = (force_start >= 0 || force_end >= 0);
537   int clear_border = 0;
538   int must_sync = 0;
539
540   if (cdla && line < Dynarr_length (cdla))
541     {
542       cdl = Dynarr_atp (cdla, line);
543       cdba = cdl->display_blocks;
544     }
545   else
546     {
547       cdl = NULL;
548       cdba = NULL;
549     }
550
551   ddl = Dynarr_atp (ddla, line);      /* assert line < Dynarr_length (ddla) */
552   ddba = ddl->display_blocks;
553
554   if (force_start >= 0 && force_start >= ddl->bounds.left_out)
555     start_pixpos = force_start;
556   else
557     start_pixpos = ddl->bounds.left_out;
558
559   if (force_end >= 0 && force_end < ddl->bounds.right_out)
560     end_pixpos = force_end;
561   else
562     end_pixpos = ddl->bounds.right_out;
563
564   /* Get the cursor parameters. */
565   if (ddl->cursor_elt != -1)
566     {
567       struct display_block *db;
568
569       /* If the lines cursor parameter is not -1 then it indicates
570          which rune in the TEXT block contains the cursor.  This means
571          that there must be at least one display block.  The TEXT
572          block, if present, must always be the first display block. */
573       assert (Dynarr_length (ddba) != 0);
574
575       db = Dynarr_atp (ddba, 0);
576       assert (db->type == TEXT);
577
578       get_cursor_size_and_location (w, db, ddl->cursor_elt, &cursor_start,
579                                     &cursor_width, &cursor_height);
580     }
581   else
582     {
583       cursor_start = cursor_width = cursor_height = 0;
584     }
585
586   /* The modeline should only have a single block and it had better be
587      a TEXT block. */
588   if (ddl->modeline)
589     {
590       /* The shadow thickness check is necessary if only the sign of
591          the size changed. */
592       if (cdba && !w->shadow_thickness_changed)
593         {
594           must_sync |= compare_display_blocks (w, cdl, ddl, 0, 0,
595                                                start_pixpos, 0, 0, 0);
596         }
597       else
598         {
599           redisplay_output_display_block (w, ddl, 0, 0, -1, start_pixpos,
600                                           0, 0, 0);
601           must_sync = 1;
602         }
603
604       if (must_sync)
605         clear_border = 1;
606     }
607
608   while (!ddl->modeline && start_pixpos < end_pixpos)
609     {
610       int block;
611       int next_start_pixpos;
612
613       block = get_next_display_block (ddl->bounds, ddba, start_pixpos,
614                                       &next_start_pixpos);
615
616       /* If we didn't find a block then we should blank the area
617          between start_pos and next_start if necessary. */
618       if (block == NO_BLOCK)
619         {
620           /* We only erase those areas which were actually previously
621              covered by a display block unless the window structure
622              changed.  In that case we clear all areas since the current
623              structures may actually represent a different buffer. */
624           while (start_pixpos < next_start_pixpos)
625             {
626               int block_end;
627               int old_block;
628
629               if (cdba)
630                 old_block = get_next_display_block (ddl->bounds, cdba,
631                                                     start_pixpos, &block_end);
632               else
633                 {
634                   old_block = NO_BLOCK;
635                   block_end = next_start_pixpos;
636                 }
637
638               if (!cdba || old_block != NO_BLOCK || b != old_b ||
639                   f->windows_structure_changed ||
640                   f->faces_changed ||
641                   force ||
642                   (cdl && (cdl->ypos != ddl->ypos ||
643                            cdl->ascent != ddl->ascent ||
644                            cdl->descent != ddl->descent ||
645                            cdl->top_clip != ddl->top_clip ||
646                            cdl->clip != ddl->clip)))
647                 {
648                   int x, y, width, height;
649                   face_index findex;
650
651                   must_sync = 1;
652                   x = start_pixpos;
653                   y = DISPLAY_LINE_YPOS (ddl);
654                   width = min (next_start_pixpos, block_end) - x;
655                   height = DISPLAY_LINE_HEIGHT (ddl);
656
657                   if (x < ddl->bounds.left_in)
658                     {
659                       findex = ddl->left_margin_findex ?
660                         ddl->left_margin_findex
661                         : get_builtin_face_cache_index (w, Vleft_margin_face);
662                     }
663                   else if (x < ddl->bounds.right_in)
664                     {
665                       /* no check here because DEFAULT_INDEX == 0 anyway */
666                       findex = ddl->default_findex;
667                     }
668                   else if (x < ddl->bounds.right_out)
669                     {
670                       findex = ddl->right_margin_findex ?
671                         ddl->right_margin_findex
672                         : get_builtin_face_cache_index (w, Vright_margin_face);
673                     }
674                   else
675                     findex = (face_index) -1;
676
677                   if (findex != (face_index) -1)
678                     {
679                       Lisp_Object window;
680
681                       XSETWINDOW (window, w);
682
683                       /* Clear the empty area. */
684                       redisplay_clear_region (window, findex, x, y, width, height);
685
686                       /* Mark that we should clear the border.  This is
687                          necessary because italic fonts may leave
688                          droppings in the border. */
689                       clear_border = 1;
690                     }
691                 }
692
693               start_pixpos = min (next_start_pixpos, block_end);
694             }
695         }
696       else
697         {
698           struct display_block *cdb, *ddb;
699           int block_end;
700           int old_block;
701
702           if (cdba)
703             old_block = get_next_display_block (ddl->bounds, cdba,
704                                                 start_pixpos, &block_end);
705           else
706             old_block = NO_BLOCK;
707
708           ddb = Dynarr_atp (ddba, block);
709           cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0);
710
711           /* If there was formerly no block over the current
712              region or if it was a block of a different type, then
713              output the entire ddb.  Otherwise, compare cdb and
714              ddb and output only the changed region. */
715           if (!force && cdb && ddb->type == cdb->type
716               /* If there was no buffer being display before the
717                  compare anyway as we might be outputting a gutter. */
718               &&
719               (b == old_b || !old_b))
720             {
721               must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
722                                                    block, start_pixpos,
723                                                    cursor_start, cursor_width,
724                                                    cursor_height);
725             }
726           else
727             {
728               int elt;
729               int first_elt = 0;
730               int last_elt = -1;
731
732               for (elt = 0; elt < Dynarr_length (ddb->runes); elt++)
733                 {
734                   struct rune *rb = Dynarr_atp (ddb->runes, elt);
735
736                   if (start_pixpos >= rb->xpos
737                       && start_pixpos < rb->xpos + rb->width)
738                     first_elt = elt;
739
740                   if (end_pixpos > rb->xpos
741                       && end_pixpos <= rb->xpos + rb->width)
742                     {
743                       last_elt = elt + 1;
744                       if (last_elt > Dynarr_length (ddb->runes))
745                         last_elt = Dynarr_length (ddb->runes);
746                       break;
747                     }
748                 }
749
750               must_sync = 1;
751               redisplay_output_display_block (w, ddl, block, first_elt,
752                                               last_elt,
753                                               start_pixpos,
754                                               cursor_start, cursor_width,
755                                               cursor_height);
756             }
757
758           start_pixpos = next_start_pixpos;
759         }
760     }
761
762   /* Clear the internal border if we are next to it and the window
763      structure or frame size has changed or if something caused
764      clear_border to be tripped.  */
765   /* #### Doing this on f->clear sucks but is necessary because of
766      window-local background values. */
767   if (f->windows_structure_changed || f->faces_changed || clear_border
768       || f->clear)
769     {
770       int y = DISPLAY_LINE_YPOS (ddl);
771       int height = DISPLAY_LINE_HEIGHT (ddl);
772
773       /* If we are in the gutter then we musn't clear the borders. */
774       if (y >= WINDOW_TEXT_TOP (w) && (y + height) <= WINDOW_TEXT_BOTTOM (w))
775         {
776           if (ddl->modeline)
777             {
778               y -= MODELINE_SHADOW_THICKNESS (w);
779               height += (2 * MODELINE_SHADOW_THICKNESS (w));
780             }
781
782           if (window_is_leftmost (w))
783             clear_left_border (w, y, height);
784           if (window_is_rightmost (w))
785             clear_right_border (w, y, height);
786         }
787     }
788
789   if (cdla)
790     sync_display_line_structs (w, line, must_sync, cdla, ddla);
791 }
792
793 /*****************************************************************************
794  redisplay_move_cursor
795
796  For the given window W, move the cursor to NEW_POINT.  Returns a
797  boolean indicating success or failure.
798  ****************************************************************************/
799
800 #define ADJ_BUFPOS (rb->bufpos + dl->offset)
801 #define ADJ_ENDPOS (rb->endpos + dl->offset)
802
803 int
804 redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
805 {
806   struct frame *f = XFRAME (w->frame);
807   struct device *d = XDEVICE (f->device);
808
809   display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
810   struct display_line *dl;
811   struct display_block *db;
812   struct rune *rb;
813   int x = w->last_point_x[CURRENT_DISP];
814   int y = w->last_point_y[CURRENT_DISP];
815
816   /*
817    * Bail if cursor_in_echo_area is non-zero and we're fiddling with
818    * the cursor in a non-active minibuffer window, since that is a
819    * special case that is handled elsewhere and this function need
820    * not handle it.  Return 1 so the caller will assume we
821    * succeeded.
822    */
823   if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
824       w != XWINDOW (FRAME_SELECTED_WINDOW (f)))
825     return 1;
826
827   if (y < 0 || y >= Dynarr_length (cla))
828     return 0;
829
830   dl = Dynarr_atp (cla, y);
831   db = get_display_block_from_line (dl, TEXT);
832
833   if (x < 0 || x >= Dynarr_length (db->runes))
834     return 0;
835
836   rb = Dynarr_atp (db->runes, x);
837
838   if (rb->cursor_type == CURSOR_OFF)
839     return 0;
840   else if (ADJ_BUFPOS == new_point
841            || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
842                && (new_point <= ADJ_ENDPOS)))
843     {
844       w->last_point_x[CURRENT_DISP] = x;
845       w->last_point_y[CURRENT_DISP] = y;
846       Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_BUFPOS),
847                    w->buffer);
848       dl->cursor_elt = x;
849       return 1;
850     }
851   else
852     {
853       DEVMETH (d, output_begin, (d));
854
855       /* #### This is a gross kludge.  Cursor handling is such a royal
856          pain in the ass. */
857       if (rb->type == RUNE_DGLYPH &&
858           (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) ||
859            EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)))
860         rb->cursor_type = NO_CURSOR;
861       else
862         rb->cursor_type = CURSOR_OFF;
863       dl->cursor_elt = -1;
864       output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
865     }
866
867   w->last_point_x[CURRENT_DISP] = -1;
868   w->last_point_y[CURRENT_DISP] = -1;
869   Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer);
870
871   /* If this isn't the selected frame, then erasing the old cursor is
872      all we actually had to do. */
873   if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
874     {
875       if (!no_output_end)
876         DEVMETH (d, output_end, (d));
877
878       return 1;
879     }
880
881   /* This should only occur in the minibuffer. */
882   if (new_point == 0)
883     {
884       w->last_point_x[CURRENT_DISP] = 0;
885       w->last_point_y[CURRENT_DISP] = y;
886       Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer);
887
888       rb = Dynarr_atp (db->runes, 0);
889       rb->cursor_type = CURSOR_ON;
890       dl->cursor_elt = 0;
891
892       output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
893
894       if (!no_output_end)
895         DEVMETH (d, output_end, (d));
896       return 1;
897     }
898   else
899     {
900       int cur_rb = 0;
901       int first = 0;
902       int cur_dl, up;
903
904       if (ADJ_BUFPOS < new_point)
905         {
906           up = 1;
907           cur_rb = x + 1;
908           cur_dl = y;
909         }
910       else /* (rb->bufpos + dl->offset) > new_point */
911         {
912           up = 0;
913
914           if (!x)
915             {
916               cur_dl = y - 1;
917               first = 0;
918             }
919           else
920             {
921               cur_rb = x - 1;
922               cur_dl = y;
923               first = 1;
924             }
925         }
926
927       while (up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0))
928         {
929           dl = Dynarr_atp (cla, cur_dl);
930           db = get_display_block_from_line (dl, TEXT);
931
932           if (!up && !first)
933             cur_rb = Dynarr_length (db->runes) - 1;
934
935           while ((!scroll_on_clipped_lines || !dl->clip) &&
936                  (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0)))
937             {
938               rb = Dynarr_atp (db->runes, cur_rb);
939
940               if (rb->cursor_type != IGNORE_CURSOR
941                   && rb->cursor_type != NO_CURSOR &&
942                   (ADJ_BUFPOS == new_point
943                    || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
944                        && (new_point <= ADJ_BUFPOS))))
945                 {
946                   rb->cursor_type = CURSOR_ON;
947                   dl->cursor_elt = cur_rb;
948
949
950                   output_display_line (w, 0, cla, cur_dl, rb->xpos,
951                                        rb->xpos + rb->width);
952
953                   w->last_point_x[CURRENT_DISP] = cur_rb;
954                   w->last_point_y[CURRENT_DISP] = cur_dl;
955                   Fset_marker (w->last_point[CURRENT_DISP],
956                                make_int (ADJ_BUFPOS), w->buffer);
957
958                   if (!no_output_end)
959                     DEVMETH (d, output_end, (d));
960                   return 1;
961                 }
962
963               (up ? cur_rb++ : cur_rb--);
964             }
965
966           (up ? (cur_rb = 0) : (first = 0));
967           (up ? cur_dl++ : cur_dl--);
968         }
969     }
970
971   if (!no_output_end)
972     DEVMETH (d, output_end, (d));
973   return 0;
974 }
975 #undef ADJ_BUFPOS
976 #undef ADJ_ENDPOS
977
978 /*****************************************************************************
979  redraw_cursor_in_window
980
981  For the given window W, redraw the cursor if it is contained within
982  the window.
983  ****************************************************************************/
984 static void
985 redraw_cursor_in_window (struct window *w, int run_end_begin_meths)
986 {
987   struct frame *f = XFRAME (w->frame);
988   struct device *d = XDEVICE (f->device);
989
990   display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
991   struct display_line *dl;
992   struct display_block *db;
993   struct rune *rb;
994
995   int x = w->last_point_x[CURRENT_DISP];
996   int y = w->last_point_y[CURRENT_DISP];
997
998   if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
999       !echo_area_active (f) && minibuf_level == 0)
1000     {
1001       MAYBE_DEVMETH (d, set_final_cursor_coords, (f, w->pixel_top, 0));
1002     }
1003
1004   if (y < 0 || y >= Dynarr_length (dla))
1005     return;
1006
1007   if (MINI_WINDOW_P (w) && f != device_selected_frame (d) &&
1008       !is_surrogate_for_selected_frame (f))
1009     return;
1010
1011   dl = Dynarr_atp (dla, y);
1012   db = get_display_block_from_line (dl, TEXT);
1013
1014   if (x < 0 || x >= Dynarr_length (db->runes))
1015     return;
1016
1017   rb = Dynarr_atp (db->runes, x);
1018
1019   /* Don't call the output routine if the block isn't actually the
1020      cursor. */
1021   if (rb->cursor_type == CURSOR_ON)
1022     {
1023       MAYBE_DEVMETH (d, set_final_cursor_coords,
1024                      (f, dl->ypos - 1, rb->xpos));
1025
1026       if (run_end_begin_meths)
1027         DEVMETH (d, output_begin, (d));
1028
1029       output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
1030
1031       if (run_end_begin_meths)
1032         DEVMETH (d, output_end, (d));
1033     }
1034 }
1035
1036 /*****************************************************************************
1037  redisplay_redraw_cursor
1038
1039  For the given frame F, redraw the cursor on the selected window.
1040  This is used to update the cursor after focus changes.
1041  ****************************************************************************/
1042 void
1043 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths)
1044 {
1045   Lisp_Object window;
1046
1047   if (!cursor_in_echo_area)
1048     window = FRAME_SELECTED_WINDOW (f);
1049   else if (FRAME_HAS_MINIBUF_P (f))
1050     window = FRAME_MINIBUF_WINDOW (f);
1051   else
1052     return;
1053
1054   redraw_cursor_in_window (XWINDOW (window), run_end_begin_meths);
1055 }
1056
1057 /****************************************************************************
1058  redisplay_output_display_block
1059
1060  Given a display line, a block number for that start line, output all
1061  runes between start and end in the specified display block.
1062  ****************************************************************************/
1063 static void
1064 redisplay_output_display_block (struct window *w, struct display_line *dl, int block,
1065                                 int start, int end, int start_pixpos, int cursor_start,
1066                                 int cursor_width, int cursor_height)
1067 {
1068   struct frame *f = XFRAME (w->frame);
1069   struct device *d = XDEVICE (f->device);
1070   struct display_block *db = Dynarr_atp (dl->display_blocks, block);
1071   rune_dynarr *rba = db->runes;
1072   struct rune *rb;
1073   int xpos, width;
1074   rb = Dynarr_atp (rba, start);
1075
1076   if (!rb)
1077       /* Nothing to do so don't do anything. */
1078       return;
1079
1080   xpos = max (start_pixpos, rb->xpos);
1081
1082   if (end < 0)
1083     end = Dynarr_length (rba);
1084
1085   rb  = Dynarr_atp (rba, end - 1);
1086   width = rb->xpos + rb->width - xpos;
1087   /* now actually output the block. */
1088   DEVMETH (d, output_display_block, (w, dl, block, start,
1089                                      end, start_pixpos,
1090                                      cursor_start, cursor_width,
1091                                      cursor_height));
1092 }
1093
1094 /****************************************************************************
1095  redisplay_unmap_subwindows
1096
1097  Remove subwindows from the area in the box defined by the given
1098  parameters.
1099  ****************************************************************************/
1100 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height,
1101                                         Lisp_Object ignored_window)
1102 {
1103   int elt;
1104
1105   for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
1106     {
1107       struct subwindow_cachel *cachel =
1108         Dynarr_atp (f->subwindow_cachels, elt);
1109
1110       if (cachel->being_displayed
1111           &&
1112           cachel->x + cachel->width > x && cachel->x < x + width
1113           &&
1114           cachel->y + cachel->height > y && cachel->y < y + height
1115           &&
1116           !EQ (cachel->subwindow, ignored_window))
1117         {
1118           unmap_subwindow (cachel->subwindow);
1119         }
1120     }
1121 }
1122
1123 /****************************************************************************
1124  redisplay_unmap_subwindows_maybe
1125
1126  Potentially subwindows from the area in the box defined by the given
1127  parameters.
1128  ****************************************************************************/
1129 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1130 {
1131   if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1132     {
1133       redisplay_unmap_subwindows (f, x, y, width, height, Qnil);
1134     }
1135 }
1136
1137 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
1138                                                   int height, Lisp_Object subwindow)
1139 {
1140   if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1141     {
1142       redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
1143     }
1144 }
1145
1146 /****************************************************************************
1147  redisplay_output_subwindow
1148
1149  output a subwindow.  This code borrows heavily from the pixmap stuff,
1150  although is much simpler not needing to account for partial
1151  pixmaps, backgrounds etc.
1152  ****************************************************************************/
1153 void
1154 redisplay_output_subwindow (struct window *w,
1155                             Lisp_Object image_instance,
1156                             struct display_box* db, struct display_glyph_area* dga,
1157                             face_index findex, int cursor_start, int cursor_width,
1158                             int cursor_height)
1159 {
1160   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1161   Lisp_Object window;
1162   struct display_glyph_area sdga;
1163
1164   dga->height = IMAGE_INSTANCE_HEIGHT (p);
1165   dga->width = IMAGE_INSTANCE_WIDTH (p);
1166
1167   /* The first thing we are going to do is update the display
1168      characteristics of the subwindow. This also clears the dirty
1169      flags as a side effect. */
1170   update_subwindow (image_instance);
1171
1172   /* This makes the glyph area fit into the display area. */
1173   if (!redisplay_normalize_glyph_area (db, dga))
1174     return;
1175
1176   XSETWINDOW (window, w);
1177
1178   /* Clear the area the subwindow is going into. */
1179   redisplay_clear_clipped_region (window, findex,
1180                                   db, dga, 0, image_instance);
1181
1182   /* This shrinks the display box to exactly enclose the glyph
1183      area. */
1184   redisplay_normalize_display_box (db, dga);
1185
1186   /* if we can't view the whole window we can't view any of it. We
1187      have to be careful here since we may be being asked to display
1188      part of a subwindow, the rest of which is on-screen as well. We
1189      need to allow this case and map the entire subwindow. We also
1190      need to be careful since the subwindow could be outside the
1191      window in the gutter or modeline - we also need to allow these
1192      cases.*/
1193   sdga.xoffset = -dga->xoffset;
1194   sdga.yoffset = -dga->yoffset;
1195   sdga.height = IMAGE_INSTANCE_HEIGHT (p);
1196   sdga.width = IMAGE_INSTANCE_WIDTH (p);
1197
1198   if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0)
1199     {
1200       map_subwindow (image_instance, db->xpos, db->ypos, dga);
1201     }
1202   else
1203     {
1204       sdga.xoffset = sdga.yoffset = 0;
1205       map_subwindow (image_instance, db->xpos - dga->xoffset,
1206                      db->ypos - dga->yoffset, &sdga);
1207     }
1208 }
1209
1210 /****************************************************************************
1211  redisplay_output_layout
1212
1213  Output a widget hierarchy. This can safely call itself recursively.
1214
1215  The complexity of outputting layouts is deciding whether to do it or
1216  not. Consider a layout enclosing some text, the text changes and is
1217  marked as dirty, but the enclosing layout has not been marked as
1218  dirty so no updates occur and the text will potentially be truncated.
1219  Alternatively we hold a back pointer in the image instance to the
1220  parent and mark the parent as dirty. But the layout code assumes that
1221  if the layout is dirty then the whole layout should be redisplayed,
1222  so we then get lots of flashing even though only the text has changed
1223  size. Of course if the text shrinks in size then we do actually need
1224  to redisplay the layout to repaint the exposed area. So what happens
1225  if we make a non-structural change like changing color? Either we
1226  redisplay everything, or we redisplay nothing. These are exactly the
1227  issues lwlib has to grapple with. We really need to know what has
1228  actually changed and make a layout decision based on that. We also
1229  really need to know what has changed so that we can only make the
1230  neccessary changes in update_subwindow.  This has all now been
1231  implemented, Viva la revolution!
1232  ****************************************************************************/
1233 void
1234 redisplay_output_layout (struct window *w,
1235                          Lisp_Object image_instance,
1236                          struct display_box* db, struct display_glyph_area* dga,
1237                          face_index findex, int cursor_start, int cursor_width,
1238                          int cursor_height)
1239 {
1240   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1241   Lisp_Object window, rest;
1242   Emchar_dynarr *buf = Dynarr_new (Emchar);
1243   struct frame *f = XFRAME (w->frame);
1244   struct device *d = XDEVICE (f->device);
1245   int layout_height, layout_width;
1246   /* We bogusly don't take f->extents_changed and f->glyphs_changed
1247      into account. This is because if we do we always redisplay the
1248      entire layout. So far I have seen no ill effects so we'll see. */
1249   int frame_really_changed = (f->buffers_changed ||
1250                               f->clip_changed ||
1251                               f->faces_changed    ||
1252                               f->frame_changed    ||
1253                               f->modeline_changed ||
1254                               f->subwindows_changed ||
1255                               f->windows_changed ||
1256                               f->windows_structure_changed);
1257
1258   XSETWINDOW (window, w);
1259
1260   layout_height = glyph_height (image_instance, window);
1261   layout_width = glyph_width (image_instance, window);
1262
1263   dga->height = layout_height;
1264   dga->width = layout_width;
1265
1266   /* This makes the glyph area fit into the display area. */
1267   if (!redisplay_normalize_glyph_area (db, dga))
1268     return;
1269
1270   /* Highly dodgy optimization. We want to only output the whole
1271      layout if we really have to. */
1272   if (frame_really_changed 
1273       || IMAGE_INSTANCE_LAYOUT_CHANGED (p)
1274       || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
1275       || IMAGE_INSTANCE_SIZE_CHANGED (p)
1276       || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
1277     {
1278       /* First clear the area we are drawing into. This is the easiest
1279          thing to do since we have many gaps that we have to make sure are
1280          filled in. */
1281       redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil);
1282
1283       /* Output a border if required */
1284       if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1285         {
1286           int edges = 0;
1287           enum edge_style style;
1288           int ypos = db->ypos;
1289           int height = dga->height;
1290
1291           if (dga->xoffset >= 0)
1292             edges |= EDGE_LEFT;
1293           if (dga->width - dga->xoffset == layout_width)
1294             edges |= EDGE_RIGHT;
1295           if (dga->yoffset >= 0)
1296             edges |= EDGE_TOP;
1297           if (dga->height - dga->yoffset == layout_height)
1298             edges |= EDGE_BOTTOM;
1299
1300           if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
1301             style = EDGE_ETCHED_IN;
1302           else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
1303             style = EDGE_ETCHED_OUT;
1304           else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in))
1305             style = EDGE_BEVEL_IN;
1306           else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1307             {
1308               style = EDGE_ETCHED_IN;
1309               if (edges & EDGE_TOP)
1310                 {
1311                   ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1312                   height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1313                 }
1314             }
1315           else
1316             style = EDGE_BEVEL_OUT;
1317
1318           MAYBE_DEVMETH (d, bevel_area,
1319                          (w, findex, db->xpos,
1320                           ypos,
1321                           dga->width, height, 2, edges, style));
1322         }
1323     }
1324
1325   /* This shrinks the display box to exactly enclose the glyph
1326      area. */
1327   redisplay_normalize_display_box (db, dga);
1328
1329   /* Flip through the widgets in the layout displaying as necessary */
1330   LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
1331     {
1332       Lisp_Object child = XCAR (rest);
1333
1334       struct display_box cdb;
1335       /* For losing HP-UX */
1336       cdb.xpos = db->xpos;
1337       cdb.ypos = db->ypos;
1338       cdb.width = db->width;
1339       cdb.height = db->height;
1340
1341       /* First determine if the image is visible at all */
1342       if (IMAGE_INSTANCEP (child))
1343         {
1344           Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
1345           /* The enclosing layout offsets are +ve at this point */
1346           struct display_glyph_area cdga;
1347           cdga.xoffset  = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
1348           cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
1349           cdga.width = glyph_width (child, window);
1350           cdga.height = glyph_height (child, window);
1351
1352           /* Although normalization is done by the output routines
1353              we have to do it here so that they don't try and
1354              clear all of db. This is true below also. */
1355           if (redisplay_normalize_glyph_area (&cdb, &cdga))
1356             {
1357               redisplay_normalize_display_box (&cdb, &cdga);
1358               /* Since the display boxes will now be totally in the
1359                  window if they are visible at all we can now check this easily. */
1360               if (cdb.xpos < db->xpos || cdb.ypos < db->ypos
1361                   || cdb.xpos + cdb.width > db->xpos + db->width
1362                   || cdb.ypos + cdb.height > db->ypos + db->height)
1363                 continue;
1364               /* We have to invert the offset here as normalization
1365                  will have made them positive which the output
1366                  routines will treat as a truely +ve offset. */
1367               cdga.xoffset = -cdga.xoffset;
1368               cdga.yoffset = -cdga.yoffset;
1369
1370               switch (IMAGE_INSTANCE_TYPE (childii))
1371                 {
1372                 case IMAGE_TEXT:
1373                   {
1374                     /* #### This is well hacked and could use some
1375                        generalisation.*/
1376                     if (redisplay_normalize_glyph_area (&cdb, &cdga)
1377                         &&
1378                         (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii)))
1379                       {
1380                         struct display_line dl; /* this is fake */
1381                         Lisp_Object string =
1382                           IMAGE_INSTANCE_TEXT_STRING (childii);
1383                         convert_bufbyte_string_into_emchar_dynarr
1384                           (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1385
1386                         redisplay_normalize_display_box (&cdb, &cdga);
1387                         /* Offsets are now +ve again so be careful
1388                            when fixing up the display line. */
1389                         xzero (dl);
1390                         /* Munge boxes into display lines. */
1391                         dl.ypos = (cdb.ypos - cdga.yoffset)
1392                           + glyph_ascent (child, window);
1393                         dl.ascent = glyph_ascent (child, window);
1394                         dl.descent = glyph_descent (child, window);
1395                         dl.top_clip = cdga.yoffset;
1396                         dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1397                         /* output_string doesn't understand offsets in
1398                            the same way as other routines - we have to
1399                            add the offset to the width so that we
1400                            output the full string. */
1401                         MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1402                                                           cdga.xoffset, cdb.xpos,
1403                                                           cdga.width + cdga.xoffset,
1404                                                           findex, 0, 0, 0, 0));
1405                         Dynarr_reset (buf);
1406                       }
1407                   }
1408                   break;
1409
1410                 case IMAGE_MONO_PIXMAP:
1411                 case IMAGE_COLOR_PIXMAP:
1412                   if (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii))
1413                     redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1414                                              0, 0, 0, 0);
1415                   break;
1416
1417                 case IMAGE_WIDGET:
1418                 case IMAGE_SUBWINDOW:
1419                   if (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii))
1420                     redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1421                                                 0, 0, 0);
1422                   break;
1423
1424                 case IMAGE_LAYOUT:
1425                   redisplay_output_layout (w, child, &cdb, &cdga, findex,
1426                                            0, 0, 0);
1427                   break;
1428
1429                 case IMAGE_NOTHING:
1430                   /* nothing is as nothing does */
1431                   break;
1432
1433                 case IMAGE_POINTER:
1434                 default:
1435                   abort ();
1436                 }
1437             }
1438         }
1439     }
1440   
1441   /* Update any display properties. I'm not sure whether this actually
1442      does anything for layouts except clear the changed flags. */
1443   update_subwindow (image_instance);
1444
1445   Dynarr_free (buf);
1446 }
1447
1448 /****************************************************************************
1449  redisplay_output_pixmap
1450
1451
1452  output a pixmap.
1453  ****************************************************************************/
1454 void
1455 redisplay_output_pixmap (struct window *w,
1456                          Lisp_Object image_instance,
1457                          struct display_box* db, struct display_glyph_area* dga,
1458                          face_index findex, int cursor_start, int cursor_width,
1459                          int cursor_height, int offset_bitmap)
1460 {
1461   struct frame *f = XFRAME (w->frame);
1462   struct device *d = XDEVICE (f->device);
1463   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1464   Lisp_Object window;
1465   XSETWINDOW (window, w);
1466
1467   dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1468   dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1469
1470   /* This makes the glyph area fit into the display area. */
1471   if (!redisplay_normalize_glyph_area (db, dga))
1472     return;
1473
1474   /* Clear the area the pixmap is going into.  The pixmap itself will
1475      always take care of the full width.  We don't want to clear where
1476      it is going to go in order to avoid flicker.  So, all we have to
1477      take care of is any area above or below the pixmap. If the pixmap
1478      has a mask in which case we have to clear the whole damn thing
1479      since we can't yet clear just the area not included in the
1480      mask. */
1481   if (!offset_bitmap)
1482     {
1483       redisplay_clear_clipped_region (window, findex,
1484                                       db, dga,
1485                                       (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
1486                                       Qnil);
1487
1488       /* This shrinks the display box to exactly enclose the glyph
1489          area. */
1490       redisplay_normalize_display_box (db, dga);
1491     }
1492   assert (db->xpos >= 0 && db->ypos >= 0);
1493
1494   MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1495                                     db, dga,
1496                                     findex, cursor_start,
1497                                     cursor_width, cursor_height,
1498                                     offset_bitmap));
1499 }
1500
1501 /****************************************************************************
1502  redisplay_clear_region
1503
1504  Clear the area in the box defined by the given parameters using the
1505  given face. This has been generalised so that subwindows can be
1506  coped with effectively.
1507  ****************************************************************************/
1508 void
1509 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1510                         int width, int height)
1511 {
1512   struct window *w = NULL;
1513   struct frame *f = NULL;
1514   struct device *d;
1515   Lisp_Object background_pixmap = Qunbound;
1516   Lisp_Object fcolor = Qnil, bcolor = Qnil;
1517
1518   if (!width || !height)
1519      return;
1520
1521   if (WINDOWP (locale))
1522     {
1523       w = XWINDOW (locale);
1524       f = XFRAME (w->frame);
1525     }
1526   else if (FRAMEP (locale))
1527     {
1528       w = NULL;
1529       f = XFRAME (locale);
1530     }
1531   else
1532     abort ();
1533
1534   d = XDEVICE (f->device);
1535
1536   /* if we have subwindows in the region we have to unmap them */
1537   redisplay_unmap_subwindows_maybe (f, x, y, width, height);
1538
1539   /* #### This isn't quite right for when this function is called
1540      from the toolbar code. */
1541
1542   /* Don't use a backing pixmap in the border area */
1543   if (x >= FRAME_LEFT_BORDER_END (f)
1544       && x < FRAME_RIGHT_BORDER_START (f)
1545       && y >= FRAME_TOP_BORDER_END (f)
1546       && y < FRAME_BOTTOM_BORDER_START (f))
1547     {
1548       Lisp_Object temp;
1549
1550       if (w)
1551         {
1552           temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1553
1554           if (IMAGE_INSTANCEP (temp)
1555               && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1556             {
1557               /* #### maybe we could implement such that a string
1558                  can be a background pixmap? */
1559               background_pixmap = temp;
1560             }
1561         }
1562       else
1563         {
1564           temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1565
1566           if (IMAGE_INSTANCEP (temp)
1567               && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1568             {
1569               background_pixmap = temp;
1570             }
1571         }
1572     }
1573
1574   if (!UNBOUNDP (background_pixmap) &&
1575       XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1576     {
1577       if (w)
1578         {
1579           fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1580           bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1581         }
1582       else
1583         {
1584           fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1585           bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1586         }
1587     }
1588   else
1589     {
1590       fcolor = (w ?
1591                 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1592                 FACE_BACKGROUND (Vdefault_face, locale));
1593
1594     }
1595
1596   if (UNBOUNDP (background_pixmap))
1597     background_pixmap = Qnil;
1598
1599   DEVMETH (d, clear_region,
1600            (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1601 }
1602
1603 /****************************************************************************
1604  redisplay_clear_clipped_region
1605
1606  Clear the area in the dest display_box not covered by the src
1607  display_glyph_area using the given face. This is a common occurance
1608  for images shorter than the display line. Clipping can be played
1609  around with by altering these. glyphsrc should be normalized.
1610  ****************************************************************************/
1611 static void
1612 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1613         struct display_box* dest, struct display_glyph_area* glyphsrc,
1614         int fullheight_p, Lisp_Object ignored_subwindow)
1615 {
1616   /* assume dest->xpos >= 0 */
1617   int clear_x;
1618   struct frame* f = XFRAME (XWINDOW (window)->frame);
1619
1620   if (glyphsrc->xoffset > 0)
1621     {
1622       clear_x = dest->xpos + glyphsrc->xoffset;
1623     }
1624   else
1625     {
1626       clear_x = dest->xpos;
1627     }
1628
1629   /* If we need the whole height cleared then just do it. */
1630   if (fullheight_p)
1631     {
1632       redisplay_clear_region (window, findex, clear_x, dest->ypos,
1633                               glyphsrc->width, dest->height);
1634     }
1635   else
1636     {
1637       int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1638
1639       /* We need to make sure that subwindows are unmapped from the
1640          whole area. */
1641       redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1642                                             glyphsrc->width, dest->height,
1643                                             ignored_subwindow);
1644       /* first the top box */
1645       if (yoffset > 0)
1646         {
1647           redisplay_clear_region (window, findex, clear_x, dest->ypos,
1648                                   glyphsrc->width, yoffset);
1649
1650         }
1651       /* Then the bottom box */
1652       if (yoffset + glyphsrc->height < dest->height)
1653         {
1654           redisplay_clear_region (window, findex, clear_x,
1655                                   dest->ypos + yoffset + glyphsrc->height,
1656                                   glyphsrc->width,
1657                                   dest->height - (yoffset + glyphsrc->height));
1658
1659         }
1660     }
1661 }
1662
1663 /*****************************************************************************
1664  redisplay_normalize_glyph_area
1665  redisplay_normalize_display_box
1666
1667  Calculate the visible box for displaying src in dest.
1668  ****************************************************************************/
1669 int
1670 redisplay_normalize_glyph_area (struct display_box* dest,
1671                                 struct display_glyph_area* glyphsrc)
1672 {
1673   if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1674       ||
1675       dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1676       ||
1677       -glyphsrc->xoffset >= glyphsrc->width
1678       ||
1679       -glyphsrc->yoffset >= glyphsrc->height)
1680     {
1681       /* It's all clipped out */
1682       return 0;
1683     }
1684
1685   /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1686   if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1687     {
1688       if (glyphsrc->xoffset > 0)
1689         glyphsrc->width = dest->width - glyphsrc->xoffset;
1690       else
1691         glyphsrc->width = dest->width;
1692     }
1693
1694   if (glyphsrc->xoffset < 0)
1695     glyphsrc->width += glyphsrc->xoffset;
1696
1697   /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1698   if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1699     {
1700       if (glyphsrc->yoffset > 0)
1701         glyphsrc->height = dest->height - glyphsrc->yoffset;
1702       else
1703         glyphsrc->height = dest->height;
1704     }
1705
1706   if (glyphsrc->yoffset < 0)
1707     glyphsrc->height += glyphsrc->yoffset;
1708
1709   return 1;
1710 }
1711
1712 static void
1713 redisplay_normalize_display_box (struct display_box* dest,
1714                                  struct display_glyph_area* glyphsrc)
1715 {
1716   /* Adjust the destination area. At the end of this the destination
1717    area will exactly enclose the glyph area. The only remaining
1718    adjustment will be offsets into the glyph area. */
1719
1720   /* Horizontal adjustment. */
1721   if (glyphsrc->xoffset > 0)
1722     {
1723       dest->xpos += glyphsrc->xoffset;
1724       dest->width -= glyphsrc->xoffset;
1725       glyphsrc->xoffset = 0;
1726     }
1727   else
1728     glyphsrc->xoffset = -glyphsrc->xoffset;
1729
1730   if (glyphsrc->width < dest->width)
1731     dest->width = glyphsrc->width;
1732
1733   /* Vertical adjustment. */
1734   if (glyphsrc->yoffset > 0)
1735     {
1736       dest->ypos += glyphsrc->yoffset;
1737       dest->height -= glyphsrc->yoffset;
1738       glyphsrc->yoffset = 0;
1739     }
1740   else
1741     glyphsrc->yoffset = -glyphsrc->yoffset;
1742
1743   if (glyphsrc->height < dest->height)
1744     dest->height = glyphsrc->height;
1745 }
1746
1747 /*****************************************************************************
1748  redisplay_display_boxes_in_window_p
1749
1750  Determine whether the require display_glyph_area is completely inside
1751  the window. 0 means the display_box is not in the window. 1 means the
1752  display_box and the display_glyph_area are in the window. -1 means
1753  the display_box is in the window but the display_glyph_area is not.
1754  ****************************************************************************/
1755 static int
1756 redisplay_display_boxes_in_window_p (struct window* w,
1757                                      struct display_box* db,
1758                                      struct display_glyph_area* dga)
1759 {
1760   int left = WINDOW_TEXT_LEFT (w);
1761   int right = WINDOW_TEXT_RIGHT (w);
1762   int top = WINDOW_TEXT_TOP (w);
1763   int bottom = WINDOW_TEXT_BOTTOM (w);
1764
1765   if (db->xpos < left || db->ypos < top
1766       || db->xpos + db->width > right
1767       || db->ypos + db->height > bottom)
1768     /* We are not displaying in a window at all */
1769     return 0;
1770
1771   if (db->xpos + dga->xoffset >= left
1772       &&
1773       db->ypos + dga->yoffset >= top
1774       &&
1775       db->xpos + dga->xoffset + dga->width <= right
1776       &&
1777       db->ypos + dga->yoffset + dga->height <= bottom)
1778     return 1;
1779
1780   return -1;
1781 }
1782
1783 /*****************************************************************************
1784  redisplay_calculate_display_boxes
1785
1786  Convert from rune/display_line co-ordinates to display_box
1787  co-ordinates.
1788  ****************************************************************************/
1789 int
1790 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1791                                    int xoffset, int start_pixpos, int width,
1792                                    struct display_box* dest,
1793                                    struct display_glyph_area* src)
1794 {
1795   dest->xpos = xpos;
1796   dest->ypos = DISPLAY_LINE_YPOS (dl);
1797   dest->width = width;
1798   dest->height = DISPLAY_LINE_HEIGHT (dl);
1799
1800   src->xoffset = -xoffset;
1801   src->yoffset = -dl->top_clip;
1802   src->width = 0;
1803   src->height = 0;
1804
1805   if (start_pixpos >=0 && start_pixpos > xpos)
1806     {
1807       /* Oops, we're asking for a start outside of the displayable
1808          area. */
1809       if (start_pixpos > xpos + width)
1810         return 0;
1811       dest->xpos = start_pixpos;
1812       dest->width -= (start_pixpos - xpos);
1813       /* Offsets are -ve when we want to clip pixels off the displayed
1814          glyph. */
1815       src->xoffset -= (start_pixpos - xpos);
1816     }
1817
1818   return 1;
1819 }
1820
1821 /*****************************************************************************
1822  redisplay_clear_top_of_window
1823
1824  If window is topmost, clear the internal border above it.
1825  ****************************************************************************/
1826 static void
1827 redisplay_clear_top_of_window (struct window *w)
1828 {
1829   Lisp_Object window;
1830   XSETWINDOW (window, w);
1831
1832   if (!NILP (Fwindow_highest_p (window)))
1833     {
1834       struct frame *f = XFRAME (w->frame);
1835       int x, y, width, height;
1836
1837       x = w->pixel_left;
1838       width = w->pixel_width;
1839
1840       if (window_is_leftmost (w))
1841         {
1842           x -= FRAME_BORDER_WIDTH (f);
1843           width += FRAME_BORDER_WIDTH (f);
1844         }
1845       if (window_is_rightmost (w))
1846         width += FRAME_BORDER_WIDTH (f);
1847
1848       y = FRAME_TOP_BORDER_START (f) - 1;
1849       height = FRAME_BORDER_HEIGHT (f) + 1;
1850
1851       redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1852     }
1853 }
1854
1855 /*****************************************************************************
1856  redisplay_clear_to_window_end
1857
1858  Clear the area between ypos1 and ypos2.  Each margin area and the
1859  text area is handled separately since they may each have their own
1860  background color.
1861  ****************************************************************************/
1862 void
1863 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1864 {
1865   struct frame *f = XFRAME (w->frame);
1866   struct device *d = XDEVICE (f->device);
1867
1868   if (HAS_DEVMETH_P (d, clear_to_window_end))
1869     DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1870   else
1871     {
1872       int height = ypos2 - ypos1;
1873
1874       if (height)
1875         {
1876           Lisp_Object window;
1877           int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1878           layout_bounds bounds;
1879
1880           bounds = calculate_display_line_boundaries (w, bflag);
1881           XSETWINDOW (window, w);
1882
1883           if (window_is_leftmost (w))
1884             redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1885                                     ypos1, FRAME_BORDER_WIDTH (f), height);
1886
1887           if (bounds.left_in - bounds.left_out > 0)
1888             redisplay_clear_region (window,
1889                                     get_builtin_face_cache_index (w, Vleft_margin_face),
1890                                     bounds.left_out, ypos1,
1891                                     bounds.left_in - bounds.left_out, height);
1892
1893           if (bounds.right_in - bounds.left_in > 0)
1894             redisplay_clear_region (window,
1895                                     DEFAULT_INDEX,
1896                                     bounds.left_in, ypos1,
1897                                     bounds.right_in - bounds.left_in, height);
1898
1899           if (bounds.right_out - bounds.right_in > 0)
1900             redisplay_clear_region (window,
1901                                     get_builtin_face_cache_index (w, Vright_margin_face),
1902                                     bounds.right_in, ypos1,
1903                                     bounds.right_out - bounds.right_in, height);
1904
1905           if (window_is_rightmost (w))
1906             redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1907                                     ypos1, FRAME_BORDER_WIDTH (f), height);
1908         }
1909     }
1910 }
1911
1912 /*****************************************************************************
1913  redisplay_clear_bottom_of_window
1914
1915  Clear window from right below the last display line to right above
1916  the modeline.  The calling function can limit the area actually
1917  erased by setting min_start and/or max_end to positive values.
1918  ****************************************************************************/
1919 void
1920 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1921                                   int min_start, int max_end)
1922 {
1923   struct frame *f = XFRAME (w->frame);
1924   int ypos1, ypos2;
1925   int ddla_len = Dynarr_length (ddla);
1926
1927   ypos2 = WINDOW_TEXT_BOTTOM (w);
1928 #ifdef HAVE_SCROLLBARS
1929   /* This adjustment is to catch the intersection of any scrollbars. */
1930   if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
1931     ypos2 += window_scrollbar_height (w);
1932 #endif
1933
1934   if (ddla_len)
1935     {
1936       if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
1937         {
1938           ypos1 = WINDOW_TEXT_TOP (w);
1939 #ifdef HAVE_SCROLLBARS
1940           /* This adjustment is to catch the intersection of any scrollbars. */
1941           if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
1942             ypos1 -= window_scrollbar_height (w);
1943 #endif
1944         }
1945       else
1946         {
1947           struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
1948           ypos1 = dl->ypos + dl->descent - dl->clip;
1949         }
1950     }
1951   else
1952     ypos1 = WINDOW_TEXT_TOP (w);
1953
1954   /* #### See if this can be made conditional on the frame
1955      changing size. */
1956   if (MINI_WINDOW_P (w))
1957     ypos2 += FRAME_BORDER_HEIGHT (f);
1958
1959   if (min_start >= 0 && ypos1 < min_start)
1960     ypos1 = min_start;
1961   if (max_end >= 0 && ypos2 > max_end)
1962     ypos2 = max_end;
1963
1964   if (ypos2 <= ypos1)
1965     return;
1966
1967   redisplay_clear_to_window_end (w, ypos1, ypos2);
1968 }
1969
1970 /*****************************************************************************
1971  redisplay_update_line
1972
1973  This is used during incremental updates to update a single line and
1974  correct the offsets on all lines below it.  At the moment
1975  update_values is false if we are only updating the modeline.
1976  ****************************************************************************/
1977 void
1978 redisplay_update_line (struct window *w, int first_line, int last_line,
1979                        int update_values)
1980 {
1981   struct frame *f = XFRAME (w->frame);
1982   struct device *d = XDEVICE (f->device);
1983
1984   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1985   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1986
1987   DEVMETH (d, output_begin, (d));
1988
1989   while (first_line <= last_line)
1990     {
1991       Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
1992                            Dynarr_atp (cdla, first_line)->bufpos);
1993       Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
1994                            Dynarr_atp (ddla, first_line)->bufpos);
1995
1996       assert (Dynarr_length (cdla) == Dynarr_length (ddla));
1997
1998       /* Output the changes. */
1999       output_display_line (w, cdla, ddla, first_line, -1, -1);
2000
2001       /* Update the offsets. */
2002       if (update_values)
2003         {
2004           int cur_line = first_line + 1;
2005           while (cur_line < Dynarr_length (cdla))
2006             {
2007               Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
2008               Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
2009               cur_line++;
2010             }
2011         }
2012
2013       /* Update the window_end_pos and other settings. */
2014       if (update_values)
2015         {
2016           w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
2017
2018           if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
2019             {
2020               w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2021               w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2022             }
2023         }
2024
2025       first_line++;
2026     }
2027
2028   /* Update the window max line length.  We have to scan the entire
2029      set of display lines otherwise we might not detect if the max is
2030      supposed to shrink. */
2031   if (update_values)
2032     {
2033       int line = 0;
2034
2035       w->max_line_len = 0;
2036       while (line < Dynarr_length (ddla))
2037         {
2038           struct display_line *dl = Dynarr_atp (ddla, line);
2039
2040           if (!dl->modeline)
2041             w->max_line_len = max (dl->num_chars, w->max_line_len);
2042
2043           line++;
2044         }
2045     }
2046
2047   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2048   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2049   Fset_marker (w->last_point[CURRENT_DISP],
2050                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2051   Fset_marker (w->last_start[CURRENT_DISP],
2052                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2053
2054   /* We don't bother updating the vertical scrollbars here.  This
2055      gives us a performance increase while having minimal loss of
2056      quality to the scrollbar slider size and position since when this
2057      function is called we know that the changes to the buffer were
2058      very localized.  We have to update the horizontal scrollbars,
2059      though, because this routine could cause a change which has a
2060      larger impact on their sizing. */
2061   /* #### See if we can get away with only calling this if
2062      max_line_len is greater than the window_char_width. */
2063 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
2064   {
2065     extern int stupid_vertical_scrollbar_drag_hack;
2066
2067     update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
2068     stupid_vertical_scrollbar_drag_hack = 1;
2069   }
2070 #endif
2071
2072   /* This has to be done after we've updated the values.  We don't
2073      call output_end for tty frames.  Redisplay will do this after all
2074      tty windows have been updated.  This cuts down on cursor
2075      flicker. */
2076   if (FRAME_TTY_P (f))
2077     redisplay_redraw_cursor (f, 0);
2078   else
2079     DEVMETH (d, output_end, (d));
2080 }
2081
2082 /*****************************************************************************
2083  redisplay_output_window
2084
2085  For the given window W, ensure that the current display lines are
2086  equal to the desired display lines, outputing changes as necessary.
2087
2088  #### Fuck me.  This just isn't going to cut it for tty's.  The output
2089  decisions for them must be based on the contents of the entire frame
2090  because that is how the available output capabilities think.  The
2091  solution is relatively simple.  Create redisplay_output_frame.  This
2092  will basically merge all of the separate window display structs into
2093  a single one for the frame.  This combination structure will be able
2094  to be passed to the same output_display_line which works for windows
2095  on X frames and the right things will happen.  It just takes time to
2096  do.
2097  ****************************************************************************/
2098 void
2099 redisplay_output_window (struct window *w)
2100 {
2101   struct frame *f = XFRAME (w->frame);
2102   struct device *d = XDEVICE (f->device);
2103
2104   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2105   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2106
2107   int cdla_len = Dynarr_length (cdla);
2108   int ddla_len = Dynarr_length (ddla);
2109
2110   int line;
2111   int need_to_clear_bottom = 0;
2112   int need_to_clear_start = -1;
2113   int need_to_clear_end = -1;
2114
2115   /* Backgrounds may have changed or windows may have gone away
2116      leaving dividers lying around. */
2117   if (f->faces_changed
2118       || f->windows_structure_changed
2119       || w->shadow_thickness_changed)
2120     need_to_clear_bottom = 1;
2121
2122   /* The first thing we do is determine if we are going to need to
2123      clear the bottom of the window.  We only need to do this if the
2124      bottom of the current display lines is below the bottom of the
2125      desired display lines.  Note that the number of lines is
2126      irrelevant.  Only the position matters.  We also clear to the
2127      bottom of the window if the modeline has shifted position. */
2128   /* #### We can't blindly not clear the bottom if f->clear is true
2129      since there might be a window-local background.  However, for
2130      those cases where there isn't, clearing the end of the window in
2131      this case sucks. */
2132   if (!need_to_clear_bottom)
2133     {
2134       struct display_line *cdl, *ddl;
2135
2136       /* If the modeline has changed position or size, clear the bottom
2137          of the window. */
2138       if (!need_to_clear_bottom)
2139         {
2140           cdl = ddl = 0;
2141
2142           if (cdla_len)
2143             cdl = Dynarr_atp (cdla, 0);
2144           if (ddla_len)
2145             ddl = Dynarr_atp (ddla, 0);
2146
2147           if (!cdl || !ddl)
2148             need_to_clear_bottom = 1;
2149           else if ((!cdl->modeline && ddl->modeline)
2150                    || (cdl->modeline && !ddl->modeline))
2151             need_to_clear_bottom = 1;
2152           else if (cdl->ypos != ddl->ypos ||
2153                    cdl->ascent != ddl->ascent ||
2154                    cdl->descent != ddl->descent ||
2155                    cdl->clip != ddl->clip)
2156             need_to_clear_bottom = 1;
2157
2158           /* #### This kludge is to make sure the modeline shadows get
2159              redrawn if the modeline position shifts. */
2160           if (need_to_clear_bottom)
2161             w->shadow_thickness_changed = 1;
2162         }
2163
2164       if (!need_to_clear_bottom)
2165         {
2166           cdl = ddl = 0;
2167
2168           if (cdla_len)
2169             cdl = Dynarr_atp (cdla, cdla_len - 1);
2170           if (ddla_len)
2171             ddl = Dynarr_atp (ddla, ddla_len - 1);
2172
2173           if (!cdl || !ddl)
2174             need_to_clear_bottom = 1;
2175           else
2176             {
2177               int cdl_bottom, ddl_bottom;
2178
2179               cdl_bottom = cdl->ypos + cdl->descent;
2180               ddl_bottom = ddl->ypos + ddl->descent;
2181
2182               if (cdl_bottom > ddl_bottom)
2183                 {
2184                   need_to_clear_bottom = 1;
2185                   need_to_clear_start = ddl_bottom;
2186                   need_to_clear_end = cdl_bottom;
2187                 }
2188             }
2189         }
2190     }
2191
2192   /* Perform any output initialization. */
2193   DEVMETH (d, output_begin, (d));
2194
2195   /* If the window's structure has changed clear the internal border
2196      above it if it is topmost (the function will check). */
2197   if (f->windows_structure_changed)
2198     redisplay_clear_top_of_window (w);
2199
2200   /* Output each line. */
2201   for (line = 0; line < Dynarr_length (ddla); line++)
2202     {
2203       output_display_line (w, cdla, ddla, line, -1, -1);
2204     }
2205
2206   /* If the number of display lines has shrunk, adjust. */
2207   if (cdla_len > ddla_len)
2208     {
2209       Dynarr_length (cdla) = ddla_len;
2210     }
2211
2212   /* Output a vertical divider between windows, if necessary. */
2213   if (window_needs_vertical_divider (w)
2214       && (f->windows_structure_changed || f->clear))
2215     {
2216       DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
2217     }
2218
2219   /* Clear the rest of the window, if necessary. */
2220   if (need_to_clear_bottom)
2221     {
2222       redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
2223                                         need_to_clear_end);
2224     }
2225
2226   w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
2227   Fset_marker (w->start[CURRENT_DISP],
2228                make_int (marker_position (w->start[DESIRED_DISP])),
2229                w->buffer);
2230   Fset_marker (w->pointm[CURRENT_DISP],
2231                make_int (marker_position (w->pointm[DESIRED_DISP])),
2232                w->buffer);
2233   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2234   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2235   Fset_marker (w->last_start[CURRENT_DISP],
2236                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2237   Fset_marker (w->last_point[CURRENT_DISP],
2238                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2239   w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2240   w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2241   w->shadow_thickness_changed = 0;
2242
2243   set_window_display_buffer (w, XBUFFER (w->buffer));
2244   find_window_mirror (w)->truncate_win = window_truncation_on (w);
2245
2246   /* Overkill on invalidating the cache.  It is very bad for it to not
2247      get invalidated when it should be. */
2248   INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
2249
2250   /* We don't call output_end for tty frames.  Redisplay will do this
2251      after all tty windows have been updated.  This cuts down on
2252      cursor flicker. */
2253   if (FRAME_TTY_P (f))
2254     redisplay_redraw_cursor (f, 0);
2255   else
2256     DEVMETH (d, output_end, (d));
2257
2258 #ifdef HAVE_SCROLLBARS
2259   update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
2260 #endif
2261 }
2262
2263 /*****************************************************************************
2264  bevel_modeline
2265
2266  Draw a 3d border around the modeline on window W.
2267  ****************************************************************************/
2268 void
2269 bevel_modeline (struct window *w, struct display_line *dl)
2270 {
2271   struct frame *f = XFRAME (w->frame);
2272   struct device *d = XDEVICE (f->device);
2273   int x, y, width, height;
2274   int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2275   enum edge_style style;
2276
2277   x = WINDOW_MODELINE_LEFT (w);
2278   width = WINDOW_MODELINE_RIGHT (w) - x;
2279   y = dl->ypos - dl->ascent - shadow_thickness;
2280   height = dl->ascent + dl->descent + 2 * shadow_thickness;
2281
2282   if (XINT (w->modeline_shadow_thickness) < 0)
2283     {
2284       style = EDGE_BEVEL_IN;
2285     }
2286   else
2287     {
2288       style = EDGE_BEVEL_OUT;
2289     }
2290
2291   MAYBE_DEVMETH (d, bevel_area,
2292                  (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,
2293                   EDGE_ALL, style));
2294 }