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