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