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