(compare_runes): Use `CHARC_EQ'.
[chise/xemacs-chise.git] / 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            !CHARC_EQ (crb->object.cglyph, drb->object.cglyph))
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   Charc_dynarr *buf = Dynarr_new (Charc);
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                         Charset_ID 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_charc_dynarr
1457                           (XSTRING_DATA (string), XSTRING_LENGTH (string),
1458                            buf);
1459
1460                         redisplay_normalize_display_box (&cdb, &cdga);
1461                         /* Offsets are now +ve again so be careful
1462                            when fixing up the display line. */
1463                         xzero (dl);
1464                         /* Munge boxes into display lines. */
1465                         dl.ypos = (cdb.ypos - cdga.yoffset)
1466                           + glyph_ascent (child, window);
1467                         dl.ascent = glyph_ascent (child, window);
1468                         dl.descent = glyph_descent (child, window);
1469                         dl.top_clip = cdga.yoffset;
1470                         dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1471                         /* output_string doesn't understand offsets in
1472                            the same way as other routines - we have to
1473                            add the offset to the width so that we
1474                            output the full string. */
1475                         MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1476                                                           cdga.xoffset, cdb.xpos,
1477                                                           cdga.width + cdga.xoffset,
1478                                                           findex, 0, 0, 0, 0));
1479                         Dynarr_reset (buf);
1480                       }
1481                   }
1482                   break;
1483
1484                 case IMAGE_MONO_PIXMAP:
1485                 case IMAGE_COLOR_PIXMAP:
1486                   if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii)
1487                       || IMAGE_INSTANCE_DIRTYP (childii))
1488                     redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1489                                              0, 0, 0, 0);
1490                   break;
1491
1492                 case IMAGE_WIDGET:
1493                   if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (childii), Qlayout))
1494                     {
1495                       redisplay_output_layout (w, child, &cdb, &cdga, findex,
1496                                                0, 0, 0);
1497                       break;
1498                     }
1499                 case IMAGE_SUBWINDOW:
1500                   if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1501                       IMAGE_INSTANCE_DIRTYP (childii))
1502                     redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1503                                                 0, 0, 0);
1504                   break;
1505
1506                 case IMAGE_NOTHING:
1507                   /* nothing is as nothing does */
1508                   break;
1509
1510                 case IMAGE_POINTER:
1511                 default:
1512                   abort ();
1513                 }
1514             }
1515           IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0;
1516         }
1517     }
1518   
1519   /* Update any display properties. I'm not sure whether this actually
1520      does anything for layouts except clear the changed flags. */
1521   update_subwindow (image_instance);
1522
1523   Dynarr_free (buf);
1524 }
1525
1526 /****************************************************************************
1527  redisplay_output_pixmap
1528
1529
1530  output a pixmap.
1531  ****************************************************************************/
1532 void
1533 redisplay_output_pixmap (struct window *w,
1534                          Lisp_Object image_instance,
1535                          struct display_box* db, struct display_glyph_area* dga,
1536                          face_index findex, int cursor_start, int cursor_width,
1537                          int cursor_height, int offset_bitmap)
1538 {
1539   struct frame *f = XFRAME (w->frame);
1540   struct device *d = XDEVICE (f->device);
1541   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1542   Lisp_Object window;
1543   XSETWINDOW (window, w);
1544
1545   dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1546   dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1547
1548   /* This makes the glyph area fit into the display area. */
1549   if (!redisplay_normalize_glyph_area (db, dga))
1550     return;
1551
1552   /* Clear the area the pixmap is going into.  The pixmap itself will
1553      always take care of the full width.  We don't want to clear where
1554      it is going to go in order to avoid flicker.  So, all we have to
1555      take care of is any area above or below the pixmap. If the pixmap
1556      has a mask in which case we have to clear the whole damn thing
1557      since we can't yet clear just the area not included in the
1558      mask. */
1559   if (!offset_bitmap)
1560     {
1561       redisplay_clear_clipped_region (window, findex,
1562                                       db, dga,
1563                                       (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
1564                                       Qnil);
1565
1566       /* This shrinks the display box to exactly enclose the glyph
1567          area. */
1568       redisplay_normalize_display_box (db, dga);
1569     }
1570   assert (db->xpos >= 0 && db->ypos >= 0);
1571
1572   MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1573                                     db, dga,
1574                                     findex, cursor_start,
1575                                     cursor_width, cursor_height,
1576                                     offset_bitmap));
1577 }
1578
1579 /****************************************************************************
1580  redisplay_clear_region
1581
1582  Clear the area in the box defined by the given parameters using the
1583  given face. This has been generalised so that subwindows can be
1584  coped with effectively.
1585  ****************************************************************************/
1586 void
1587 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1588                         int width, int height)
1589 {
1590   struct window *w = NULL;
1591   struct frame *f = NULL;
1592   struct device *d;
1593   Lisp_Object background_pixmap = Qunbound;
1594   Lisp_Object fcolor = Qnil, bcolor = Qnil;
1595
1596   if (!width || !height)
1597      return;
1598
1599   if (WINDOWP (locale))
1600     {
1601       w = XWINDOW (locale);
1602       f = XFRAME (w->frame);
1603     }
1604   else if (FRAMEP (locale))
1605     {
1606       w = NULL;
1607       f = XFRAME (locale);
1608     }
1609   else
1610     abort ();
1611
1612   d = XDEVICE (f->device);
1613
1614   /* if we have subwindows in the region we have to unmap them */
1615   redisplay_unmap_subwindows_maybe (f, x, y, width, height);
1616
1617   /* #### This isn't quite right for when this function is called
1618      from the toolbar code. */
1619
1620   /* Don't use a backing pixmap in the border area */
1621   if (x >= FRAME_LEFT_BORDER_END (f)
1622       && x < FRAME_RIGHT_BORDER_START (f)
1623       && y >= FRAME_TOP_BORDER_END (f)
1624       && y < FRAME_BOTTOM_BORDER_START (f))
1625     {
1626       Lisp_Object temp;
1627
1628       if (w)
1629         {
1630           temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1631
1632           if (IMAGE_INSTANCEP (temp)
1633               && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1634             {
1635               /* #### maybe we could implement such that a string
1636                  can be a background pixmap? */
1637               background_pixmap = temp;
1638             }
1639         }
1640       else
1641         {
1642           temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1643
1644           if (IMAGE_INSTANCEP (temp)
1645               && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1646             {
1647               background_pixmap = temp;
1648             }
1649         }
1650     }
1651
1652   if (!UNBOUNDP (background_pixmap) &&
1653       XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1654     {
1655       if (w)
1656         {
1657           fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1658           bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1659         }
1660       else
1661         {
1662           fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1663           bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1664         }
1665     }
1666   else
1667     {
1668       fcolor = (w ?
1669                 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1670                 FACE_BACKGROUND (Vdefault_face, locale));
1671
1672     }
1673
1674   if (UNBOUNDP (background_pixmap))
1675     background_pixmap = Qnil;
1676
1677   DEVMETH (d, clear_region,
1678            (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1679 }
1680
1681 /****************************************************************************
1682  redisplay_clear_clipped_region
1683
1684  Clear the area in the dest display_box not covered by the src
1685  display_glyph_area using the given face. This is a common occurance
1686  for images shorter than the display line. Clipping can be played
1687  around with by altering these. glyphsrc should be normalized.
1688  ****************************************************************************/
1689 static void
1690 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1691         struct display_box* dest, struct display_glyph_area* glyphsrc,
1692         int fullheight_p, Lisp_Object ignored_subwindow)
1693 {
1694   /* assume dest->xpos >= 0 */
1695   int clear_x;
1696   struct frame* f = XFRAME (XWINDOW (window)->frame);
1697
1698   if (glyphsrc->xoffset > 0)
1699     {
1700       clear_x = dest->xpos + glyphsrc->xoffset;
1701     }
1702   else
1703     {
1704       clear_x = dest->xpos;
1705     }
1706
1707   /* If we need the whole height cleared then just do it. */
1708   if (fullheight_p)
1709     {
1710       redisplay_clear_region (window, findex, clear_x, dest->ypos,
1711                               glyphsrc->width, dest->height);
1712     }
1713   else
1714     {
1715       int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1716
1717       /* We need to make sure that subwindows are unmapped from the
1718          whole area. */
1719       redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1720                                             glyphsrc->width, dest->height,
1721                                             ignored_subwindow);
1722       /* first the top box */
1723       if (yoffset > 0)
1724         {
1725           redisplay_clear_region (window, findex, clear_x, dest->ypos,
1726                                   glyphsrc->width, yoffset);
1727
1728         }
1729       /* Then the bottom box */
1730       if (yoffset + glyphsrc->height < dest->height)
1731         {
1732           redisplay_clear_region (window, findex, clear_x,
1733                                   dest->ypos + yoffset + glyphsrc->height,
1734                                   glyphsrc->width,
1735                                   dest->height - (yoffset + glyphsrc->height));
1736
1737         }
1738     }
1739 }
1740
1741 /*****************************************************************************
1742  redisplay_normalize_glyph_area
1743  redisplay_normalize_display_box
1744
1745  Calculate the visible box for displaying src in dest.
1746  ****************************************************************************/
1747 int
1748 redisplay_normalize_glyph_area (struct display_box* dest,
1749                                 struct display_glyph_area* glyphsrc)
1750 {
1751   if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1752       ||
1753       dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1754       ||
1755       -glyphsrc->xoffset >= glyphsrc->width
1756       ||
1757       -glyphsrc->yoffset >= glyphsrc->height)
1758     {
1759       /* It's all clipped out */
1760       return 0;
1761     }
1762
1763   /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1764   if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1765     {
1766       if (glyphsrc->xoffset > 0)
1767         glyphsrc->width = dest->width - glyphsrc->xoffset;
1768       else
1769         glyphsrc->width = dest->width;
1770     }
1771
1772   if (glyphsrc->xoffset < 0)
1773     glyphsrc->width += glyphsrc->xoffset;
1774
1775   /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1776   if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1777     {
1778       if (glyphsrc->yoffset > 0)
1779         glyphsrc->height = dest->height - glyphsrc->yoffset;
1780       else
1781         glyphsrc->height = dest->height;
1782     }
1783
1784   if (glyphsrc->yoffset < 0)
1785     glyphsrc->height += glyphsrc->yoffset;
1786
1787   return 1;
1788 }
1789
1790 static void
1791 redisplay_normalize_display_box (struct display_box* dest,
1792                                  struct display_glyph_area* glyphsrc)
1793 {
1794   /* Adjust the destination area. At the end of this the destination
1795    area will exactly enclose the glyph area. The only remaining
1796    adjustment will be offsets into the glyph area. */
1797
1798   /* Horizontal adjustment. */
1799   if (glyphsrc->xoffset > 0)
1800     {
1801       dest->xpos += glyphsrc->xoffset;
1802       dest->width -= glyphsrc->xoffset;
1803       glyphsrc->xoffset = 0;
1804     }
1805   else
1806     glyphsrc->xoffset = -glyphsrc->xoffset;
1807
1808   if (glyphsrc->width < dest->width)
1809     dest->width = glyphsrc->width;
1810
1811   /* Vertical adjustment. */
1812   if (glyphsrc->yoffset > 0)
1813     {
1814       dest->ypos += glyphsrc->yoffset;
1815       dest->height -= glyphsrc->yoffset;
1816       glyphsrc->yoffset = 0;
1817     }
1818   else
1819     glyphsrc->yoffset = -glyphsrc->yoffset;
1820
1821   if (glyphsrc->height < dest->height)
1822     dest->height = glyphsrc->height;
1823 }
1824
1825 /*****************************************************************************
1826  redisplay_display_boxes_in_window_p
1827
1828  Determine whether the require display_glyph_area is completely inside
1829  the window. 0 means the display_box is not in the window. 1 means the
1830  display_box and the display_glyph_area are in the window. -1 means
1831  the display_box is in the window but the display_glyph_area is not.
1832  ****************************************************************************/
1833 static int
1834 redisplay_display_boxes_in_window_p (struct window* w,
1835                                      struct display_box* db,
1836                                      struct display_glyph_area* dga)
1837 {
1838   int left = WINDOW_TEXT_LEFT (w);
1839   int right = WINDOW_TEXT_RIGHT (w);
1840   int top = WINDOW_TEXT_TOP (w);
1841   int bottom = WINDOW_TEXT_BOTTOM (w);
1842
1843   if (db->xpos < left || db->ypos < top
1844       || db->xpos + db->width > right
1845       || db->ypos + db->height > bottom)
1846     /* We are not displaying in a window at all */
1847     return 0;
1848
1849   if (db->xpos + dga->xoffset >= left
1850       &&
1851       db->ypos + dga->yoffset >= top
1852       &&
1853       db->xpos + dga->xoffset + dga->width <= right
1854       &&
1855       db->ypos + dga->yoffset + dga->height <= bottom)
1856     return 1;
1857
1858   return -1;
1859 }
1860
1861 /*****************************************************************************
1862  redisplay_calculate_display_boxes
1863
1864  Convert from rune/display_line co-ordinates to display_box
1865  co-ordinates.
1866  ****************************************************************************/
1867 int
1868 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1869                                    int xoffset, int start_pixpos, int width,
1870                                    struct display_box* dest,
1871                                    struct display_glyph_area* src)
1872 {
1873   dest->xpos = xpos;
1874   dest->ypos = DISPLAY_LINE_YPOS (dl);
1875   dest->width = width;
1876   dest->height = DISPLAY_LINE_HEIGHT (dl);
1877
1878   src->xoffset = -xoffset;
1879   src->yoffset = -dl->top_clip;
1880   src->width = 0;
1881   src->height = 0;
1882
1883   if (start_pixpos >=0 && start_pixpos > xpos)
1884     {
1885       /* Oops, we're asking for a start outside of the displayable
1886          area. */
1887       if (start_pixpos > xpos + width)
1888         return 0;
1889       dest->xpos = start_pixpos;
1890       dest->width -= (start_pixpos - xpos);
1891       /* Offsets are -ve when we want to clip pixels off the displayed
1892          glyph. */
1893       src->xoffset -= (start_pixpos - xpos);
1894     }
1895
1896   return 1;
1897 }
1898
1899 /*****************************************************************************
1900  redisplay_clear_top_of_window
1901
1902  If window is topmost, clear the internal border above it.
1903  ****************************************************************************/
1904 static void
1905 redisplay_clear_top_of_window (struct window *w)
1906 {
1907   Lisp_Object window;
1908   XSETWINDOW (window, w);
1909
1910   if (!NILP (Fwindow_highest_p (window)))
1911     {
1912       struct frame *f = XFRAME (w->frame);
1913       int x, y, width, height;
1914
1915       x = w->pixel_left;
1916       width = w->pixel_width;
1917
1918       if (window_is_leftmost (w))
1919         {
1920           x -= FRAME_BORDER_WIDTH (f);
1921           width += FRAME_BORDER_WIDTH (f);
1922         }
1923       if (window_is_rightmost (w))
1924         width += FRAME_BORDER_WIDTH (f);
1925
1926       y = FRAME_TOP_BORDER_START (f) - 1;
1927       height = FRAME_BORDER_HEIGHT (f) + 1;
1928
1929       redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1930     }
1931 }
1932
1933 /*****************************************************************************
1934  redisplay_clear_to_window_end
1935
1936  Clear the area between ypos1 and ypos2.  Each margin area and the
1937  text area is handled separately since they may each have their own
1938  background color.
1939  ****************************************************************************/
1940 void
1941 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1942 {
1943   struct frame *f = XFRAME (w->frame);
1944   struct device *d = XDEVICE (f->device);
1945
1946   if (HAS_DEVMETH_P (d, clear_to_window_end))
1947     DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1948   else
1949     {
1950       int height = ypos2 - ypos1;
1951
1952       if (height)
1953         {
1954           Lisp_Object window;
1955           int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1956           layout_bounds bounds;
1957
1958           bounds = calculate_display_line_boundaries (w, bflag);
1959           XSETWINDOW (window, w);
1960
1961           if (window_is_leftmost (w))
1962             redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1963                                     ypos1, FRAME_BORDER_WIDTH (f), height);
1964
1965           if (bounds.left_in - bounds.left_out > 0)
1966             redisplay_clear_region (window,
1967                                     get_builtin_face_cache_index (w, Vleft_margin_face),
1968                                     bounds.left_out, ypos1,
1969                                     bounds.left_in - bounds.left_out, height);
1970
1971           if (bounds.right_in - bounds.left_in > 0)
1972             redisplay_clear_region (window,
1973                                     DEFAULT_INDEX,
1974                                     bounds.left_in, ypos1,
1975                                     bounds.right_in - bounds.left_in, height);
1976
1977           if (bounds.right_out - bounds.right_in > 0)
1978             redisplay_clear_region (window,
1979                                     get_builtin_face_cache_index (w, Vright_margin_face),
1980                                     bounds.right_in, ypos1,
1981                                     bounds.right_out - bounds.right_in, height);
1982
1983           if (window_is_rightmost (w))
1984             redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1985                                     ypos1, FRAME_BORDER_WIDTH (f), height);
1986         }
1987     }
1988 }
1989
1990 /*****************************************************************************
1991  redisplay_clear_bottom_of_window
1992
1993  Clear window from right below the last display line to right above
1994  the modeline.  The calling function can limit the area actually
1995  erased by setting min_start and/or max_end to positive values.
1996  ****************************************************************************/
1997 void
1998 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1999                                   int min_start, int max_end)
2000 {
2001   struct frame *f = XFRAME (w->frame);
2002   int ypos1, ypos2;
2003   int ddla_len = Dynarr_length (ddla);
2004
2005   ypos2 = WINDOW_TEXT_BOTTOM (w);
2006 #ifdef HAVE_SCROLLBARS
2007   /* This adjustment is to catch the intersection of any scrollbars. */
2008   if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
2009     ypos2 += window_scrollbar_height (w);
2010 #endif
2011
2012   if (ddla_len)
2013     {
2014       if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
2015         {
2016           ypos1 = WINDOW_TEXT_TOP (w);
2017 #ifdef HAVE_SCROLLBARS
2018           /* This adjustment is to catch the intersection of any scrollbars. */
2019           if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
2020             ypos1 -= window_scrollbar_height (w);
2021 #endif
2022         }
2023       else
2024         {
2025           struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
2026           ypos1 = dl->ypos + dl->descent - dl->clip;
2027         }
2028     }
2029   else
2030     ypos1 = WINDOW_TEXT_TOP (w);
2031
2032   /* #### See if this can be made conditional on the frame
2033      changing size. */
2034   if (MINI_WINDOW_P (w))
2035     ypos2 += FRAME_BORDER_HEIGHT (f);
2036
2037   if (min_start >= 0 && ypos1 < min_start)
2038     ypos1 = min_start;
2039   if (max_end >= 0 && ypos2 > max_end)
2040     ypos2 = max_end;
2041
2042   if (ypos2 <= ypos1)
2043     return;
2044
2045   redisplay_clear_to_window_end (w, ypos1, ypos2);
2046 }
2047
2048 /*****************************************************************************
2049  redisplay_update_line
2050
2051  This is used during incremental updates to update a single line and
2052  correct the offsets on all lines below it.  At the moment
2053  update_values is false if we are only updating the modeline.
2054  ****************************************************************************/
2055 void
2056 redisplay_update_line (struct window *w, int first_line, int last_line,
2057                        int update_values)
2058 {
2059   struct frame *f = XFRAME (w->frame);
2060   struct device *d = XDEVICE (f->device);
2061
2062   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2063   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2064
2065   MAYBE_DEVMETH (d, window_output_begin, (w));
2066
2067   while (first_line <= last_line)
2068     {
2069       Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
2070                            Dynarr_atp (cdla, first_line)->bufpos);
2071       Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
2072                            Dynarr_atp (ddla, first_line)->bufpos);
2073
2074       assert (Dynarr_length (cdla) == Dynarr_length (ddla));
2075
2076       /* Output the changes. */
2077       output_display_line (w, cdla, ddla, first_line, -1, -1);
2078
2079       /* Update the offsets. */
2080       if (update_values)
2081         {
2082           int cur_line = first_line + 1;
2083           while (cur_line < Dynarr_length (cdla))
2084             {
2085               Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
2086               Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
2087               cur_line++;
2088             }
2089         }
2090
2091       /* Update the window_end_pos and other settings. */
2092       if (update_values)
2093         {
2094           w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
2095
2096           if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
2097             {
2098               w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2099               w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2100             }
2101         }
2102
2103       first_line++;
2104     }
2105
2106   /* Update the window max line length.  We have to scan the entire
2107      set of display lines otherwise we might not detect if the max is
2108      supposed to shrink. */
2109   if (update_values)
2110     {
2111       int line = 0;
2112
2113       w->max_line_len = 0;
2114       while (line < Dynarr_length (ddla))
2115         {
2116           struct display_line *dl = Dynarr_atp (ddla, line);
2117
2118           if (!dl->modeline)
2119             w->max_line_len = max (dl->num_chars, w->max_line_len);
2120
2121           line++;
2122         }
2123     }
2124
2125   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2126   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2127   Fset_marker (w->last_point[CURRENT_DISP],
2128                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2129   Fset_marker (w->last_start[CURRENT_DISP],
2130                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2131
2132   /* We don't bother updating the vertical scrollbars here.  This
2133      gives us a performance increase while having minimal loss of
2134      quality to the scrollbar slider size and position since when this
2135      function is called we know that the changes to the buffer were
2136      very localized.  We have to update the horizontal scrollbars,
2137      though, because this routine could cause a change which has a
2138      larger impact on their sizing. */
2139   /* #### See if we can get away with only calling this if
2140      max_line_len is greater than the window_char_width. */
2141 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
2142   {
2143     extern int stupid_vertical_scrollbar_drag_hack;
2144
2145     update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
2146     stupid_vertical_scrollbar_drag_hack = 1;
2147   }
2148 #endif
2149
2150   redisplay_redraw_cursor (f, 0);
2151   MAYBE_DEVMETH (d, window_output_end, (w));
2152 }
2153
2154 /*****************************************************************************
2155  redisplay_output_window
2156
2157  For the given window W, ensure that the current display lines are
2158  equal to the desired display lines, outputing changes as necessary.
2159
2160  #### Fuck me.  This just isn't going to cut it for tty's.  The output
2161  decisions for them must be based on the contents of the entire frame
2162  because that is how the available output capabilities think.  The
2163  solution is relatively simple.  Create redisplay_output_frame.  This
2164  will basically merge all of the separate window display structs into
2165  a single one for the frame.  This combination structure will be able
2166  to be passed to the same output_display_line which works for windows
2167  on X frames and the right things will happen.  It just takes time to
2168  do.
2169  ****************************************************************************/
2170 void
2171 redisplay_output_window (struct window *w)
2172 {
2173   struct frame *f = XFRAME (w->frame);
2174   struct device *d = XDEVICE (f->device);
2175
2176   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2177   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2178
2179   int cdla_len = Dynarr_length (cdla);
2180   int ddla_len = Dynarr_length (ddla);
2181
2182   int line;
2183   int need_to_clear_bottom = 0;
2184   int need_to_clear_start = -1;
2185   int need_to_clear_end = -1;
2186
2187   /* Backgrounds may have changed or windows may have gone away
2188      leaving dividers lying around. */
2189   if (f->faces_changed
2190       || f->windows_structure_changed
2191       || w->shadow_thickness_changed)
2192     need_to_clear_bottom = 1;
2193
2194   /* The first thing we do is determine if we are going to need to
2195      clear the bottom of the window.  We only need to do this if the
2196      bottom of the current display lines is below the bottom of the
2197      desired display lines.  Note that the number of lines is
2198      irrelevant.  Only the position matters.  We also clear to the
2199      bottom of the window if the modeline has shifted position. */
2200   /* #### We can't blindly not clear the bottom if f->clear is true
2201      since there might be a window-local background.  However, for
2202      those cases where there isn't, clearing the end of the window in
2203      this case sucks. */
2204   if (!need_to_clear_bottom)
2205     {
2206       struct display_line *cdl, *ddl;
2207
2208       /* If the modeline has changed position or size, clear the bottom
2209          of the window. */
2210       if (!need_to_clear_bottom)
2211         {
2212           cdl = ddl = 0;
2213
2214           if (cdla_len)
2215             cdl = Dynarr_atp (cdla, 0);
2216           if (ddla_len)
2217             ddl = Dynarr_atp (ddla, 0);
2218
2219           if (!cdl || !ddl)
2220             need_to_clear_bottom = 1;
2221           else if ((!cdl->modeline && ddl->modeline)
2222                    || (cdl->modeline && !ddl->modeline))
2223             need_to_clear_bottom = 1;
2224           else if (cdl->ypos != ddl->ypos ||
2225                    cdl->ascent != ddl->ascent ||
2226                    cdl->descent != ddl->descent ||
2227                    cdl->clip != ddl->clip)
2228             need_to_clear_bottom = 1;
2229
2230           /* #### This kludge is to make sure the modeline shadows get
2231              redrawn if the modeline position shifts. */
2232           if (need_to_clear_bottom)
2233             w->shadow_thickness_changed = 1;
2234         }
2235
2236       if (!need_to_clear_bottom)
2237         {
2238           cdl = ddl = 0;
2239
2240           if (cdla_len)
2241             cdl = Dynarr_atp (cdla, cdla_len - 1);
2242           if (ddla_len)
2243             ddl = Dynarr_atp (ddla, ddla_len - 1);
2244
2245           if (!cdl || !ddl)
2246             need_to_clear_bottom = 1;
2247           else
2248             {
2249               int cdl_bottom, ddl_bottom;
2250
2251               cdl_bottom = cdl->ypos + cdl->descent;
2252               ddl_bottom = ddl->ypos + ddl->descent;
2253
2254               if (cdl_bottom > ddl_bottom)
2255                 {
2256                   need_to_clear_bottom = 1;
2257                   need_to_clear_start = ddl_bottom;
2258                   need_to_clear_end = cdl_bottom;
2259                 }
2260             }
2261         }
2262     }
2263
2264   /* Perform any output initialization. */
2265   MAYBE_DEVMETH (d, window_output_begin, (w));
2266
2267   /* If the window's structure has changed clear the internal border
2268      above it if it is topmost (the function will check). */
2269   if (f->windows_structure_changed)
2270     redisplay_clear_top_of_window (w);
2271
2272   /* Output each line. */
2273   for (line = 0; line < Dynarr_length (ddla); line++)
2274     {
2275       output_display_line (w, cdla, ddla, line, -1, -1);
2276     }
2277
2278   /* If the number of display lines has shrunk, adjust. */
2279   if (cdla_len > ddla_len)
2280     {
2281       Dynarr_length (cdla) = ddla_len;
2282     }
2283
2284   /* Output a vertical divider between windows, if necessary. */
2285   if (window_needs_vertical_divider (w)
2286       && (f->windows_structure_changed || f->clear))
2287     {
2288       MAYBE_DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
2289     }
2290
2291   /* Clear the rest of the window, if necessary. */
2292   if (need_to_clear_bottom)
2293     {
2294       redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
2295                                         need_to_clear_end);
2296     }
2297
2298   w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
2299   Fset_marker (w->start[CURRENT_DISP],
2300                make_int (marker_position (w->start[DESIRED_DISP])),
2301                w->buffer);
2302   Fset_marker (w->pointm[CURRENT_DISP],
2303                make_int (marker_position (w->pointm[DESIRED_DISP])),
2304                w->buffer);
2305   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2306   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2307   Fset_marker (w->last_start[CURRENT_DISP],
2308                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2309   Fset_marker (w->last_point[CURRENT_DISP],
2310                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2311   w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2312   w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2313   w->shadow_thickness_changed = 0;
2314
2315   set_window_display_buffer (w, XBUFFER (w->buffer));
2316   find_window_mirror (w)->truncate_win = window_truncation_on (w);
2317
2318   /* Overkill on invalidating the cache.  It is very bad for it to not
2319      get invalidated when it should be. */
2320   INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
2321
2322   redisplay_redraw_cursor (f, 0);
2323   MAYBE_DEVMETH (d, window_output_end, (w));
2324
2325 #ifdef HAVE_SCROLLBARS
2326   update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
2327 #endif
2328 }
2329
2330 /*****************************************************************************
2331  bevel_modeline
2332
2333  Draw a 3d border around the modeline on window W.
2334  ****************************************************************************/
2335 void
2336 bevel_modeline (struct window *w, struct display_line *dl)
2337 {
2338   struct frame *f = XFRAME (w->frame);
2339   struct device *d = XDEVICE (f->device);
2340   int x, y, width, height;
2341   int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2342   enum edge_style style;
2343
2344   x = WINDOW_MODELINE_LEFT (w);
2345   width = WINDOW_MODELINE_RIGHT (w) - x;
2346   y = dl->ypos - dl->ascent - shadow_thickness;
2347   height = dl->ascent + dl->descent + 2 * shadow_thickness;
2348
2349   if (XINT (w->modeline_shadow_thickness) < 0)
2350     {
2351       style = EDGE_BEVEL_IN;
2352     }
2353   else
2354     {
2355       style = EDGE_BEVEL_OUT;
2356     }
2357
2358   MAYBE_DEVMETH (d, bevel_area,
2359                  (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,
2360                   EDGE_ALL, style));
2361 }