XEmacs 21.4.10 "Military Intelligence".
[chise/xemacs-chise.git.1] / src / redisplay-output.c
index 61f22de..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,7 +230,10 @@ 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 &&
@@ -270,7 +274,7 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb)
          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
@@ -1161,8 +1165,9 @@ 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)
 {
   Lisp_Object rest;
 
@@ -1172,14 +1177,14 @@ static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width
       if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii)
          &&
          IMAGE_INSTANCE_DISPLAY_X (ii)
-         + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) > x
+         + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) > (unsigned) x
          &&
-         IMAGE_INSTANCE_DISPLAY_X (ii) < x + width
+         IMAGE_INSTANCE_DISPLAY_X (ii) < (unsigned) (x + width)
          &&
          IMAGE_INSTANCE_DISPLAY_Y (ii)
-         + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > y
+         + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > (unsigned) y
          &&
-         IMAGE_INSTANCE_DISPLAY_Y (ii) < y + height
+         IMAGE_INSTANCE_DISPLAY_Y (ii) < (unsigned) (y + height)
          &&
          !EQ (XCAR (rest), ignored_window))
        {
@@ -1263,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);
     }
@@ -1343,17 +1353,22 @@ redisplay_output_layout (Lisp_Object domain,
          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))
@@ -1373,9 +1388,8 @@ redisplay_output_layout (Lisp_Object domain,
            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));
        }
     }
 
@@ -1542,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
@@ -1739,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,
@@ -1751,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;
@@ -1822,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
@@ -1840,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
       &&
@@ -1852,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;
 }
 
 /*****************************************************************************
@@ -1863,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;
@@ -1873,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
@@ -1898,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;
@@ -2135,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;
@@ -2263,7 +2347,7 @@ redisplay_output_window (struct window *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. */