XEmacs 21.4.10 "Military Intelligence".
[chise/xemacs-chise.git.1] / src / redisplay-output.c
index ae45602..b19d74f 100644 (file)
@@ -2,7 +2,7 @@
    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
    Copyright (C) 1995, 1996 Ben Wing.
    Copyright (C) 1996 Chuck Thompson.
-   Copyright (C) 1999 Andy Piper.
+   Copyright (C) 1999, 2002 Andy Piper.
 
 This file is part of XEmacs.
 
@@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA.  */
 #include "glyphs.h"
 #include "redisplay.h"
 #include "faces.h"
+#include "gutter.h"
 
 static int compare_runes (struct window *w, struct rune *crb,
                          struct rune *drb);
@@ -181,7 +182,7 @@ sync_display_line_structs (struct window *w, int line, int do_blocks,
 /*****************************************************************************
  compare_runes
 
- Compare to runes to see if each of their fields is equal.  If so,
+ Compare two runes to see if each of their fields is equal.  If so,
  return true otherwise return false.
  ****************************************************************************/
 static int
@@ -229,11 +230,14 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb)
   else if (crb->type == RUNE_DGLYPH &&
           (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
            !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
-           crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
+           crb->object.dglyph.xoffset != drb->object.dglyph.xoffset ||
+           crb->object.dglyph.yoffset != drb->object.dglyph.yoffset ||
+            crb->object.dglyph.ascent != drb->object.dglyph.ascent ||
+            crb->object.dglyph.descent != drb->object.dglyph.descent))
     return 0;
   /* Only check dirtiness if we know something has changed. */
   else if (crb->type == RUNE_DGLYPH &&
-          (XGLYPH_DIRTYP (crb->object.dglyph.glyph) || 
+          (XGLYPH_DIRTYP (crb->object.dglyph.glyph) ||
            crb->findex != drb->findex))
     {
       /* We need some way of telling redisplay_output_layout () that the
@@ -250,29 +254,32 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb)
       XSETWINDOW (window, w);
       image = glyph_image_instance (crb->object.dglyph.glyph,
                                    window, ERROR_ME_NOT, 1);
+
+      if (!IMAGE_INSTANCEP (image))
+       return 0;
       ii = XIMAGE_INSTANCE (image);
 
-      if (TEXT_IMAGE_INSTANCEP (image) && 
-         (crb->findex != drb->findex || 
+      if (TEXT_IMAGE_INSTANCEP (image) &&
+         (crb->findex != drb->findex ||
           WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
        return 0;
 
-      /* It is quite common of the two glyphs to be EQ since in many
+      /* It is quite common for the two glyphs to be EQ since in many
         cases they will actually be the same object. This does not
         mean, however, that nothing has changed. We therefore need to
         check the current hash of the glyph against the last recorded
         display hash and the pending display items. See
         update_subwindow (). */
       if (image_instance_changed (image) ||
-         crb->findex != drb->findex || 
+         crb->findex != drb->findex ||
          WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
        {
-         /* We now now we are going to re-output the glyph, but since
+         /* Now we are going to re-output the glyph, but since
             this is for some internal reason not related to geometry
             changes, send a hint to the output routines that they can
             take some short cuts. This is most useful for
             layouts. This flag should get reset by the output
-            routines. 
+            routines.
 
             #### It is possible for us to get here when the
             face_cachel is dirty. I do not know what the implications
@@ -281,13 +288,7 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb)
          return 0;
        }
       else
-       {
-#ifdef DEBUG_WIDGET_OUTPUT
-         if (XIMAGE_INSTANCE_TYPE (image) == IMAGE_LAYOUT)
-           printf ("glyph layout %p considered unchanged\n", ii);
-#endif
-         return 1;
-       }
+       return 1;
     }
   /* We now do this last so that glyph checks can do their own thing
      for face changes. Face changes quite often happen when we are
@@ -901,7 +902,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
     }
   else
     {
-      DEVMETH (d, output_begin, (d));
+      {
+       MAYBE_DEVMETH (d, frame_output_begin, (f));
+       MAYBE_DEVMETH (d, window_output_begin, (w));
+      }
       rb->cursor_type = CURSOR_OFF;
       dl->cursor_elt = -1;
       output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
@@ -916,7 +920,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
   if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
     {
       if (!no_output_end)
-       DEVMETH (d, output_end, (d));
+       {
+         MAYBE_DEVMETH (d, window_output_end, (w));
+         MAYBE_DEVMETH (d, frame_output_end, (f));
+       }
 
       return 1;
     }
@@ -935,7 +942,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
       output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
 
       if (!no_output_end)
-       DEVMETH (d, output_end, (d));
+       {
+         MAYBE_DEVMETH (d, window_output_end, (w));
+         MAYBE_DEVMETH (d, frame_output_end, (f));
+       }
       return 1;
     }
   else
@@ -999,7 +1009,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
                               make_int (ADJ_BUFPOS), w->buffer);
 
                  if (!no_output_end)
-                   DEVMETH (d, output_end, (d));
+                   {
+                     MAYBE_DEVMETH (d, window_output_end, (w));
+                     MAYBE_DEVMETH (d, frame_output_end, (f));
+                   }
                  return 1;
                }
 
@@ -1012,7 +1025,10 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
     }
 
   if (!no_output_end)
-    DEVMETH (d, output_end, (d));
+    {
+      MAYBE_DEVMETH (d, window_output_end, (w));
+      MAYBE_DEVMETH (d, frame_output_end, (f));
+    }
   return 0;
 }
 #undef ADJ_BUFPOS
@@ -1067,12 +1083,18 @@ redraw_cursor_in_window (struct window *w, int run_end_begin_meths)
                     (f, dl->ypos - 1, rb->xpos));
 
       if (run_end_begin_meths)
-       DEVMETH (d, output_begin, (d));
+       {
+         MAYBE_DEVMETH (d, frame_output_begin, (f));
+         MAYBE_DEVMETH (d, window_output_begin, (w));
+       }
 
       output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
 
       if (run_end_begin_meths)
-       DEVMETH (d, output_end, (d));
+       {
+         MAYBE_DEVMETH (d, window_output_end, (w));
+         MAYBE_DEVMETH (d, frame_output_end, (f));
+       }
     }
 }
 
@@ -1143,25 +1165,30 @@ redisplay_output_display_block (struct window *w, struct display_line *dl, int b
  Remove subwindows from the area in the box defined by the given
  parameters.
  ****************************************************************************/
-static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height,
-                                       Lisp_Object ignored_window)
+static void
+redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height,
+                           Lisp_Object ignored_window)
 {
-  int elt;
+  Lisp_Object rest;
 
-  for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
+  LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))
     {
-      struct subwindow_cachel *cachel =
-       Dynarr_atp (f->subwindow_cachels, elt);
-
-      if (cachel->being_displayed
+      Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest));
+      if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii)
+         &&
+         IMAGE_INSTANCE_DISPLAY_X (ii)
+         + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) > (unsigned) x
          &&
-         cachel->x + cachel->width > x && cachel->x < x + width
+         IMAGE_INSTANCE_DISPLAY_X (ii) < (unsigned) (x + width)
          &&
-         cachel->y + cachel->height > y && cachel->y < y + height
+         IMAGE_INSTANCE_DISPLAY_Y (ii)
+         + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > (unsigned) y
          &&
-         !EQ (cachel->subwindow, ignored_window))
+         IMAGE_INSTANCE_DISPLAY_Y (ii) < (unsigned) (y + height)
+         &&
+         !EQ (XCAR (rest), ignored_window))
        {
-         unmap_subwindow (cachel->subwindow);
+         unmap_subwindow (XCAR (rest));
        }
     }
 }
@@ -1174,7 +1201,7 @@ static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width
  ****************************************************************************/
 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
 {
-  if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
+  if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))))
     {
       redisplay_unmap_subwindows (f, x, y, width, height, Qnil);
     }
@@ -1183,7 +1210,7 @@ void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width,
 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
                                                  int height, Lisp_Object subwindow)
 {
-  if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
+  if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))))
     {
       redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
     }
@@ -1213,7 +1240,7 @@ redisplay_output_subwindow (struct window *w,
   /* The first thing we are going to do is update the display
      characteristics of the subwindow. This also clears the dirty
      flags as a side effect. */
-  update_subwindow (image_instance);
+  redisplay_subwindow (image_instance);
 
   /* This makes the glyph area fit into the display area. */
   if (!redisplay_normalize_glyph_area (db, dga))
@@ -1241,7 +1268,12 @@ redisplay_output_subwindow (struct window *w,
   sdga.height = IMAGE_INSTANCE_HEIGHT (p);
   sdga.width = IMAGE_INSTANCE_WIDTH (p);
 
-  if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0)
+  if (redisplay_display_boxes_in_window_p (w, db, &sdga) == 0
+      ||
+      /* We only want to do full subwindow display for windows that
+        are completely in the gutter, otherwise we must clip to be
+        safe. */
+      display_boxes_in_gutter_p (XFRAME (w->frame), db, &sdga) <= 0)
     {
       map_subwindow (image_instance, db->xpos, db->ypos, dga);
     }
@@ -1273,27 +1305,25 @@ redisplay_output_subwindow (struct window *w,
  issues lwlib has to grapple with. We really need to know what has
  actually changed and make a layout decision based on that. We also
  really need to know what has changed so that we can only make the
- neccessary changes in update_subwindow.  This has all now been
+ necessary changes in update_subwindow.  This has all now been
  implemented, Viva la revolution!
  ****************************************************************************/
 void
-redisplay_output_layout (struct window *w,
+redisplay_output_layout (Lisp_Object domain,
                         Lisp_Object image_instance,
                         struct display_box* db, struct display_glyph_area* dga,
                         face_index findex, int cursor_start, int cursor_width,
                         int cursor_height)
 {
   Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
-  Lisp_Object window, rest;
+  Lisp_Object rest, window = DOMAIN_WINDOW (domain);
   Emchar_dynarr *buf = Dynarr_new (Emchar);
-  struct frame *f = XFRAME (w->frame);
-  struct device *d = XDEVICE (f->device);
+  struct window *w = XWINDOW (window);
+  struct device *d = DOMAIN_XDEVICE (domain);
   int layout_height, layout_width;
 
-  XSETWINDOW (window, w);
-
-  layout_height = glyph_height (image_instance, window);
-  layout_width = glyph_width (image_instance, window);
+  layout_height = glyph_height (image_instance, domain);
+  layout_width = glyph_width (image_instance, domain);
 
   dga->height = layout_height;
   dga->width = layout_width;
@@ -1323,17 +1353,22 @@ redisplay_output_layout (struct window *w,
          int edges = 0;
          enum edge_style style;
          int ypos = db->ypos;
+         int xpos = db->xpos;
          int height = dga->height;
+         int width = dga->width;
 
-         if (dga->xoffset >= 0)
+         /* The bevel_area routines always draw in from the specified
+            area so there is no need to adjust the displayed area to
+            make sure that the lines are visible. */
+         if (dga->xoffset >= 0) 
            edges |= EDGE_LEFT;
-         if (dga->width - dga->xoffset == layout_width)
+         if (dga->width - dga->xoffset == layout_width) 
            edges |= EDGE_RIGHT;
-         if (dga->yoffset >= 0)
+         if (dga->yoffset >= 0) 
            edges |= EDGE_TOP;
          if (dga->height - dga->yoffset == layout_height)
            edges |= EDGE_BOTTOM;
-
+         
          if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
            style = EDGE_ETCHED_IN;
          else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
@@ -1353,9 +1388,8 @@ redisplay_output_layout (struct window *w,
            style = EDGE_BEVEL_OUT;
 
          MAYBE_DEVMETH (d, bevel_area,
-                        (w, findex, db->xpos,
-                         ypos,
-                         dga->width, height, 2, edges, style));
+                        (w, findex, xpos, ypos, width, height,
+                         DEFAULT_WIDGET_SHADOW_WIDTH, edges, style));
        }
     }
 
@@ -1366,7 +1400,8 @@ redisplay_output_layout (struct window *w,
   /* Flip through the widgets in the layout displaying as necessary */
   LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
     {
-      Lisp_Object child = XCAR (rest);
+      Lisp_Object child = glyph_image_instance (XCAR (rest), image_instance,
+                                               ERROR_ME_NOT, 1);
 
       struct display_box cdb;
       /* For losing HP-UX */
@@ -1384,10 +1419,10 @@ redisplay_output_layout (struct window *w,
          struct display_glyph_area cdga;
          cdga.xoffset  = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
          cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
-         cdga.width = glyph_width (child, window);
-         cdga.height = glyph_height (child, window);
+         cdga.width = glyph_width (child, image_instance);
+         cdga.height = glyph_height (child, image_instance);
 
-         IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 
+         IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) =
            IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p);
 
          /* Although normalization is done by the output routines
@@ -1439,9 +1474,9 @@ redisplay_output_layout (struct window *w,
                        xzero (dl);
                        /* Munge boxes into display lines. */
                        dl.ypos = (cdb.ypos - cdga.yoffset)
-                         + glyph_ascent (child, window);
-                       dl.ascent = glyph_ascent (child, window);
-                       dl.descent = glyph_descent (child, window);
+                         + glyph_ascent (child, image_instance);
+                       dl.ascent = glyph_ascent (child, image_instance);
+                       dl.descent = glyph_descent (child, image_instance);
                        dl.top_clip = cdga.yoffset;
                        dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
                        /* output_string doesn't understand offsets in
@@ -1466,6 +1501,12 @@ redisplay_output_layout (struct window *w,
                  break;
 
                case IMAGE_WIDGET:
+                 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (childii), Qlayout))
+                   {
+                     redisplay_output_layout (image_instance, child, &cdb, &cdga, findex,
+                                              0, 0, 0);
+                     break;
+                   }
                case IMAGE_SUBWINDOW:
                  if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
                      IMAGE_INSTANCE_DIRTYP (childii))
@@ -1473,11 +1514,6 @@ redisplay_output_layout (struct window *w,
                                                0, 0, 0);
                  break;
 
-               case IMAGE_LAYOUT:
-                 redisplay_output_layout (w, child, &cdb, &cdga, findex,
-                                          0, 0, 0);
-                 break;
-
                case IMAGE_NOTHING:
                  /* nothing is as nothing does */
                  break;
@@ -1490,10 +1526,10 @@ redisplay_output_layout (struct window *w,
          IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0;
        }
     }
-  
+
   /* Update any display properties. I'm not sure whether this actually
      does anything for layouts except clear the changed flags. */
-  update_subwindow (image_instance);
+  redisplay_subwindow (image_instance);
 
   Dynarr_free (buf);
 }
@@ -1520,10 +1556,24 @@ redisplay_output_pixmap (struct window *w,
   dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
   dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
 
+#ifdef DEBUG_REDISPLAY
+  printf ("redisplay_output_pixmap(request) \
+[%dx%d@%d+%d] in [%dx%d@%d+%d]\n", 
+         db->width, db->height, db->xpos, db->ypos,
+         dga->width, dga->height, dga->xoffset, dga->yoffset);
+#endif
+
   /* This makes the glyph area fit into the display area. */
   if (!redisplay_normalize_glyph_area (db, dga))
     return;
 
+#ifdef DEBUG_REDISPLAY
+  printf ("redisplay_output_pixmap(normalized) \
+[%dx%d@%d+%d] in [%dx%d@%d+%d]\n",
+         db->width, db->height, db->xpos, db->ypos,
+         dga->width, dga->height, dga->xoffset, dga->yoffset);
+#endif
+
   /* Clear the area the pixmap is going into.  The pixmap itself will
      always take care of the full width.  We don't want to clear where
      it is going to go in order to avoid flicker.  So, all we have to
@@ -1535,7 +1585,7 @@ redisplay_output_pixmap (struct window *w,
     {
       redisplay_clear_clipped_region (window, findex,
                                      db, dga,
-                                     (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
+                                     (IMAGE_INSTANCE_PIXMAP_MASK (p) != 0),
                                      Qnil);
 
       /* This shrinks the display box to exactly enclose the glyph
@@ -1657,7 +1707,7 @@ redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
  redisplay_clear_clipped_region
 
  Clear the area in the dest display_box not covered by the src
- display_glyph_area using the given face. This is a common occurance
+ display_glyph_area using the given face. This is a common occurrence
  for images shorter than the display line. Clipping can be played
  around with by altering these. glyphsrc should be normalized.
  ****************************************************************************/
@@ -1717,7 +1767,28 @@ redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
  redisplay_normalize_glyph_area
  redisplay_normalize_display_box
 
- Calculate the visible box for displaying src in dest.
+ Calculate the visible box for displaying glyphsrc in dest.
+
+ display_box and display_glyph_area are used to represent an area to
+ displayed and where to display it. Using these two structures all
+ combinations of clipping and position can be accommodated.
+
+ dest - display_box
+
+       xpos - absolute horizontal position of area.
+
+       ypos - absolute vertical position of area.
+
+  glyphsrc - display_glyph_area
+
+       xoffset - horizontal offset of the glyph, +ve means display
+       the glyph with the x position offset by xoffset, -ve means
+       display starting xoffset into the glyph.
+
+       yoffset - vertical offset of the glyph, +ve means display the
+       glyph with y position offset by yoffset, -ve means display
+       starting xoffset into the glyph.
+
  ****************************************************************************/
 int
 redisplay_normalize_glyph_area (struct display_box* dest,
@@ -1729,34 +1800,67 @@ redisplay_normalize_glyph_area (struct display_box* dest,
       ||
       -glyphsrc->xoffset >= glyphsrc->width
       ||
-      -glyphsrc->yoffset >= glyphsrc->height)
+      -glyphsrc->yoffset >= glyphsrc->height
+      ||
+      /* #### Not sure why this wasn't coped with before but normalizing
+        to zero width or height is definitely wrong. */
+      (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width
+       &&
+       dest->width - glyphsrc->xoffset <= 0)
+      ||
+      (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height
+       &&
+       dest->height - glyphsrc->yoffset <= 0))
     {
       /* It's all clipped out */
       return 0;
     }
 
-  /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
+  /* Horizontal offsets. This works because xoffset can be -ve as well
+     as +ve.  When we enter this function the glyphsrc width and
+     height are set to the actual glyph width and height irrespective
+     of how much can be displayed. We are trying to clip both the
+     offset into the image and the rightmost bounding box. Its
+     possible for the glyph width to be much larger than the area we
+     are displaying into (e.g. a large glyph in a small frame). */
   if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
     {
+      /* glyphsrc offset is +ve we are trying to display offset from the
+        origin (the bounding box contains some space and then the
+        glyph). At most the width we want to display is dest->width -
+        glyphsrc->xoffset. */
       if (glyphsrc->xoffset > 0)
        glyphsrc->width = dest->width - glyphsrc->xoffset;
+      /* glyphsrc offset is -ve we are trying to display hard up
+        against the dest corner inset into the glyphsrc by
+        xoffset.*/
+      else if (glyphsrc->xoffset < 0) 
+       {
+         glyphsrc->width += glyphsrc->xoffset;
+         glyphsrc->width = min (glyphsrc->width, dest->width);
+       }
       else
        glyphsrc->width = dest->width;
     }
 
-  if (glyphsrc->xoffset < 0)
+  else if (glyphsrc->xoffset < 0) 
     glyphsrc->width += glyphsrc->xoffset;
 
   /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
   if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
     {
-      if (glyphsrc->yoffset > 0)
+      if ((glyphsrc->yoffset > 0) && (dest->height > glyphsrc->yoffset))
        glyphsrc->height = dest->height - glyphsrc->yoffset;
+      else if (glyphsrc->yoffset < 0) 
+       {
+         glyphsrc->height += glyphsrc->yoffset;
+         glyphsrc->height = min (glyphsrc->height, dest->height);
+       }
       else
        glyphsrc->height = dest->height;
     }
 
-  if (glyphsrc->yoffset < 0)
+  else if (glyphsrc->yoffset < 0)
     glyphsrc->height += glyphsrc->yoffset;
 
   return 1;
@@ -1800,9 +1904,9 @@ redisplay_normalize_display_box (struct display_box* dest,
 /*****************************************************************************
  redisplay_display_boxes_in_window_p
 
- Determine whether the require display_glyph_area is completely inside
- the window. 0 means the display_box is not in the window. 1 means the
- display_box and the display_glyph_area are in the window. -1 means
+ Determine whether the required display_glyph_area is completely inside
+ the window. -1 means the display_box is not in the window. 1 means the
+ display_box and the display_glyph_area are in the window. 0 means
  the display_box is in the window but the display_glyph_area is not.
  ****************************************************************************/
 static int
@@ -1818,8 +1922,8 @@ redisplay_display_boxes_in_window_p (struct window* w,
   if (db->xpos < left || db->ypos < top
       || db->xpos + db->width > right
       || db->ypos + db->height > bottom)
-    /* We are not displaying in a window at all */
-    return 0;
+      /* We are not displaying in a window at all */
+      return -1;
 
   if (db->xpos + dga->xoffset >= left
       &&
@@ -1830,7 +1934,7 @@ redisplay_display_boxes_in_window_p (struct window* w,
       db->ypos + dga->yoffset + dga->height <= bottom)
     return 1;
 
-  return -1;
+  return 0;
 }
 
 /*****************************************************************************
@@ -1841,8 +1945,8 @@ redisplay_display_boxes_in_window_p (struct window* w,
  ****************************************************************************/
 int
 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
-                                  int xoffset, int start_pixpos, int width,
-                                  struct display_box* dest,
+                                  int xoffset, int yoffset, int start_pixpos,
+                                   int width, struct display_box* dest,
                                   struct display_glyph_area* src)
 {
   dest->xpos = xpos;
@@ -1851,10 +1955,11 @@ redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
   dest->height = DISPLAY_LINE_HEIGHT (dl);
 
   src->xoffset = -xoffset;
-  src->yoffset = -dl->top_clip;
   src->width = 0;
   src->height = 0;
 
+  src->yoffset = -dl->top_clip + yoffset;
+
   if (start_pixpos >=0 && start_pixpos > xpos)
     {
       /* Oops, we're asking for a start outside of the displayable
@@ -1876,7 +1981,7 @@ redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
 
  If window is topmost, clear the internal border above it.
  ****************************************************************************/
-static void
+void
 redisplay_clear_top_of_window (struct window *w)
 {
   Lisp_Object window;
@@ -2037,7 +2142,7 @@ redisplay_update_line (struct window *w, int first_line, int last_line,
   display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
   display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
 
-  DEVMETH (d, output_begin, (d));
+  MAYBE_DEVMETH (d, window_output_begin, (w));
 
   while (first_line <= last_line)
     {
@@ -2113,6 +2218,7 @@ redisplay_update_line (struct window *w, int first_line, int last_line,
      larger impact on their sizing. */
   /* #### See if we can get away with only calling this if
      max_line_len is greater than the window_char_width. */
+  /* #### BILL!!! Should we do this for GTK as well? */
 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
   {
     extern int stupid_vertical_scrollbar_drag_hack;
@@ -2122,14 +2228,8 @@ redisplay_update_line (struct window *w, int first_line, int last_line,
   }
 #endif
 
-  /* This has to be done after we've updated the values.  We don't
-     call output_end for tty frames.  Redisplay will do this after all
-     tty windows have been updated.  This cuts down on cursor
-     flicker. */
-  if (FRAME_TTY_P (f))
-    redisplay_redraw_cursor (f, 0);
-  else
-    DEVMETH (d, output_end, (d));
+  redisplay_redraw_cursor (f, 0);
+  MAYBE_DEVMETH (d, window_output_end, (w));
 }
 
 /*****************************************************************************
@@ -2243,11 +2343,11 @@ redisplay_output_window (struct window *w)
     }
 
   /* Perform any output initialization. */
-  DEVMETH (d, output_begin, (d));
+  MAYBE_DEVMETH (d, window_output_begin, (w));
 
   /* If the window's structure has changed clear the internal border
      above it if it is topmost (the function will check). */
-  if (f->windows_structure_changed)
+  if (f->windows_structure_changed || f->faces_changed)
     redisplay_clear_top_of_window (w);
 
   /* Output each line. */
@@ -2266,7 +2366,7 @@ redisplay_output_window (struct window *w)
   if (window_needs_vertical_divider (w)
       && (f->windows_structure_changed || f->clear))
     {
-      DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
+      MAYBE_DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
     }
 
   /* Clear the rest of the window, if necessary. */
@@ -2300,13 +2400,8 @@ redisplay_output_window (struct window *w)
      get invalidated when it should be. */
   INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
 
-  /* We don't call output_end for tty frames.  Redisplay will do this
-     after all tty windows have been updated.  This cuts down on
-     cursor flicker. */
-  if (FRAME_TTY_P (f))
-    redisplay_redraw_cursor (f, 0);
-  else
-    DEVMETH (d, output_end, (d));
+  redisplay_redraw_cursor (f, 0);
+  MAYBE_DEVMETH (d, window_output_end, (w));
 
 #ifdef HAVE_SCROLLBARS
   update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);