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