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