Index: src/extents.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/extents.c,v
retrieving revision 1.31.2.1
diff -u -r1.31.2.1 extents.c
--- src/extents.c	2001/04/16 09:24:51	1.31.2.1
+++ src/extents.c	2002/04/23 05:32:44
@@ -2753,9 +2753,10 @@
 
 face_index
 extent_fragment_update (struct window *w, struct extent_fragment *ef,
-			Bytind pos)
+			Bytind pos, Lisp_Object last_glyph)
 {
   int i;
+  int seen_glyph = NILP (last_glyph) ? 1 : 0;
   Extent_List *sel =
     buffer_or_string_stack_of_extents_force (ef->object)->extents;
   EXTENT lhe = 0;
@@ -2796,11 +2797,15 @@
       if (extent_start (e) == mempos && !NILP (extent_begin_glyph (e)))
 	{
 	  Lisp_Object glyph = extent_begin_glyph (e);
-	  struct glyph_block gb;
-
-	  gb.glyph = glyph;
-	  XSETEXTENT (gb.extent, e);
-	  Dynarr_add (ef->begin_glyphs, gb);
+	  if (seen_glyph) {
+	    struct glyph_block gb;
+	    
+	    gb.glyph = glyph;
+	    XSETEXTENT (gb.extent, e);
+	    Dynarr_add (ef->begin_glyphs, gb);
+	  }
+	  else if (EQ (glyph, last_glyph))
+	    seen_glyph = 1;
 	}
     }
 
@@ -2811,11 +2816,15 @@
       if (extent_end (e) == mempos && !NILP (extent_end_glyph (e)))
 	{
 	  Lisp_Object glyph = extent_end_glyph (e);
-	  struct glyph_block gb;
+	  if (seen_glyph) {
+	    struct glyph_block gb;
 
-	  gb.glyph = glyph;
-	  XSETEXTENT (gb.extent, e);
-	  Dynarr_add (ef->end_glyphs, gb);
+	    gb.glyph = glyph;
+	    XSETEXTENT (gb.extent, e);
+	    Dynarr_add (ef->end_glyphs, gb);
+	  }
+	  else if (EQ (glyph, last_glyph))
+	    seen_glyph = 1;
 	}
     }
 
@@ -2950,9 +2959,9 @@
   if (extent_detached_p (ext))
     strcpy (bp, "detached");
   else
-    sprintf (bp, "%ld, %ld",
-	     (long) XINT (Fextent_start_position (obj)),
-	     (long) XINT (Fextent_end_position (obj)));
+    sprintf (bp, "%d, %d",
+	     XINT (Fextent_start_position (obj)),
+	     XINT (Fextent_end_position (obj)));
   bp += strlen (bp);
   *bp++ = (extent_end_open_p (anc) ? ')': ']');
   if (!NILP (extent_end_glyph (anc))) *bp++ = '*';
Index: src/extents.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/extents.h,v
retrieving revision 1.11
diff -u -r1.11 extents.h
--- src/extents.h	2001/04/12 18:23:43	1.11
+++ src/extents.h	2002/04/23 05:32:45
@@ -328,7 +328,7 @@
 face_index extent_fragment_update (struct window *w,
 				   struct extent_fragment *ef,
 				   /* Note this is in Bytinds */
-				   Bytind pos);
+				   Bytind pos, Lisp_Object last_glyph);
 void extent_fragment_delete (struct extent_fragment *ef);
 
 
Index: src/redisplay-gtk.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay-gtk.c,v
retrieving revision 1.2.2.1
diff -u -r1.2.2.1 redisplay-gtk.c
--- src/redisplay-gtk.c	2001/10/23 08:35:35	1.2.2.1
+++ src/redisplay-gtk.c	2002/04/23 05:32:50
@@ -421,8 +421,8 @@
 	      struct display_box dbox;
 	      struct display_glyph_area dga;
 	      redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
-						 start_pixpos, rb->width,
-						 &dbox, &dga);
+						 rb->object.dglyph.yoffset ,start_pixpos,
+                                                 rb->width, &dbox, &dga);
 
 	      XSETWINDOW (window, w);
 	      instance = glyph_image_instance (rb->object.dglyph.glyph,
Index: src/redisplay-msw.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay-msw.c,v
retrieving revision 1.29
diff -u -r1.29 redisplay-msw.c
--- src/redisplay-msw.c	2001/04/12 18:24:14	1.29
+++ src/redisplay-msw.c	2002/04/23 05:32:51
@@ -309,6 +309,7 @@
       struct display_glyph_area dga;
       redisplay_calculate_display_boxes (dl, rb->xpos, 
 					 /*rb->object.dglyph.xoffset*/ 0,
+                                         /*rb->object.dglyph.yoffset*/ 0,
 					 start_pixpos, rb->width,
 					 &db, &dga);
       /* blank the background in the appropriate color */
@@ -512,7 +513,7 @@
     {
       struct display_box db;
       struct display_glyph_area dga;
-      redisplay_calculate_display_boxes (dl, xpos + xoffset, 0,
+      redisplay_calculate_display_boxes (dl, xpos + xoffset, 0, 0,
 					 clip_start, width, &db, &dga);
       /* blank the background in the appropriate color */
       mswindows_update_dc (hdc,
@@ -1165,8 +1166,8 @@
 	      struct display_glyph_area dga;
 
 	      redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
-						 start_pixpos, rb->width,
-						 &dbox, &dga);
+						 rb->object.dglyph.yoffset,
+                                                 start_pixpos, rb->width, &dbox, &dga);
 
 	      XSETWINDOW (window, w);
 	      instance = glyph_image_instance (rb->object.dglyph.glyph,
Index: src/redisplay-output.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay-output.c,v
retrieving revision 1.12.2.1
diff -u -r1.12.2.1 redisplay-output.c
--- src/redisplay-output.c	2001/10/23 08:35:37	1.12.2.1
+++ src/redisplay-output.c	2002/04/23 05:32:52
@@ -230,7 +230,10 @@
   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 &&
@@ -1549,10 +1552,24 @@
   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
@@ -1745,8 +1762,29 @@
 /*****************************************************************************
  redisplay_normalize_glyph_area
  redisplay_normalize_display_box
+
+ 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.
 
- Calculate the visible box for displaying src in dest.
+  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,
@@ -1774,28 +1812,51 @@
       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;
@@ -1880,8 +1941,8 @@
  ****************************************************************************/
 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;
@@ -1890,9 +1951,10 @@
   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)
     {
Index: src/redisplay-x.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay-x.c,v
retrieving revision 1.25.2.1
diff -u -r1.25.2.1 redisplay-x.c
--- src/redisplay-x.c	2001/10/23 08:35:37	1.25.2.1
+++ src/redisplay-x.c	2002/04/23 05:32:54
@@ -439,11 +439,12 @@
 	      Lisp_Object instance;
 	      struct display_box dbox;
 	      struct display_glyph_area dga;
+
 	      redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset,
-						 start_pixpos, rb->width,
-						 &dbox, &dga);
+						 rb->object.dglyph.yoffset, start_pixpos,
+                                                 rb->width, &dbox, &dga);
 
-	      XSETWINDOW (window, w);
+              XSETWINDOW (window, w);
 	      instance = glyph_image_instance (rb->object.dglyph.glyph,
 					       window, ERROR_ME_NOT, 1);
 	      findex = rb->findex;
Index: src/redisplay.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay.c,v
retrieving revision 1.62.2.1.2.2
diff -u -r1.62.2.1.2.2 redisplay.c
--- src/redisplay.c	2002/03/30 21:46:02	1.62.2.1.2.2
+++ src/redisplay.c	2002/04/23 05:32:59
@@ -147,9 +147,9 @@
 			   to be skipped before anything is displayed. */
   Bytind bi_start_col_enabled;
   int start_col_xoffset;	/* Number of pixels that still need to
-			   be skipped.  This is used for
-			   horizontal scrolling of glyphs, where we want
-			   to be able to scroll over part of the glyph. */
+                                   be skipped.  This is used for
+                                   horizontal scrolling of glyphs, where we want
+                                   to be able to scroll over part of the glyph. */
 
   int hscroll_glyph_width_adjust;  /* how much the width of the hscroll
 				      glyph differs from space_width (w).
@@ -163,18 +163,20 @@
   struct extent_fragment *ef;
   face_index findex;
 
-  /* The height of a pixmap may either be predetermined if the user
-     has set a baseline value, or it may be dependent on whatever the
-     line ascent and descent values end up being, based just on font
-     information.  In the first case we can immediately update the
-     values, thus their inclusion here.  In the last case we cannot
-     determine the actual contribution to the line height until we
-     have finished laying out all text on the line.  Thus we propagate
-     the max height of such pixmaps and do a final calculation after
-     all text has been added to the line. */
+  /* The height of a pixmap may either be predetermined if the user has set a
+     baseline value, or it may be dependent on whatever the line ascent and
+     descent values end up being, based just on font and pixmap-ascent
+     information.  In the first case we can immediately update the values, thus
+     their inclusion here.  In the last case we cannot determine the actual
+     contribution to the line height until we have finished laying out all text
+     on the line.  Thus we propagate the max height of such pixmaps and do a
+     final calculation (in calculate_baseline()) after all text has been added
+     to the line. */
   int new_ascent;
   int new_descent;
   int max_pixmap_height;
+  int need_baseline_computation;
+  int end_glyph_width;		/* Well, it is the kitchen sink after all ... */
 
   Lisp_Object result_str; /* String where we put the result of
 			     generating a formatted string in the modeline. */
@@ -192,15 +194,24 @@
   PROP_STRING,
   PROP_CHAR,
   PROP_MINIBUF_PROMPT,
-  PROP_BLANK
+  PROP_BLANK,
+  PROP_GLYPH
 };
 
 /* Data that should be propagated to the next line.  Either a single
-   Emchar or a string of Bufbyte's.
+   Emchar, a string of Bufbyte's or a glyph.
 
    The actual data that is propagated ends up as a Dynarr of these
    blocks.
 
+   prop_blocks are used to indicate that data that was supposed to go
+   on the previous line couldn't actually be displayed. Generally this
+   shouldn't happen if we are clipping the end of lines. If we are
+   wrapping then we need to display the propagation data before moving
+   on. Its questionable whether we should wrap or clip glyphs in this
+   instance. Most e-lisp relies on clipping so we preserve this
+   behavior.
+
    #### It's unclean that both Emchars and Bufbytes are here.
    */
 
@@ -229,6 +240,14 @@
       int width;
       face_index findex;
     } p_blank;
+
+    struct
+    {
+      /* Not used as yet, but could be used to wrap rather than clip glyphs. */
+      int width;		
+      Lisp_Object glyph;
+    } p_glyph;
+
   } data;
 };
 
@@ -265,6 +284,9 @@
 static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to,
 				     Bufpos point, int no_regen);
 static int point_visible (struct window *w, Bufpos point, int type);
+static void calculate_yoffset (struct display_line *dl,
+                               struct display_block *fixup);
+static void calculate_baseline (pos_data *data);
 
 /* This used to be 10 but 30 seems to give much better performance. */
 #define INIT_MAX_PREEMPTS	30
@@ -680,6 +702,108 @@
   return bounds;
 }
 
+/* This takes a display_block and its containing line and corrects the yoffset
+   of each glyph in the block to cater for the ascent of the line as a
+   whole. Must be called *after* the line-ascent is known! */
+
+static void
+calculate_yoffset (struct display_line *dl, struct display_block *fixup)
+{
+  int i;
+  for (i=0; i<Dynarr_length (fixup->runes); i++)
+    {
+      struct rune *r = Dynarr_atp (fixup->runes,i);
+      if (r->type == RUNE_DGLYPH)
+        {
+          if (r->object.dglyph.ascent < dl->ascent)
+            r->object.dglyph.yoffset = dl->ascent - r->object.dglyph.ascent +
+	      r->object.dglyph.descent;
+        }
+    }
+}
+
+/* Calculate the textual baseline (the ascent and descent values for the
+   display_line as a whole).
+
+   If the baseline is completely blank, or contains no manually positioned
+   glyphs, then the textual baseline is simply the baseline of the default font.
+   (The `contains no manually positioned glyphs' part is actually done for
+   us by `add_emchar_rune'.)
+
+   If the baseline contains pixmaps, and they're all manually positioned, then
+   the textual baseline location is constrained that way, and we need do no
+   work.
+
+   If the baseline contains pixmaps, and at least one is automatically
+   positioned, then the textual ascent is the largest ascent on the line, and
+   the textual descent is the largest descent (which is how things are set up at
+   entry to this function anyway): except that if the max_ascent + max_descent
+   is too small for the height of the line (say you've adjusted the baseline of
+   a short glyph, and there's a tall one next to it), then take the ascent and
+   descent for the line individually from the largest of the explicitly set
+   ascent/descent, and the rescaled ascent/descent of the default font, scaled
+   such that the largest glyph will fit.
+
+   This means that if you have a short glyph (but taller than the default
+   font's descent) forced right under the baseline, and a really tall
+   automatically positioned glyph, that the descent for the line is just big
+   enough for the manually positioned short glyph, and the tall one uses as
+   much of that space as the default font would were it as tall as the tall
+   glyph; but that the ascent is big enough for the tall glyph to fit.
+
+   This behaviour means that under no circumstances will changing the baseline
+   of a short glyph cause a tall glyph to move around; nor will it move the
+   textual baseline more than necessary. (Changing a tall glyph's baseline
+   might move the text's baseline arbitrarily, of course.) */
+
+static void
+calculate_baseline (pos_data *data)
+{
+  /* Blank line: baseline is default font's baseline. */
+
+  if (!data->new_ascent && !data->new_descent)
+    {
+      /* We've got a blank line so initialize these values from the default
+         face. */
+      default_face_font_info (data->window, &data->new_ascent,
+			      &data->new_descent, 0, 0, 0);
+    }
+  
+  /* No automatically positioned glyphs? Return at once. */
+  if (!data->need_baseline_computation)
+    return;
+
+  /* Is the tallest glyph on the line automatically positioned?
+     If it's manually positioned, or it's automatically positioned
+     and there's enough room for it anyway, we need do no more work. */
+  if (data->max_pixmap_height > data->new_ascent + data->new_descent)
+    {
+      int default_font_ascent, default_font_descent, default_font_height;
+      int scaled_default_font_ascent, scaled_default_font_descent;
+      
+      default_face_font_info (data->window, &default_font_ascent,
+			      &default_font_descent, &default_font_height,
+			      0, 0);
+
+      scaled_default_font_ascent = data->max_pixmap_height *
+	default_font_ascent / default_font_height;
+
+      data->new_ascent = max (data->new_ascent, scaled_default_font_ascent);
+
+      /* The ascent may have expanded now. Do we still need to grow the descent,
+         or are things big enough?
+
+         The +1 caters for the baseline row itself. */
+      if (data->max_pixmap_height > data->new_ascent + data->new_descent)
+        {
+          scaled_default_font_descent = (data->max_pixmap_height *
+					 default_font_descent / default_font_height) + 1;
+
+          data->new_descent = max (data->new_descent, scaled_default_font_descent);
+        }
+    }
+}
+
 /* Given a display line and a starting position, ensure that the
    contents of the display line accurately represent the visual
    representation of the buffer contents starting from the given
@@ -870,11 +994,13 @@
 	    data->last_char_width = fi->width;
 	  else
 	    data->last_char_width = -1;
-      if (!no_contribute_to_line_height)
-        {
-          data->new_ascent  = max (data->new_ascent,  (int) fi->ascent);
-          data->new_descent = max (data->new_descent, (int) fi->descent);
-        }
+
+	  if (!no_contribute_to_line_height)
+	    {
+	      data->new_ascent  = max (data->new_ascent,  (int) fi->ascent);
+	      data->new_descent = max (data->new_descent, (int) fi->descent);
+	    }
+
 	  data->last_charset = charset;
 	  data->last_findex = data->findex;
 	}
@@ -1127,12 +1253,11 @@
 static prop_block_dynarr *
 add_octal_runes (pos_data *data)
 {
-  prop_block_dynarr *prop, *add_failed;
+  prop_block_dynarr *add_failed, *prop = 0;
   Emchar orig_char = data->ch;
   unsigned int orig_cursor_type = data->cursor_type;
 
   /* Initialize */
-  prop = NULL;
   add_failed = NULL;
 
   if (data->start_col)
@@ -1192,7 +1317,7 @@
   ADD_NEXT_OCTAL_RUNE_CHAR;
 
   data->cursor_type = orig_cursor_type;
-  return prop;
+  return NULL;
 }
 
 #undef ADD_NEXT_OCTAL_RUNE_CHAR
@@ -1565,6 +1690,7 @@
       Lisp_Object face;
       Lisp_Object instance;
       face_index findex;
+      prop_block_dynarr *retval = 0;
 
       if (cachel)
 	width = cachel->width;
@@ -1576,7 +1702,6 @@
 
       if (data->start_col || data->start_col_xoffset)
 	{
-	  prop_block_dynarr *retval;
 	  int glyph_char_width = width / space_width (w);
 
 	  /* If we still have not fully scrolled horizontally after
@@ -1612,17 +1737,41 @@
       if (data->pixpos + width > data->max_pixpos)
 	{
 	  /* If this is the first object we are attempting to add to
-             the line then we ignore the horizontal_clip threshold.
-             Otherwise we will loop until the bottom of the window
-             continually failing to add this glyph because it is wider
-             than the window.  We could alternatively just completely
-             ignore the glyph and proceed from there but I think that
-             this is a better solution. */
+	     the line then we ignore the horizontal_clip threshold.
+	     Otherwise we will loop until the bottom of the window
+	     continually failing to add this glyph because it is wider
+	     than the window.  We could alternatively just completely
+	     ignore the glyph and proceed from there but I think that
+	     this is a better solution.
+	     
+	     This does, however, create a different problem in that we
+	     can end up adding the object to every single line, never
+	     getting any further - for instance an extent with a long
+	     start-glyph that covers multitple following
+	     characters.  */
 	  if (Dynarr_length (data->db->runes)
 	      && data->max_pixpos - data->pixpos < horizontal_clip)
 	    return ADD_FAILED;
-	  else
+	  else {
+	    struct prop_block pb;
+
+	    /* We need to account for the width of the end-of-line
+	       glyph if there is nothing more in the line to display,
+	       since we will not display it in this instance. It seems
+	       kind of gross doing it here, but otherwise we have to
+	       search the runes in create_text_block(). */
+	    if (data->ch == '\n')
+	      data->max_pixpos += data->end_glyph_width;
 	    width = data->max_pixpos - data->pixpos;
+	    /* Add the glyph we are displaying, but clipping, to the
+	       propagation data so that we don't try and do it
+	       again. */ 
+	    retval = Dynarr_new (prop_block);
+	    pb.type = PROP_GLYPH;
+	    pb.data.p_glyph.glyph = gb->glyph;
+	    pb.data.p_glyph.width = width;
+	    Dynarr_add (retval, pb);
+	  }
 	}
 
       if (cachel)
@@ -1638,6 +1787,8 @@
 
       baseline = glyph_baseline (gb->glyph, data->window);
 
+      rb.object.dglyph.descent = 0; /* Gets reset lower down, if it is known. */
+
       if (glyph_contrib_p (gb->glyph, data->window))
 	{
 	  /* A pixmap that has not had a baseline explicitly set.  Its
@@ -1645,6 +1796,7 @@
 	  if (NILP (baseline))
 	    {
 	      int height = ascent + descent;
+	      data->need_baseline_computation = 1;
 	      data->max_pixmap_height = max (data->max_pixmap_height, height);
 	    }
 
@@ -1667,6 +1819,9 @@
 
 	      data->new_ascent = max (data->new_ascent, pix_ascent);
 	      data->new_descent = max (data->new_descent, pix_descent);
+	      data->max_pixmap_height = max (data->max_pixmap_height, height);
+	      
+	      rb.object.dglyph.descent = pix_descent;
 	    }
 
 	  /* Otherwise something is screwed up. */
@@ -1698,7 +1853,7 @@
 	  data->findex = orig_findex;
 	  data->bi_bufpos = orig_bufpos;
 	  data->bi_start_col_enabled = orig_start_col_enabled;
-	  return NULL;
+	  return retval;
 	}
 
       rb.findex = findex;
@@ -1715,6 +1870,9 @@
       rb.object.dglyph.glyph = gb->glyph;
       rb.object.dglyph.extent = gb->extent;
       rb.object.dglyph.xoffset = xoffset;
+      rb.object.dglyph.ascent = ascent;
+      rb.object.dglyph.yoffset = 0;   /* Until we know better, assume that it has
+					 a normal (textual) baseline. */
 
       if (allow_cursor)
 	{
@@ -1750,7 +1908,7 @@
       Dynarr_add (data->db->runes, rb);
       data->pixpos += width;
 
-      return NULL;
+      return retval;
     }
   else
     {
@@ -1779,7 +1937,7 @@
 	abort ();	/* there are no unknown types */
     }
 
-  return NULL;	/* shut up compiler */
+  return NULL;
 }
 
 /* Add all glyphs at position POS_TYPE that are contained in the given
@@ -1839,7 +1997,6 @@
 			   is_surrogate_for_selected_frame (f));
 
   int truncate_win = window_truncation_on (w);
-  int end_glyph_width;
 
   /* If the buffer's value of selective_display is an integer then
      only lines that start with less than selective_display columns of
@@ -1937,10 +2094,10 @@
      glyph.  Save the width of the end glyph for later use. */
   data.max_pixpos = dl->bounds.right_in;
   if (truncate_win)
-    end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
+    data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
   else
-    end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
-  data.max_pixpos -= end_glyph_width;
+    data.end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
+  data.max_pixpos -= data.end_glyph_width;
 
   if (cursor_in_echo_area && MINI_WINDOW_P (w) && echo_area_active (f))
     {
@@ -2033,10 +2190,25 @@
       /* Check for face changes. */
       if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
 	{
+	  Lisp_Object last_glyph = Qnil;
+
+	  /* Deal with glyphs that we have already displayed. The
+	     theory is that if we end up with a PROP_GLYPH in the
+	     propagation data then we are clipping the glyph and there
+	     can be no propagation data before that point. The theory
+	     works because we always recalculate the extent-fragments
+	     for propagated data, we never actually propagate the
+	     fragments that still need to be displayed. */
+	  if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH) 
+	    {
+	      last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph;
+	      Dynarr_free (*prop);
+	      *prop = 0;
+	    }
 	  /* Now compute the face and begin/end-glyph information. */
 	  data.findex =
 	    /* Remember that the extent-fragment routines deal in Bytind's. */
-	    extent_fragment_update (w, data.ef, data.bi_bufpos);
+	    extent_fragment_update (w, data.ef, data.bi_bufpos, last_glyph);
 
 	  get_display_tables (w, data.findex, &face_dt, &window_dt);
 
@@ -2106,9 +2278,9 @@
 	}
 
       /* If there is propagation data, then it represents the current
-         buffer position being displayed.  Add them and advance the
-         position counter.  This might also add the minibuffer
-         prompt. */
+	 buffer position being displayed.  Add them and advance the
+	 position counter.  This might also add the minibuffer
+	 prompt. */
       else if (*prop)
 	{
 	  dl->used_prop_data = 1;
@@ -2132,17 +2304,43 @@
 	 a line are handled correctly. */
       else if (Dynarr_length (data.ef->end_glyphs) > 0)
 	{
+	  /* #### I think this is safe, but could be wrong. */
+	  data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
 	  *prop = add_glyph_runes (&data, END_GLYPHS);
-	  if (*prop)
-	    goto done;
+	  if (*prop) 
+	    {
+	      /* If we just clipped a glyph and we are at the end of a
+		 line then do appropriate processing to not get a
+		 continuation glyph. */
+	      if (Dynarr_atp (*prop, 0)->type == PROP_GLYPH
+		  && data.ch == '\n')
+		{ 
+		  data.blank_width = DEVMETH (d, eol_cursor_width, ());
+		  add_emchar_rune (&data); /* discard prop data. */
+		}
+	      goto done;
+	    }
 	}
 
       /* If there are begin glyphs, add them to the line. */
       else if (Dynarr_length (data.ef->begin_glyphs) > 0)
 	{
+	  /* #### I think this is safe, but could be wrong. */
+	  data.ch = BI_BUF_FETCH_CHAR (b, data.bi_bufpos);
 	  *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
-	  if (*prop)
-	    goto done;
+	  if (*prop) 
+	    {
+	      /* If we just clipped a glyph and we are at the end of a
+		 line then do appropriate processing to not get a
+		 continuation glyph. */
+	      if (Dynarr_atp (*prop, 0)->type == PROP_GLYPH
+		  && data.ch == '\n')
+		{ 
+		  data.blank_width = DEVMETH (d, eol_cursor_width, ());
+		  add_emchar_rune (&data); /* discard prop data. */
+		}
+	      goto done;
+	    }
 	}
 
       /* If at end-of-buffer, we've already processed begin and
@@ -2176,7 +2374,7 @@
 	      /* We aren't going to be adding an end glyph so give its
                  space back in order to make sure that the cursor can
                  fit. */
-	      data.max_pixpos += end_glyph_width;
+	      data.max_pixpos += data.end_glyph_width;
 
 	      if (selective > 0
 		  && (bi_spaces_at_point
@@ -2257,7 +2455,7 @@
 
 	      /* We won't be adding a truncation or continuation glyph
                  so give up the room allocated for them. */
-	      data.max_pixpos += end_glyph_width;
+	      data.max_pixpos += data.end_glyph_width;
 
 	      if (!NILP (b->selective_display_ellipses))
 		{
@@ -2466,7 +2664,7 @@
              for the next newline.  We also add the end-of-line glyph which
              we know will fit because we adjusted the right border before
              we starting laying out the line. */
-	  data.max_pixpos += end_glyph_width;
+	  data.max_pixpos += data.end_glyph_width;
 	  data.findex = DEFAULT_INDEX;
 	  gb.extent = Qnil;
 
@@ -2600,27 +2798,8 @@
     }
   else
     db->end_pos = dl->bounds.right_white;
-
-  /* update line height parameters */
-  if (!data.new_ascent && !data.new_descent)
-    {
-      /* We've got a blank line so initialize these values from the default
-         face. */
-      default_face_font_info (data.window, &data.new_ascent,
-			      &data.new_descent, 0, 0, 0);
-    }
-
-  if (data.max_pixmap_height)
-    {
-      int height = data.new_ascent + data.new_descent;
-      int pix_ascent, pix_descent;
-
-      pix_descent = data.max_pixmap_height * data.new_descent / height;
-      pix_ascent = data.max_pixmap_height - pix_descent;
 
-      data.new_ascent = max (data.new_ascent, pix_ascent);
-      data.new_descent = max (data.new_descent, pix_descent);
-    }
+  calculate_baseline (&data);
 
   dl->ascent = data.new_ascent;
   dl->descent = data.new_descent;
@@ -2638,6 +2817,8 @@
       dl->descent = descent;
   }
 
+  calculate_yoffset (dl, db);
+
   dl->cursor_elt = data.cursor_x;
   /* #### lossage lossage lossage! Fix this shit! */
   if (data.bi_bufpos > BI_BUF_ZV (b))
@@ -2726,18 +2907,8 @@
       gb.extent = Qnil;
       add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, 0);
     }
-
-  if (data.max_pixmap_height)
-    {
-      int height = data.new_ascent + data.new_descent;
-      int pix_ascent, pix_descent;
-
-      pix_descent = data.max_pixmap_height * data.new_descent / height;
-      pix_ascent = data.max_pixmap_height - pix_descent;
 
-      data.new_ascent = max (data.new_ascent, pix_ascent);
-      data.new_descent = max (data.new_descent, pix_descent);
-    }
+  calculate_baseline (&data);
 
   dl->ascent = data.new_ascent;
   dl->descent = data.new_descent;
@@ -2745,6 +2916,8 @@
   data.db->start_pos = dl->bounds.left_in;
   data.db->end_pos = data.pixpos;
 
+  calculate_yoffset (dl, data.db);
+
   return data.pixpos - dl->bounds.left_in;
 }
 
@@ -2815,21 +2988,14 @@
 
       (reverse ? elt-- : elt++);
     }
-
-  if (data.max_pixmap_height)
-    {
-      int height = data.new_ascent + data.new_descent;
-      int pix_ascent, pix_descent;
 
-      pix_descent = data.max_pixmap_height * data.new_descent / height;
-      pix_ascent = data.max_pixmap_height - pix_descent;
-      data.new_ascent = max (data.new_ascent, pix_ascent);
-      data.new_descent = max (data.new_descent, pix_descent);
-    }
+  calculate_baseline (&data);
 
   dl->ascent = data.new_ascent;
   dl->descent = data.new_descent;
 
+  calculate_yoffset (dl, data.db);
+
   return data.pixpos;
 }
 
@@ -4259,9 +4425,9 @@
 
 
 /***************************************************************************/
-/*								*/
-/*                            displayable string routines			*/
-/*								*/
+/*                                                                         */
+/*                            displayable string routines                  */
+/*                                                                         */
 /***************************************************************************/
 
 /* Given a position for a string in a window, ensure that the given
@@ -4303,7 +4469,6 @@
   pos_data data;
 
   int truncate_win = b ? window_truncation_on (w) : 0;
-  int end_glyph_width = 0;
 
   /* We're going to ditch selective display for static text, it's an
      FSF thing and invisible extents are the way to go here.
@@ -4411,13 +4576,7 @@
   /* Set the right boundary adjusting it to take into account any end
      glyph.  Save the width of the end glyph for later use. */
   data.max_pixpos = dl->bounds.right_in;
-#if 0
-  if (truncate_win)
-    end_glyph_width = GLYPH_CACHEL_WIDTH (w, TRUN_GLYPH_INDEX);
-  else
-    end_glyph_width = GLYPH_CACHEL_WIDTH (w, CONT_GLYPH_INDEX);
-#endif
-  data.max_pixpos -= end_glyph_width;
+  data.max_pixpos -= data.end_glyph_width;
 
   data.cursor_type = NO_CURSOR;
   data.cursor_x = -1;
@@ -4473,10 +4632,18 @@
       /* Check for face changes. */
       if (initial || (!no_more_frags && data.bi_bufpos == data.ef->end))
 	{
+	  Lisp_Object last_glyph = Qnil;
+	  /* Deal with clipped glyphs that we have already displayed. */
+	  if (*prop && Dynarr_atp (*prop, 0)->type == PROP_GLYPH) 
+	    {
+	      last_glyph = Dynarr_atp (*prop, 0)->data.p_glyph.glyph;
+	      Dynarr_free (*prop);
+	      *prop = 0;
+	    }
 	  /* Now compute the face and begin/end-glyph information. */
 	  data.findex =
 	    /* Remember that the extent-fragment routines deal in Bytind's. */
-	    extent_fragment_update (w, data.ef, data.bi_bufpos);
+	    extent_fragment_update (w, data.ef, data.bi_bufpos, last_glyph);
 	  /* This is somewhat cheesy but the alternative is to
              propagate default_face into extent_fragment_update. */
 	  if (data.findex == DEFAULT_INDEX)
@@ -4568,15 +4735,19 @@
 	 a line are handled correctly. */
       else if (Dynarr_length (data.ef->end_glyphs) > 0)
 	{
+	  data.ch = string_char (s, data.bi_bufpos);
 	  *prop = add_glyph_runes (&data, END_GLYPHS);
-	  if (*prop)
+
+	  if (*prop) 
 	    goto done;
 	}
 
       /* If there are begin glyphs, add them to the line. */
       else if (Dynarr_length (data.ef->begin_glyphs) > 0)
 	{
+	  data.ch = string_char (s, data.bi_bufpos);
 	  *prop = add_glyph_runes (&data, BEGIN_GLYPHS);
+
 	  if (*prop)
 	    goto done;
 	}
@@ -4612,7 +4783,7 @@
 	      /* We aren't going to be adding an end glyph so give its
                  space back in order to make sure that the cursor can
                  fit. */
-	      data.max_pixpos += end_glyph_width;
+	      data.max_pixpos += data.end_glyph_width;
 	      goto done;
 	    }
 
@@ -4654,7 +4825,7 @@
 	      *prop = add_blank_rune (&data, w, char_tab_width);
 
 	      /* add_blank_rune is only supposed to be called with
-                 sizes guaranteed to fit in the available space. */
+		 sizes guaranteed to fit in the available space. */
 	      assert (!(*prop));
 
 	      if (prop_width)
@@ -4710,7 +4881,7 @@
 	}
     }
 
-done:
+ done:
 
   /* Determine the starting point of the next line if we did not hit the
      end of the buffer. */
@@ -4743,7 +4914,7 @@
              for the next newline.  We also add the end-of-line glyph which
              we know will fit because we adjusted the right border before
              we starting laying out the line. */
-	  data.max_pixpos += end_glyph_width;
+	  data.max_pixpos += data.end_glyph_width;
 	  data.findex = default_face;
 	  gb.extent = Qnil;
 
@@ -4771,7 +4942,7 @@
 	      cachel = GLYPH_CACHEL (w, CONT_GLYPH_INDEX);
 	    }
 
-	  if (end_glyph_width)
+	  if (data.end_glyph_width)
 	    add_glyph_rune (&data, &gb, BEGIN_GLYPHS, 0, cachel);
 
 	  if (truncate_win && data.bi_bufpos == bi_string_zv)
@@ -4849,28 +5020,9 @@
     }
   else
     db->end_pos = dl->bounds.right_white;
-
-  /* update line height parameters */
-  if (!data.new_ascent && !data.new_descent)
-    {
-      /* We've got a blank line so initialize these values from the default
-         face. */
-      default_face_font_info (data.window, &data.new_ascent,
-			      &data.new_descent, 0, 0, 0);
-    }
-
-  if (data.max_pixmap_height)
-    {
-      int height = data.new_ascent + data.new_descent;
-      int pix_ascent, pix_descent;
 
-      pix_descent = data.max_pixmap_height * data.new_descent / height;
-      pix_ascent = data.max_pixmap_height - pix_descent;
+  calculate_baseline (&data);
 
-      data.new_ascent = max (data.new_ascent, pix_ascent);
-      data.new_descent = max (data.new_descent, pix_descent);
-    }
-
   dl->ascent = data.new_ascent;
   dl->descent = data.new_descent;
 
@@ -4886,6 +5038,8 @@
     if (dl->descent < descent)
       dl->descent = descent;
   }
+
+  calculate_yoffset (dl, db);
 
   dl->cursor_elt = data.cursor_x;
   /* #### lossage lossage lossage! Fix this shit! */
Index: src/redisplay.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/redisplay.h,v
retrieving revision 1.8
diff -u -r1.8 redisplay.h
--- src/redisplay.h	2001/04/12 18:24:15	1.8
+++ src/redisplay.h	2002/04/23 05:33:00
@@ -147,6 +147,9 @@
                                    If this is a rune in the modeline
                                    then this might be nil. */
 
+      int ascent;               /* Ascent of this glyph, in pixels. */
+      int descent;              /* Descent of this glyph, in pixels. */
+      int yoffset;              /* Offset from line top to reach glyph top */
       int xoffset;		/* Number of pixels that need to be
 				   chopped off the left of the glyph.
 				   This has the effect of shifting the
@@ -768,8 +771,8 @@
 			      face_index findex, int cursor_start, int cursor_width,
 			      int cursor_height, int offset_bitmap);
 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);
 int redisplay_normalize_glyph_area (struct display_box* dest,
 				    struct display_glyph_area* glyphsrc);
