XEmacs 21.4.6 "Common Lisp".
[chise/xemacs-chise.git.1] / src / redisplay-output.c
index 4d5fe0c..421acba 100644 (file)
@@ -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);
@@ -101,7 +102,7 @@ sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra)
  For the given LINE in window W, make the current display line equal
  the desired display line.
  ****************************************************************************/
-static void
+void
 sync_display_line_structs (struct window *w, int line, int do_blocks,
                           display_line_dynarr *cdla,
                           display_line_dynarr *ddla)
@@ -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
@@ -211,10 +212,7 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb)
      #### It would really be worth it to arrange for this function to
      be (almost) a single call to memcmp. */
 
-  if ((crb->findex != drb->findex) ||
-      (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
-    return 0;
-  else if (crb->xpos != drb->xpos)
+  if (crb->xpos != drb->xpos)
     return 0;
   else if (crb->width != drb->width)
     return 0;
@@ -236,17 +234,68 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb)
     return 0;
   /* Only check dirtiness if we know something has changed. */
   else if (crb->type == RUNE_DGLYPH &&
-          XFRAME (w->frame)->glyphs_changed)
+          (XGLYPH_DIRTYP (crb->object.dglyph.glyph) ||
+           crb->findex != drb->findex))
     {
-      glyph_index gindex = get_glyph_cachel_index (w, drb->object.dglyph.glyph);
-      /* Although doing the cachel lookup for every comparison is
-        very expensive.we have to do it to make sure the cache is
-        up-to-date. */
-      if (GLYPH_CACHEL_DIRTYP (w, gindex))
+      /* We need some way of telling redisplay_output_layout () that the
+         only reason we are outputting it is because something has
+         changed internally. That way we can optimize whether we need
+         to clear the layout first and also only output the components
+         that have changed. The image_instance dirty flag and
+         display_hash are no good to us because these will invariably
+         have been set anyway if the layout has changed. So it looks
+         like we need yet another change flag that we can set here and
+         then clear in redisplay_output_layout (). */
+      Lisp_Object window, image;
+      Lisp_Image_Instance* ii;
+      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 ||
+          WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
+       return 0;
+
+      /* 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 ||
+         WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
+       {
+         /* 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.
+
+            #### It is possible for us to get here when the
+            face_cachel is dirty. I do not know what the implications
+            of this are.*/
+         IMAGE_INSTANCE_OPTIMIZE_OUTPUT (ii) = 1;
+         return 0;
+       }
       else
        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
+     trying to output something in the gutter, this would normally
+     lead to a lot of flashing. The indices can quite often be
+     different and yet the faces are the same, we do not want to
+     re-output in this instance. */
+  else  if (crb->findex != drb->findex ||
+           WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
+    return 0;
   else
     return 1;
 }
@@ -850,16 +899,11 @@ redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
     }
   else
     {
-      DEVMETH (d, output_begin, (d));
-
-      /* #### This is a gross kludge.  Cursor handling is such a royal
-         pain in the ass. */
-      if (rb->type == RUNE_DGLYPH &&
-         (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) ||
-          EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)))
-       rb->cursor_type = NO_CURSOR;
-      else
-       rb->cursor_type = CURSOR_OFF;
+      {
+       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);
     }
@@ -873,7 +917,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;
     }
@@ -892,7 +939,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
@@ -956,7 +1006,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;
                }
 
@@ -969,7 +1022,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
@@ -1024,12 +1080,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));
+       }
     }
 }
 
@@ -1067,6 +1129,8 @@ redisplay_output_display_block (struct window *w, struct display_line *dl, int b
 {
   struct frame *f = XFRAME (w->frame);
   struct device *d = XDEVICE (f->device);
+  /* Temporarily disabled until generalization is done. */
+#if 0
   struct display_block *db = Dynarr_atp (dl->display_blocks, block);
   rune_dynarr *rba = db->runes;
   struct rune *rb;
@@ -1084,6 +1148,7 @@ redisplay_output_display_block (struct window *w, struct display_line *dl, int b
 
   rb  = Dynarr_atp (rba, end - 1);
   width = rb->xpos + rb->width - xpos;
+#endif
   /* now actually output the block. */
   DEVMETH (d, output_display_block, (w, dl, block, start,
                                     end, start_pixpos,
@@ -1097,25 +1162,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) > x
          &&
-         cachel->x + cachel->width > x && cachel->x < x + width
+         IMAGE_INSTANCE_DISPLAY_X (ii) < x + width
          &&
-         cachel->y + cachel->height > y && cachel->y < y + height
+         IMAGE_INSTANCE_DISPLAY_Y (ii)
+         + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > y
          &&
-         !EQ (cachel->subwindow, ignored_window))
+         IMAGE_INSTANCE_DISPLAY_Y (ii) < y + height
+         &&
+         !EQ (XCAR (rest), ignored_window))
        {
-         unmap_subwindow (cachel->subwindow);
+         unmap_subwindow (XCAR (rest));
        }
     }
 }
@@ -1128,7 +1198,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);
     }
@@ -1137,7 +1207,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);
     }
@@ -1167,7 +1237,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))
@@ -1195,7 +1265,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);
     }
@@ -1227,49 +1302,38 @@ 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;
-  /* We bogusly don't take f->extents_changed and f->glyphs_changed
-     into account. This is because if we do we always redisplay the
-     entire layout. So far I have seen no ill effects so we'll see. */
-  int frame_really_changed = (f->buffers_changed ||
-                             f->clip_changed ||
-                             f->faces_changed    ||
-                             f->frame_changed    ||
-                             f->modeline_changed ||
-                             f->subwindows_changed ||
-                             f->windows_changed ||
-                             f->windows_structure_changed);
 
-  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;
-
+#ifdef DEBUG_WIDGET_OUTPUT
+  printf ("outputing layout glyph %p\n", p);
+#endif
   /* This makes the glyph area fit into the display area. */
   if (!redisplay_normalize_glyph_area (db, dga))
     return;
 
   /* Highly dodgy optimization. We want to only output the whole
      layout if we really have to. */
-  if (frame_really_changed 
+  if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p)
       || IMAGE_INSTANCE_LAYOUT_CHANGED (p)
       || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
       || IMAGE_INSTANCE_SIZE_CHANGED (p)
@@ -1329,7 +1393,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 */
@@ -1342,12 +1407,16 @@ redisplay_output_layout (struct window *w,
       if (IMAGE_INSTANCEP (child))
        {
          Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
+
          /* The enclosing layout offsets are +ve at this point */
          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 (p);
 
          /* Although normalization is done by the output routines
             we have to do it here so that they don't try and
@@ -1363,7 +1432,7 @@ redisplay_output_layout (struct window *w,
                continue;
              /* We have to invert the offset here as normalization
                 will have made them positive which the output
-                routines will treat as a truely +ve offset. */
+                routines will treat as a truly +ve offset. */
              cdga.xoffset = -cdga.xoffset;
              cdga.yoffset = -cdga.yoffset;
 
@@ -1375,11 +1444,20 @@ redisplay_output_layout (struct window *w,
                       generalisation.*/
                    if (redisplay_normalize_glyph_area (&cdb, &cdga)
                        &&
-                       (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii)))
+                       (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
+                        IMAGE_INSTANCE_DIRTYP (childii)))
                      {
                        struct display_line dl; /* this is fake */
                        Lisp_Object string =
                          IMAGE_INSTANCE_TEXT_STRING (childii);
+                       unsigned char charsets[NUM_LEADING_BYTES];
+                       struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
+
+                       find_charsets_in_bufbyte_string (charsets,
+                                                        XSTRING_DATA (string),
+                                                        XSTRING_LENGTH (string));
+                       ensure_face_cachel_complete (cachel, window, charsets);
+
                        convert_bufbyte_string_into_emchar_dynarr
                          (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
 
@@ -1389,9 +1467,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
@@ -1409,23 +1487,26 @@ redisplay_output_layout (struct window *w,
 
                case IMAGE_MONO_PIXMAP:
                case IMAGE_COLOR_PIXMAP:
-                 if (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii))
+                 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii)
+                     || IMAGE_INSTANCE_DIRTYP (childii))
                    redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
                                             0, 0, 0, 0);
                  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 (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii))
+                 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
+                     IMAGE_INSTANCE_DIRTYP (childii))
                    redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
                                                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;
@@ -1435,12 +1516,13 @@ redisplay_output_layout (struct window *w,
                  abort ();
                }
            }
+         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);
 }
@@ -1482,7 +1564,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
@@ -1604,7 +1686,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.
  ****************************************************************************/
@@ -1676,7 +1758,17 @@ 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;
@@ -1747,9 +1839,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
@@ -1765,8 +1857,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
       &&
@@ -1777,7 +1869,7 @@ redisplay_display_boxes_in_window_p (struct window* w,
       db->ypos + dga->yoffset + dga->height <= bottom)
     return 1;
 
-  return -1;
+  return 0;
 }
 
 /*****************************************************************************
@@ -1823,7 +1915,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;
@@ -1984,7 +2076,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)
     {
@@ -2060,6 +2152,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;
@@ -2069,14 +2162,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));
 }
 
 /*****************************************************************************
@@ -2190,11 +2277,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. */
@@ -2213,7 +2300,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. */
@@ -2247,13 +2334,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);