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