XEmacs 21.2.38 (Peisino)
[chise/xemacs-chise.git.1] / src / redisplay-output.c
1 /* Synchronize redisplay structures and output changes.
2    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3    Copyright (C) 1995, 1996 Ben Wing.
4    Copyright (C) 1996 Chuck Thompson.
5    Copyright (C) 1999 Andy Piper.
6
7 This file is part of XEmacs.
8
9 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with XEmacs; see the file COPYING.  If not, write to
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 /* Synched up with: Not in FSF. */
25
26 /* This file has been Mule-ized. */
27
28 /* Author: Chuck Thompson */
29
30 /* Heavily hacked for modularity, gutter and subwindow support by Andy
31    Piper. */
32
33 #include <config.h>
34 #include "lisp.h"
35
36 #include "buffer.h"
37 #include "window.h"
38 #include "frame.h"
39 #include "device.h"
40 #include "glyphs.h"
41 #include "redisplay.h"
42 #include "faces.h"
43 #include "gutter.h"
44
45 static int compare_runes (struct window *w, struct rune *crb,
46                           struct rune *drb);
47 static void redraw_cursor_in_window (struct window *w,
48                                      int run_end_begin_glyphs);
49 static void redisplay_output_display_block (struct window *w, struct display_line *dl,
50                                             int block, int start, int end, int start_pixpos,
51                                             int cursor_start, int cursor_width,
52                                             int cursor_height);
53 static void redisplay_normalize_display_box (struct display_box* dest,
54                                              struct display_glyph_area* src);
55 static int redisplay_display_boxes_in_window_p (struct window* w,
56                                                 struct display_box* db,
57                                                 struct display_glyph_area* dga);
58 static void redisplay_clear_clipped_region (Lisp_Object locale, face_index findex,
59                                             struct display_box* dest,
60                                             struct display_glyph_area* glyphsrc,
61                                             int fullheight_p, Lisp_Object);
62
63 /*****************************************************************************
64  sync_rune_structs
65
66  Synchronize the given rune blocks.
67  ****************************************************************************/
68 static void
69 sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra)
70 {
71   int rune_elt;
72   int max_move = ((Dynarr_length (dra) > Dynarr_largest (cra))
73                   ? Dynarr_largest (cra)
74                   : Dynarr_length (dra));
75
76   if (max_move)
77     {
78       /* #### Doing this directly breaks the encapsulation.  But, the
79          running time of this function has a measurable impact on
80          redisplay performance so avoiding all excess overhead is a
81          good thing.  Is all of this true? */
82       memcpy (cra->base, dra->base, sizeof (struct rune) * max_move);
83       Dynarr_set_size (cra, max_move);
84     }
85   else
86     Dynarr_reset (cra);
87
88   for (rune_elt = max_move; rune_elt < Dynarr_length (dra); rune_elt++)
89     {
90       struct rune rb, *crb;
91       struct rune *drb = Dynarr_atp (dra, rune_elt);
92
93       crb = &rb;
94       memcpy (crb, drb, sizeof (struct rune));
95       Dynarr_add (cra, *crb);
96     }
97 }
98
99 /*****************************************************************************
100  sync_display_line_structs
101
102  For the given LINE in window W, make the current display line equal
103  the desired display line.
104  ****************************************************************************/
105 void
106 sync_display_line_structs (struct window *w, int line, int do_blocks,
107                            display_line_dynarr *cdla,
108                            display_line_dynarr *ddla)
109 {
110   int cdla_len = Dynarr_length (cdla);
111
112   struct display_line dl, *clp, *dlp;
113   int db_elt;
114
115   dlp = Dynarr_atp (ddla, line);
116   if (line >= Dynarr_largest (cdla))
117     {
118       clp = &dl;
119       clp->display_blocks = Dynarr_new (display_block);
120     }
121   else
122     {
123       clp = Dynarr_atp (cdla, line);
124       if (clp->display_blocks)
125         Dynarr_reset (clp->display_blocks);
126       if (clp->left_glyphs)
127         {
128           Dynarr_free (clp->left_glyphs);
129           clp->left_glyphs = 0;
130         }
131       if (clp->right_glyphs)
132         {
133           Dynarr_free (clp->right_glyphs);
134           clp->right_glyphs = 0;
135         }
136     }
137   {
138     display_block_dynarr *tdb = clp->display_blocks;
139
140     memcpy (clp, dlp, sizeof (struct display_line));
141     clp->display_blocks = tdb;
142     clp->left_glyphs = 0;
143     clp->right_glyphs = 0;
144   }
145
146   if (!do_blocks && line >= cdla_len)
147     {
148       Dynarr_add (cdla, *clp);
149       return;
150     }
151
152   for (db_elt = 0; db_elt < Dynarr_length (dlp->display_blocks); db_elt++)
153     {
154       struct display_block db, *cdb;
155       struct display_block *ddb = Dynarr_atp (dlp->display_blocks, db_elt);
156
157       if (db_elt >= Dynarr_largest (clp->display_blocks))
158         {
159           cdb = &db;
160           memcpy (cdb, ddb, sizeof (struct display_block));
161           cdb->runes = Dynarr_new (rune);
162           Dynarr_add (clp->display_blocks, *cdb);
163         }
164       else
165         {
166           rune_dynarr *tr;
167
168           cdb = Dynarr_atp (clp->display_blocks, db_elt);
169           tr = cdb->runes;
170           memcpy (cdb, ddb, sizeof (struct display_block));
171           cdb->runes = tr;
172           Dynarr_increment (clp->display_blocks);
173         }
174
175       sync_rune_structs (w, cdb->runes, ddb->runes);
176     }
177
178   if (line >= cdla_len)
179     Dynarr_add (cdla, *clp);
180 }
181
182 /*****************************************************************************
183  compare_runes
184
185  Compare to runes to see if each of their fields is equal.  If so,
186  return true otherwise return false.
187  ****************************************************************************/
188 static int
189 compare_runes (struct window *w, struct rune *crb, struct rune *drb)
190 {
191   /* Do not compare the values of bufpos and endpos.  They do not
192      affect the display characteristics. */
193
194   /* Note: (hanoi 6) spends 95% of its time in redisplay, and about
195      30% here. Not using bitfields for rune.type alone gives a redisplay
196      speed up of 10%.
197
198      #### In profile arcs run of a normal Gnus session this function
199      is run 6.76 million times, only to return 1 in 6.73 million of
200      those.
201
202      In addition a quick look GCC sparc assembly shows that GCC is not
203      doing a good job here.
204      1. The function is not inlined (too complicated?)
205      2. It seems to be reloading the crb and drb variables all the
206      time.
207      3. It doesn't seem to notice that the second half of these if's
208      are really a switch statement.
209
210      So I (JV) conjecture
211
212      #### It would really be worth it to arrange for this function to
213      be (almost) a single call to memcmp. */
214
215   if (crb->xpos != drb->xpos)
216     return 0;
217   else if (crb->width != drb->width)
218     return 0;
219   else if (crb->cursor_type != drb->cursor_type)
220     return 0;
221   else if (crb->type != drb->type)
222     return 0;
223   else if (crb->type == RUNE_CHAR &&
224            (crb->object.chr.ch != drb->object.chr.ch))
225     return 0;
226   else if (crb->type == RUNE_HLINE &&
227            (crb->object.hline.thickness != drb->object.hline.thickness ||
228             crb->object.hline.yoffset != drb->object.hline.yoffset))
229     return 0;
230   else if (crb->type == RUNE_DGLYPH &&
231            (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
232             !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
233             crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
234     return 0;
235   /* Only check dirtiness if we know something has changed. */
236   else if (crb->type == RUNE_DGLYPH &&
237            (XGLYPH_DIRTYP (crb->object.dglyph.glyph) ||
238             crb->findex != drb->findex))
239     {
240       /* We need some way of telling redisplay_output_layout () that the
241          only reason we are outputting it is because something has
242          changed internally. That way we can optimize whether we need
243          to clear the layout first and also only output the components
244          that have changed. The image_instance dirty flag and
245          display_hash are no good to us because these will invariably
246          have been set anyway if the layout has changed. So it looks
247          like we need yet another change flag that we can set here and
248          then clear in redisplay_output_layout (). */
249       Lisp_Object window, image;
250       Lisp_Image_Instance* ii;
251       XSETWINDOW (window, w);
252       image = glyph_image_instance (crb->object.dglyph.glyph,
253                                     window, ERROR_ME_NOT, 1);
254
255       if (!IMAGE_INSTANCEP (image))
256         return 0;
257       ii = XIMAGE_INSTANCE (image);
258
259       if (TEXT_IMAGE_INSTANCEP (image) &&
260           (crb->findex != drb->findex ||
261            WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
262         return 0;
263
264       /* It is quite common for the two glyphs to be EQ since in many
265          cases they will actually be the same object. This does not
266          mean, however, that nothing has changed. We therefore need to
267          check the current hash of the glyph against the last recorded
268          display hash and the pending display items. See
269          update_subwindow (). */
270       if (image_instance_changed (image) ||
271           crb->findex != drb->findex ||
272           WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
273         {
274           /* We now 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 redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height,
1166                                         Lisp_Object ignored_window)
1167 {
1168   Lisp_Object rest;
1169
1170   LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
1171     {
1172       Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
1173       if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii)
1174           &&
1175           IMAGE_INSTANCE_DISPLAY_X (ii)
1176           + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) > x
1177           &&
1178           IMAGE_INSTANCE_DISPLAY_X (ii) < x + width
1179           &&
1180           IMAGE_INSTANCE_DISPLAY_Y (ii)
1181           + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > y
1182           &&
1183           IMAGE_INSTANCE_DISPLAY_Y (ii) < y + height
1184           &&
1185           !EQ (XCAR (rest), ignored_window))
1186         {
1187           unmap_subwindow (XCAR (rest));
1188         }
1189     }
1190 }
1191
1192 /****************************************************************************
1193  redisplay_unmap_subwindows_maybe
1194
1195  Potentially subwindows from the area in the box defined by the given
1196  parameters.
1197  ****************************************************************************/
1198 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1199 {
1200   if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))))
1201     {
1202       redisplay_unmap_subwindows (f, x, y, width, height, Qnil);
1203     }
1204 }
1205
1206 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
1207                                                   int height, Lisp_Object subwindow)
1208 {
1209   if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))))
1210     {
1211       redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
1212     }
1213 }
1214
1215 /****************************************************************************
1216  redisplay_output_subwindow
1217
1218  output a subwindow.  This code borrows heavily from the pixmap stuff,
1219  although is much simpler not needing to account for partial
1220  pixmaps, backgrounds etc.
1221  ****************************************************************************/
1222 void
1223 redisplay_output_subwindow (struct window *w,
1224                             Lisp_Object image_instance,
1225                             struct display_box* db, struct display_glyph_area* dga,
1226                             face_index findex, int cursor_start, int cursor_width,
1227                             int cursor_height)
1228 {
1229   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1230   Lisp_Object window;
1231   struct display_glyph_area sdga;
1232
1233   dga->height = IMAGE_INSTANCE_HEIGHT (p);
1234   dga->width = IMAGE_INSTANCE_WIDTH (p);
1235
1236   /* The first thing we are going to do is update the display
1237      characteristics of the subwindow. This also clears the dirty
1238      flags as a side effect. */
1239   redisplay_subwindow (image_instance);
1240
1241   /* This makes the glyph area fit into the display area. */
1242   if (!redisplay_normalize_glyph_area (db, dga))
1243     return;
1244
1245   XSETWINDOW (window, w);
1246
1247   /* Clear the area the subwindow is going into. */
1248   redisplay_clear_clipped_region (window, findex,
1249                                   db, dga, 0, image_instance);
1250
1251   /* This shrinks the display box to exactly enclose the glyph
1252      area. */
1253   redisplay_normalize_display_box (db, dga);
1254
1255   /* if we can't view the whole window we can't view any of it. We
1256      have to be careful here since we may be being asked to display
1257      part of a subwindow, the rest of which is on-screen as well. We
1258      need to allow this case and map the entire subwindow. We also
1259      need to be careful since the subwindow could be outside the
1260      window in the gutter or modeline - we also need to allow these
1261      cases.*/
1262   sdga.xoffset = -dga->xoffset;
1263   sdga.yoffset = -dga->yoffset;
1264   sdga.height = IMAGE_INSTANCE_HEIGHT (p);
1265   sdga.width = IMAGE_INSTANCE_WIDTH (p);
1266
1267   if (redisplay_display_boxes_in_window_p (w, db, &sdga) == 0
1268       ||
1269       /* We only want to do full subwindow display for windows that
1270          are completely in the gutter, otherwise we must clip to be
1271          safe. */
1272       display_boxes_in_gutter_p (XFRAME (w->frame), db, &sdga) <= 0)
1273     {
1274       map_subwindow (image_instance, db->xpos, db->ypos, dga);
1275     }
1276   else
1277     {
1278       sdga.xoffset = sdga.yoffset = 0;
1279       map_subwindow (image_instance, db->xpos - dga->xoffset,
1280                      db->ypos - dga->yoffset, &sdga);
1281     }
1282 }
1283
1284 /****************************************************************************
1285  redisplay_output_layout
1286
1287  Output a widget hierarchy. This can safely call itself recursively.
1288
1289  The complexity of outputting layouts is deciding whether to do it or
1290  not. Consider a layout enclosing some text, the text changes and is
1291  marked as dirty, but the enclosing layout has not been marked as
1292  dirty so no updates occur and the text will potentially be truncated.
1293  Alternatively we hold a back pointer in the image instance to the
1294  parent and mark the parent as dirty. But the layout code assumes that
1295  if the layout is dirty then the whole layout should be redisplayed,
1296  so we then get lots of flashing even though only the text has changed
1297  size. Of course if the text shrinks in size then we do actually need
1298  to redisplay the layout to repaint the exposed area. So what happens
1299  if we make a non-structural change like changing color? Either we
1300  redisplay everything, or we redisplay nothing. These are exactly the
1301  issues lwlib has to grapple with. We really need to know what has
1302  actually changed and make a layout decision based on that. We also
1303  really need to know what has changed so that we can only make the
1304  necessary changes in update_subwindow.  This has all now been
1305  implemented, Viva la revolution!
1306  ****************************************************************************/
1307 void
1308 redisplay_output_layout (Lisp_Object domain,
1309                          Lisp_Object image_instance,
1310                          struct display_box* db, struct display_glyph_area* dga,
1311                          face_index findex, int cursor_start, int cursor_width,
1312                          int cursor_height)
1313 {
1314   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1315   Lisp_Object rest, window = DOMAIN_WINDOW (domain);
1316   Emchar_dynarr *buf = Dynarr_new (Emchar);
1317   struct window *w = XWINDOW (window);
1318   struct device *d = DOMAIN_XDEVICE (domain);
1319   int layout_height, layout_width;
1320
1321   layout_height = glyph_height (image_instance, domain);
1322   layout_width = glyph_width (image_instance, domain);
1323
1324   dga->height = layout_height;
1325   dga->width = layout_width;
1326 #ifdef DEBUG_WIDGET_OUTPUT
1327   printf ("outputing layout glyph %p\n", p);
1328 #endif
1329   /* This makes the glyph area fit into the display area. */
1330   if (!redisplay_normalize_glyph_area (db, dga))
1331     return;
1332
1333   /* Highly dodgy optimization. We want to only output the whole
1334      layout if we really have to. */
1335   if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p)
1336       || IMAGE_INSTANCE_LAYOUT_CHANGED (p)
1337       || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
1338       || IMAGE_INSTANCE_SIZE_CHANGED (p)
1339       || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
1340     {
1341       /* First clear the area we are drawing into. This is the easiest
1342          thing to do since we have many gaps that we have to make sure are
1343          filled in. */
1344       redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil);
1345
1346       /* Output a border if required */
1347       if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1348         {
1349           int edges = 0;
1350           enum edge_style style;
1351           int ypos = db->ypos;
1352           int height = dga->height;
1353
1354           if (dga->xoffset >= 0)
1355             edges |= EDGE_LEFT;
1356           if (dga->width - dga->xoffset == layout_width)
1357             edges |= EDGE_RIGHT;
1358           if (dga->yoffset >= 0)
1359             edges |= EDGE_TOP;
1360           if (dga->height - dga->yoffset == layout_height)
1361             edges |= EDGE_BOTTOM;
1362
1363           if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
1364             style = EDGE_ETCHED_IN;
1365           else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
1366             style = EDGE_ETCHED_OUT;
1367           else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in))
1368             style = EDGE_BEVEL_IN;
1369           else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1370             {
1371               style = EDGE_ETCHED_IN;
1372               if (edges & EDGE_TOP)
1373                 {
1374                   ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1375                   height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1376                 }
1377             }
1378           else
1379             style = EDGE_BEVEL_OUT;
1380
1381           MAYBE_DEVMETH (d, bevel_area,
1382                          (w, findex, db->xpos,
1383                           ypos,
1384                           dga->width, height, 2, edges, style));
1385         }
1386     }
1387
1388   /* This shrinks the display box to exactly enclose the glyph
1389      area. */
1390   redisplay_normalize_display_box (db, dga);
1391
1392   /* Flip through the widgets in the layout displaying as necessary */
1393   LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
1394     {
1395       Lisp_Object child = glyph_image_instance (XCAR (rest), image_instance,
1396                                                 ERROR_ME_NOT, 1);
1397
1398       struct display_box cdb;
1399       /* For losing HP-UX */
1400       cdb.xpos = db->xpos;
1401       cdb.ypos = db->ypos;
1402       cdb.width = db->width;
1403       cdb.height = db->height;
1404
1405       /* First determine if the image is visible at all */
1406       if (IMAGE_INSTANCEP (child))
1407         {
1408           Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
1409
1410           /* The enclosing layout offsets are +ve at this point */
1411           struct display_glyph_area cdga;
1412           cdga.xoffset  = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
1413           cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
1414           cdga.width = glyph_width (child, image_instance);
1415           cdga.height = glyph_height (child, image_instance);
1416
1417           IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) =
1418             IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p);
1419
1420           /* Although normalization is done by the output routines
1421              we have to do it here so that they don't try and
1422              clear all of db. This is true below also. */
1423           if (redisplay_normalize_glyph_area (&cdb, &cdga))
1424             {
1425               redisplay_normalize_display_box (&cdb, &cdga);
1426               /* Since the display boxes will now be totally in the
1427                  window if they are visible at all we can now check this easily. */
1428               if (cdb.xpos < db->xpos || cdb.ypos < db->ypos
1429                   || cdb.xpos + cdb.width > db->xpos + db->width
1430                   || cdb.ypos + cdb.height > db->ypos + db->height)
1431                 continue;
1432               /* We have to invert the offset here as normalization
1433                  will have made them positive which the output
1434                  routines will treat as a truly +ve offset. */
1435               cdga.xoffset = -cdga.xoffset;
1436               cdga.yoffset = -cdga.yoffset;
1437
1438               switch (IMAGE_INSTANCE_TYPE (childii))
1439                 {
1440                 case IMAGE_TEXT:
1441                   {
1442                     /* #### This is well hacked and could use some
1443                        generalisation.*/
1444                     if (redisplay_normalize_glyph_area (&cdb, &cdga)
1445                         &&
1446                         (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1447                          IMAGE_INSTANCE_DIRTYP (childii)))
1448                       {
1449                         struct display_line dl; /* this is fake */
1450                         Lisp_Object string =
1451                           IMAGE_INSTANCE_TEXT_STRING (childii);
1452                         unsigned char charsets[NUM_LEADING_BYTES];
1453                         struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
1454
1455                         find_charsets_in_bufbyte_string (charsets,
1456                                                          XSTRING_DATA (string),
1457                                                          XSTRING_LENGTH (string));
1458                         ensure_face_cachel_complete (cachel, window, charsets);
1459
1460                         convert_bufbyte_string_into_emchar_dynarr
1461                           (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1462
1463                         redisplay_normalize_display_box (&cdb, &cdga);
1464                         /* Offsets are now +ve again so be careful
1465                            when fixing up the display line. */
1466                         xzero (dl);
1467                         /* Munge boxes into display lines. */
1468                         dl.ypos = (cdb.ypos - cdga.yoffset)
1469                           + glyph_ascent (child, image_instance);
1470                         dl.ascent = glyph_ascent (child, image_instance);
1471                         dl.descent = glyph_descent (child, image_instance);
1472                         dl.top_clip = cdga.yoffset;
1473                         dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1474                         /* output_string doesn't understand offsets in
1475                            the same way as other routines - we have to
1476                            add the offset to the width so that we
1477                            output the full string. */
1478                         MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1479                                                           cdga.xoffset, cdb.xpos,
1480                                                           cdga.width + cdga.xoffset,
1481                                                           findex, 0, 0, 0, 0));
1482                         Dynarr_reset (buf);
1483                       }
1484                   }
1485                   break;
1486
1487                 case IMAGE_MONO_PIXMAP:
1488                 case IMAGE_COLOR_PIXMAP:
1489                   if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii)
1490                       || IMAGE_INSTANCE_DIRTYP (childii))
1491                     redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1492                                              0, 0, 0, 0);
1493                   break;
1494
1495                 case IMAGE_WIDGET:
1496                   if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (childii), Qlayout))
1497                     {
1498                       redisplay_output_layout (image_instance, child, &cdb, &cdga, findex,
1499                                                0, 0, 0);
1500                       break;
1501                     }
1502                 case IMAGE_SUBWINDOW:
1503                   if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1504                       IMAGE_INSTANCE_DIRTYP (childii))
1505                     redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1506                                                 0, 0, 0);
1507                   break;
1508
1509                 case IMAGE_NOTHING:
1510                   /* nothing is as nothing does */
1511                   break;
1512
1513                 case IMAGE_POINTER:
1514                 default:
1515                   abort ();
1516                 }
1517             }
1518           IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0;
1519         }
1520     }
1521
1522   /* Update any display properties. I'm not sure whether this actually
1523      does anything for layouts except clear the changed flags. */
1524   redisplay_subwindow (image_instance);
1525
1526   Dynarr_free (buf);
1527 }
1528
1529 /****************************************************************************
1530  redisplay_output_pixmap
1531
1532
1533  output a pixmap.
1534  ****************************************************************************/
1535 void
1536 redisplay_output_pixmap (struct window *w,
1537                          Lisp_Object image_instance,
1538                          struct display_box* db, struct display_glyph_area* dga,
1539                          face_index findex, int cursor_start, int cursor_width,
1540                          int cursor_height, int offset_bitmap)
1541 {
1542   struct frame *f = XFRAME (w->frame);
1543   struct device *d = XDEVICE (f->device);
1544   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1545   Lisp_Object window;
1546   XSETWINDOW (window, w);
1547
1548   dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1549   dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1550
1551   /* This makes the glyph area fit into the display area. */
1552   if (!redisplay_normalize_glyph_area (db, dga))
1553     return;
1554
1555   /* Clear the area the pixmap is going into.  The pixmap itself will
1556      always take care of the full width.  We don't want to clear where
1557      it is going to go in order to avoid flicker.  So, all we have to
1558      take care of is any area above or below the pixmap. If the pixmap
1559      has a mask in which case we have to clear the whole damn thing
1560      since we can't yet clear just the area not included in the
1561      mask. */
1562   if (!offset_bitmap)
1563     {
1564       redisplay_clear_clipped_region (window, findex,
1565                                       db, dga,
1566                                       (IMAGE_INSTANCE_PIXMAP_MASK (p) != 0),
1567                                       Qnil);
1568
1569       /* This shrinks the display box to exactly enclose the glyph
1570          area. */
1571       redisplay_normalize_display_box (db, dga);
1572     }
1573   assert (db->xpos >= 0 && db->ypos >= 0);
1574
1575   MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1576                                     db, dga,
1577                                     findex, cursor_start,
1578                                     cursor_width, cursor_height,
1579                                     offset_bitmap));
1580 }
1581
1582 /****************************************************************************
1583  redisplay_clear_region
1584
1585  Clear the area in the box defined by the given parameters using the
1586  given face. This has been generalised so that subwindows can be
1587  coped with effectively.
1588  ****************************************************************************/
1589 void
1590 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1591                         int width, int height)
1592 {
1593   struct window *w = NULL;
1594   struct frame *f = NULL;
1595   struct device *d;
1596   Lisp_Object background_pixmap = Qunbound;
1597   Lisp_Object fcolor = Qnil, bcolor = Qnil;
1598
1599   if (!width || !height)
1600      return;
1601
1602   if (WINDOWP (locale))
1603     {
1604       w = XWINDOW (locale);
1605       f = XFRAME (w->frame);
1606     }
1607   else if (FRAMEP (locale))
1608     {
1609       w = NULL;
1610       f = XFRAME (locale);
1611     }
1612   else
1613     abort ();
1614
1615   d = XDEVICE (f->device);
1616
1617   /* if we have subwindows in the region we have to unmap them */
1618   redisplay_unmap_subwindows_maybe (f, x, y, width, height);
1619
1620   /* #### This isn't quite right for when this function is called
1621      from the toolbar code. */
1622
1623   /* Don't use a backing pixmap in the border area */
1624   if (x >= FRAME_LEFT_BORDER_END (f)
1625       && x < FRAME_RIGHT_BORDER_START (f)
1626       && y >= FRAME_TOP_BORDER_END (f)
1627       && y < FRAME_BOTTOM_BORDER_START (f))
1628     {
1629       Lisp_Object temp;
1630
1631       if (w)
1632         {
1633           temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1634
1635           if (IMAGE_INSTANCEP (temp)
1636               && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1637             {
1638               /* #### maybe we could implement such that a string
1639                  can be a background pixmap? */
1640               background_pixmap = temp;
1641             }
1642         }
1643       else
1644         {
1645           temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1646
1647           if (IMAGE_INSTANCEP (temp)
1648               && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1649             {
1650               background_pixmap = temp;
1651             }
1652         }
1653     }
1654
1655   if (!UNBOUNDP (background_pixmap) &&
1656       XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1657     {
1658       if (w)
1659         {
1660           fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1661           bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1662         }
1663       else
1664         {
1665           fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1666           bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1667         }
1668     }
1669   else
1670     {
1671       fcolor = (w ?
1672                 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1673                 FACE_BACKGROUND (Vdefault_face, locale));
1674
1675     }
1676
1677   if (UNBOUNDP (background_pixmap))
1678     background_pixmap = Qnil;
1679
1680   DEVMETH (d, clear_region,
1681            (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1682 }
1683
1684 /****************************************************************************
1685  redisplay_clear_clipped_region
1686
1687  Clear the area in the dest display_box not covered by the src
1688  display_glyph_area using the given face. This is a common occurrence
1689  for images shorter than the display line. Clipping can be played
1690  around with by altering these. glyphsrc should be normalized.
1691  ****************************************************************************/
1692 static void
1693 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1694         struct display_box* dest, struct display_glyph_area* glyphsrc,
1695         int fullheight_p, Lisp_Object ignored_subwindow)
1696 {
1697   /* assume dest->xpos >= 0 */
1698   int clear_x;
1699   struct frame* f = XFRAME (XWINDOW (window)->frame);
1700
1701   if (glyphsrc->xoffset > 0)
1702     {
1703       clear_x = dest->xpos + glyphsrc->xoffset;
1704     }
1705   else
1706     {
1707       clear_x = dest->xpos;
1708     }
1709
1710   /* If we need the whole height cleared then just do it. */
1711   if (fullheight_p)
1712     {
1713       redisplay_clear_region (window, findex, clear_x, dest->ypos,
1714                               glyphsrc->width, dest->height);
1715     }
1716   else
1717     {
1718       int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1719
1720       /* We need to make sure that subwindows are unmapped from the
1721          whole area. */
1722       redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1723                                             glyphsrc->width, dest->height,
1724                                             ignored_subwindow);
1725       /* first the top box */
1726       if (yoffset > 0)
1727         {
1728           redisplay_clear_region (window, findex, clear_x, dest->ypos,
1729                                   glyphsrc->width, yoffset);
1730
1731         }
1732       /* Then the bottom box */
1733       if (yoffset + glyphsrc->height < dest->height)
1734         {
1735           redisplay_clear_region (window, findex, clear_x,
1736                                   dest->ypos + yoffset + glyphsrc->height,
1737                                   glyphsrc->width,
1738                                   dest->height - (yoffset + glyphsrc->height));
1739
1740         }
1741     }
1742 }
1743
1744 /*****************************************************************************
1745  redisplay_normalize_glyph_area
1746  redisplay_normalize_display_box
1747
1748  Calculate the visible box for displaying src in dest.
1749  ****************************************************************************/
1750 int
1751 redisplay_normalize_glyph_area (struct display_box* dest,
1752                                 struct display_glyph_area* glyphsrc)
1753 {
1754   if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1755       ||
1756       dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1757       ||
1758       -glyphsrc->xoffset >= glyphsrc->width
1759       ||
1760       -glyphsrc->yoffset >= glyphsrc->height)
1761     {
1762       /* It's all clipped out */
1763       return 0;
1764     }
1765
1766   /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1767   if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1768     {
1769       if (glyphsrc->xoffset > 0)
1770         glyphsrc->width = dest->width - glyphsrc->xoffset;
1771       else
1772         glyphsrc->width = dest->width;
1773     }
1774
1775   if (glyphsrc->xoffset < 0)
1776     glyphsrc->width += glyphsrc->xoffset;
1777
1778   /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1779   if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1780     {
1781       if (glyphsrc->yoffset > 0)
1782         glyphsrc->height = dest->height - glyphsrc->yoffset;
1783       else
1784         glyphsrc->height = dest->height;
1785     }
1786
1787   if (glyphsrc->yoffset < 0)
1788     glyphsrc->height += glyphsrc->yoffset;
1789
1790   return 1;
1791 }
1792
1793 static void
1794 redisplay_normalize_display_box (struct display_box* dest,
1795                                  struct display_glyph_area* glyphsrc)
1796 {
1797   /* Adjust the destination area. At the end of this the destination
1798    area will exactly enclose the glyph area. The only remaining
1799    adjustment will be offsets into the glyph area. */
1800
1801   /* Horizontal adjustment. */
1802   if (glyphsrc->xoffset > 0)
1803     {
1804       dest->xpos += glyphsrc->xoffset;
1805       dest->width -= glyphsrc->xoffset;
1806       glyphsrc->xoffset = 0;
1807     }
1808   else
1809     glyphsrc->xoffset = -glyphsrc->xoffset;
1810
1811   if (glyphsrc->width < dest->width)
1812     dest->width = glyphsrc->width;
1813
1814   /* Vertical adjustment. */
1815   if (glyphsrc->yoffset > 0)
1816     {
1817       dest->ypos += glyphsrc->yoffset;
1818       dest->height -= glyphsrc->yoffset;
1819       glyphsrc->yoffset = 0;
1820     }
1821   else
1822     glyphsrc->yoffset = -glyphsrc->yoffset;
1823
1824   if (glyphsrc->height < dest->height)
1825     dest->height = glyphsrc->height;
1826 }
1827
1828 /*****************************************************************************
1829  redisplay_display_boxes_in_window_p
1830
1831  Determine whether the required display_glyph_area is completely inside
1832  the window. -1 means the display_box is not in the window. 1 means the
1833  display_box and the display_glyph_area are in the window. 0 means
1834  the display_box is in the window but the display_glyph_area is not.
1835  ****************************************************************************/
1836 static int
1837 redisplay_display_boxes_in_window_p (struct window* w,
1838                                      struct display_box* db,
1839                                      struct display_glyph_area* dga)
1840 {
1841   int left = WINDOW_TEXT_LEFT (w);
1842   int right = WINDOW_TEXT_RIGHT (w);
1843   int top = WINDOW_TEXT_TOP (w);
1844   int bottom = WINDOW_TEXT_BOTTOM (w);
1845
1846   if (db->xpos < left || db->ypos < top
1847       || db->xpos + db->width > right
1848       || db->ypos + db->height > bottom)
1849       /* We are not displaying in a window at all */
1850       return -1;
1851
1852   if (db->xpos + dga->xoffset >= left
1853       &&
1854       db->ypos + dga->yoffset >= top
1855       &&
1856       db->xpos + dga->xoffset + dga->width <= right
1857       &&
1858       db->ypos + dga->yoffset + dga->height <= bottom)
1859     return 1;
1860
1861   return 0;
1862 }
1863
1864 /*****************************************************************************
1865  redisplay_calculate_display_boxes
1866
1867  Convert from rune/display_line co-ordinates to display_box
1868  co-ordinates.
1869  ****************************************************************************/
1870 int
1871 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1872                                    int xoffset, int start_pixpos, int width,
1873                                    struct display_box* dest,
1874                                    struct display_glyph_area* src)
1875 {
1876   dest->xpos = xpos;
1877   dest->ypos = DISPLAY_LINE_YPOS (dl);
1878   dest->width = width;
1879   dest->height = DISPLAY_LINE_HEIGHT (dl);
1880
1881   src->xoffset = -xoffset;
1882   src->yoffset = -dl->top_clip;
1883   src->width = 0;
1884   src->height = 0;
1885
1886   if (start_pixpos >=0 && start_pixpos > xpos)
1887     {
1888       /* Oops, we're asking for a start outside of the displayable
1889          area. */
1890       if (start_pixpos > xpos + width)
1891         return 0;
1892       dest->xpos = start_pixpos;
1893       dest->width -= (start_pixpos - xpos);
1894       /* Offsets are -ve when we want to clip pixels off the displayed
1895          glyph. */
1896       src->xoffset -= (start_pixpos - xpos);
1897     }
1898
1899   return 1;
1900 }
1901
1902 /*****************************************************************************
1903  redisplay_clear_top_of_window
1904
1905  If window is topmost, clear the internal border above it.
1906  ****************************************************************************/
1907 static void
1908 redisplay_clear_top_of_window (struct window *w)
1909 {
1910   Lisp_Object window;
1911   XSETWINDOW (window, w);
1912
1913   if (!NILP (Fwindow_highest_p (window)))
1914     {
1915       struct frame *f = XFRAME (w->frame);
1916       int x, y, width, height;
1917
1918       x = w->pixel_left;
1919       width = w->pixel_width;
1920
1921       if (window_is_leftmost (w))
1922         {
1923           x -= FRAME_BORDER_WIDTH (f);
1924           width += FRAME_BORDER_WIDTH (f);
1925         }
1926       if (window_is_rightmost (w))
1927         width += FRAME_BORDER_WIDTH (f);
1928
1929       y = FRAME_TOP_BORDER_START (f) - 1;
1930       height = FRAME_BORDER_HEIGHT (f) + 1;
1931
1932       redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1933     }
1934 }
1935
1936 /*****************************************************************************
1937  redisplay_clear_to_window_end
1938
1939  Clear the area between ypos1 and ypos2.  Each margin area and the
1940  text area is handled separately since they may each have their own
1941  background color.
1942  ****************************************************************************/
1943 void
1944 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1945 {
1946   struct frame *f = XFRAME (w->frame);
1947   struct device *d = XDEVICE (f->device);
1948
1949   if (HAS_DEVMETH_P (d, clear_to_window_end))
1950     DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1951   else
1952     {
1953       int height = ypos2 - ypos1;
1954
1955       if (height)
1956         {
1957           Lisp_Object window;
1958           int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1959           layout_bounds bounds;
1960
1961           bounds = calculate_display_line_boundaries (w, bflag);
1962           XSETWINDOW (window, w);
1963
1964           if (window_is_leftmost (w))
1965             redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1966                                     ypos1, FRAME_BORDER_WIDTH (f), height);
1967
1968           if (bounds.left_in - bounds.left_out > 0)
1969             redisplay_clear_region (window,
1970                                     get_builtin_face_cache_index (w, Vleft_margin_face),
1971                                     bounds.left_out, ypos1,
1972                                     bounds.left_in - bounds.left_out, height);
1973
1974           if (bounds.right_in - bounds.left_in > 0)
1975             redisplay_clear_region (window,
1976                                     DEFAULT_INDEX,
1977                                     bounds.left_in, ypos1,
1978                                     bounds.right_in - bounds.left_in, height);
1979
1980           if (bounds.right_out - bounds.right_in > 0)
1981             redisplay_clear_region (window,
1982                                     get_builtin_face_cache_index (w, Vright_margin_face),
1983                                     bounds.right_in, ypos1,
1984                                     bounds.right_out - bounds.right_in, height);
1985
1986           if (window_is_rightmost (w))
1987             redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1988                                     ypos1, FRAME_BORDER_WIDTH (f), height);
1989         }
1990     }
1991 }
1992
1993 /*****************************************************************************
1994  redisplay_clear_bottom_of_window
1995
1996  Clear window from right below the last display line to right above
1997  the modeline.  The calling function can limit the area actually
1998  erased by setting min_start and/or max_end to positive values.
1999  ****************************************************************************/
2000 void
2001 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
2002                                   int min_start, int max_end)
2003 {
2004   struct frame *f = XFRAME (w->frame);
2005   int ypos1, ypos2;
2006   int ddla_len = Dynarr_length (ddla);
2007
2008   ypos2 = WINDOW_TEXT_BOTTOM (w);
2009 #ifdef HAVE_SCROLLBARS
2010   /* This adjustment is to catch the intersection of any scrollbars. */
2011   if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
2012     ypos2 += window_scrollbar_height (w);
2013 #endif
2014
2015   if (ddla_len)
2016     {
2017       if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
2018         {
2019           ypos1 = WINDOW_TEXT_TOP (w);
2020 #ifdef HAVE_SCROLLBARS
2021           /* This adjustment is to catch the intersection of any scrollbars. */
2022           if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
2023             ypos1 -= window_scrollbar_height (w);
2024 #endif
2025         }
2026       else
2027         {
2028           struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
2029           ypos1 = dl->ypos + dl->descent - dl->clip;
2030         }
2031     }
2032   else
2033     ypos1 = WINDOW_TEXT_TOP (w);
2034
2035   /* #### See if this can be made conditional on the frame
2036      changing size. */
2037   if (MINI_WINDOW_P (w))
2038     ypos2 += FRAME_BORDER_HEIGHT (f);
2039
2040   if (min_start >= 0 && ypos1 < min_start)
2041     ypos1 = min_start;
2042   if (max_end >= 0 && ypos2 > max_end)
2043     ypos2 = max_end;
2044
2045   if (ypos2 <= ypos1)
2046     return;
2047
2048   redisplay_clear_to_window_end (w, ypos1, ypos2);
2049 }
2050
2051 /*****************************************************************************
2052  redisplay_update_line
2053
2054  This is used during incremental updates to update a single line and
2055  correct the offsets on all lines below it.  At the moment
2056  update_values is false if we are only updating the modeline.
2057  ****************************************************************************/
2058 void
2059 redisplay_update_line (struct window *w, int first_line, int last_line,
2060                        int update_values)
2061 {
2062   struct frame *f = XFRAME (w->frame);
2063   struct device *d = XDEVICE (f->device);
2064
2065   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2066   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2067
2068   MAYBE_DEVMETH (d, window_output_begin, (w));
2069
2070   while (first_line <= last_line)
2071     {
2072       Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
2073                            Dynarr_atp (cdla, first_line)->bufpos);
2074       Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
2075                            Dynarr_atp (ddla, first_line)->bufpos);
2076
2077       assert (Dynarr_length (cdla) == Dynarr_length (ddla));
2078
2079       /* Output the changes. */
2080       output_display_line (w, cdla, ddla, first_line, -1, -1);
2081
2082       /* Update the offsets. */
2083       if (update_values)
2084         {
2085           int cur_line = first_line + 1;
2086           while (cur_line < Dynarr_length (cdla))
2087             {
2088               Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
2089               Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
2090               cur_line++;
2091             }
2092         }
2093
2094       /* Update the window_end_pos and other settings. */
2095       if (update_values)
2096         {
2097           w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
2098
2099           if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
2100             {
2101               w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2102               w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2103             }
2104         }
2105
2106       first_line++;
2107     }
2108
2109   /* Update the window max line length.  We have to scan the entire
2110      set of display lines otherwise we might not detect if the max is
2111      supposed to shrink. */
2112   if (update_values)
2113     {
2114       int line = 0;
2115
2116       w->max_line_len = 0;
2117       while (line < Dynarr_length (ddla))
2118         {
2119           struct display_line *dl = Dynarr_atp (ddla, line);
2120
2121           if (!dl->modeline)
2122             w->max_line_len = max (dl->num_chars, w->max_line_len);
2123
2124           line++;
2125         }
2126     }
2127
2128   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2129   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2130   Fset_marker (w->last_point[CURRENT_DISP],
2131                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2132   Fset_marker (w->last_start[CURRENT_DISP],
2133                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2134
2135   /* We don't bother updating the vertical scrollbars here.  This
2136      gives us a performance increase while having minimal loss of
2137      quality to the scrollbar slider size and position since when this
2138      function is called we know that the changes to the buffer were
2139      very localized.  We have to update the horizontal scrollbars,
2140      though, because this routine could cause a change which has a
2141      larger impact on their sizing. */
2142   /* #### See if we can get away with only calling this if
2143      max_line_len is greater than the window_char_width. */
2144 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
2145   {
2146     extern int stupid_vertical_scrollbar_drag_hack;
2147
2148     update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
2149     stupid_vertical_scrollbar_drag_hack = 1;
2150   }
2151 #endif
2152
2153   redisplay_redraw_cursor (f, 0);
2154   MAYBE_DEVMETH (d, window_output_end, (w));
2155 }
2156
2157 /*****************************************************************************
2158  redisplay_output_window
2159
2160  For the given window W, ensure that the current display lines are
2161  equal to the desired display lines, outputing changes as necessary.
2162
2163  #### Fuck me.  This just isn't going to cut it for tty's.  The output
2164  decisions for them must be based on the contents of the entire frame
2165  because that is how the available output capabilities think.  The
2166  solution is relatively simple.  Create redisplay_output_frame.  This
2167  will basically merge all of the separate window display structs into
2168  a single one for the frame.  This combination structure will be able
2169  to be passed to the same output_display_line which works for windows
2170  on X frames and the right things will happen.  It just takes time to
2171  do.
2172  ****************************************************************************/
2173 void
2174 redisplay_output_window (struct window *w)
2175 {
2176   struct frame *f = XFRAME (w->frame);
2177   struct device *d = XDEVICE (f->device);
2178
2179   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2180   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2181
2182   int cdla_len = Dynarr_length (cdla);
2183   int ddla_len = Dynarr_length (ddla);
2184
2185   int line;
2186   int need_to_clear_bottom = 0;
2187   int need_to_clear_start = -1;
2188   int need_to_clear_end = -1;
2189
2190   /* Backgrounds may have changed or windows may have gone away
2191      leaving dividers lying around. */
2192   if (f->faces_changed
2193       || f->windows_structure_changed
2194       || w->shadow_thickness_changed)
2195     need_to_clear_bottom = 1;
2196
2197   /* The first thing we do is determine if we are going to need to
2198      clear the bottom of the window.  We only need to do this if the
2199      bottom of the current display lines is below the bottom of the
2200      desired display lines.  Note that the number of lines is
2201      irrelevant.  Only the position matters.  We also clear to the
2202      bottom of the window if the modeline has shifted position. */
2203   /* #### We can't blindly not clear the bottom if f->clear is true
2204      since there might be a window-local background.  However, for
2205      those cases where there isn't, clearing the end of the window in
2206      this case sucks. */
2207   if (!need_to_clear_bottom)
2208     {
2209       struct display_line *cdl, *ddl;
2210
2211       /* If the modeline has changed position or size, clear the bottom
2212          of the window. */
2213       if (!need_to_clear_bottom)
2214         {
2215           cdl = ddl = 0;
2216
2217           if (cdla_len)
2218             cdl = Dynarr_atp (cdla, 0);
2219           if (ddla_len)
2220             ddl = Dynarr_atp (ddla, 0);
2221
2222           if (!cdl || !ddl)
2223             need_to_clear_bottom = 1;
2224           else if ((!cdl->modeline && ddl->modeline)
2225                    || (cdl->modeline && !ddl->modeline))
2226             need_to_clear_bottom = 1;
2227           else if (cdl->ypos != ddl->ypos ||
2228                    cdl->ascent != ddl->ascent ||
2229                    cdl->descent != ddl->descent ||
2230                    cdl->clip != ddl->clip)
2231             need_to_clear_bottom = 1;
2232
2233           /* #### This kludge is to make sure the modeline shadows get
2234              redrawn if the modeline position shifts. */
2235           if (need_to_clear_bottom)
2236             w->shadow_thickness_changed = 1;
2237         }
2238
2239       if (!need_to_clear_bottom)
2240         {
2241           cdl = ddl = 0;
2242
2243           if (cdla_len)
2244             cdl = Dynarr_atp (cdla, cdla_len - 1);
2245           if (ddla_len)
2246             ddl = Dynarr_atp (ddla, ddla_len - 1);
2247
2248           if (!cdl || !ddl)
2249             need_to_clear_bottom = 1;
2250           else
2251             {
2252               int cdl_bottom, ddl_bottom;
2253
2254               cdl_bottom = cdl->ypos + cdl->descent;
2255               ddl_bottom = ddl->ypos + ddl->descent;
2256
2257               if (cdl_bottom > ddl_bottom)
2258                 {
2259                   need_to_clear_bottom = 1;
2260                   need_to_clear_start = ddl_bottom;
2261                   need_to_clear_end = cdl_bottom;
2262                 }
2263             }
2264         }
2265     }
2266
2267   /* Perform any output initialization. */
2268   MAYBE_DEVMETH (d, window_output_begin, (w));
2269
2270   /* If the window's structure has changed clear the internal border
2271      above it if it is topmost (the function will check). */
2272   if (f->windows_structure_changed)
2273     redisplay_clear_top_of_window (w);
2274
2275   /* Output each line. */
2276   for (line = 0; line < Dynarr_length (ddla); line++)
2277     {
2278       output_display_line (w, cdla, ddla, line, -1, -1);
2279     }
2280
2281   /* If the number of display lines has shrunk, adjust. */
2282   if (cdla_len > ddla_len)
2283     {
2284       Dynarr_length (cdla) = ddla_len;
2285     }
2286
2287   /* Output a vertical divider between windows, if necessary. */
2288   if (window_needs_vertical_divider (w)
2289       && (f->windows_structure_changed || f->clear))
2290     {
2291       MAYBE_DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
2292     }
2293
2294   /* Clear the rest of the window, if necessary. */
2295   if (need_to_clear_bottom)
2296     {
2297       redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
2298                                         need_to_clear_end);
2299     }
2300
2301   w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
2302   Fset_marker (w->start[CURRENT_DISP],
2303                make_int (marker_position (w->start[DESIRED_DISP])),
2304                w->buffer);
2305   Fset_marker (w->pointm[CURRENT_DISP],
2306                make_int (marker_position (w->pointm[DESIRED_DISP])),
2307                w->buffer);
2308   w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2309   w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2310   Fset_marker (w->last_start[CURRENT_DISP],
2311                Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2312   Fset_marker (w->last_point[CURRENT_DISP],
2313                Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2314   w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2315   w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2316   w->shadow_thickness_changed = 0;
2317
2318   set_window_display_buffer (w, XBUFFER (w->buffer));
2319   find_window_mirror (w)->truncate_win = window_truncation_on (w);
2320
2321   /* Overkill on invalidating the cache.  It is very bad for it to not
2322      get invalidated when it should be. */
2323   INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
2324
2325   redisplay_redraw_cursor (f, 0);
2326   MAYBE_DEVMETH (d, window_output_end, (w));
2327
2328 #ifdef HAVE_SCROLLBARS
2329   update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
2330 #endif
2331 }
2332
2333 /*****************************************************************************
2334  bevel_modeline
2335
2336  Draw a 3d border around the modeline on window W.
2337  ****************************************************************************/
2338 void
2339 bevel_modeline (struct window *w, struct display_line *dl)
2340 {
2341   struct frame *f = XFRAME (w->frame);
2342   struct device *d = XDEVICE (f->device);
2343   int x, y, width, height;
2344   int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2345   enum edge_style style;
2346
2347   x = WINDOW_MODELINE_LEFT (w);
2348   width = WINDOW_MODELINE_RIGHT (w) - x;
2349   y = dl->ypos - dl->ascent - shadow_thickness;
2350   height = dl->ascent + dl->descent + 2 * shadow_thickness;
2351
2352   if (XINT (w->modeline_shadow_thickness) < 0)
2353     {
2354       style = EDGE_BEVEL_IN;
2355     }
2356   else
2357     {
2358       style = EDGE_BEVEL_OUT;
2359     }
2360
2361   MAYBE_DEVMETH (d, bevel_area,
2362                  (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,
2363                   EDGE_ALL, style));
2364 }