XEmacs 21.2.34 "Molpe".
[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 of 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
1173       if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii)
1174           &&
1175           IMAGE_INSTANCE_DISPLAY_X (ii)
1176           + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) > x 
1177           && 
1178           IMAGE_INSTANCE_DISPLAY_X (ii) < x + width
1179           &&
1180           IMAGE_INSTANCE_DISPLAY_Y (ii)
1181           + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > y 
1182           && 
1183           IMAGE_INSTANCE_DISPLAY_Y (ii) < y + height
1184           &&
1185           !EQ (XCAR (rest), ignored_window))
1186         {
1187           unmap_subwindow (XCAR (rest));
1188         }
1189     }
1190 }
1191
1192 /****************************************************************************
1193  redisplay_unmap_subwindows_maybe
1194
1195  Potentially subwindows from the area in the box defined by the given
1196  parameters.
1197  ****************************************************************************/
1198 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1199 {
1200   if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))))
1201     {
1202       redisplay_unmap_subwindows (f, x, y, width, height, Qnil);
1203     }
1204 }
1205
1206 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
1207                                                   int height, Lisp_Object subwindow)
1208 {
1209   if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))))
1210     {
1211       redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
1212     }
1213 }
1214
1215 /****************************************************************************
1216  redisplay_output_subwindow
1217
1218  output a subwindow.  This code borrows heavily from the pixmap stuff,
1219  although is much simpler not needing to account for partial
1220  pixmaps, backgrounds etc.
1221  ****************************************************************************/
1222 void
1223 redisplay_output_subwindow (struct window *w,
1224                             Lisp_Object image_instance,
1225                             struct display_box* db, struct display_glyph_area* dga,
1226                             face_index findex, int cursor_start, int cursor_width,
1227                             int cursor_height)
1228 {
1229   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1230   Lisp_Object window;
1231   struct display_glyph_area sdga;
1232
1233   dga->height = IMAGE_INSTANCE_HEIGHT (p);
1234   dga->width = IMAGE_INSTANCE_WIDTH (p);
1235
1236   /* The first thing we are going to do is update the display
1237      characteristics of the subwindow. This also clears the dirty
1238      flags as a side effect. */
1239   update_subwindow (image_instance);
1240
1241   /* This makes the glyph area fit into the display area. */
1242   if (!redisplay_normalize_glyph_area (db, dga))
1243     return;
1244
1245   XSETWINDOW (window, w);
1246
1247   /* Clear the area the subwindow is going into. */
1248   redisplay_clear_clipped_region (window, findex,
1249                                   db, dga, 0, image_instance);
1250
1251   /* This shrinks the display box to exactly enclose the glyph
1252      area. */
1253   redisplay_normalize_display_box (db, dga);
1254
1255   /* if we can't view the whole window we can't view any of it. We
1256      have to be careful here since we may be being asked to display
1257      part of a subwindow, the rest of which is on-screen as well. We
1258      need to allow this case and map the entire subwindow. We also
1259      need to be careful since the subwindow could be outside the
1260      window in the gutter or modeline - we also need to allow these
1261      cases.*/
1262   sdga.xoffset = -dga->xoffset;
1263   sdga.yoffset = -dga->yoffset;
1264   sdga.height = IMAGE_INSTANCE_HEIGHT (p);
1265   sdga.width = IMAGE_INSTANCE_WIDTH (p);
1266
1267   if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0)
1268     {
1269       map_subwindow (image_instance, db->xpos, db->ypos, dga);
1270     }
1271   else
1272     {
1273       sdga.xoffset = sdga.yoffset = 0;
1274       map_subwindow (image_instance, db->xpos - dga->xoffset,
1275                      db->ypos - dga->yoffset, &sdga);
1276     }
1277 }
1278
1279 /****************************************************************************
1280  redisplay_output_layout
1281
1282  Output a widget hierarchy. This can safely call itself recursively.
1283
1284  The complexity of outputting layouts is deciding whether to do it or
1285  not. Consider a layout enclosing some text, the text changes and is
1286  marked as dirty, but the enclosing layout has not been marked as
1287  dirty so no updates occur and the text will potentially be truncated.
1288  Alternatively we hold a back pointer in the image instance to the
1289  parent and mark the parent as dirty. But the layout code assumes that
1290  if the layout is dirty then the whole layout should be redisplayed,
1291  so we then get lots of flashing even though only the text has changed
1292  size. Of course if the text shrinks in size then we do actually need
1293  to redisplay the layout to repaint the exposed area. So what happens
1294  if we make a non-structural change like changing color? Either we
1295  redisplay everything, or we redisplay nothing. These are exactly the
1296  issues lwlib has to grapple with. We really need to know what has
1297  actually changed and make a layout decision based on that. We also
1298  really need to know what has changed so that we can only make the
1299  neccessary changes in update_subwindow.  This has all now been
1300  implemented, Viva la revolution!
1301  ****************************************************************************/
1302 void
1303 redisplay_output_layout (struct window *w,
1304                          Lisp_Object image_instance,
1305                          struct display_box* db, struct display_glyph_area* dga,
1306                          face_index findex, int cursor_start, int cursor_width,
1307                          int cursor_height)
1308 {
1309   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1310   Lisp_Object window, rest;
1311   Emchar_dynarr *buf = Dynarr_new (Emchar);
1312   struct frame *f = XFRAME (w->frame);
1313   struct device *d = XDEVICE (f->device);
1314   int layout_height, layout_width;
1315
1316   XSETWINDOW (window, w);
1317
1318   layout_height = glyph_height (image_instance, window);
1319   layout_width = glyph_width (image_instance, window);
1320
1321   dga->height = layout_height;
1322   dga->width = layout_width;
1323 #ifdef DEBUG_WIDGET_OUTPUT
1324   printf ("outputing layout glyph %p\n", p);
1325 #endif
1326   /* This makes the glyph area fit into the display area. */
1327   if (!redisplay_normalize_glyph_area (db, dga))
1328     return;
1329
1330   /* Highly dodgy optimization. We want to only output the whole
1331      layout if we really have to. */
1332   if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p)
1333       || IMAGE_INSTANCE_LAYOUT_CHANGED (p)
1334       || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
1335       || IMAGE_INSTANCE_SIZE_CHANGED (p)
1336       || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
1337     {
1338       /* First clear the area we are drawing into. This is the easiest
1339          thing to do since we have many gaps that we have to make sure are
1340          filled in. */
1341       redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil);
1342
1343       /* Output a border if required */
1344       if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1345         {
1346           int edges = 0;
1347           enum edge_style style;
1348           int ypos = db->ypos;
1349           int height = dga->height;
1350
1351           if (dga->xoffset >= 0)
1352             edges |= EDGE_LEFT;
1353           if (dga->width - dga->xoffset == layout_width)
1354             edges |= EDGE_RIGHT;
1355           if (dga->yoffset >= 0)
1356             edges |= EDGE_TOP;
1357           if (dga->height - dga->yoffset == layout_height)
1358             edges |= EDGE_BOTTOM;
1359
1360           if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
1361             style = EDGE_ETCHED_IN;
1362           else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
1363             style = EDGE_ETCHED_OUT;
1364           else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in))
1365             style = EDGE_BEVEL_IN;
1366           else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1367             {
1368               style = EDGE_ETCHED_IN;
1369               if (edges & EDGE_TOP)
1370                 {
1371                   ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1372                   height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1373                 }
1374             }
1375           else
1376             style = EDGE_BEVEL_OUT;
1377
1378           MAYBE_DEVMETH (d, bevel_area,
1379                          (w, findex, db->xpos,
1380                           ypos,
1381                           dga->width, height, 2, edges, style));
1382         }
1383     }
1384
1385   /* This shrinks the display box to exactly enclose the glyph
1386      area. */
1387   redisplay_normalize_display_box (db, dga);
1388
1389   /* Flip through the widgets in the layout displaying as necessary */
1390   LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
1391     {
1392       Lisp_Object child = XCAR (rest);
1393
1394       struct display_box cdb;
1395       /* For losing HP-UX */
1396       cdb.xpos = db->xpos;
1397       cdb.ypos = db->ypos;
1398       cdb.width = db->width;
1399       cdb.height = db->height;
1400
1401       /* First determine if the image is visible at all */
1402       if (IMAGE_INSTANCEP (child))
1403         {
1404           Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
1405
1406           /* The enclosing layout offsets are +ve at this point */
1407           struct display_glyph_area cdga;
1408           cdga.xoffset  = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
1409           cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
1410           cdga.width = glyph_width (child, window);
1411           cdga.height = glyph_height (child, window);
1412
1413           IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 
1414             IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p);
1415
1416           /* Although normalization is done by the output routines
1417              we have to do it here so that they don't try and
1418              clear all of db. This is true below also. */
1419           if (redisplay_normalize_glyph_area (&cdb, &cdga))
1420             {
1421               redisplay_normalize_display_box (&cdb, &cdga);
1422               /* Since the display boxes will now be totally in the
1423                  window if they are visible at all we can now check this easily. */
1424               if (cdb.xpos < db->xpos || cdb.ypos < db->ypos
1425                   || cdb.xpos + cdb.width > db->xpos + db->width
1426                   || cdb.ypos + cdb.height > db->ypos + db->height)
1427                 continue;
1428               /* We have to invert the offset here as normalization
1429                  will have made them positive which the output
1430                  routines will treat as a truly +ve offset. */
1431               cdga.xoffset = -cdga.xoffset;
1432               cdga.yoffset = -cdga.yoffset;
1433
1434               switch (IMAGE_INSTANCE_TYPE (childii))
1435                 {
1436                 case IMAGE_TEXT:
1437                   {
1438                     /* #### This is well hacked and could use some
1439                        generalisation.*/
1440                     if (redisplay_normalize_glyph_area (&cdb, &cdga)
1441                         &&
1442                         (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1443                          IMAGE_INSTANCE_DIRTYP (childii)))
1444                       {
1445                         struct display_line dl; /* this is fake */
1446                         Lisp_Object string =
1447                           IMAGE_INSTANCE_TEXT_STRING (childii);
1448                         unsigned char charsets[NUM_LEADING_BYTES];
1449                         struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
1450
1451                         find_charsets_in_bufbyte_string (charsets,
1452                                                          XSTRING_DATA (string),
1453                                                          XSTRING_LENGTH (string));
1454                         ensure_face_cachel_complete (cachel, window, charsets);
1455
1456                         convert_bufbyte_string_into_emchar_dynarr
1457                           (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1458
1459                         redisplay_normalize_display_box (&cdb, &cdga);
1460                         /* Offsets are now +ve again so be careful
1461                            when fixing up the display line. */
1462                         xzero (dl);
1463                         /* Munge boxes into display lines. */
1464                         dl.ypos = (cdb.ypos - cdga.yoffset)
1465                           + glyph_ascent (child, window);
1466                         dl.ascent = glyph_ascent (child, window);
1467                         dl.descent = glyph_descent (child, window);
1468                         dl.top_clip = cdga.yoffset;
1469                         dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1470                         /* output_string doesn't understand offsets in
1471                            the same way as other routines - we have to
1472                            add the offset to the width so that we
1473                            output the full string. */
1474                         MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1475                                                           cdga.xoffset, cdb.xpos,
1476                                                           cdga.width + cdga.xoffset,
1477                                                           findex, 0, 0, 0, 0));
1478                         Dynarr_reset (buf);
1479                       }
1480                   }
1481                   break;
1482
1483                 case IMAGE_MONO_PIXMAP:
1484                 case IMAGE_COLOR_PIXMAP:
1485                   if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii)
1486                       || IMAGE_INSTANCE_DIRTYP (childii))
1487                     redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1488                                              0, 0, 0, 0);
1489                   break;
1490
1491                 case IMAGE_WIDGET:
1492                   if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (childii), Qlayout))
1493                     {
1494                       redisplay_output_layout (w, child, &cdb, &cdga, findex,
1495                                                0, 0, 0);
1496                       break;
1497                     }
1498                 case IMAGE_SUBWINDOW:
1499                   if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1500                       IMAGE_INSTANCE_DIRTYP (childii))
1501                     redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1502                                                 0, 0, 0);
1503                   break;
1504
1505                 case IMAGE_NOTHING:
1506                   /* nothing is as nothing does */
1507                   break;
1508
1509                 case IMAGE_POINTER:
1510                 default:
1511                   abort ();
1512                 }
1513             }
1514           IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0;
1515         }
1516     }
1517   
1518   /* Update any display properties. I'm not sure whether this actually
1519      does anything for layouts except clear the changed flags. */
1520   update_subwindow (image_instance);
1521
1522   Dynarr_free (buf);
1523 }
1524
1525 /****************************************************************************
1526  redisplay_output_pixmap
1527
1528
1529  output a pixmap.
1530  ****************************************************************************/
1531 void
1532 redisplay_output_pixmap (struct window *w,
1533                          Lisp_Object image_instance,
1534                          struct display_box* db, struct display_glyph_area* dga,
1535                          face_index findex, int cursor_start, int cursor_width,
1536                          int cursor_height, int offset_bitmap)
1537 {
1538   struct frame *f = XFRAME (w->frame);
1539   struct device *d = XDEVICE (f->device);
1540   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1541   Lisp_Object window;
1542   XSETWINDOW (window, w);
1543
1544   dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1545   dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1546
1547   /* This makes the glyph area fit into the display area. */
1548   if (!redisplay_normalize_glyph_area (db, dga))
1549     return;
1550
1551   /* Clear the area the pixmap is going into.  The pixmap itself will
1552      always take care of the full width.  We don't want to clear where
1553      it is going to go in order to avoid flicker.  So, all we have to
1554      take care of is any area above or below the pixmap. If the pixmap
1555      has a mask in which case we have to clear the whole damn thing
1556      since we can't yet clear just the area not included in the
1557      mask. */
1558   if (!offset_bitmap)
1559     {
1560       redisplay_clear_clipped_region (window, findex,
1561                                       db, dga,
1562                                       (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
1563                                       Qnil);
1564
1565       /* This shrinks the display box to exactly enclose the glyph
1566          area. */
1567       redisplay_normalize_display_box (db, dga);
1568     }
1569   assert (db->xpos >= 0 && db->ypos >= 0);
1570
1571   MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1572                                     db, dga,
1573                                     findex, cursor_start,
1574                                     cursor_width, cursor_height,
1575                                     offset_bitmap));
1576 }
1577
1578 /****************************************************************************
1579  redisplay_clear_region
1580
1581  Clear the area in the box defined by the given parameters using the
1582  given face. This has been generalised so that subwindows can be
1583  coped with effectively.
1584  ****************************************************************************/
1585 void
1586 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1587                         int width, int height)
1588 {
1589   struct window *w = NULL;
1590   struct frame *f = NULL;
1591   struct device *d;
1592   Lisp_Object background_pixmap = Qunbound;
1593   Lisp_Object fcolor = Qnil, bcolor = Qnil;
1594
1595   if (!width || !height)
1596      return;
1597
1598   if (WINDOWP (locale))
1599     {
1600       w = XWINDOW (locale);
1601       f = XFRAME (w->frame);
1602     }
1603   else if (FRAMEP (locale))
1604     {
1605       w = NULL;
1606       f = XFRAME (locale);
1607     }
1608   else
1609     abort ();
1610
1611   d = XDEVICE (f->device);
1612
1613   /* if we have subwindows in the region we have to unmap them */
1614   redisplay_unmap_subwindows_maybe (f, x, y, width, height);
1615
1616   /* #### This isn't quite right for when this function is called
1617      from the toolbar code. */
1618
1619   /* Don't use a backing pixmap in the border area */
1620   if (x >= FRAME_LEFT_BORDER_END (f)
1621       && x < FRAME_RIGHT_BORDER_START (f)
1622       && y >= FRAME_TOP_BORDER_END (f)
1623       && y < FRAME_BOTTOM_BORDER_START (f))
1624     {
1625       Lisp_Object temp;
1626
1627       if (w)
1628         {
1629           temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1630
1631           if (IMAGE_INSTANCEP (temp)
1632               && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1633             {
1634               /* #### maybe we could implement such that a string
1635                  can be a background pixmap? */
1636               background_pixmap = temp;
1637             }
1638         }
1639       else
1640         {
1641           temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1642
1643           if (IMAGE_INSTANCEP (temp)
1644               && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1645             {
1646               background_pixmap = temp;
1647             }
1648         }
1649     }
1650
1651   if (!UNBOUNDP (background_pixmap) &&
1652       XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1653     {
1654       if (w)
1655         {
1656           fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1657           bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1658         }
1659       else
1660         {
1661           fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1662           bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1663         }
1664     }
1665   else
1666     {
1667       fcolor = (w ?
1668                 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1669                 FACE_BACKGROUND (Vdefault_face, locale));
1670
1671     }
1672
1673   if (UNBOUNDP (background_pixmap))
1674     background_pixmap = Qnil;
1675
1676   DEVMETH (d, clear_region,
1677            (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1678 }
1679
1680 /****************************************************************************
1681  redisplay_clear_clipped_region
1682
1683  Clear the area in the dest display_box not covered by the src
1684  display_glyph_area using the given face. This is a common occurance
1685  for images shorter than the display line. Clipping can be played
1686  around with by altering these. glyphsrc should be normalized.
1687  ****************************************************************************/
1688 static void
1689 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1690         struct display_box* dest, struct display_glyph_area* glyphsrc,
1691         int fullheight_p, Lisp_Object ignored_subwindow)
1692 {
1693   /* assume dest->xpos >= 0 */
1694   int clear_x;
1695   struct frame* f = XFRAME (XWINDOW (window)->frame);
1696
1697   if (glyphsrc->xoffset > 0)
1698     {
1699       clear_x = dest->xpos + glyphsrc->xoffset;
1700     }
1701   else
1702     {
1703       clear_x = dest->xpos;
1704     }
1705
1706   /* If we need the whole height cleared then just do it. */
1707   if (fullheight_p)
1708     {
1709       redisplay_clear_region (window, findex, clear_x, dest->ypos,
1710                               glyphsrc->width, dest->height);
1711     }
1712   else
1713     {
1714       int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1715
1716       /* We need to make sure that subwindows are unmapped from the
1717          whole area. */
1718       redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1719                                             glyphsrc->width, dest->height,
1720                                             ignored_subwindow);
1721       /* first the top box */
1722       if (yoffset > 0)
1723         {
1724           redisplay_clear_region (window, findex, clear_x, dest->ypos,
1725                                   glyphsrc->width, yoffset);
1726
1727         }
1728       /* Then the bottom box */
1729       if (yoffset + glyphsrc->height < dest->height)
1730         {
1731           redisplay_clear_region (window, findex, clear_x,
1732                                   dest->ypos + yoffset + glyphsrc->height,
1733                                   glyphsrc->width,
1734                                   dest->height - (yoffset + glyphsrc->height));
1735
1736         }
1737     }
1738 }
1739
1740 /*****************************************************************************
1741  redisplay_normalize_glyph_area
1742  redisplay_normalize_display_box
1743
1744  Calculate the visible box for displaying src in dest.
1745  ****************************************************************************/
1746 int
1747 redisplay_normalize_glyph_area (struct display_box* dest,
1748                                 struct display_glyph_area* glyphsrc)
1749 {
1750   if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1751       ||
1752       dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1753       ||
1754       -glyphsrc->xoffset >= glyphsrc->width
1755       ||
1756       -glyphsrc->yoffset >= glyphsrc->height)
1757     {
1758       /* It's all clipped out */
1759       return 0;
1760     }
1761
1762   /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1763   if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1764     {
1765       if (glyphsrc->xoffset > 0)
1766         glyphsrc->width = dest->width - glyphsrc->xoffset;
1767       else
1768         glyphsrc->width = dest->width;
1769     }
1770
1771   if (glyphsrc->xoffset < 0)
1772     glyphsrc->width += glyphsrc->xoffset;
1773
1774   /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1775   if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1776     {
1777       if (glyphsrc->yoffset > 0)
1778         glyphsrc->height = dest->height - glyphsrc->yoffset;
1779       else
1780         glyphsrc->height = dest->height;
1781     }
1782
1783   if (glyphsrc->yoffset < 0)
1784     glyphsrc->height += glyphsrc->yoffset;
1785
1786   return 1;
1787 }
1788
1789 static void
1790 redisplay_normalize_display_box (struct display_box* dest,
1791                                  struct display_glyph_area* glyphsrc)
1792 {
1793   /* Adjust the destination area. At the end of this the destination
1794    area will exactly enclose the glyph area. The only remaining
1795    adjustment will be offsets into the glyph area. */
1796
1797   /* Horizontal adjustment. */
1798   if (glyphsrc->xoffset > 0)
1799     {
1800       dest->xpos += glyphsrc->xoffset;
1801       dest->width -= glyphsrc->xoffset;
1802       glyphsrc->xoffset = 0;
1803     }
1804   else
1805     glyphsrc->xoffset = -glyphsrc->xoffset;
1806
1807   if (glyphsrc->width < dest->width)
1808     dest->width = glyphsrc->width;
1809
1810   /* Vertical adjustment. */
1811   if (glyphsrc->yoffset > 0)
1812     {
1813       dest->ypos += glyphsrc->yoffset;
1814       dest->height -= glyphsrc->yoffset;
1815       glyphsrc->yoffset = 0;
1816     }
1817   else
1818     glyphsrc->yoffset = -glyphsrc->yoffset;
1819
1820   if (glyphsrc->height < dest->height)
1821     dest->height = glyphsrc->height;
1822 }
1823
1824 /*****************************************************************************
1825  redisplay_display_boxes_in_window_p
1826
1827  Determine whether the require display_glyph_area is completely inside
1828  the window. 0 means the display_box is not in the window. 1 means the
1829  display_box and the display_glyph_area are in the window. -1 means
1830  the display_box is in the window but the display_glyph_area is not.
1831  ****************************************************************************/
1832 static int
1833 redisplay_display_boxes_in_window_p (struct window* w,
1834                                      struct display_box* db,
1835                                      struct display_glyph_area* dga)
1836 {
1837   int left = WINDOW_TEXT_LEFT (w);
1838   int right = WINDOW_TEXT_RIGHT (w);
1839   int top = WINDOW_TEXT_TOP (w);
1840   int bottom = WINDOW_TEXT_BOTTOM (w);
1841
1842   if (db->xpos < left || db->ypos < top
1843       || db->xpos + db->width > right
1844       || db->ypos + db->height > bottom)
1845     /* We are not displaying in a window at all */
1846     return 0;
1847
1848   if (db->xpos + dga->xoffset >= left
1849       &&
1850       db->ypos + dga->yoffset >= top
1851       &&
1852       db->xpos + dga->xoffset + dga->width <= right
1853       &&
1854       db->ypos + dga->yoffset + dga->height <= bottom)
1855     return 1;
1856
1857   return -1;
1858 }
1859
1860 /*****************************************************************************
1861  redisplay_calculate_display_boxes
1862
1863  Convert from rune/display_line co-ordinates to display_box
1864  co-ordinates.
1865  ****************************************************************************/
1866 int
1867 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1868                                    int xoffset, int start_pixpos, int width,
1869                                    struct display_box* dest,
1870                                    struct display_glyph_area* src)
1871 {
1872   dest->xpos = xpos;
1873   dest->ypos = DISPLAY_LINE_YPOS (dl);
1874   dest->width = width;
1875   dest->height = DISPLAY_LINE_HEIGHT (dl);
1876
1877   src->xoffset = -xoffset;
1878   src->yoffset = -dl->top_clip;
1879   src->width = 0;
1880   src->height = 0;
1881
1882   if (start_pixpos >=0 && start_pixpos > xpos)
1883     {
1884       /* Oops, we're asking for a start outside of the displayable
1885          area. */
1886       if (start_pixpos > xpos + width)
1887         return 0;
1888       dest->xpos = start_pixpos;
1889       dest->width -= (start_pixpos - xpos);
1890       /* Offsets are -ve when we want to clip pixels off the displayed
1891          glyph. */
1892       src->xoffset -= (start_pixpos - xpos);
1893     }
1894
1895   return 1;
1896 }
1897
1898 /*****************************************************************************
1899  redisplay_clear_top_of_window
1900
1901  If window is topmost, clear the internal border above it.
1902  ****************************************************************************/
1903 static void
1904 redisplay_clear_top_of_window (struct window *w)
1905 {
1906   Lisp_Object window;
1907   XSETWINDOW (window, w);
1908
1909   if (!NILP (Fwindow_highest_p (window)))
1910     {
1911       struct frame *f = XFRAME (w->frame);
1912       int x, y, width, height;
1913
1914       x = w->pixel_left;
1915       width = w->pixel_width;
1916
1917       if (window_is_leftmost (w))
1918         {
1919           x -= FRAME_BORDER_WIDTH (f);
1920           width += FRAME_BORDER_WIDTH (f);
1921         }
1922       if (window_is_rightmost (w))
1923         width += FRAME_BORDER_WIDTH (f);
1924
1925       y = FRAME_TOP_BORDER_START (f) - 1;
1926       height = FRAME_BORDER_HEIGHT (f) + 1;
1927
1928       redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1929     }
1930 }
1931
1932 /*****************************************************************************
1933  redisplay_clear_to_window_end
1934
1935  Clear the area between ypos1 and ypos2.  Each margin area and the
1936  text area is handled separately since they may each have their own
1937  background color.
1938  ****************************************************************************/
1939 void
1940 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1941 {
1942   struct frame *f = XFRAME (w->frame);
1943   struct device *d = XDEVICE (f->device);
1944
1945   if (HAS_DEVMETH_P (d, clear_to_window_end))
1946     DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1947   else
1948     {
1949       int height = ypos2 - ypos1;
1950
1951       if (height)
1952         {
1953           Lisp_Object window;
1954           int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1955           layout_bounds bounds;
1956
1957           bounds = calculate_display_line_boundaries (w, bflag);
1958           XSETWINDOW (window, w);
1959
1960           if (window_is_leftmost (w))
1961             redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1962                                     ypos1, FRAME_BORDER_WIDTH (f), height);
1963
1964           if (bounds.left_in - bounds.left_out > 0)
1965             redisplay_clear_region (window,
1966                                     get_builtin_face_cache_index (w, Vleft_margin_face),
1967                                     bounds.left_out, ypos1,
1968                                     bounds.left_in - bounds.left_out, height);
1969
1970           if (bounds.right_in - bounds.left_in > 0)
1971             redisplay_clear_region (window,
1972                                     DEFAULT_INDEX,
1973                                     bounds.left_in, ypos1,
1974                                     bounds.right_in - bounds.left_in, height);
1975
1976           if (bounds.right_out - bounds.right_in > 0)
1977             redisplay_clear_region (window,
1978                                     get_builtin_face_cache_index (w, Vright_margin_face),
1979                                     bounds.right_in, ypos1,
1980                                     bounds.right_out - bounds.right_in, height);
1981
1982           if (window_is_rightmost (w))
1983             redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1984                                     ypos1, FRAME_BORDER_WIDTH (f), height);
1985         }
1986     }
1987 }
1988
1989 /*****************************************************************************
1990  redisplay_clear_bottom_of_window
1991
1992  Clear window from right below the last display line to right above
1993  the modeline.  The calling function can limit the area actually
1994  erased by setting min_start and/or max_end to positive values.
1995  ****************************************************************************/
1996 void
1997 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1998                                   int min_start, int max_end)
1999 {
2000   struct frame *f = XFRAME (w->frame);
2001   int ypos1, ypos2;
2002   int ddla_len = Dynarr_length (ddla);
2003
2004   ypos2 = WINDOW_TEXT_BOTTOM (w);
2005 #ifdef HAVE_SCROLLBARS
2006   /* This adjustment is to catch the intersection of any scrollbars. */
2007   if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
2008     ypos2 += window_scrollbar_height (w);
2009 #endif
2010
2011   if (ddla_len)
2012     {
2013       if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
2014         {
2015           ypos1 = WINDOW_TEXT_TOP (w);
2016 #ifdef HAVE_SCROLLBARS
2017           /* This adjustment is to catch the intersection of any scrollbars. */
2018           if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
2019             ypos1 -= window_scrollbar_height (w);
2020 #endif
2021         }
2022       else
2023         {
2024           struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
2025           ypos1 = dl->ypos + dl->descent - dl->clip;
2026         }
2027     }
2028   else
2029     ypos1 = WINDOW_TEXT_TOP (w);
2030
2031   /* #### See if this can be made conditional on the frame
2032      changing size. */
2033   if (MINI_WINDOW_P (w))
2034     ypos2 += FRAME_BORDER_HEIGHT (f);
2035
2036   if (min_start >= 0 && ypos1 < min_start)
2037     ypos1 = min_start;
2038   if (max_end >= 0 && ypos2 > max_end)
2039     ypos2 = max_end;
2040
2041   if (ypos2 <= ypos1)
2042     return;
2043
2044   redisplay_clear_to_window_end (w, ypos1, ypos2);
2045 }
2046
2047 /*****************************************************************************
2048  redisplay_update_line
2049
2050  This is used during incremental updates to update a single line and
2051  correct the offsets on all lines below it.  At the moment
2052  update_values is false if we are only updating the modeline.
2053  ****************************************************************************/
2054 void
2055 redisplay_update_line (struct window *w, int first_line, int last_line,
2056                        int update_values)
2057 {
2058   struct frame *f = XFRAME (w->frame);
2059   struct device *d = XDEVICE (f->device);
2060
2061   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2062   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2063
2064   MAYBE_DEVMETH (d, window_output_begin, (w));
2065
2066   while (first_line <= last_line)
2067     {
2068       Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
2069                            Dynarr_atp (cdla, first_line)->bufpos);
2070       Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
2071                            Dynarr_atp (ddla, first_line)->bufpos);
2072
2073       assert (Dynarr_length (cdla) == Dynarr_length (ddla));
2074
2075       /* Output the changes. */
2076       output_display_line (w, cdla, ddla, first_line, -1, -1);
2077
2078       /* Update the offsets. */
2079       if (update_values)
2080         {
2081           int cur_line = first_line + 1;
2082           while (cur_line < Dynarr_length (cdla))
2083             {
2084               Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
2085               Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
2086               cur_line++;
2087             }
2088         }
2089
2090       /* Update the window_end_pos and other settings. */
2091       if (update_values)
2092         {
2093           w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
2094
2095           if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
2096             {
2097               w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2098               w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2099             }
2100         }
2101
2102       first_line++;
2103     }
2104
2105   /* Update the window max line length.  We have to scan the entire
2106      set of display lines otherwise we might not detect if the max is
2107      supposed to shrink. */
2108   if (update_values)
2109     {
2110       int line = 0;
2111
2112       w->max_line_len = 0;
2113       while (line < Dynarr_length (ddla))
2114         {
2115           struct display_line *dl = Dynarr_atp (ddla, line);
2116
2117           if (!dl->modeline)
2118             w->max_line_len = max (dl->num_chars, w->max_line_len);
2119
2120           line++;
2121         }
2122     }
2123
2124   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2125   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2126   Fset_marker (w->last_point[CURRENT_DISP],
2127                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2128   Fset_marker (w->last_start[CURRENT_DISP],
2129                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2130
2131   /* We don't bother updating the vertical scrollbars here.  This
2132      gives us a performance increase while having minimal loss of
2133      quality to the scrollbar slider size and position since when this
2134      function is called we know that the changes to the buffer were
2135      very localized.  We have to update the horizontal scrollbars,
2136      though, because this routine could cause a change which has a
2137      larger impact on their sizing. */
2138   /* #### See if we can get away with only calling this if
2139      max_line_len is greater than the window_char_width. */
2140 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
2141   {
2142     extern int stupid_vertical_scrollbar_drag_hack;
2143
2144     update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
2145     stupid_vertical_scrollbar_drag_hack = 1;
2146   }
2147 #endif
2148
2149   redisplay_redraw_cursor (f, 0);
2150   MAYBE_DEVMETH (d, window_output_end, (w));
2151 }
2152
2153 /*****************************************************************************
2154  redisplay_output_window
2155
2156  For the given window W, ensure that the current display lines are
2157  equal to the desired display lines, outputing changes as necessary.
2158
2159  #### Fuck me.  This just isn't going to cut it for tty's.  The output
2160  decisions for them must be based on the contents of the entire frame
2161  because that is how the available output capabilities think.  The
2162  solution is relatively simple.  Create redisplay_output_frame.  This
2163  will basically merge all of the separate window display structs into
2164  a single one for the frame.  This combination structure will be able
2165  to be passed to the same output_display_line which works for windows
2166  on X frames and the right things will happen.  It just takes time to
2167  do.
2168  ****************************************************************************/
2169 void
2170 redisplay_output_window (struct window *w)
2171 {
2172   struct frame *f = XFRAME (w->frame);
2173   struct device *d = XDEVICE (f->device);
2174
2175   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2176   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2177
2178   int cdla_len = Dynarr_length (cdla);
2179   int ddla_len = Dynarr_length (ddla);
2180
2181   int line;
2182   int need_to_clear_bottom = 0;
2183   int need_to_clear_start = -1;
2184   int need_to_clear_end = -1;
2185
2186   /* Backgrounds may have changed or windows may have gone away
2187      leaving dividers lying around. */
2188   if (f->faces_changed
2189       || f->windows_structure_changed
2190       || w->shadow_thickness_changed)
2191     need_to_clear_bottom = 1;
2192
2193   /* The first thing we do is determine if we are going to need to
2194      clear the bottom of the window.  We only need to do this if the
2195      bottom of the current display lines is below the bottom of the
2196      desired display lines.  Note that the number of lines is
2197      irrelevant.  Only the position matters.  We also clear to the
2198      bottom of the window if the modeline has shifted position. */
2199   /* #### We can't blindly not clear the bottom if f->clear is true
2200      since there might be a window-local background.  However, for
2201      those cases where there isn't, clearing the end of the window in
2202      this case sucks. */
2203   if (!need_to_clear_bottom)
2204     {
2205       struct display_line *cdl, *ddl;
2206
2207       /* If the modeline has changed position or size, clear the bottom
2208          of the window. */
2209       if (!need_to_clear_bottom)
2210         {
2211           cdl = ddl = 0;
2212
2213           if (cdla_len)
2214             cdl = Dynarr_atp (cdla, 0);
2215           if (ddla_len)
2216             ddl = Dynarr_atp (ddla, 0);
2217
2218           if (!cdl || !ddl)
2219             need_to_clear_bottom = 1;
2220           else if ((!cdl->modeline && ddl->modeline)
2221                    || (cdl->modeline && !ddl->modeline))
2222             need_to_clear_bottom = 1;
2223           else if (cdl->ypos != ddl->ypos ||
2224                    cdl->ascent != ddl->ascent ||
2225                    cdl->descent != ddl->descent ||
2226                    cdl->clip != ddl->clip)
2227             need_to_clear_bottom = 1;
2228
2229           /* #### This kludge is to make sure the modeline shadows get
2230              redrawn if the modeline position shifts. */
2231           if (need_to_clear_bottom)
2232             w->shadow_thickness_changed = 1;
2233         }
2234
2235       if (!need_to_clear_bottom)
2236         {
2237           cdl = ddl = 0;
2238
2239           if (cdla_len)
2240             cdl = Dynarr_atp (cdla, cdla_len - 1);
2241           if (ddla_len)
2242             ddl = Dynarr_atp (ddla, ddla_len - 1);
2243
2244           if (!cdl || !ddl)
2245             need_to_clear_bottom = 1;
2246           else
2247             {
2248               int cdl_bottom, ddl_bottom;
2249
2250               cdl_bottom = cdl->ypos + cdl->descent;
2251               ddl_bottom = ddl->ypos + ddl->descent;
2252
2253               if (cdl_bottom > ddl_bottom)
2254                 {
2255                   need_to_clear_bottom = 1;
2256                   need_to_clear_start = ddl_bottom;
2257                   need_to_clear_end = cdl_bottom;
2258                 }
2259             }
2260         }
2261     }
2262
2263   /* Perform any output initialization. */
2264   MAYBE_DEVMETH (d, window_output_begin, (w));
2265
2266   /* If the window's structure has changed clear the internal border
2267      above it if it is topmost (the function will check). */
2268   if (f->windows_structure_changed)
2269     redisplay_clear_top_of_window (w);
2270
2271   /* Output each line. */
2272   for (line = 0; line < Dynarr_length (ddla); line++)
2273     {
2274       output_display_line (w, cdla, ddla, line, -1, -1);
2275     }
2276
2277   /* If the number of display lines has shrunk, adjust. */
2278   if (cdla_len > ddla_len)
2279     {
2280       Dynarr_length (cdla) = ddla_len;
2281     }
2282
2283   /* Output a vertical divider between windows, if necessary. */
2284   if (window_needs_vertical_divider (w)
2285       && (f->windows_structure_changed || f->clear))
2286     {
2287       MAYBE_DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
2288     }
2289
2290   /* Clear the rest of the window, if necessary. */
2291   if (need_to_clear_bottom)
2292     {
2293       redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
2294                                         need_to_clear_end);
2295     }
2296
2297   w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
2298   Fset_marker (w->start[CURRENT_DISP],
2299                make_int (marker_position (w->start[DESIRED_DISP])),
2300                w->buffer);
2301   Fset_marker (w->pointm[CURRENT_DISP],
2302                make_int (marker_position (w->pointm[DESIRED_DISP])),
2303                w->buffer);
2304   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2305   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2306   Fset_marker (w->last_start[CURRENT_DISP],
2307                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2308   Fset_marker (w->last_point[CURRENT_DISP],
2309                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2310   w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2311   w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2312   w->shadow_thickness_changed = 0;
2313
2314   set_window_display_buffer (w, XBUFFER (w->buffer));
2315   find_window_mirror (w)->truncate_win = window_truncation_on (w);
2316
2317   /* Overkill on invalidating the cache.  It is very bad for it to not
2318      get invalidated when it should be. */
2319   INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
2320
2321   redisplay_redraw_cursor (f, 0);
2322   MAYBE_DEVMETH (d, window_output_end, (w));
2323
2324 #ifdef HAVE_SCROLLBARS
2325   update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
2326 #endif
2327 }
2328
2329 /*****************************************************************************
2330  bevel_modeline
2331
2332  Draw a 3d border around the modeline on window W.
2333  ****************************************************************************/
2334 void
2335 bevel_modeline (struct window *w, struct display_line *dl)
2336 {
2337   struct frame *f = XFRAME (w->frame);
2338   struct device *d = XDEVICE (f->device);
2339   int x, y, width, height;
2340   int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2341   enum edge_style style;
2342
2343   x = WINDOW_MODELINE_LEFT (w);
2344   width = WINDOW_MODELINE_RIGHT (w) - x;
2345   y = dl->ypos - dl->ascent - shadow_thickness;
2346   height = dl->ascent + dl->descent + 2 * shadow_thickness;
2347
2348   if (XINT (w->modeline_shadow_thickness) < 0)
2349     {
2350       style = EDGE_BEVEL_IN;
2351     }
2352   else
2353     {
2354       style = EDGE_BEVEL_OUT;
2355     }
2356
2357   MAYBE_DEVMETH (d, bevel_area,
2358                  (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,
2359                   EDGE_ALL, style));
2360 }