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