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