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