emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] Changes to emacs/src/xdisp.c


From: Kim F. Storm
Subject: [Emacs-diffs] Changes to emacs/src/xdisp.c
Date: Sun, 16 Mar 2003 15:45:47 -0500

Index: emacs/src/xdisp.c
diff -c emacs/src/xdisp.c:1.810 emacs/src/xdisp.c:1.811
*** emacs/src/xdisp.c:1.810     Wed Mar 12 17:57:28 2003
--- emacs/src/xdisp.c   Sun Mar 16 15:45:46 2003
***************
*** 280,285 ****
--- 280,286 ----
  Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
  Lisp_Object Qmargin;
  extern Lisp_Object Qheight;
+ extern Lisp_Object QCwidth, QCheight, QCascent;
  
  /* Non-nil means highlight trailing whitespace.  */
  
***************
*** 15660,15665 ****
--- 15661,17656 ----
  
  
  /***********************************************************************
+                            Glyph Display
+  ***********************************************************************/
+ 
+ #if GLYPH_DEBUG
+ 
+ void
+ dump_glyph_string (s)
+      struct glyph_string *s;
+ {
+   fprintf (stderr, "glyph string\n");
+   fprintf (stderr, "  x, y, w, h = %d, %d, %d, %d\n",
+          s->x, s->y, s->width, s->height);
+   fprintf (stderr, "  ybase = %d\n", s->ybase);
+   fprintf (stderr, "  hl = %d\n", s->hl);
+   fprintf (stderr, "  left overhang = %d, right = %d\n",
+          s->left_overhang, s->right_overhang);
+   fprintf (stderr, "  nchars = %d\n", s->nchars);
+   fprintf (stderr, "  extends to end of line = %d\n",
+          s->extends_to_end_of_line_p);
+   fprintf (stderr, "  font height = %d\n", FONT_HEIGHT (s->font));
+   fprintf (stderr, "  bg width = %d\n", s->background_width);
+ }
+ 
+ #endif /* GLYPH_DEBUG */
+ 
+ /* Initialize glyph string S.  CHAR2B is a suitably allocated vector
+    of XChar2b structures for S; it can't be allocated in
+    init_glyph_string because it must be allocated via `alloca'.  W
+    is the window on which S is drawn.  ROW and AREA are the glyph row
+    and area within the row from which S is constructed.  START is the
+    index of the first glyph structure covered by S.  HL is a
+    face-override for drawing S.  */
+ 
+ #ifdef HAVE_NTGUI
+ #define OPTIONAL_HDC(hdc)  hdc,
+ #define DECLARE_HDC(hdc)   HDC hdc;
+ #define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
+ #define RELEASE_HDC(hdc, f)  release_frame_dc ((f), (hdc))
+ #endif
+ 
+ #ifndef OPTIONAL_HDC
+ #define OPTIONAL_HDC(hdc)
+ #define DECLARE_HDC(hdc)
+ #define ALLOCATE_HDC(hdc, f)
+ #define RELEASE_HDC(hdc, f)
+ #endif
+ 
+ static void
+ init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
+      struct glyph_string *s;
+      DECLARE_HDC (hdc)
+      XChar2b *char2b;
+      struct window *w;
+      struct glyph_row *row;
+      enum glyph_row_area area;
+      int start;
+      enum draw_glyphs_face hl;
+ {
+   bzero (s, sizeof *s);
+   s->w = w;
+   s->f = XFRAME (w->frame);
+ #ifdef HAVE_NTGUI
+   s->hdc = hdc;
+ #endif
+   s->display = FRAME_X_DISPLAY (s->f);
+   s->window = FRAME_X_WINDOW (s->f);
+   s->char2b = char2b;
+   s->hl = hl;
+   s->row = row;
+   s->area = area;
+   s->first_glyph = row->glyphs[area] + start;
+   s->height = row->height;
+   s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+ 
+   /* Display the internal border below the tool-bar window.  */
+   if (s->w == XWINDOW (s->f->tool_bar_window))
+     s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
+ 
+   s->ybase = s->y + row->ascent;
+ }
+ 
+ 
+ /* Append the list of glyph strings with head H and tail T to the list
+    with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the result.  */
+ 
+ static INLINE void
+ append_glyph_string_lists (head, tail, h, t)
+      struct glyph_string **head, **tail;
+      struct glyph_string *h, *t;
+ {
+   if (h)
+     {
+       if (*head)
+       (*tail)->next = h;
+       else
+       *head = h;
+       h->prev = *tail;
+       *tail = t;
+     }
+ }
+ 
+ 
+ /* Prepend the list of glyph strings with head H and tail T to the
+    list with head *HEAD and tail *TAIL.  Set *HEAD and *TAIL to the
+    result.  */
+ 
+ static INLINE void
+ prepend_glyph_string_lists (head, tail, h, t)
+      struct glyph_string **head, **tail;
+      struct glyph_string *h, *t;
+ {
+   if (h)
+     {
+       if (*head)
+       (*head)->prev = t;
+       else
+       *tail = t;
+       t->next = *head;
+       *head = h;
+     }
+ }
+ 
+ 
+ /* Append glyph string S to the list with head *HEAD and tail *TAIL.
+    Set *HEAD and *TAIL to the resulting list.  */
+ 
+ static INLINE void
+ append_glyph_string (head, tail, s)
+      struct glyph_string **head, **tail;
+      struct glyph_string *s;
+ {
+   s->next = s->prev = NULL;
+   append_glyph_string_lists (head, tail, s, s);
+ }
+ 
+ 
+ /* Get face and two-byte form of character glyph GLYPH on frame F.
+    The encoding of GLYPH->u.ch is returned in *CHAR2B.  Value is
+    a pointer to a realized face that is ready for display.  */
+ 
+ static INLINE struct face *
+ get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
+      struct frame *f;
+      struct glyph *glyph;
+      XChar2b *char2b;
+      int *two_byte_p;
+ {
+   struct face *face;
+ 
+   xassert (glyph->type == CHAR_GLYPH);
+   face = FACE_FROM_ID (f, glyph->face_id);
+ 
+   if (two_byte_p)
+     *two_byte_p = 0;
+ 
+   if (!glyph->multibyte_p)
+     {
+       /* Unibyte case.  We don't have to encode, but we have to make
+        sure to use a face suitable for unibyte.  */
+       STORE_XCHAR2B (char2b, 0, glyph->u.ch);
+     }
+   else if (glyph->u.ch < 128
+          && glyph->face_id < BASIC_FACE_ID_SENTINEL)
+     {
+       /* Case of ASCII in a face known to fit ASCII.  */
+       STORE_XCHAR2B (char2b, 0, glyph->u.ch);
+     }
+   else
+     {
+       int c1, c2, charset;
+ 
+       /* Split characters into bytes.  If c2 is -1 afterwards, C is
+        really a one-byte character so that byte1 is zero.  */
+       SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
+       if (c2 > 0)
+       STORE_XCHAR2B (char2b, c1, c2);
+       else
+       STORE_XCHAR2B (char2b, 0, c1);
+ 
+       /* Maybe encode the character in *CHAR2B.  */
+       if (charset != CHARSET_ASCII)
+       {
+         struct font_info *font_info
+           = FONT_INFO_FROM_ID (f, face->font_info_id);
+         if (font_info)
+           glyph->font_type
+             = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
+       }
+     }
+ 
+   /* Make sure X resources of the face are allocated.  */
+   xassert (face != NULL);
+   PREPARE_FACE_FOR_DISPLAY (f, face);
+   return face;
+ }
+ 
+ 
+ /* Fill glyph string S with composition components specified by S->cmp.
+ 
+    FACES is an array of faces for all components of this composition.
+    S->gidx is the index of the first component for S.
+    OVERLAPS_P non-zero means S should draw the foreground only, and
+    use its physical height for clipping.
+ 
+    Value is the index of a component not in S.  */
+ 
+ static int
+ fill_composite_glyph_string (s, faces, overlaps_p)
+      struct glyph_string *s;
+      struct face **faces;
+      int overlaps_p;
+ {
+   int i;
+ 
+   xassert (s);
+ 
+   s->for_overlaps_p = overlaps_p;
+ 
+   s->face = faces[s->gidx];
+   s->font = s->face->font;
+   s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+ 
+   /* For all glyphs of this composition, starting at the offset
+      S->gidx, until we reach the end of the definition or encounter a
+      glyph that requires the different face, add it to S.  */
+   ++s->nchars;
+   for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
+     ++s->nchars;
+ 
+   /* All glyph strings for the same composition has the same width,
+      i.e. the width set for the first component of the composition.  */
+ 
+   s->width = s->first_glyph->pixel_width;
+ 
+   /* If the specified font could not be loaded, use the frame's
+      default font, but record the fact that we couldn't load it in
+      the glyph string so that we can draw rectangles for the
+      characters of the glyph string.  */
+   if (s->font == NULL)
+     {
+       s->font_not_found_p = 1;
+       s->font = FRAME_FONT (s->f);
+     }
+ 
+   /* Adjust base line for subscript/superscript text.  */
+   s->ybase += s->first_glyph->voffset;
+ 
+   xassert (s->face && s->face->gc);
+ 
+   /* This glyph string must always be drawn with 16-bit functions.  */
+   s->two_byte_p = 1;
+ 
+   return s->gidx + s->nchars;
+ }
+ 
+ 
+ /* Fill glyph string S from a sequence of character glyphs.
+ 
+    FACE_ID is the face id of the string.  START is the index of the
+    first glyph to consider, END is the index of the last + 1.
+    OVERLAPS_P non-zero means S should draw the foreground only, and
+    use its physical height for clipping.
+ 
+    Value is the index of the first glyph not in S.  */
+ 
+ static int
+ fill_glyph_string (s, face_id, start, end, overlaps_p)
+      struct glyph_string *s;
+      int face_id;
+      int start, end, overlaps_p;
+ {
+   struct glyph *glyph, *last;
+   int voffset;
+   int glyph_not_available_p;
+ 
+   xassert (s->f == XFRAME (s->w->frame));
+   xassert (s->nchars == 0);
+   xassert (start >= 0 && end > start);
+ 
+   s->for_overlaps_p = overlaps_p,
+   glyph = s->row->glyphs[s->area] + start;
+   last = s->row->glyphs[s->area] + end;
+   voffset = glyph->voffset;
+ 
+   glyph_not_available_p = glyph->glyph_not_available_p;
+ 
+   while (glyph < last
+        && glyph->type == CHAR_GLYPH
+        && glyph->voffset == voffset
+        /* Same face id implies same font, nowadays.  */
+        && glyph->face_id == face_id
+        && glyph->glyph_not_available_p == glyph_not_available_p)
+     {
+       int two_byte_p;
+ 
+       s->face = get_glyph_face_and_encoding (s->f, glyph,
+                                              s->char2b + s->nchars,
+                                              &two_byte_p);
+       s->two_byte_p = two_byte_p;
+       ++s->nchars;
+       xassert (s->nchars <= end - start);
+       s->width += glyph->pixel_width;
+       ++glyph;
+     }
+ 
+   s->font = s->face->font;
+   s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+ 
+   /* If the specified font could not be loaded, use the frame's font,
+      but record the fact that we couldn't load it in
+      S->font_not_found_p so that we can draw rectangles for the
+      characters of the glyph string.  */
+   if (s->font == NULL || glyph_not_available_p)
+     {
+       s->font_not_found_p = 1;
+       s->font = FRAME_FONT (s->f);
+     }
+ 
+   /* Adjust base line for subscript/superscript text.  */
+   s->ybase += voffset;
+ 
+   xassert (s->face && s->face->gc);
+   return glyph - s->row->glyphs[s->area];
+ }
+ 
+ 
+ /* Fill glyph string S from image glyph S->first_glyph.  */
+ 
+ static void
+ fill_image_glyph_string (s)
+      struct glyph_string *s;
+ {
+   xassert (s->first_glyph->type == IMAGE_GLYPH);
+   s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
+   xassert (s->img);
+   s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
+   s->font = s->face->font;
+   s->width = s->first_glyph->pixel_width;
+ 
+   /* Adjust base line for subscript/superscript text.  */
+   s->ybase += s->first_glyph->voffset;
+ }
+ 
+ 
+ /* Fill glyph string S from a sequence of stretch glyphs.
+ 
+    ROW is the glyph row in which the glyphs are found, AREA is the
+    area within the row.  START is the index of the first glyph to
+    consider, END is the index of the last + 1.
+ 
+    Value is the index of the first glyph not in S.  */
+ 
+ static int
+ fill_stretch_glyph_string (s, row, area, start, end)
+      struct glyph_string *s;
+      struct glyph_row *row;
+      enum glyph_row_area area;
+      int start, end;
+ {
+   struct glyph *glyph, *last;
+   int voffset, face_id;
+ 
+   xassert (s->first_glyph->type == STRETCH_GLYPH);
+ 
+   glyph = s->row->glyphs[s->area] + start;
+   last = s->row->glyphs[s->area] + end;
+   face_id = glyph->face_id;
+   s->face = FACE_FROM_ID (s->f, face_id);
+   s->font = s->face->font;
+   s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+   s->width = glyph->pixel_width;
+   voffset = glyph->voffset;
+ 
+   for (++glyph;
+        (glyph < last
+       && glyph->type == STRETCH_GLYPH
+       && glyph->voffset == voffset
+       && glyph->face_id == face_id);
+        ++glyph)
+     s->width += glyph->pixel_width;
+ 
+   /* Adjust base line for subscript/superscript text.  */
+   s->ybase += voffset;
+ 
+   /* The case that face->gc == 0 is handled when drawing the glyph
+      string by calling PREPARE_FACE_FOR_DISPLAY.  */
+   xassert (s->face);
+   return glyph - s->row->glyphs[s->area];
+ }
+ 
+ 
+ /* EXPORT for RIF:
+    Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
+    frame F.  Overhangs of glyphs other than type CHAR_GLYPH are
+    assumed to be zero.  */
+ 
+ void
+ x_get_glyph_overhangs (glyph, f, left, right)
+      struct glyph *glyph;
+      struct frame *f;
+      int *left, *right;
+ {
+   *left = *right = 0;
+ 
+   if (glyph->type == CHAR_GLYPH)
+     {
+       XFontStruct *font;
+       struct face *face;
+       struct font_info *font_info;
+       XChar2b char2b;
+       XCharStruct *pcm;
+ 
+       face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
+       font = face->font;
+       font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
+       if (font  /* ++KFS: Should this be font_info ?  */
+         && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
+       {
+         if (pcm->rbearing > pcm->width)
+           *right = pcm->rbearing - pcm->width;
+         if (pcm->lbearing < 0)
+           *left = -pcm->lbearing;
+       }
+     }
+ }
+ 
+ 
+ /* Return the index of the first glyph preceding glyph string S that
+    is overwritten by S because of S's left overhang.  Value is -1
+    if no glyphs are overwritten.  */
+ 
+ static int
+ left_overwritten (s)
+      struct glyph_string *s;
+ {
+   int k;
+ 
+   if (s->left_overhang)
+     {
+       int x = 0, i;
+       struct glyph *glyphs = s->row->glyphs[s->area];
+       int first = s->first_glyph - glyphs;
+ 
+       for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
+       x -= glyphs[i].pixel_width;
+ 
+       k = i + 1;
+     }
+   else
+     k = -1;
+ 
+   return k;
+ }
+ 
+ 
+ /* Return the index of the first glyph preceding glyph string S that
+    is overwriting S because of its right overhang.  Value is -1 if no
+    glyph in front of S overwrites S.  */
+ 
+ static int
+ left_overwriting (s)
+      struct glyph_string *s;
+ {
+   int i, k, x;
+   struct glyph *glyphs = s->row->glyphs[s->area];
+   int first = s->first_glyph - glyphs;
+ 
+   k = -1;
+   x = 0;
+   for (i = first - 1; i >= 0; --i)
+     {
+       int left, right;
+       x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
+       if (x + right > 0)
+       k = i;
+       x -= glyphs[i].pixel_width;
+     }
+ 
+   return k;
+ }
+ 
+ 
+ /* Return the index of the last glyph following glyph string S that is
+    not overwritten by S because of S's right overhang.  Value is -1 if
+    no such glyph is found.  */
+ 
+ static int
+ right_overwritten (s)
+      struct glyph_string *s;
+ {
+   int k = -1;
+ 
+   if (s->right_overhang)
+     {
+       int x = 0, i;
+       struct glyph *glyphs = s->row->glyphs[s->area];
+       int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+       int end = s->row->used[s->area];
+ 
+       for (i = first; i < end && s->right_overhang > x; ++i)
+       x += glyphs[i].pixel_width;
+ 
+       k = i;
+     }
+ 
+   return k;
+ }
+ 
+ 
+ /* Return the index of the last glyph following glyph string S that
+    overwrites S because of its left overhang.  Value is negative
+    if no such glyph is found.  */
+ 
+ static int
+ right_overwriting (s)
+      struct glyph_string *s;
+ {
+   int i, k, x;
+   int end = s->row->used[s->area];
+   struct glyph *glyphs = s->row->glyphs[s->area];
+   int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+ 
+   k = -1;
+   x = 0;
+   for (i = first; i < end; ++i)
+     {
+       int left, right;
+       x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
+       if (x - left < 0)
+       k = i;
+       x += glyphs[i].pixel_width;
+     }
+ 
+   return k;
+ }
+ 
+ 
+ /* Get face and two-byte form of character C in face FACE_ID on frame
+    F.  The encoding of C is returned in *CHAR2B.  MULTIBYTE_P non-zero
+    means we want to display multibyte text.  DISPLAY_P non-zero means
+    make sure that X resources for the face returned are allocated.
+    Value is a pointer to a realized face that is ready for display if
+    DISPLAY_P is non-zero.  */
+ 
+ static INLINE struct face *
+ get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
+      struct frame *f;
+      int c, face_id;
+      XChar2b *char2b;
+      int multibyte_p, display_p;
+ {
+   struct face *face = FACE_FROM_ID (f, face_id);
+ 
+   if (!multibyte_p)
+     {
+       /* Unibyte case.  We don't have to encode, but we have to make
+        sure to use a face suitable for unibyte.  */
+       STORE_XCHAR2B (char2b, 0, c);
+       face_id = FACE_FOR_CHAR (f, face, c);
+       face = FACE_FROM_ID (f, face_id);
+     }
+   else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
+     {
+       /* Case of ASCII in a face known to fit ASCII.  */
+       STORE_XCHAR2B (char2b, 0, c);
+     }
+   else
+     {
+       int c1, c2, charset;
+ 
+       /* Split characters into bytes.  If c2 is -1 afterwards, C is
+        really a one-byte character so that byte1 is zero.  */
+       SPLIT_CHAR (c, charset, c1, c2);
+       if (c2 > 0)
+       STORE_XCHAR2B (char2b, c1, c2);
+       else
+       STORE_XCHAR2B (char2b, 0, c1);
+ 
+       /* Maybe encode the character in *CHAR2B.  */
+       if (face->font != NULL)
+       {
+         struct font_info *font_info
+           = FONT_INFO_FROM_ID (f, face->font_info_id);
+         if (font_info)
+           rif->encode_char (c, char2b, font_info, 0);
+       }
+     }
+ 
+   /* Make sure X resources of the face are allocated.  */
+ #ifdef HAVE_X_WINDOWS
+   if (display_p)
+ #endif
+     {
+       xassert (face != NULL);
+       PREPARE_FACE_FOR_DISPLAY (f, face);
+     }
+ 
+   return face;
+ }
+ 
+ 
+ /* Set background width of glyph string S.  START is the index of the
+    first glyph following S.  LAST_X is the right-most x-position + 1
+    in the drawing area.  */
+ 
+ static INLINE void
+ set_glyph_string_background_width (s, start, last_x)
+      struct glyph_string *s;
+      int start;
+      int last_x;
+ {
+   /* If the face of this glyph string has to be drawn to the end of
+      the drawing area, set S->extends_to_end_of_line_p.  */
+   struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
+ 
+   if (start == s->row->used[s->area]
+       && s->area == TEXT_AREA
+       && ((s->hl == DRAW_NORMAL_TEXT
+          && (s->row->fill_line_p
+              || s->face->background != default_face->background
+              || s->face->stipple != default_face->stipple
+              || s->row->mouse_face_p))
+         || s->hl == DRAW_MOUSE_FACE
+         || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
+             && s->row->fill_line_p)))
+       s->extends_to_end_of_line_p = 1;
+ 
+   /* If S extends its face to the end of the line, set its
+      background_width to the distance to the right edge of the drawing
+      area.  */
+   if (s->extends_to_end_of_line_p)
+     s->background_width = last_x - s->x + 1;
+   else
+     s->background_width = s->width;
+ }
+ 
+ 
+ /* Compute overhangs and x-positions for glyph string S and its
+    predecessors, or successors.  X is the starting x-position for S.
+    BACKWARD_P non-zero means process predecessors.  */
+ 
+ static void
+ compute_overhangs_and_x (s, x, backward_p)
+      struct glyph_string *s;
+      int x;
+      int backward_p;
+ {
+   if (backward_p)
+     {
+       while (s)
+       {
+         if (rif->compute_glyph_string_overhangs)
+           rif->compute_glyph_string_overhangs (s);
+         x -= s->width;
+         s->x = x;
+         s = s->prev;
+       }
+     }
+   else
+     {
+       while (s)
+       {
+         if (rif->compute_glyph_string_overhangs)
+           rif->compute_glyph_string_overhangs (s);
+         s->x = x;
+         x += s->width;
+         s = s->next;
+       }
+     }
+ }
+ 
+ 
+ 
+ /* The following macros are only called from x_draw_glyphs below.
+    They reference the following parameters of that function directly:
+      `w', `row', `area', and `overlap_p'
+    as well as the following local variables:
+      `s', `f', and `hdc' (in W32)  */
+ 
+ #ifdef HAVE_NTGUI
+ /* On W32, silently add local `hdc' variable to argument list of
+    init_glyph_string.  */
+ #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
+   init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
+ #else
+ #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
+   init_glyph_string (s, char2b, w, row, area, start, hl)
+ #endif
+ 
+ /* Add a glyph string for a stretch glyph to the list of strings
+    between HEAD and TAIL.  START is the index of the stretch glyph in
+    row area AREA of glyph row ROW.  END is the index of the last glyph
+    in that glyph row area.  X is the current output position assigned
+    to the new glyph string constructed.  HL overrides that face of the
+    glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn.  LAST_X
+    is the right-most x-position of the drawing area.  */
+ 
+ /* SunOS 4 bundled cc, barfed on continuations in the arg lists here
+    and below -- keep them on one line.  */
+ #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X)   \
+      do                                                                       
    \
+        {                                                                  \
+        s = (struct glyph_string *) alloca (sizeof *s);                    \
+        INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);              \
+        START = fill_stretch_glyph_string (s, row, area, START, END);      \
+        append_glyph_string (&HEAD, &TAIL, s);                             \
+          s->x = (X);                                                      \
+        }                                                                  \
+      while (0)
+ 
+ 
+ /* Add a glyph string for an image glyph to the list of strings
+    between HEAD and TAIL.  START is the index of the image glyph in
+    row area AREA of glyph row ROW.  END is the index of the last glyph
+    in that glyph row area.  X is the current output position assigned
+    to the new glyph string constructed.  HL overrides that face of the
+    glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn.  LAST_X
+    is the right-most x-position of the drawing area.  */
+ 
+ #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+      do                                                                       
\
+        {                                                              \
+        s = (struct glyph_string *) alloca (sizeof *s);                \
+        INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL);          \
+        fill_image_glyph_string (s);                                   \
+        append_glyph_string (&HEAD, &TAIL, s);                         \
+        ++START;                                                       \
+          s->x = (X);                                                  \
+        }                                                              \
+      while (0)
+ 
+ 
+ /* Add a glyph string for a sequence of character glyphs to the list
+    of strings between HEAD and TAIL.  START is the index of the first
+    glyph in row area AREA of glyph row ROW that is part of the new
+    glyph string.  END is the index of the last glyph in that glyph row
+    area.  X is the current output position assigned to the new glyph
+    string constructed.  HL overrides that face of the glyph; e.g. it
+    is DRAW_CURSOR if a cursor has to be drawn.  LAST_X is the
+    right-most x-position of the drawing area.  */
+ 
+ #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)       
   \
+      do                                                                       
   \
+        {                                                                 \
+        int c, face_id;                                                   \
+        XChar2b *char2b;                                                  \
+                                                                          \
+        c = (row)->glyphs[area][START].u.ch;                              \
+        face_id = (row)->glyphs[area][START].face_id;                     \
+                                                                          \
+        s = (struct glyph_string *) alloca (sizeof *s);                   \
+        char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b);     \
+        INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL);           \
+        append_glyph_string (&HEAD, &TAIL, s);                            \
+        s->x = (X);                                                       \
+        START = fill_glyph_string (s, face_id, START, END, overlaps_p);   \
+        }                                                                 \
+      while (0)
+ 
+ 
+ /* Add a glyph string for a composite sequence to the list of strings
+    between HEAD and TAIL.  START is the index of the first glyph in
+    row area AREA of glyph row ROW that is part of the new glyph
+    string.  END is the index of the last glyph in that glyph row area.
+    X is the current output position assigned to the new glyph string
+    constructed.  HL overrides that face of the glyph; e.g. it is
+    DRAW_CURSOR if a cursor has to be drawn.  LAST_X is the right-most
+    x-position of the drawing area.  */
+ 
+ #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
+   do {                                                                        
  \
+     int cmp_id = (row)->glyphs[area][START].u.cmp_id;                   \
+     int face_id = (row)->glyphs[area][START].face_id;                   \
+     struct face *base_face = FACE_FROM_ID (f, face_id);                       
  \
+     struct composition *cmp = composition_table[cmp_id];                \
+     int glyph_len = cmp->glyph_len;                                     \
+     XChar2b *char2b;                                                    \
+     struct face **faces;                                                \
+     struct glyph_string *first_s = NULL;                                \
+     int n;                                                              \
+                                                                         \
+     base_face = base_face->ascii_face;                                        
  \
+     char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len);               
  \
+     faces = (struct face **) alloca ((sizeof *faces) * glyph_len);      \
+     /* At first, fill in `char2b' and `faces'.  */                      \
+     for (n = 0; n < glyph_len; n++)                                     \
+       {                                                                       
  \
+       int c = COMPOSITION_GLYPH (cmp, n);                               \
+       int this_face_id = FACE_FOR_CHAR (f, base_face, c);               \
+       faces[n] = FACE_FROM_ID (f, this_face_id);                        \
+       get_char_face_and_encoding (f, c, this_face_id,                   \
+                                   char2b + n, 1, 1);                    \
+       }                                                                       
  \
+                                                                         \
+     /* Make glyph_strings for each glyph sequence that is drawable by   \
+        the same face, and append them to HEAD/TAIL.  */                       
  \
+     for (n = 0; n < cmp->glyph_len;)                                    \
+       {                                                                       
  \
+       s = (struct glyph_string *) alloca (sizeof *s);                   \
+       INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL);       \
+       append_glyph_string (&(HEAD), &(TAIL), s);                        \
+       s->cmp = cmp;                                                     \
+       s->gidx = n;                                                      \
+       s->x = (X);                                                       \
+                                                                         \
+       if (n == 0)                                                       \
+         first_s = s;                                                    \
+                                                                         \
+       n = fill_composite_glyph_string (s, faces, overlaps_p);           \
+       }                                                                       
  \
+                                                                         \
+     ++START;                                                            \
+     s = first_s;                                                        \
+   } while (0)
+ 
+ 
+ /* Build a list of glyph strings between HEAD and TAIL for the glyphs
+    of AREA of glyph row ROW on window W between indices START and END.
+    HL overrides the face for drawing glyph strings, e.g. it is
+    DRAW_CURSOR to draw a cursor.  X and LAST_X are start and end
+    x-positions of the drawing area.
+ 
+    This is an ugly monster macro construct because we must use alloca
+    to allocate glyph strings (because x_draw_glyphs can be called
+    asynchronously).  */
+ 
+ #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X)       \
+      do                                                                       
   \
+        {                                                                 \
+        HEAD = TAIL = NULL;                                               \
+        while (START < END)                                               \
+          {                                                               \
+              struct glyph *first_glyph = (row)->glyphs[area] + START;    \
+              switch (first_glyph->type)                                       
   \
+              {                                                           \
+              case CHAR_GLYPH:                                            \
+                  BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL,       \
+                                          HL, X, LAST_X);                 \
+                break;                                                    \
+                                                                          \
+              case COMPOSITE_GLYPH:                                       \
+                  BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL,        
   \
+                                              HL, X, LAST_X);             \
+                break;                                                    \
+                                                                          \
+              case STRETCH_GLYPH:                                         \
+                BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL,       \
+                                            HL, X, LAST_X);               \
+                break;                                                    \
+                                                                          \
+              case IMAGE_GLYPH:                                           \
+                BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL,         \
+                                          HL, X, LAST_X);                 \
+                break;                                                    \
+                                                                          \
+              default:                                                    \
+                abort ();                                                 \
+              }                                                           \
+                                                                          \
+              set_glyph_string_background_width (s, START, LAST_X);       \
+            (X) += s->width;                                              \
+             }                                                            \
+        }                                                                 \
+      while (0)
+ 
+ 
+ /* Draw glyphs between START and END in AREA of ROW on window W,
+    starting at x-position X.  X is relative to AREA in W.  HL is a
+    face-override with the following meaning:
+ 
+    DRAW_NORMAL_TEXT   draw normally
+    DRAW_CURSOR                draw in cursor face
+    DRAW_MOUSE_FACE    draw in mouse face.
+    DRAW_INVERSE_VIDEO draw in mode line face
+    DRAW_IMAGE_SUNKEN  draw an image with a sunken relief around it
+    DRAW_IMAGE_RAISED  draw an image with a raised relief around it
+ 
+    If OVERLAPS_P is non-zero, draw only the foreground of characters
+    and clip to the physical height of ROW.
+ 
+    Value is the x-position reached, relative to AREA of W.  */
+ 
+ int
+ x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
+      struct window *w;
+      int x;
+      struct glyph_row *row;
+      enum glyph_row_area area;
+      int start, end;
+      enum draw_glyphs_face hl;
+      int overlaps_p;
+ {
+   struct glyph_string *head, *tail;
+   struct glyph_string *s;
+   int last_x, area_width;
+   int x_reached;
+   int i, j;
+   struct frame *f = XFRAME (WINDOW_FRAME (w));
+   DECLARE_HDC (hdc);
+ 
+   ALLOCATE_HDC (hdc, f);
+ 
+   /* Let's rather be paranoid than getting a SEGV.  */
+   end = min (end, row->used[area]);
+   start = max (0, start);
+   start = min (end, start);
+ 
+   /* Translate X to frame coordinates.  Set last_x to the right
+      end of the drawing area.  */
+   if (row->full_width_p)
+     {
+       /* X is relative to the left edge of W, without scroll bars
+        or fringes.  */
+       int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
+ 
+       x += window_left_x;
+       area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
+       last_x = window_left_x + area_width;
+ 
+       if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+       {
+         int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
+         if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+           last_x += width;
+         else
+           x -= width;
+       }
+ 
+       x += FRAME_INTERNAL_BORDER_WIDTH (f);
+       /* ++KFS: W32 and MAC versions had -= in next line (bug??)  */
+       last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
+     }
+   else
+     {
+       x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
+       area_width = window_box_width (w, area);
+       last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
+     }
+ 
+   /* Build a doubly-linked list of glyph_string structures between
+      head and tail from what we have to draw.  Note that the macro
+      BUILD_GLYPH_STRINGS will modify its start parameter.  That's
+      the reason we use a separate variable `i'.  */
+   i = start;
+   BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
+   if (tail)
+     x_reached = tail->x + tail->background_width;
+   else
+     x_reached = x;
+ 
+   /* If there are any glyphs with lbearing < 0 or rbearing > width in
+      the row, redraw some glyphs in front or following the glyph
+      strings built above.  */
+   if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
+     {
+       int dummy_x = 0;
+       struct glyph_string *h, *t;
+ 
+       /* Compute overhangs for all glyph strings.  */
+       if (rif->compute_glyph_string_overhangs)
+       for (s = head; s; s = s->next)
+         rif->compute_glyph_string_overhangs (s);
+ 
+       /* Prepend glyph strings for glyphs in front of the first glyph
+        string that are overwritten because of the first glyph
+        string's left overhang.  The background of all strings
+        prepended must be drawn because the first glyph string
+        draws over it.  */
+       i = left_overwritten (head);
+       if (i >= 0)
+       {
+         j = i;
+         BUILD_GLYPH_STRINGS (j, start, h, t,
+                              DRAW_NORMAL_TEXT, dummy_x, last_x);
+         start = i;
+         compute_overhangs_and_x (t, head->x, 1);
+         prepend_glyph_string_lists (&head, &tail, h, t);
+       }
+ 
+       /* Prepend glyph strings for glyphs in front of the first glyph
+        string that overwrite that glyph string because of their
+        right overhang.  For these strings, only the foreground must
+        be drawn, because it draws over the glyph string at `head'.
+        The background must not be drawn because this would overwrite
+        right overhangs of preceding glyphs for which no glyph
+        strings exist.  */
+       i = left_overwriting (head);
+       if (i >= 0)
+       {
+         BUILD_GLYPH_STRINGS (i, start, h, t,
+                              DRAW_NORMAL_TEXT, dummy_x, last_x);
+         for (s = h; s; s = s->next)
+           s->background_filled_p = 1;
+         compute_overhangs_and_x (t, head->x, 1);
+         prepend_glyph_string_lists (&head, &tail, h, t);
+       }
+ 
+       /* Append glyphs strings for glyphs following the last glyph
+        string tail that are overwritten by tail.  The background of
+        these strings has to be drawn because tail's foreground draws
+        over it.  */
+       i = right_overwritten (tail);
+       if (i >= 0)
+       {
+         BUILD_GLYPH_STRINGS (end, i, h, t,
+                              DRAW_NORMAL_TEXT, x, last_x);
+         compute_overhangs_and_x (h, tail->x + tail->width, 0);
+         append_glyph_string_lists (&head, &tail, h, t);
+       }
+ 
+       /* Append glyph strings for glyphs following the last glyph
+        string tail that overwrite tail.  The foreground of such
+        glyphs has to be drawn because it writes into the background
+        of tail.  The background must not be drawn because it could
+        paint over the foreground of following glyphs.  */
+       i = right_overwriting (tail);
+       if (i >= 0)
+       {
+         BUILD_GLYPH_STRINGS (end, i, h, t,
+                              DRAW_NORMAL_TEXT, x, last_x);
+         for (s = h; s; s = s->next)
+           s->background_filled_p = 1;
+         compute_overhangs_and_x (h, tail->x + tail->width, 0);
+         append_glyph_string_lists (&head, &tail, h, t);
+       }
+     }
+ 
+   /* Draw all strings.  */
+   for (s = head; s; s = s->next)
+     rif->draw_glyph_string (s);
+ 
+   if (area == TEXT_AREA
+       && !row->full_width_p
+       /* When drawing overlapping rows, only the glyph strings'
+        foreground is drawn, which doesn't erase a cursor
+        completely. */
+       && !overlaps_p)
+     {
+       int x0 = head ? head->x : x;
+       int x1 = tail ? tail->x + tail->background_width : x;
+ 
+       x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
+       x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
+ 
+       /* ++KFS: W32 and MAC versions had following test here:
+        if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
+       */
+ 
+       if (XFASTINT (w->left_margin_width) != 0)
+       {
+         int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
+         x0 -= left_area_width;
+         x1 -= left_area_width;
+       }
+ 
+       notice_overwritten_cursor (w, area, x0, x1,
+                                row->y, MATRIX_ROW_BOTTOM_Y (row));
+     }
+ 
+   /* Value is the x-position up to which drawn, relative to AREA of W.
+      This doesn't include parts drawn because of overhangs.  */
+   x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
+   if (!row->full_width_p)
+     {
+       /* ++KFS: W32 and MAC versions only had this test here:
+        if (area > LEFT_MARGIN_AREA)
+       */
+ 
+       if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
+       x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
+       if (area > TEXT_AREA)
+       x_reached -= window_box_width (w, TEXT_AREA);
+     }
+ 
+   RELEASE_HDC (hdc, f);
+ 
+   return x_reached;
+ }
+ 
+ 
+ /* Store one glyph for IT->char_to_display in IT->glyph_row.
+    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
+ 
+ static INLINE void
+ append_glyph (it)
+      struct it *it;
+ {
+   struct glyph *glyph;
+   enum glyph_row_area area = it->area;
+ 
+   xassert (it->glyph_row);
+   xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
+ 
+   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+   if (glyph < it->glyph_row->glyphs[area + 1])
+     {
+       glyph->charpos = CHARPOS (it->position);
+       glyph->object = it->object;
+       glyph->pixel_width = it->pixel_width;
+       glyph->voffset = it->voffset;
+       glyph->type = CHAR_GLYPH;
+       glyph->multibyte_p = it->multibyte_p;
+       glyph->left_box_line_p = it->start_of_box_run_p;
+       glyph->right_box_line_p = it->end_of_box_run_p;
+       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
+                                     || it->phys_descent > it->descent);
+       glyph->padding_p = 0;
+       glyph->glyph_not_available_p = it->glyph_not_available_p;
+       glyph->face_id = it->face_id;
+       glyph->u.ch = it->char_to_display;
+       glyph->font_type = FONT_TYPE_UNKNOWN;
+       ++it->glyph_row->used[area];
+     }
+ }
+ 
+ /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
+    Called from x_produce_glyphs when IT->glyph_row is non-null.  */
+ 
+ static INLINE void
+ append_composite_glyph (it)
+      struct it *it;
+ {
+   struct glyph *glyph;
+   enum glyph_row_area area = it->area;
+ 
+   xassert (it->glyph_row);
+ 
+   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+   if (glyph < it->glyph_row->glyphs[area + 1])
+     {
+       glyph->charpos = CHARPOS (it->position);
+       glyph->object = it->object;
+       glyph->pixel_width = it->pixel_width;
+       glyph->voffset = it->voffset;
+       glyph->type = COMPOSITE_GLYPH;
+       glyph->multibyte_p = it->multibyte_p;
+       glyph->left_box_line_p = it->start_of_box_run_p;
+       glyph->right_box_line_p = it->end_of_box_run_p;
+       glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
+                                     || it->phys_descent > it->descent);
+       glyph->padding_p = 0;
+       glyph->glyph_not_available_p = 0;
+       glyph->face_id = it->face_id;
+       glyph->u.cmp_id = it->cmp_id;
+       glyph->font_type = FONT_TYPE_UNKNOWN;
+       ++it->glyph_row->used[area];
+     }
+ }
+ 
+ 
+ /* Change IT->ascent and IT->height according to the setting of
+    IT->voffset.  */
+ 
+ static INLINE void
+ take_vertical_position_into_account (it)
+      struct it *it;
+ {
+   if (it->voffset)
+     {
+       if (it->voffset < 0)
+       /* Increase the ascent so that we can display the text higher
+          in the line.  */
+       it->ascent += abs (it->voffset);
+       else
+       /* Increase the descent so that we can display the text lower
+          in the line.  */
+       it->descent += it->voffset;
+     }
+ }
+ 
+ 
+ /* Produce glyphs/get display metrics for the image IT is loaded with.
+    See the description of struct display_iterator in dispextern.h for
+    an overview of struct display_iterator.  */
+ 
+ static void
+ produce_image_glyph (it)
+      struct it *it;
+ {
+   struct image *img;
+   struct face *face;
+ 
+   xassert (it->what == IT_IMAGE);
+ 
+   face = FACE_FROM_ID (it->f, it->face_id);
+   img = IMAGE_FROM_ID (it->f, it->image_id);
+   xassert (img);
+ 
+   /* Make sure X resources of the face and image are loaded.  */
+   PREPARE_FACE_FOR_DISPLAY (it->f, face);
+   prepare_image_for_display (it->f, img);
+ 
+   it->ascent = it->phys_ascent = image_ascent (img, face);
+   it->descent = it->phys_descent = img->height + 2 * img->vmargin - 
it->ascent;
+   it->pixel_width = img->width + 2 * img->hmargin;
+ 
+   it->nglyphs = 1;
+ 
+   if (face->box != FACE_NO_BOX)
+     {
+       if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
+ 
+       if (it->start_of_box_run_p)
+       it->pixel_width += abs (face->box_line_width);
+       if (it->end_of_box_run_p)
+       it->pixel_width += abs (face->box_line_width);
+     }
+ 
+   take_vertical_position_into_account (it);
+ 
+   if (it->glyph_row)
+     {
+       struct glyph *glyph;
+       enum glyph_row_area area = it->area;
+ 
+       glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+       if (glyph < it->glyph_row->glyphs[area + 1])
+       {
+         glyph->charpos = CHARPOS (it->position);
+         glyph->object = it->object;
+         glyph->pixel_width = it->pixel_width;
+         glyph->voffset = it->voffset;
+         glyph->type = IMAGE_GLYPH;
+         glyph->multibyte_p = it->multibyte_p;
+         glyph->left_box_line_p = it->start_of_box_run_p;
+         glyph->right_box_line_p = it->end_of_box_run_p;
+         glyph->overlaps_vertically_p = 0;
+           glyph->padding_p = 0;
+         glyph->glyph_not_available_p = 0;
+         glyph->face_id = it->face_id;
+         glyph->u.img_id = img->id;
+         glyph->font_type = FONT_TYPE_UNKNOWN;
+         ++it->glyph_row->used[area];
+       }
+     }
+ }
+ 
+ 
+ /* Append a stretch glyph to IT->glyph_row.  OBJECT is the source
+    of the glyph, WIDTH and HEIGHT are the width and height of the
+    stretch.  ASCENT is the percentage/100 of HEIGHT to use for the
+    ascent of the glyph (0 <= ASCENT <= 1).  */
+ 
+ static void
+ append_stretch_glyph (it, object, width, height, ascent)
+      struct it *it;
+      Lisp_Object object;
+      int width, height;
+      double ascent;
+ {
+   struct glyph *glyph;
+   enum glyph_row_area area = it->area;
+ 
+   xassert (ascent >= 0 && ascent <= 1);
+ 
+   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+   if (glyph < it->glyph_row->glyphs[area + 1])
+     {
+       glyph->charpos = CHARPOS (it->position);
+       glyph->object = object;
+       glyph->pixel_width = width;
+       glyph->voffset = it->voffset;
+       glyph->type = STRETCH_GLYPH;
+       glyph->multibyte_p = it->multibyte_p;
+       glyph->left_box_line_p = it->start_of_box_run_p;
+       glyph->right_box_line_p = it->end_of_box_run_p;
+       glyph->overlaps_vertically_p = 0;
+       glyph->padding_p = 0;
+       glyph->glyph_not_available_p = 0;
+       glyph->face_id = it->face_id;
+       glyph->u.stretch.ascent = height * ascent;
+       glyph->u.stretch.height = height;
+       glyph->font_type = FONT_TYPE_UNKNOWN;
+       ++it->glyph_row->used[area];
+     }
+ }
+ 
+ 
+ /* Produce a stretch glyph for iterator IT.  IT->object is the value
+    of the glyph property displayed.  The value must be a list
+    `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
+    being recognized:
+ 
+    1. `:width WIDTH' specifies that the space should be WIDTH *
+    canonical char width wide.  WIDTH may be an integer or floating
+    point number.
+ 
+    2. `:relative-width FACTOR' specifies that the width of the stretch
+    should be computed from the width of the first character having the
+    `glyph' property, and should be FACTOR times that width.
+ 
+    3. `:align-to HPOS' specifies that the space should be wide enough
+    to reach HPOS, a value in canonical character units.
+ 
+    Exactly one of the above pairs must be present.
+ 
+    4. `:height HEIGHT' specifies that the height of the stretch produced
+    should be HEIGHT, measured in canonical character units.
+ 
+    5. `:relative-height FACTOR' specifies that the height of the
+    stretch should be FACTOR times the height of the characters having
+    the glyph property.
+ 
+    Either none or exactly one of 4 or 5 must be present.
+ 
+    6. `:ascent ASCENT'  specifies that ASCENT percent of the height
+    of the stretch should be used for the ascent of the stretch.
+    ASCENT must be in the range 0 <= ASCENT <= 100.  */
+ 
+ #define NUMVAL(X)                             \
+      ((INTEGERP (X) || FLOATP (X))            \
+       ? XFLOATINT (X)                         \
+       : - 1)
+ 
+ 
+ static void
+ produce_stretch_glyph (it)
+      struct it *it;
+ {
+   /* (space :width WIDTH :height HEIGHT.  */
+   Lisp_Object prop, plist;
+   int width = 0, height = 0;
+   double ascent = 0;
+   struct face *face = FACE_FROM_ID (it->f, it->face_id);
+   XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
+ 
+   PREPARE_FACE_FOR_DISPLAY (it->f, face);
+ 
+   /* List should start with `space'.  */
+   xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
+   plist = XCDR (it->object);
+ 
+   /* Compute the width of the stretch.  */
+   if (prop = Fplist_get (plist, QCwidth),
+       NUMVAL (prop) > 0)
+     /* Absolute width `:width WIDTH' specified and valid.  */
+     width = NUMVAL (prop) * CANON_X_UNIT (it->f);
+   else if (prop = Fplist_get (plist, QCrelative_width),
+          NUMVAL (prop) > 0)
+     {
+       /* Relative width `:relative-width FACTOR' specified and valid.
+        Compute the width of the characters having the `glyph'
+        property.  */
+       struct it it2;
+       unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
+ 
+       it2 = *it;
+       if (it->multibyte_p)
+       {
+         int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
+                       - IT_BYTEPOS (*it));
+         it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
+       }
+       else
+       it2.c = *p, it2.len = 1;
+ 
+       it2.glyph_row = NULL;
+       it2.what = IT_CHARACTER;
+       x_produce_glyphs (&it2);
+       width = NUMVAL (prop) * it2.pixel_width;
+     }
+   else if (prop = Fplist_get (plist, QCalign_to),
+          NUMVAL (prop) > 0)
+     width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
+   else
+     /* Nothing specified -> width defaults to canonical char width.  */
+     width = CANON_X_UNIT (it->f);
+ 
+   /* Compute height.  */
+   if (prop = Fplist_get (plist, QCheight),
+       NUMVAL (prop) > 0)
+     height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
+   else if (prop = Fplist_get (plist, QCrelative_height),
+          NUMVAL (prop) > 0)
+     height = FONT_HEIGHT (font) * NUMVAL (prop);
+   else
+     height = FONT_HEIGHT (font);
+ 
+   /* Compute percentage of height used for ascent.  If
+      `:ascent ASCENT' is present and valid, use that.  Otherwise,
+      derive the ascent from the font in use.  */
+   if (prop = Fplist_get (plist, QCascent),
+       NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
+     ascent = NUMVAL (prop) / 100.0;
+   else
+     ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
+ 
+   if (width <= 0)
+     width = 1;
+   if (height <= 0)
+     height = 1;
+ 
+   if (it->glyph_row)
+     {
+       Lisp_Object object = it->stack[it->sp - 1].string;
+       if (!STRINGP (object))
+       object = it->w->buffer;
+       append_stretch_glyph (it, object, width, height, ascent);
+     }
+ 
+   it->pixel_width = width;
+   it->ascent = it->phys_ascent = height * ascent;
+   it->descent = it->phys_descent = height - it->ascent;
+   it->nglyphs = 1;
+ 
+   if (face->box != FACE_NO_BOX)
+     {
+       if (face->box_line_width > 0)
+       {
+         it->ascent += face->box_line_width;
+         it->descent += face->box_line_width;
+       }
+ 
+       if (it->start_of_box_run_p)
+       it->pixel_width += abs (face->box_line_width);
+       if (it->end_of_box_run_p)
+       it->pixel_width += abs (face->box_line_width);
+     }
+ 
+   take_vertical_position_into_account (it);
+ }
+ 
+ /* RIF:
+    Produce glyphs/get display metrics for the display element IT is
+    loaded with.  See the description of struct display_iterator in
+    dispextern.h for an overview of struct display_iterator.  */
+ 
+ void
+ x_produce_glyphs (it)
+      struct it *it;
+ {
+   it->glyph_not_available_p = 0;
+ 
+   if (it->what == IT_CHARACTER)
+     {
+       XChar2b char2b;
+       XFontStruct *font;
+       struct face *face = FACE_FROM_ID (it->f, it->face_id);
+       XCharStruct *pcm;
+       int font_not_found_p;
+       struct font_info *font_info;
+       int boff;                       /* baseline offset */
+       /* We may change it->multibyte_p upon unibyte<->multibyte
+        conversion.  So, save the current value now and restore it
+        later.
+ 
+        Note: It seems that we don't have to record multibyte_p in
+        struct glyph because the character code itself tells if or
+        not the character is multibyte.  Thus, in the future, we must
+        consider eliminating the field `multibyte_p' in the struct
+        glyph.  */
+       int saved_multibyte_p = it->multibyte_p;
+ 
+       /* Maybe translate single-byte characters to multibyte, or the
+        other way.  */
+       it->char_to_display = it->c;
+       if (!ASCII_BYTE_P (it->c))
+       {
+         if (unibyte_display_via_language_environment
+             && SINGLE_BYTE_CHAR_P (it->c)
+             && (it->c >= 0240
+                 || !NILP (Vnonascii_translation_table)))
+           {
+             it->char_to_display = unibyte_char_to_multibyte (it->c);
+             it->multibyte_p = 1;
+             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+             face = FACE_FROM_ID (it->f, it->face_id);
+           }
+         else if (!SINGLE_BYTE_CHAR_P (it->c)
+                  && !it->multibyte_p)
+           {
+             it->multibyte_p = 1;
+             it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+             face = FACE_FROM_ID (it->f, it->face_id);
+           }
+       }
+ 
+       /* Get font to use.  Encode IT->char_to_display.  */
+       get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
+                                 &char2b, it->multibyte_p, 0);
+       font = face->font;
+ 
+       /* When no suitable font found, use the default font.  */
+       font_not_found_p = font == NULL;
+       if (font_not_found_p)
+       {
+         font = FRAME_FONT (it->f);
+         boff = FRAME_BASELINE_OFFSET (it->f);
+         font_info = NULL;
+       }
+       else
+       {
+         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+         boff = font_info->baseline_offset;
+         if (font_info->vertical_centering)
+           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+       }
+ 
+       if (it->char_to_display >= ' '
+         && (!it->multibyte_p || it->char_to_display < 128))
+       {
+         /* Either unibyte or ASCII.  */
+         int stretched_p;
+ 
+         it->nglyphs = 1;
+ 
+         pcm = rif->per_char_metric (font, &char2b,
+                                     FONT_TYPE_FOR_UNIBYTE (font, 
it->char_to_display));
+         it->ascent = FONT_BASE (font) + boff;
+         it->descent = FONT_DESCENT (font) - boff;
+ 
+         if (pcm)
+           {
+             it->phys_ascent = pcm->ascent + boff;
+             it->phys_descent = pcm->descent - boff;
+             it->pixel_width = pcm->width;
+           }
+         else
+           {
+             it->glyph_not_available_p = 1;
+               it->phys_ascent = FONT_BASE (font) + boff;
+               it->phys_descent = FONT_DESCENT (font) - boff;
+             it->pixel_width = FONT_WIDTH (font);
+           }
+ 
+         /* If this is a space inside a region of text with
+            `space-width' property, change its width.  */
+         stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
+         if (stretched_p)
+           it->pixel_width *= XFLOATINT (it->space_width);
+ 
+         /* If face has a box, add the box thickness to the character
+            height.  If character has a box line to the left and/or
+            right, add the box line width to the character's width.  */
+         if (face->box != FACE_NO_BOX)
+           {
+             int thick = face->box_line_width;
+ 
+             if (thick > 0)
+               {
+                 it->ascent += thick;
+                 it->descent += thick;
+               }
+             else
+               thick = -thick;
+ 
+             if (it->start_of_box_run_p)
+               it->pixel_width += thick;
+             if (it->end_of_box_run_p)
+               it->pixel_width += thick;
+           }
+ 
+         /* If face has an overline, add the height of the overline
+            (1 pixel) and a 1 pixel margin to the character height.  */
+         if (face->overline_p)
+           it->ascent += 2;
+ 
+         take_vertical_position_into_account (it);
+ 
+         /* If we have to actually produce glyphs, do it.  */
+         if (it->glyph_row)
+           {
+             if (stretched_p)
+               {
+                 /* Translate a space with a `space-width' property
+                    into a stretch glyph.  */
+                 double ascent = (double) FONT_BASE (font)
+                                 / FONT_HEIGHT (font);
+                 append_stretch_glyph (it, it->object, it->pixel_width,
+                                       it->ascent + it->descent, ascent);
+               }
+             else
+               append_glyph (it);
+ 
+             /* If characters with lbearing or rbearing are displayed
+                in this line, record that fact in a flag of the
+                glyph row.  This is used to optimize X output code.  */
+             if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
+               it->glyph_row->contains_overlapping_glyphs_p = 1;
+           }
+       }
+       else if (it->char_to_display == '\n')
+       {
+         /* A newline has no width but we need the height of the line.  */
+         it->pixel_width = 0;
+         it->nglyphs = 0;
+         it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+         it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+ 
+         if (face->box != FACE_NO_BOX
+             && face->box_line_width > 0)
+           {
+             it->ascent += face->box_line_width;
+             it->descent += face->box_line_width;
+           }
+       }
+       else if (it->char_to_display == '\t')
+       {
+         int tab_width = it->tab_width * CANON_X_UNIT (it->f);
+         int x = it->current_x + it->continuation_lines_width;
+         int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
+ 
+         /* If the distance from the current position to the next tab
+            stop is less than a canonical character width, use the
+            tab stop after that.  */
+         if (next_tab_x - x < CANON_X_UNIT (it->f))
+           next_tab_x += tab_width;
+ 
+         it->pixel_width = next_tab_x - x;
+         it->nglyphs = 1;
+         it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+         it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+ 
+         if (it->glyph_row)
+           {
+             double ascent = (double) it->ascent / (it->ascent + it->descent);
+             append_stretch_glyph (it, it->object, it->pixel_width,
+                                   it->ascent + it->descent, ascent);
+           }
+       }
+       else
+       {
+         /* A multi-byte character.  Assume that the display width of the
+            character is the width of the character multiplied by the
+            width of the font.  */
+ 
+         /* If we found a font, this font should give us the right
+            metrics.  If we didn't find a font, use the frame's
+            default font and calculate the width of the character
+            from the charset width; this is what old redisplay code
+            did.  */
+ 
+         pcm = rif->per_char_metric (font, &char2b,
+                                     FONT_TYPE_FOR_MULTIBYTE (font, it->c));
+ 
+         if (font_not_found_p || !pcm)
+           {
+             int charset = CHAR_CHARSET (it->char_to_display);
+ 
+             it->glyph_not_available_p = 1;
+             it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
+                                * CHARSET_WIDTH (charset));
+             it->phys_ascent = FONT_BASE (font) + boff;
+             it->phys_descent = FONT_DESCENT (font) - boff;
+           }
+         else
+           {
+             it->pixel_width = pcm->width;
+             it->phys_ascent = pcm->ascent + boff;
+             it->phys_descent = pcm->descent - boff;
+             if (it->glyph_row
+                 && (pcm->lbearing < 0
+                     || pcm->rbearing > pcm->width))
+               it->glyph_row->contains_overlapping_glyphs_p = 1;
+           }
+         it->nglyphs = 1;
+           it->ascent = FONT_BASE (font) + boff;
+           it->descent = FONT_DESCENT (font) - boff;
+         if (face->box != FACE_NO_BOX)
+           {
+             int thick = face->box_line_width;
+ 
+             if (thick > 0)
+               {
+                 it->ascent += thick;
+                 it->descent += thick;
+               }
+             else
+               thick = - thick;
+ 
+             if (it->start_of_box_run_p)
+               it->pixel_width += thick;
+             if (it->end_of_box_run_p)
+               it->pixel_width += thick;
+           }
+ 
+         /* If face has an overline, add the height of the overline
+            (1 pixel) and a 1 pixel margin to the character height.  */
+         if (face->overline_p)
+           it->ascent += 2;
+ 
+         take_vertical_position_into_account (it);
+ 
+         if (it->glyph_row)
+           append_glyph (it);
+       }
+       it->multibyte_p = saved_multibyte_p;
+     }
+   else if (it->what == IT_COMPOSITION)
+     {
+       /* Note: A composition is represented as one glyph in the
+        glyph matrix.  There are no padding glyphs.  */
+       XChar2b char2b;
+       XFontStruct *font;
+       struct face *face = FACE_FROM_ID (it->f, it->face_id);
+       XCharStruct *pcm;
+       int font_not_found_p;
+       struct font_info *font_info;
+       int boff;                       /* baseline offset */
+       struct composition *cmp = composition_table[it->cmp_id];
+ 
+       /* Maybe translate single-byte characters to multibyte.  */
+       it->char_to_display = it->c;
+       if (unibyte_display_via_language_environment
+         && SINGLE_BYTE_CHAR_P (it->c)
+         && (it->c >= 0240
+             || (it->c >= 0200
+                 && !NILP (Vnonascii_translation_table))))
+       {
+         it->char_to_display = unibyte_char_to_multibyte (it->c);
+       }
+ 
+       /* Get face and font to use.  Encode IT->char_to_display.  */
+       it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+       face = FACE_FROM_ID (it->f, it->face_id);
+       get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
+                                 &char2b, it->multibyte_p, 0);
+       font = face->font;
+ 
+       /* When no suitable font found, use the default font.  */
+       font_not_found_p = font == NULL;
+       if (font_not_found_p)
+       {
+         font = FRAME_FONT (it->f);
+         boff = FRAME_BASELINE_OFFSET (it->f);
+         font_info = NULL;
+       }
+       else
+       {
+         font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+         boff = font_info->baseline_offset;
+         if (font_info->vertical_centering)
+           boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+       }
+ 
+       /* There are no padding glyphs, so there is only one glyph to
+        produce for the composition.  Important is that pixel_width,
+        ascent and descent are the values of what is drawn by
+        draw_glyphs (i.e. the values of the overall glyphs composed).  */
+       it->nglyphs = 1;
+ 
+       /* If we have not yet calculated pixel size data of glyphs of
+        the composition for the current face font, calculate them
+        now.  Theoretically, we have to check all fonts for the
+        glyphs, but that requires much time and memory space.  So,
+        here we check only the font of the first glyph.  This leads
+        to incorrect display very rarely, and C-l (recenter) can
+        correct the display anyway.  */
+       if (cmp->font != (void *) font)
+       {
+         /* Ascent and descent of the font of the first character of
+            this composition (adjusted by baseline offset).  Ascent
+            and descent of overall glyphs should not be less than
+            them respectively.  */
+         int font_ascent = FONT_BASE (font) + boff;
+         int font_descent = FONT_DESCENT (font) - boff;
+         /* Bounding box of the overall glyphs.  */
+         int leftmost, rightmost, lowest, highest;
+         int i, width, ascent, descent;
+ 
+         cmp->font = (void *) font;
+ 
+         /* Initialize the bounding box.  */
+         if (font_info
+             && (pcm = rif->per_char_metric (font, &char2b,
+                                             FONT_TYPE_FOR_MULTIBYTE (font, 
it->c))))
+           {
+             width = pcm->width;
+             ascent = pcm->ascent;
+             descent = pcm->descent;
+           }
+         else
+           {
+             width = FONT_WIDTH (font);
+             ascent = FONT_BASE (font);
+             descent = FONT_DESCENT (font);
+           }
+ 
+         rightmost = width;
+         lowest = - descent + boff;
+         highest = ascent + boff;
+         leftmost = 0;
+ 
+         if (font_info
+             && font_info->default_ascent
+             && CHAR_TABLE_P (Vuse_default_ascent)
+             && !NILP (Faref (Vuse_default_ascent,
+                              make_number (it->char_to_display))))
+           highest = font_info->default_ascent + boff;
+ 
+         /* Draw the first glyph at the normal position.  It may be
+            shifted to right later if some other glyphs are drawn at
+            the left.  */
+         cmp->offsets[0] = 0;
+         cmp->offsets[1] = boff;
+ 
+         /* Set cmp->offsets for the remaining glyphs.  */
+         for (i = 1; i < cmp->glyph_len; i++)
+           {
+             int left, right, btm, top;
+             int ch = COMPOSITION_GLYPH (cmp, i);
+             int face_id = FACE_FOR_CHAR (it->f, face, ch);
+ 
+             face = FACE_FROM_ID (it->f, face_id);
+             get_char_face_and_encoding (it->f, ch, face->id,
+                                         &char2b, it->multibyte_p, 0);
+             font = face->font;
+             if (font == NULL)
+               {
+                 font = FRAME_FONT (it->f);
+                 boff = it->f->output_data.x->baseline_offset;
+                 font_info = NULL;
+               }
+             else
+               {
+                 font_info
+                   = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+                 boff = font_info->baseline_offset;
+                 if (font_info->vertical_centering)
+                   boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+               }
+ 
+             if (font_info
+                 && (pcm = rif->per_char_metric (font, &char2b, 
+                                                 FONT_TYPE_FOR_MULTIBYTE 
(font, ch))))
+               {
+                 width = pcm->width;
+                 ascent = pcm->ascent;
+                 descent = pcm->descent;
+               }
+             else
+               {
+                 width = FONT_WIDTH (font);
+                 ascent = 1;
+                 descent = 0;
+               }
+ 
+             if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
+               {
+                 /* Relative composition with or without
+                    alternate chars.  */
+                 left = (leftmost + rightmost - width) / 2;
+                 btm = - descent + boff;
+                 if (font_info && font_info->relative_compose
+                     && (! CHAR_TABLE_P (Vignore_relative_composition)
+                         || NILP (Faref (Vignore_relative_composition,
+                                         make_number (ch)))))
+                   {
+ 
+                     if (- descent >= font_info->relative_compose)
+                       /* One extra pixel between two glyphs.  */
+                       btm = highest + 1;
+                     else if (ascent <= 0)
+                       /* One extra pixel between two glyphs.  */
+                       btm = lowest - 1 - ascent - descent;
+                   }
+               }
+             else
+               {
+                 /* A composition rule is specified by an integer
+                    value that encodes global and new reference
+                    points (GREF and NREF).  GREF and NREF are
+                    specified by numbers as below:
+ 
+                       0---1---2 -- ascent
+                       |       |
+                       |       |
+                       |       |
+                       9--10--11 -- center
+                       |       |
+                    ---3---4---5--- baseline
+                       |       |
+                       6---7---8 -- descent
+                 */
+                 int rule = COMPOSITION_RULE (cmp, i);
+                 int gref, nref, grefx, grefy, nrefx, nrefy;
+ 
+                 COMPOSITION_DECODE_RULE (rule, gref, nref);
+                 grefx = gref % 3, nrefx = nref % 3;
+                 grefy = gref / 3, nrefy = nref / 3;
+ 
+                 left = (leftmost
+                         + grefx * (rightmost - leftmost) / 2
+                         - nrefx * width / 2);
+                 btm = ((grefy == 0 ? highest
+                         : grefy == 1 ? 0
+                         : grefy == 2 ? lowest
+                         : (highest + lowest) / 2)
+                        - (nrefy == 0 ? ascent + descent
+                           : nrefy == 1 ? descent - boff
+                           : nrefy == 2 ? 0
+                           : (ascent + descent) / 2));
+               }
+ 
+             cmp->offsets[i * 2] = left;
+             cmp->offsets[i * 2 + 1] = btm + descent;
+ 
+             /* Update the bounding box of the overall glyphs. */
+             right = left + width;
+             top = btm + descent + ascent;
+             if (left < leftmost)
+               leftmost = left;
+             if (right > rightmost)
+               rightmost = right;
+             if (top > highest)
+               highest = top;
+             if (btm < lowest)
+               lowest = btm;
+           }
+ 
+         /* If there are glyphs whose x-offsets are negative,
+            shift all glyphs to the right and make all x-offsets
+            non-negative.  */
+         if (leftmost < 0)
+           {
+             for (i = 0; i < cmp->glyph_len; i++)
+               cmp->offsets[i * 2] -= leftmost;
+             rightmost -= leftmost;
+           }
+ 
+         cmp->pixel_width = rightmost;
+         cmp->ascent = highest;
+         cmp->descent = - lowest;
+         if (cmp->ascent < font_ascent)
+           cmp->ascent = font_ascent;
+         if (cmp->descent < font_descent)
+           cmp->descent = font_descent;
+       }
+ 
+       it->pixel_width = cmp->pixel_width;
+       it->ascent = it->phys_ascent = cmp->ascent;
+       it->descent = it->phys_descent = cmp->descent;
+ 
+       if (face->box != FACE_NO_BOX)
+       {
+         int thick = face->box_line_width;
+ 
+         if (thick > 0)
+           {
+             it->ascent += thick;
+             it->descent += thick;
+           }
+         else
+           thick = - thick;
+ 
+         if (it->start_of_box_run_p)
+           it->pixel_width += thick;
+         if (it->end_of_box_run_p)
+           it->pixel_width += thick;
+       }
+ 
+       /* If face has an overline, add the height of the overline
+        (1 pixel) and a 1 pixel margin to the character height.  */
+       if (face->overline_p)
+       it->ascent += 2;
+ 
+       take_vertical_position_into_account (it);
+ 
+       if (it->glyph_row)
+       append_composite_glyph (it);
+     }
+   else if (it->what == IT_IMAGE)
+     produce_image_glyph (it);
+   else if (it->what == IT_STRETCH)
+     produce_stretch_glyph (it);
+ 
+   /* Accumulate dimensions.  Note: can't assume that it->descent > 0
+      because this isn't true for images with `:ascent 100'.  */
+   xassert (it->ascent >= 0 && it->descent >= 0);
+   if (it->area == TEXT_AREA)
+     it->current_x += it->pixel_width;
+ 
+   it->descent += it->extra_line_spacing;
+ 
+   it->max_ascent = max (it->max_ascent, it->ascent);
+   it->max_descent = max (it->max_descent, it->descent);
+   it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
+   it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
+ }
+ 
+ 
+ 
+ 
+ 
+ 
+ /***********************************************************************
                             Cursor types
   ***********************************************************************/
  
***************
*** 15855,15860 ****
--- 17846,17908 ----
      }
  
    return NO_CURSOR;
+ }
+ 
+ 
+ /* Notice when the text cursor of window W has been completely
+    overwritten by a drawing operation that outputs glyphs in AREA
+    starting at X0 and ending at X1 in the line starting at Y0 and
+    ending at Y1.  X coordinates are area-relative.  X1 < 0 means all
+    the rest of the line after X0 has been written.  Y coordinates
+    are window-relative.  */
+ 
+ void
+ notice_overwritten_cursor (w, area, x0, x1, y0, y1)
+      struct window *w;
+      enum glyph_row_area area;
+      int x0, y0, x1, y1;
+ {
+ #ifdef HAVE_CARBON
+   /* ++KFS:  Why is there a special version of this for the mac ? */
+   if (area == TEXT_AREA
+       && w->phys_cursor_on_p
+       && y0 <= w->phys_cursor.y
+       && y1 >= w->phys_cursor.y + w->phys_cursor_height
+       && x0 <= w->phys_cursor.x
+       && (x1 < 0 || x1 > w->phys_cursor.x))
+     w->phys_cursor_on_p = 0;
+ #else
+   if (area == TEXT_AREA && w->phys_cursor_on_p)
+     {
+       int cx0 = w->phys_cursor.x;
+       int cx1 = cx0 + w->phys_cursor_width;
+       int cy0 = w->phys_cursor.y;
+       int cy1 = cy0 + w->phys_cursor_height;
+ 
+       if (x0 <= cx0 && (x1 < 0 || x1 >= cx1))
+       {
+         /* The cursor image will be completely removed from the
+            screen if the output area intersects the cursor area in
+            y-direction.  When we draw in [y0 y1[, and some part of
+            the cursor is at y < y0, that part must have been drawn
+            before.  When scrolling, the cursor is erased before
+            actually scrolling, so we don't come here.  When not
+            scrolling, the rows above the old cursor row must have
+            changed, and in this case these rows must have written
+            over the cursor image.
+ 
+            Likewise if part of the cursor is below y1, with the
+            exception of the cursor being in the first blank row at
+            the buffer and window end because update_text_area
+            doesn't draw that row.  (Except when it does, but
+            that's handled in update_text_area.)  */
+ 
+         if (((y0 >= cy0 && y0 < cy1) || (y1 > cy0 && y1 < cy1))
+             && w->current_matrix->rows[w->phys_cursor.vpos].displays_text_p)
+           w->phys_cursor_on_p = 0;
+       }
+     }
+ #endif
  }
  
  




reply via email to

[Prev in Thread] Current Thread [Next in Thread]